Skip to content

chore: update dependency handlebars to v4.7.9 [security] - autoclosed#714

Closed
renovate[bot] wants to merge 1 commit intomasterfrom
renovate/npm-handlebars-vulnerability
Closed

chore: update dependency handlebars to v4.7.9 [security] - autoclosed#714
renovate[bot] wants to merge 1 commit intomasterfrom
renovate/npm-handlebars-vulnerability

Conversation

@renovate
Copy link
Copy Markdown
Contributor

@renovate renovate bot commented Mar 27, 2026

This PR contains the following updates:

Package Change Age Adoption Passing Confidence
handlebars (source) 4.7.84.7.9 age adoption passing confidence

GitHub Vulnerability Alerts

GHSA-442j-39wm-28r2

Summary

In lib/handlebars/runtime.js, the container.lookup() function uses container.lookupProperty() as a gate check to enforce prototype-access controls, but then discards the validated result and performs a second, unguarded property access (depths[i][name]). This Time-of-Check Time-of-Use (TOCTOU) pattern means the security check and the actual read are decoupled, and the raw access bypasses any sanitization that lookupProperty may perform.

Only relevant when the compat compile option is enabled ({compat: true}), which activates depthedLookup in lib/handlebars/compiler/javascript-compiler.js.

Description

The vulnerable code in lib/handlebars/runtime.js (lines 137–144):

lookup: function (depths, name) {
  const len = depths.length;
  for (let i = 0; i < len; i++) {
    let result = depths[i] && container.lookupProperty(depths[i], name);
    if (result != null) {
      return depths[i][name];  // BUG: should be `return result;`
    }
  }
},

container.lookupProperty() (lines 119–136) enforces hasOwnProperty checks and resultIsAllowed() prototype-access controls. However, container.lookup() only uses lookupProperty as a boolean gate — if the gate passes (result != null), it then performs an independent, raw depths[i][name] access that circumvents any transformation or wrapped value that lookupProperty may have returned.

Workarounds

  • Avoid enabling { compat: true } when rendering templates that include untrusted data.
  • Ensure context data objects are plain JSON (no Proxies, no getter-based accessor properties).

GHSA-7rx3-28cr-v5wh

Summary

The prototype method blocklist in lib/handlebars/internal/proto-access.js blocks constructor, __defineGetter__, __defineSetter__, and __lookupGetter__, but omits the symmetric __lookupSetter__. This omission is only exploitable when the non-default runtime option allowProtoMethodsByDefault: true is explicitly set — in that configuration __lookupSetter__ becomes accessible while its counterparts remain blocked, creating an inconsistent security boundary.

4.6.0 is the version that introduced protoAccessControl and the allowProtoMethodsByDefault runtime option.

Description

In lib/handlebars/internal/proto-access.js:

const methodWhiteList = Object.create(null);
methodWhiteList['constructor']      = false;
methodWhiteList['__defineGetter__'] = false;
methodWhiteList['__defineSetter__'] = false;
methodWhiteList['__lookupGetter__'] = false;
// __lookupSetter__ intentionally blocked in CVE-2021-23383,
// but omitted here — creating an asymmetric blocklist

All four legacy accessor helpers (__defineGetter__, __defineSetter__, __lookupGetter__, __lookupSetter__) were involved in the exploit chain addressed by CVE-2021-23383. Three of the four were explicitly blocked; __lookupSetter__ was left out.

When allowProtoMethodsByDefault: true is set, any prototype method not present in methodWhiteList is permitted by default. Because __lookupSetter__ is absent from the list, it passes the checkWhiteList check and is accessible in templates, while __lookupGetter__ (its sibling) is correctly denied.

Workarounds

  • Do not set allowProtoMethodsByDefault: true. The default configuration is not affected.
  • If allowProtoMethodsByDefault must be enabled, ensure templates do not reference __lookupSetter__ through untrusted input.

Release Notes

handlebars-lang/handlebars.js (handlebars)

v4.7.9

Compare Source

Commits


Configuration

📅 Schedule: Branch creation - "" (UTC), Automerge - At any time (no schedule defined).

🚦 Automerge: Enabled.

Rebasing: Whenever PR is behind base branch, or you tick the rebase/retry checkbox.

🔕 Ignore: Close this PR and you won't be reminded about this update again.


  • If you want to rebase/retry this PR, check this box

This PR was generated by Mend Renovate. View the repository job log.

@renovate renovate bot requested a review from a team March 28, 2026 00:29
@renovate renovate bot changed the title chore: update dependency handlebars to v4.7.9 [security] chore: update dependency handlebars to v4.7.9 [security] - autoclosed Mar 29, 2026
@renovate renovate bot closed this Mar 29, 2026
@renovate renovate bot deleted the renovate/npm-handlebars-vulnerability branch March 29, 2026 13:14
Signed-off-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
@renovate renovate bot changed the title chore: update dependency handlebars to v4.7.9 [security] - autoclosed chore: update dependency handlebars to v4.7.9 [security] Mar 29, 2026
@renovate renovate bot reopened this Mar 29, 2026
@renovate renovate bot force-pushed the renovate/npm-handlebars-vulnerability branch 2 times, most recently from 3cf9e37 to 227435a Compare March 29, 2026 20:40
@renovate renovate bot changed the title chore: update dependency handlebars to v4.7.9 [security] chore: update dependency handlebars to v4.7.9 [security] - autoclosed Mar 30, 2026
@renovate renovate bot closed this Mar 30, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

0 participants