From cbc317508b91e8e8030e75d42c0cb8796f0bdddb Mon Sep 17 00:00:00 2001 From: Yang Jun Date: Sun, 19 Jul 2026 14:09:46 +0800 Subject: [PATCH] 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 --- src/context/context.ts | 5 ++--- test/integration/liquid/scope-security.spec.ts | 4 ++++ 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/src/context/context.ts b/src/context/context.ts index 471e29760..ec0ecd5a1 100644 --- a/src/context/context.ts +++ b/src/context/context.ts @@ -1,7 +1,7 @@ import { Drop } from '../drop/drop' import { __assign } from 'tslib' import { NormalizedFullOptions, defaultOptions, RenderOptions } from '../liquid-options' -import { createScope, isBlockedScopeKey, Scope, shouldBlockScopeKeyRead } from './scope' +import { createScope, Scope, shouldBlockScopeKeyRead } from './scope' import { hasOwnProperty, isArray, isNil, isUndefined, isString, isFunction, isNumber, toLiquid, InternalUndefinedVariableError, toValueSync, isObject, Limiter, toValue, readArrayElement } from '../util' type PropertyKey = string | number; @@ -116,9 +116,9 @@ export class Context { }) } private findScope (key: string | number) { - if (isBlockedScopeKey(key) && this.ownPropertyOnly) return createScope() const hasKey = (obj: Scope) => { if (obj == null) return false + if (shouldBlockScopeKeyRead(obj, key, this.ownPropertyOnly)) return false return this.ownPropertyOnly ? hasOwnProperty.call(obj, key) : key in obj @@ -128,7 +128,6 @@ export class Context { if (hasKey(candidate)) return candidate } if (hasKey(this.environments)) return this.environments - if (hasKey(this.globals)) return this.globals return this.globals } readProperty (obj: Scope, key: (PropertyKey | Drop)) { diff --git a/test/integration/liquid/scope-security.spec.ts b/test/integration/liquid/scope-security.spec.ts index 6442c9e67..9172bd314 100644 --- a/test/integration/liquid/scope-security.spec.ts +++ b/test/integration/liquid/scope-security.spec.ts @@ -72,6 +72,10 @@ describe('scope security', function () { await expect(liquid.parseAndRender('{{ foo.constructor.name }}', scope, { ownPropertyOnly: false })).resolves.toBe('') }) + it('should not resolve top-level inherited constructor when ownPropertyOnly=false', async function () { + await expect(liquid.parseAndRender('{{ constructor.name }}', { name: 'Alice' }, { ownPropertyOnly: false })).resolves.toBe('') + }) + it('should not write increment to __proto__ on user scope', async function () { const scope = Object.create(null) as Record await expect(liquid.parseAndRender('{% increment __proto__ %}', scope)).resolves.toBe('')