[Pkg-javascript-devel] Bug#1132141: node-handlebars: CVE-2026-33916 CVE-2026-33937 CVE-2026-33938 CVE-2026-33939 CVE-2026-33940 CVE-2026-33941
Salvatore Bonaccorso
carnil at debian.org
Sat Mar 28 13:56:32 GMT 2026
Source: node-handlebars
Version: 3:4.7.7+~4.1.0-1
Severity: important
Tags: security upstream
X-Debbugs-Cc: carnil at debian.org, Debian Security Team <team at security.debian.org>
Hi,
The following vulnerabilities were published for node-handlebars.
CVE-2026-33916[0]:
| Handlebars provides the power necessary to let users build semantic
| templates. In versions 4.0.0 through 4.7.8, `resolvePartial()` in
| the Handlebars runtime resolves partial names via a plain property
| lookup on `options.partials` without guarding against prototype-
| chain traversal. When `Object.prototype` has been polluted with a
| string value whose key matches a partial reference in a template,
| the polluted string is used as the partial body and rendered without
| HTML escaping, resulting in reflected or stored XSS. Version 4.7.9
| fixes the issue. Some workarounds are available. Apply
| `Object.freeze(Object.prototype)` early in application startup to
| prevent prototype pollution. Note: this may break other libraries,
| and/or use the Handlebars runtime-only build (`handlebars/runtime`),
| which does not compile templates and reduces the attack surface.
CVE-2026-33937[1]:
| Handlebars provides the power necessary to let users build semantic
| templates. In versions 4.0.0 through 4.7.8, `Handlebars.compile()`
| accepts a pre-parsed AST object in addition to a template string.
| The `value` field of a `NumberLiteral` AST node is emitted directly
| into the generated JavaScript without quoting or sanitization. An
| attacker who can supply a crafted AST to `compile()` can therefore
| inject and execute arbitrary JavaScript, leading to Remote Code
| Execution on the server. Version 4.7.9 fixes the issue. Some
| workarounds are available. Validate input type before calling
| `Handlebars.compile()`; ensure the argument is always a `string`,
| never a plain object or JSON-deserialized value. Use the Handlebars
| runtime-only build (`handlebars/runtime`) on the server if templates
| are pre-compiled at build time; `compile()` will be unavailable.
CVE-2026-33938[2]:
| 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 `{{> @partial-
| block}}` compiles and executes that AST, enabling arbitrary
| JavaScript execution on the server. Version 4.7.9 fixes the issue.
| Some workarounds are available. First, use the runtime-only build
| (`require('handlebars/runtime')`). The `compile()` method is
| absent, eliminating the vulnerable fallback path. Second, audit
| registered helpers for any that write arbitrary values to context
| objects. Helpers should treat context data as read-only. Third,
| avoid registering helpers from third-party packages (such as
| `handlebars-helpers`) in contexts where templates or context data
| can be influenced by untrusted input.
CVE-2026-33939[3]:
| 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. `{{*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. Version 4.7.9 fixes the
| issue. Some workarounds are available. Wrap compilation and
| rendering in `try/catch`. 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.
CVE-2026-33940[4]:
| Handlebars provides the power necessary to let users build semantic
| templates. In versions 4.0.0 through 4.7.8, 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.
| Version 4.7.9 fixes the issue. Some workarounds are available.
| First, use the runtime-only build (`require('handlebars/runtime')`).
| Without `compile()`, the fallback compilation path in
| `invokePartial` is unreachable. Second, sanitize context data before
| rendering: Ensure no value in the context is a non-primitive object
| that could be passed to a dynamic partial. Third, avoid dynamic
| partial lookups (`{{> (lookup ...)}}`) when context data is user-
| controlled.
CVE-2026-33941[5]:
| Handlebars provides the power necessary to let users build semantic
| templates. In versions 4.0.0 through 4.7.8, the Handlebars CLI
| precompiler (`bin/handlebars` / `lib/precompiler.js`) concatenates
| user-controlled strings — template file names and several CLI
| options — directly into the JavaScript it emits, without any
| escaping or sanitization. An attacker who can influence template
| filenames or CLI arguments can inject arbitrary JavaScript that
| executes when the generated bundle is loaded in Node.js or a
| browser. Version 4.7.9 fixes the issue. Some workarounds are
| available. First, validate all CLI inputs before invoking the
| precompiler. Reject filenames and option values that contain
| characters with JavaScript string-escaping significance (`"`, `'`,
| `;`, etc.). Second, use a fixed, trusted namespace string passed via
| a configuration file rather than command-line arguments in
| automated pipelines. Third, run the precompiler in a sandboxed
| environment (container with no write access to sensitive paths) to
| limit the impact of successful exploitation. Fourth, audit template
| filenames in any repository or package that is consumed by an
| automated build pipeline.
If you fix the vulnerabilities please also make sure to include the
CVE (Common Vulnerabilities & Exposures) ids in your changelog entry.
For further information see:
[0] https://security-tracker.debian.org/tracker/CVE-2026-33916
https://www.cve.org/CVERecord?id=CVE-2026-33916
[1] https://security-tracker.debian.org/tracker/CVE-2026-33937
https://www.cve.org/CVERecord?id=CVE-2026-33937
[2] https://security-tracker.debian.org/tracker/CVE-2026-33938
https://www.cve.org/CVERecord?id=CVE-2026-33938
[3] https://security-tracker.debian.org/tracker/CVE-2026-33939
https://www.cve.org/CVERecord?id=CVE-2026-33939
[4] https://security-tracker.debian.org/tracker/CVE-2026-33940
https://www.cve.org/CVERecord?id=CVE-2026-33940
[5] https://security-tracker.debian.org/tracker/CVE-2026-33941
https://www.cve.org/CVERecord?id=CVE-2026-33941
Regards,
Salvatore
More information about the Pkg-javascript-devel
mailing list