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]>
This commit is contained in:
Yang Jun
2026-07-21 20:38:46 +08:00
co-authored by Cursor
parent bc207a66b7
commit 12fa904ebd
5 changed files with 14 additions and 34 deletions
@@ -8,22 +8,6 @@ describe('scope security', function () {
liquid = new Liquid()
})
it('should not read __proto__ from passed scope', async function () {
const scope = JSON.parse('{"__proto__": {"polluted": true}, "name": "Alice"}')
await expect(liquid.parseAndRender('{{ name }}', scope)).resolves.toBe('Alice')
await expect(liquid.parseAndRender('{{ __proto__.polluted }}', scope)).resolves.toBe('')
})
it('should not read constructor from passed scope', async function () {
const scope = { name: 'Alice', constructor: { name: 'Object' } }
await expect(liquid.parseAndRender('{{ constructor.name }}', scope)).resolves.toBe('')
})
it('should block inherited constructor when ownPropertyOnly=false', async function () {
await expect(liquid.parseAndRender('{{ foo.constructor.name }}', { foo: {} }, { ownPropertyOnly: false })).resolves.toBe('')
await expect(liquid.parseAndRender('{{ constructor.name }}', { name: 'Alice' }, { ownPropertyOnly: false })).resolves.toBe('')
})
it('should iterate plain objects via inherited Symbol.iterator (ownPropertyOnly exception)', async function () {
// eslint-disable-next-line no-extend-native
(Object.prototype as any)[Symbol.iterator] = function * () { yield 'inherited' }