feat: v11 scope security and ownPropertyOnly hardening (#898) - #938
Merged
Conversation
Co-authored-by: Cursor <cursoragent@cursor.com>
Coverage Report for CI Build 30026771598Warning No base build found for commit Coverage: 99.528%Details
Uncovered ChangesNo uncovered changes found. Coverage RegressionsRequires a base build to compare against. How to fix this → Coverage Stats💛 - Coveralls |
Co-authored-by: Cursor <cursoragent@cursor.com>
Block writes to dangerous keys in assign/capture/increment/decrement, use own-property Symbol.iterator for plain objects when ownPropertyOnly is true, fix inherited size reads, and sanitize filter iteration scopes. Co-authored-by: Cursor <cursoragent@cursor.com>
Block __proto__, constructor, and prototype only when ownPropertyOnly is true or when access would traverse the prototype chain. Allow own properties with those names when ownPropertyOnly is false. Co-authored-by: Cursor <cursoragent@cursor.com>
Iteration is documented as an ownPropertyOnly exception; restore isIterable/toEnumerable and document inherited Symbol.iterator behavior. Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
Use shouldBlockScopeKeyRead in findScope hasKey so inherited constructor/__proto__/prototype do not falsely match environments. Remove redundant globals hasKey check; globals remains the fallback scope. Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
Move readSize, readFirst, and readLast to private Context methods using this.ownPropertyOnly. Remove redundant shouldBlockScopeKeyRead from findScope. Co-authored-by: Cursor <cursoragent@cursor.com>
Centralize null-prototype scope creation in push() so callers pass plain objects; Drop instances and existing null-proto frames are pushed as-is. Remove sanitizeScope in favor of createScope via Object.assign.
Write blocking on assign/capture/increment/decrement duplicated read-side protection in readJSProperty; null-proto scopes from push already prevent prototype pollution on managed writes. Co-authored-by: Cursor <cursoragent@cursor.com>
Restore null-prototype hardening for Jekyll include bindings, colocate blocked-key checks with readJSProperty, align ownPropertyOnly JSDoc with security docs, and drop integration tests duplicated in context.spec. Co-authored-by: Cursor <cursoragent@cursor.com>
Drop null-prototype passthrough in push(), inline blocked-key checks, remove redundant createScope at include tag, trim verbose docs, and drop implementation-detail unit tests. Co-authored-by: Cursor <cursoragent@cursor.com>
Inline findScope and blocked-key checks, shorten ownPropertyOnly docs, and drop implementation-detail push() unit tests. Co-authored-by: Cursor <cursoragent@cursor.com>
Set.has already returns false for non-string PropertyKey values; widen BLOCKED_SCOPE_KEYS type so TypeScript accepts the direct has(key) call. Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
Split the OR condition into two explicit checks so inherited proto keys are always blocked and own proto keys are blocked only when ownPropertyOnly is true. Co-authored-by: Cursor <cursoragent@cursor.com>
Proto keys block inherited access only; ownPropertyOnly is checked once before return for all keys. Own __proto__/constructor/prototype properties are readable—sanitize untrusted scope input. Co-authored-by: Cursor <cursoragent@cursor.com>
Proto keys were incorrectly blocked even when ownPropertyOnly=false. Inherited access is now gated only by ownPropertyOnly; docs updated. Co-authored-by: Cursor <cursoragent@cursor.com>
Dangerous keys (__proto__, constructor, prototype) are blocked only when ownPropertyOnly is true (default). With false, full prototype access is allowed as an explicit opt-out; use bourne for untrusted input. Co-authored-by: Cursor <cursoragent@cursor.com>
Details live in Security Model; keep options.md consistent with strictFilters/strictVariables tone. Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
__proto__,constructor, andprototypewhenownPropertyOnlyistrue(default) inreadJSProperty; withfalse, full prototype access is allowed—sanitize untrusted scope input (e.g. bourne).findScopewithownPropertyOnly(own-property vsinchecks on scope frames and environments) before falling back to globals; no separate write-path blocking—null-prototype managed frames frompush()cover tag writes.Context.push()wraps plain objects viacreateScope(Object.assign(Object.create(null), …));Dropinstances are pushed as-is. Tags use the returned scope for in-place updates.readSize/readFirst/readLastontoContextso inheritedsizeon plain objects is not surfaced whenownPropertyOnlyistrue. Iteration/Symbol.iteratorbehavior unchanged (documented exception in Security Model).ownPropertyOnlyin options tutorial andLiquidOptionsJSDoc (one line + link).Breaking change (v11)
Context.push()now returns the pushedScopeinstead of the numeric result ofArray.prototype.push().Test plan
npm run build && npm test -- context.spec scope-securityownPropertyOnly: trueblocks own/inherited dangerous keys and inheritedsizeon plain objects (context.spec,scope-security.spec.ts)ownPropertyOnly: falseallows own/inherited blocked keys when explicitly opted out (context.spec)Symbol.iteratoron plain objects still works;Dropiteration unchanged (scope-security.spec.ts)Closes #898