Skip to content

fix(amplify-velocity-template): block prototype-chain property access in vtl reference resolver - #14964

Merged
sarayev merged 1 commit into
devfrom
fix/vtl-prototype-chain-access
Jul 27, 2026
Merged

fix(amplify-velocity-template): block prototype-chain property access in vtl reference resolver#14964
sarayev merged 1 commit into
devfrom
fix/vtl-prototype-chain-access

Conversation

@sarayev

@sarayev sarayev commented Jul 24, 2026

Copy link
Copy Markdown
Contributor

Description of changes

The VTL reference resolver mapped property, index, and method access in a
template directly onto JavaScript property lookups with no restriction on
which names could be resolved. Because JavaScript objects expose their
internal machinery through the prototype chain, a template could walk from
any context value up to the Function constructor — for example
$ctx.constructor.constructor("...") — and from there build and invoke
arbitrary code, escaping the intended template sandbox.

This change hardens the resolver so that JavaScript-internal, prototype-chain
property names can never be resolved or invoked from a template.

Blocked-property guard in the reference resolver

Adds a single isBlockedProperty guard backed by a small list of
prototype-chain names: constructor, __proto__, prototype,
__defineGetter__, __defineSetter__, __lookupGetter__, and
__lookupSetter__. The guard is applied consistently to all three access
paths the resolver supports:

  • dot / property access ($ctx.constructor)
  • bracket / index access ($ctx['constructor'])
  • method-call access ($ctx.constructor(...))

When a template references one of these names it now resolves to an undefined
reference, so it renders as empty (or the literal text under non-silent
reference notation) and can never be called. This closes the path from a
context value to the Function constructor.

Backward compatibility

Only these JavaScript-internal names change behavior. Normal data access and
method calls are unaffected — $ctx.name, $ctx['name'],
$str.toUpperCase(), $list.size(), and $map.keySet() all continue to
work exactly as before. Real template data has no legitimate need to resolve
prototype-chain properties, so this narrows the resolver's surface without
affecting valid templates.

Issue #, if available

N/A

Description of how you validated changes

Added regression tests in packages/amplify-velocity-template/tests/references.test.js:

  • Negative assertions that dot, bracket, and chained constructor /
    __proto__ / prototype access all render empty.
  • An execution-safety assertion that a chained constructor invocation
    ($!ctx.constructor.constructor("globalThis.__vtlMarker = true").call())
    renders empty and leaves the global marker unset, proving no code was
    executed.
  • Positive regressions confirming normal property access and normal method
    calls (toUpperCase(), size(), keySet()) still resolve correctly.

Ran the full package suite with mocha:

153 passing (59ms)

0 failing.

Checklist

  • PR description included
  • yarn test passes
  • Tests are changed or added
  • Relevant documentation is changed or added (and PR referenced)
  • New AWS SDK calls or CloudFormation actions have been added to relevant test and service IAM policies
  • Pull request labels are added

By submitting this pull request, I confirm that my contribution is made under the terms of the Apache 2.0 license.

… in vtl reference resolver

The VTL reference resolver mapped property, index, and method access
directly to JavaScript property lookups with no restriction, which
allowed a template to traverse the object prototype chain (for example
via constructor or __proto__) and reach the Function constructor.

This adds a blocked-property guard that is applied on all three access
paths (property, bracket/index, and method call) so that names such as
constructor, __proto__, and prototype resolve as an undefined reference
and blocked names can never be invoked. Normal data and method access
is unaffected. Package build and tests run green (153 passing, 0
failing).
---
Prompt: Harden the amplify-velocity-template VTL reference resolver
against JavaScript prototype-chain property access
(constructor/__proto__/prototype); cut a branch from latest dev,
implement, test, and commit.
@sarayev
sarayev marked this pull request as ready for review July 24, 2026 13:03
@sarayev
sarayev requested review from a team as code owners July 24, 2026 13:03
@sarayev
sarayev merged commit b208637 into dev Jul 27, 2026
5 checks passed
@sarayev
sarayev deleted the fix/vtl-prototype-chain-access branch July 27, 2026 11:27
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants