CVE-2026-33939: Handlebars.js has Denial of Service via Malformed Decorator Syntax in Template Compilation
Summary
When a Handlebars template contains decorator syntax referencing an unregistered decorator (e.g. {{n}}), the compiled template calls lookupProperty(decorators, "n"), which returns undefined. The runtime then immediately invokes the result as a function, causing an unhandled TypeError: ... is not a function that crashes the Node.js process. Any application that compiles user-supplied templates without wrapping the call in a try/catch is vulnerable to a single-request Denial of Service.
Description
In lib/handlebars/compiler/javascript-compiler.js, the code generated for a decorator invocation looks like:
javascript fn = lookupProperty(decorators, "n")(fn, props, container, options) || fn;
When "n" is not a registered decorator, lookupProperty(decorators, "n") returns undefined. The expression immediately attempts to call undefined as a function, producing:
TypeError: lookupProperty(...) is not a function
Because the error is thrown inside the compiled template function and is not caught by the runtime, it propagates up as an unhandled exception and — when not caught by the application — crashes the Node.js process.
This inconsistency is notable: references to unregistered helpers produce a clean "Missing helper: ..." error, while references to unregistered decorators cause a hard crash.
Attack scenario: An attacker submits {{n}} as template content to any endpoint that calls Handlebars.compile(userInput)(). Each request crashes the server process; with process managers that auto-restart (PM2, systemd), repeated submissions create a persistent DoS.
Proof of Concept
javascript const Handlebars = require('handlebars'); // Handlebars 4.7.8, Node.js v22.x
// Any of these payloads crash the process Handlebars.compile('{{n}}')({}); Handlebars.compile('{{decorator}}')({}); Handlebars.compile('{{constructor}}')({});
Expected crash output: TypeError: lookupProperty(...) is not a function at Function.eval [as decorator] (eval at compile (...javascript-compiler.js:134:36))
Workarounds
- Wrap compilation and rendering in try/catch: javascript try { const result = Handlebars.compile(userInput)(context); res.send(result); } catch (err) { res.status(400).send('Invalid template'); } - Validate template input before passing it to compile(). Reject templates containing decorator syntax ({{...}}) if decorators are not used in your application. - Use the pre-compilation workflow: compile templates at build time and serve only pre-compiled templates; do not call compile() at request time.
Other sources
Handlebars provides the power necessary to let users build semantic templates. In versions 4.0.0 through 4.7.8, when a Handlebars template contains decorator syntax referencing an unregistered decorator (e.g. {
— 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
Reject templates containing Handlebars decorator syntax (`{{*...}}`) if decorators are not used in your application (e.g., `{{*n}}`, `{{*constructor}}`, `{{*decorator}}`).
Handlebars templates decorator_syntax_allowed = false - Configuration
Wrap the compilation and rendering path in `try/catch` so that `Handlebars.compile(userInput)` / the compiled template invocation errors (e.g., `TypeError: ... is not a function` from unregistered decorator syntax) do not propagate as unhandled exceptions that crash the Node.js process.
Node.js/Express route using Handlebars.compile(userInput) compile_and_render_error_handling = wrap_in_try_catch - Compensating control
Use the pre-compilation workflow: compile templates at build time and serve only pre-compiled templates; do not call `Handlebars.compile()` at request time.
Event History
Frequently Asked Questions
What is the severity of CVE-2026-33939?
CVE-2026-33939 has been classified with a medium severity due to the potential for unhandled TypeErrors when unregistered decorators are invoked.
How do I fix CVE-2026-33939?
To fix CVE-2026-33939, upgrade Handlebars to version 4.7.9 or later.
What software is affected by CVE-2026-33939?
CVE-2026-33939 affects Handlebars versions between 4.0.0 and 4.7.8.
What type of vulnerability is CVE-2026-33939?
CVE-2026-33939 is a runtime vulnerability that occurs when invoking undefined decorators in Handlebars templates.
What mitigation strategies can be applied for CVE-2026-33939?
Mitigation for CVE-2026-33939 involves ensuring all decorators used in templates are properly registered.