* feat: block dangerous scope keys and harden findScope (#898)
Co-authored-by: Cursor <[email protected]>
* docs: fix ownPropertyOnly default in security model
Co-authored-by: Cursor <[email protected]>
* feat: harden scope writes, iteration, and readSize (#898)
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 <[email protected]>
* fix: tie proto key blocking to ownPropertyOnly policy
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 <[email protected]>
* fix: revert ownPropertyOnly iteration hardening
Iteration is documented as an ownPropertyOnly exception; restore
isIterable/toEnumerable and document inherited Symbol.iterator behavior.
Co-authored-by: Cursor <[email protected]>
* docs: fix ownPropertyOnly blocked-keys wording in options
Co-authored-by: Cursor <[email protected]>
* fix: unify blocked-key checks in findScope
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 <[email protected]>
* test: trim redundant scope-security integration tests
Co-authored-by: Cursor <[email protected]>
* refactor: move readSize to Context methods
Move readSize, readFirst, and readLast to private Context methods using this.ownPropertyOnly. Remove redundant shouldBlockScopeKeyRead from findScope.
Co-authored-by: Cursor <[email protected]>
* refactor: wrap plain scopes in Context.push()
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.
* refactor: drop redundant tag write-path blocking
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 <[email protected]>
* fix: address scope-security review findings
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 <[email protected]>
* refactor: simplify scope-security MR
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 <[email protected]>
* refactor: trim scope-security helpers and docs
Inline findScope and blocked-key checks, shorten ownPropertyOnly docs,
and drop implementation-detail push() unit tests.
Co-authored-by: Cursor <[email protected]>
* refactor: encapsulate Drop passthrough in createScope
* refactor: drop redundant typeof in blocked key check
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 <[email protected]>
* docs: shorten ownPropertyOnly proto-key wording
Co-authored-by: Cursor <[email protected]>
* fix: clarify blocked key checks in readJSProperty
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 <[email protected]>
* fix: apply ownPropertyOnly uniformly in readJSProperty
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 <[email protected]>
* fix: remove BLOCKED_SCOPE_KEYS; ownPropertyOnly is the sole read policy
Proto keys were incorrectly blocked even when ownPropertyOnly=false.
Inherited access is now gated only by ownPropertyOnly; docs updated.
Co-authored-by: Cursor <[email protected]>
* fix: restore BLOCKED_SCOPE_KEYS gated by ownPropertyOnly
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 <[email protected]>
* docs: shorten ownPropertyOnly entry in options tutorial
Details live in Security Model; keep options.md consistent with strictFilters/strictVariables tone.
Co-authored-by: Cursor <[email protected]>
* docs: simplify ownPropertyOnly JSDoc in LiquidOptions
Co-authored-by: Cursor <[email protected]>
* test: cover readSize branches in Context
Co-authored-by: Cursor <[email protected]>
---------
Co-authored-by: Cursor <[email protected]>
* feat: remove memoryLimit option (#910)
Co-authored-by: Cursor <[email protected]>
* feat: add templateLimit, outputLengthLimit, and maxDepth DoS limits
Enforce v11 resource guards in render and tags, fix for offset/else behavior, and update tutorials for Tag-class registration.
Co-authored-by: Cursor <[email protected]>
* docs: revert unnecessary tutorial churn from memoryLimit PR
Restore the two-example register-filters-tags structure (Value + Hash)
and undo unrelated constructor/emitter doc edits not required for DoS limits.
Co-authored-by: Cursor <[email protected]>
* docs: trim security-model prose and update render-tag-content
Remove diary-style engine comparisons from security-model.md.
Update render-tag-content tutorial to Tag class examples with tpls class field.
Co-authored-by: Cursor <[email protected]>
* docs: note maxDepth stack overflow applies to renderSync only
Explain why async render does not need maxDepth for stack protection based on generator/toPromise driving.
Co-authored-by: Cursor <[email protected]>
* refactor: track maxDepth via depthLimit Limiter on Context
Replace increaseDepth/decreaseDepth with a shared Limiter that supports
paired use/release, matching templateLimit and outputLengthLimit patterns.
Co-authored-by: Cursor <[email protected]>
* fix: remove spurious diff noise in filter files
Restore misc.ts from origin/next with LF line endings and re-apply only
memoryLimit removal, avoiding CRLF and blank-line churn in the export block.
Co-authored-by: Cursor <[email protected]>
* refactor: minimize PR diff noise
Co-authored-by: Cursor <[email protected]>
* feat: cap strftime pad width at 1M
docs: restructure security model with production guidance
Co-authored-by: Cursor <[email protected]>
* refactor: simplify depthLimit in partial tags and tighten security docs
Drop try/finally around depthLimit in include, layout, and render; release at generator end. Consolidate production guidance in security-model.md. Fix padded-blocks lint in dos.spec.ts.
Co-authored-by: Cursor <[email protected]>
---------
Co-authored-by: Cursor <[email protected]>
Remove KeepingTypeEmitter and always stringify via SimpleEmitter. On next, map breaking commits to patch so alpha stays on 11.x.
Co-authored-by: Cursor <[email protected]>
* fix: enforce ownPropertyOnly for inherited array indices
Route array index access (including negative indices, first/last, and the
first/last filters) through a shared readArrayElement helper so that
ownPropertyOnly hides prototype-inherited array indices, closing the
GHSA-fwxr-j5w2-587m bypass. The option's scope (property/index access
only, not filter transforms or iteration) is documented on the option.
Co-authored-by: Cursor <[email protected]>
* fix(filters): invoke Array.prototype methods on unsanitized array values
Call built-ins via Array.prototype.<m>.call(...) for values that come
from scope (join, compact, concat, slice, where/reject) so an overridden
instance method on unsanitized data cannot hijack filter behavior.
Methods on freshly-created arrays are left as-is.
Co-authored-by: Cursor <[email protected]>
* fix(filters): use String.prototype.slice for the string branch of slice
Route the non-array branch through String.prototype.slice.call so the
slice filter never dispatches through a possibly-overridden instance
method, matching the Array.prototype guard.
Co-authored-by: Cursor <[email protected]>
---------
Co-authored-by: Cursor <[email protected]>
* docs: add GitHub buttons and improve option docs
* chore: replace husky with prepush check
* docs: revamp homepage and switch to custom GitHub buttons
- Make the docs English-only by removing all zh-cn content, the language switcher UI, and related JS/config
- Rework homepage feature cards (Safe & Typed, Pure JavaScript, Shopify & Jekyll, Streaming) and refresh section colors/layout
- Replace buttons.github.io with custom Star/Sponsor buttons featuring a live star count and dark-mode support
- Drop the buttons.js script and tidy banner, header, footer, and share partials
Co-authored-by: Cursor <[email protected]>
* fix: restore tsconfig settings and changelog build
Re-add suppressImplicitAnyIndexErrors and downlevelIteration removed in
a75033e2c, which broke the rollup TypeScript build on CI. Drop zh-cn
changelog output now that translations were removed.
Co-authored-by: Cursor <[email protected]>
* fix: resolve TS errors without deprecated tsconfig options
Co-authored-by: Cursor <[email protected]>
---------
Co-authored-by: Cursor <[email protected]>
- `relativeReference` is enabled by default, set to `false` to disable
- Referenced files are still constrained within root/partias/layouts
- fix: relative filenames are not constrained (which allows arbitrary filesystem read)
Example Usage:
{% render "../foo/bar.html" %}
Note:
../foo/bar.html' should also be within `partials` (or `root` if `partials` not set)