{"id":"CVE-2026-33939","aliases":["CLSA-2026-1782349135","CLSA-2026-1782435546","CLSA-2026-1792139237","DEBIAN-CVE-2026-33939","EUVD-2026-16858","GHSA-442j-39wm-28r2","GHSA-7rx3-28cr-v5wh","GHSA-9cx6-37pm-9jff","ROOT-APP-NPM-CVE-2026-33939","ROOT-APP-NPM-GHSA-7rx3-28cr-v5wh","UBUNTU-CVE-2026-33939"],"status":"published","title":"Handlebars.js has Denial of Service via Malformed Decorator Syntax in Template Compilation","description":"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.","severity":{"version":"3.1","score":7.5,"vector":"CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H","level":"high","assessor":"cna","from":"cve"},"epss":{"day":"2026-11-10","score":0.00627,"percentile":0.50396,"model":"v2026.06.15"},"facts":{"in_kev":false,"known_exploited":false,"public_exploit":false,"fix_available":true},"cwes":["CWE-1321","CWE-248","CWE-367","CWE-754"],"published":"2026-03-27T18:21:15Z","modified":"2026-10-28T02:30:51Z","fixes":[{"ecosystem":"npm","package":"handlebars","fixed_in":["4.7.9"],"sources":["ghsa","osv"]},{"ecosystem":"Debian:14","package":"node-handlebars","fixed_in":["3:4.7.9-1"],"sources":["osv"]},{"ecosystem":"Root:npm","package":"handlebars","fixed_in":["4.7.7-aikido.2","4.7.8-aikido.6","4.7.7-aikido.3","4.7.7-aikido.4","4.7.7-aikido.5"],"sources":["osv"]},{"ecosystem":"Root:npm","package":"@rootio/handlebars","fixed_in":["4.7.8-root.io.2","4.7.8-root.io.3","4.7.8-root.io.4","4.7.8-root.io.5","4.7.7-root.io.1","4.7.7-root.io.2","4.7.8-root.io.6","4.7.7-root.io.3","4.7.7-root.io.4","4.7.7-root.io.5"],"sources":["osv"]}],"affected":[{"source":"ghsa","ecosystem":"npm","package":"handlebars","ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"4.0.0"},{"last_affected":"4.7.8"},{"fixed":"4.7.9"}]}]},{"source":"ghsa","ecosystem":"npm","package":"handlebars","ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"4.6.0"},{"last_affected":"4.7.8"},{"fixed":"4.7.9"}]}]},{"source":"ghsa","ecosystem":"npm","package":"handlebars","ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"4.0.0"},{"last_affected":"4.7.8"},{"fixed":"4.7.9"}]}]},{"source":"osv","ecosystem":"TuxCare:npm","package":"handlebars","ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"4.7.7-tuxcare.0"},{"fixed":"4.7.7-tuxcare.1"}]}],"versions":["4.7.7"],"bundled":6},{"source":"osv","ecosystem":"TuxCare:npm","package":"handlebars","ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"4.7.8-tuxcare.0"},{"fixed":"4.7.8-tuxcare.1"}]}],"versions":["4.7.8"],"bundled":6},{"source":"osv","ecosystem":"TuxCare:npm","package":"handlebars","ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"4.5.3-tuxcare.0"},{"fixed":"4.5.3-tuxcare.3"}]}],"versions":["4.5.3","4.5.3-tuxcare.1","4.5.3-tuxcare.2"],"bundled":6},{"source":"osv","ecosystem":"Debian:12","package":"node-handlebars","ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"0"}]}],"versions":["3:4.7.10-1","3:4.7.7+~4.1.0-1","3:4.7.9-1","3:4.7.9-2","3:4.7.9-3","3:4.7.9-4","3:4.7.9-5","3:4.7.9-6"]},{"source":"osv","ecosystem":"Debian:13","package":"node-handlebars","ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"0"}]}],"versions":["3:4.7.10-1","3:4.7.7+~4.1.0-1","3:4.7.9-1","3:4.7.9-2","3:4.7.9-3","3:4.7.9-4","3:4.7.9-5","3:4.7.9-6"]},{"source":"osv","ecosystem":"Debian:14","package":"node-handlebars","ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"0"},{"fixed":"3:4.7.9-1"}]}],"versions":["3:4.7.7+~4.1.0-1"]},{"source":"osv","ecosystem":"npm","package":"handlebars","ranges":[{"type":"SEMVER","events":[{"introduced":"4.0.0"},{"fixed":"4.7.9"}]}]},{"source":"osv","ecosystem":"npm","package":"handlebars","ranges":[{"type":"SEMVER","events":[{"introduced":"4.6.0"},{"fixed":"4.7.9"}]}]},{"source":"osv","ecosystem":"npm","package":"handlebars","ranges":[{"type":"SEMVER","events":[{"introduced":"4.0.0"},{"fixed":"4.7.9"}]}]},{"source":"osv","ecosystem":"Root:npm","package":"handlebars","ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"0"},{"fixed":"4.7.7-aikido.2"},{"fixed":"4.7.8-aikido.6"},{"fixed":"4.7.7-aikido.3"},{"fixed":"4.7.7-aikido.4"},{"fixed":"4.7.7-aikido.5"}]}]},{"source":"osv","ecosystem":"Root:npm","package":"@rootio/handlebars","ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"0"},{"fixed":"4.7.8-root.io.2"},{"fixed":"4.7.8-root.io.3"},{"fixed":"4.7.8-root.io.4"},{"fixed":"4.7.8-root.io.5"},{"fixed":"4.7.7-root.io.1"},{"fixed":"4.7.7-root.io.2"},{"fixed":"4.7.8-root.io.6"},{"fixed":"4.7.7-root.io.3"},{"fixed":"4.7.7-root.io.4"},{"fixed":"4.7.7-root.io.5"}]}]},{"source":"osv","ecosystem":"Root:npm","package":"handlebars","ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"0"},{"fixed":"4.7.8-aikido.6"},{"fixed":"4.7.7-aikido.3"},{"fixed":"4.7.7-aikido.4"},{"fixed":"4.7.7-aikido.5"}]}]},{"source":"osv","ecosystem":"Root:npm","package":"@rootio/handlebars","ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"0"},{"fixed":"4.7.8-root.io.5"},{"fixed":"4.7.8-root.io.6"},{"fixed":"4.7.7-root.io.3"},{"fixed":"4.7.7-root.io.4"},{"fixed":"4.7.7-root.io.5"}]}]},{"source":"osv","ecosystem":"Ubuntu:18.04:LTS","package":"node-handlebars","ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"0"}]}],"versions":["3:4.0.10-5"]},{"source":"osv","ecosystem":"Ubuntu:20.04:LTS","package":"node-handlebars","ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"0"}]}],"versions":["3:4.1.0-1","3:4.5.3-1","3:4.7.2-1"]},{"source":"osv","ecosystem":"Ubuntu:22.04:LTS","package":"node-handlebars","ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"0"}]}],"versions":["3:4.7.6+~4.1.0-2","3:4.7.7+~4.1.0-1"]},{"source":"osv","ecosystem":"Ubuntu:24.04:LTS","package":"node-handlebars","ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"0"}]}],"versions":["3:4.7.7+~4.1.0-1"]},{"source":"osv","ecosystem":"Ubuntu:25.10","package":"node-handlebars","ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"0"}]}],"versions":["3:4.7.7+~4.1.0-1"]},{"source":"osv","ecosystem":"Ubuntu:26.10","package":"node-handlebars","ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"0"}]}],"versions":["3:4.7.7+~4.1.0-1","3:4.7.9-5"]},{"source":"osv","ecosystem":"Ubuntu:26.04:LTS","package":"node-handlebars","ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"0"}]}],"versions":["3:4.7.7+~4.1.0-1"]}],"products":[{"vendor":"handlebars-lang","product":"handlebars.js"},{"vendor":"handlebarsjs","product":"handlebars"},{"vendor":"red hat","product":"cluster observability operator 1.5.0"},{"vendor":"red hat","product":"cryostat 4"},{"vendor":"red hat","product":"logging subsystem for red hat openshift"},{"vendor":"red hat","product":"red hat data grid 8"},{"vendor":"red hat","product":"red hat enterprise linux 10"},{"vendor":"red hat","product":"red hat enterprise linux 7"},{"vendor":"red hat","product":"red hat enterprise linux 8"},{"vendor":"red hat","product":"red hat enterprise linux 9"},{"vendor":"red hat","product":"red hat openshift ai (rhoai)"},{"vendor":"red hat","product":"red hat openshift dev spaces 3.27"},{"vendor":"red hat","product":"red hat process automation 7"}],"references":[{"url":"https://github.com/handlebars-lang/handlebars.js/security/advisories/GHSA-9cx6-37pm-9jff","tags":["x_refsource_CONFIRM","exploit","Exploit","Vendor Advisory","advisory","web","report"]},{"url":"https://github.com/handlebars-lang/handlebars.js/commit/68d8df5a88e0a26fe9e6084c5c6aaebe67b07da2","tags":["x_refsource_MISC","Patch","fix","web","report"]},{"url":"https://github.com/handlebars-lang/handlebars.js/releases/tag/v4.7.9","tags":["x_refsource_MISC","Release Notes","web","report"]},{"url":"https://access.redhat.com/security/cve/CVE-2026-33939","tags":["vdb-entry","x_refsource_REDHAT","advisory"]},{"url":"https://bugzilla.redhat.com/show_bug.cgi?id=2452508","tags":["issue-tracking","x_refsource_REDHAT","report"]},{"url":"https://security.access.redhat.com/data/csaf/v2/vex/2026/cve-2026-33939.json","tags":["x_sadp-csaf-vex","web"]},{"url":"https://access.redhat.com/errata/RHSA-2026:34342","tags":["vendor-advisory","x_refsource_REDHAT","advisory"]},{"url":"https://access.redhat.com/errata/RHSA-2026:10175","tags":["vendor-advisory","x_refsource_REDHAT","advisory"]},{"url":"https://github.com/handlebars-lang/handlebars.js/security/advisories/GHSA-442j-39wm-28r2","tags":["web"]},{"url":"https://github.com/advisories/GHSA-442j-39wm-28r2"},{"url":"https://github.com/handlebars-lang/handlebars.js/security/advisories/GHSA-7rx3-28cr-v5wh","tags":["web"]},{"url":"https://github.com/advisories/GHSA-765h-qjxv-5f44","tags":["advisory"]},{"url":"https://github.com/advisories/GHSA-7rx3-28cr-v5wh"},{"url":"https://nvd.nist.gov/vuln/detail/CVE-2026-33939","tags":["advisory"]},{"url":"https://github.com/advisories/GHSA-9cx6-37pm-9jff"},{"url":"https://github.com/CVEProject/cvelistV5/tree/main/cves/2026/33xxx/CVE-2026-33939.json","tags":["advisory"]},{"url":"https://security-tracker.debian.org/tracker/CVE-2026-33939","tags":["advisory"]},{"url":"https://github.com/handlebars-lang/handlebars.js","tags":["package"]},{"url":"https://ubuntu.com/security/CVE-2026-33939","tags":["report"]},{"url":"https://www.cve.org/CVERecord?id=CVE-2026-33939","tags":["report"]}],"sources":{"cve":[{"id":"CVE-2026-33939","title":"Handlebars.js has Denial of Service via Malformed Decorator Syntax in Template Compilation","description":"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.","status":"published","published":"2026-03-27T21:08:24.664Z","modified":"2026-09-04T12:04:44.445Z","cvss":[{"version":"3.1","score":7.5,"vector":"CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H","level":"high","assessor":"cna"},{"version":"3.1","score":7.5,"vector":"CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H","level":"high","assessor":"adp"}],"cwes":["CWE-754","CWE-248"],"updated_at":"2026-11-02T14:20:08.009733Z"}],"euvd":[{"id":"EUVD-2026-16858","description":"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.","status":"published","published":"2026-03-27T21:08:24Z","modified":"2026-09-04T12:04:44Z","cvss":[{"version":"3.1","score":7.5,"vector":"CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H","level":"high"}],"updated_at":"2026-11-02T18:01:12.73639Z"}],"ghsa":[{"id":"GHSA-442j-39wm-28r2","title":"Handlebars.js has a Property Access Validation Bypass in container.lookup","description":"## Summary\n\nIn `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.\n\nOnly relevant when the **compat** compile option is enabled (`{compat: true}`), which activates `depthedLookup` in `lib/handlebars/compiler/javascript-compiler.js`.\n\n## Description\n\nThe vulnerable code in `lib/handlebars/runtime.js` (lines 137–144):\n\n```javascript\nlookup: function (depths, name) {\n  const len = depths.length;\n  for (let i = 0; i \u003c len; i++) {\n    let result = depths[i] \u0026\u0026 container.lookupProperty(depths[i], name);\n    if (result != null) {\n      return depths[i][name];  // BUG: should be `return result;`\n    }\n  }\n},\n```\n\n`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.\n\n## Workarounds\n\n- Avoid enabling `{ compat: true }` when rendering templates that include untrusted data.\n- Ensure context data objects are plain JSON (no Proxies, no getter-based accessor properties).","status":"published","published":"2026-03-29T15:16:37Z","modified":"2026-03-29T15:16:37Z","cvss":[{"version":"3.1","score":3.7,"vector":"CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:U/C:L/I:N/A:N","level":"low"}],"cwes":["CWE-367"],"updated_at":"2026-11-02T14:39:44.97342Z"},{"id":"GHSA-7rx3-28cr-v5wh","title":"Handlebars.js has a Prototype Method Access Control Gap via Missing __lookupSetter__ Blocklist Entry","description":"## Summary\n\nThe 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.\n\n`4.6.0` is the version that introduced `protoAccessControl` and the `allowProtoMethodsByDefault` runtime option.\n\n## Description\n\nIn `lib/handlebars/internal/proto-access.js`:\n\n```javascript\nconst methodWhiteList = Object.create(null);\nmethodWhiteList['constructor']      = false;\nmethodWhiteList['__defineGetter__'] = false;\nmethodWhiteList['__defineSetter__'] = false;\nmethodWhiteList['__lookupGetter__'] = false;\n// __lookupSetter__ intentionally blocked in CVE-2021-23383,\n// but omitted here — creating an asymmetric blocklist\n```\n\nAll 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.\n\nWhen `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.\n\n## Workarounds\n\n- Do **not** set `allowProtoMethodsByDefault: true`. The default configuration is not affected.\n- If `allowProtoMethodsByDefault` must be enabled, ensure templates do not reference  `__lookupSetter__` through untrusted input.","status":"published","published":"2026-03-29T15:17:15Z","modified":"2026-03-29T15:17:16Z","cvss":[{"version":"3.1","score":4.8,"vector":"CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:U/C:L/I:L/A:N","level":"medium"}],"cwes":["CWE-1321"],"updated_at":"2026-11-02T14:39:44.97342Z"},{"id":"GHSA-9cx6-37pm-9jff","title":"Handlebars.js has Denial of Service via Malformed Decorator Syntax in Template Compilation","description":"## Summary\n\nWhen 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.\n\n## Description\n\nIn `lib/handlebars/compiler/javascript-compiler.js`, the code generated for a decorator invocation looks like:\n\n```javascript\nfn = lookupProperty(decorators, \"n\")(fn, props, container, options) || fn;\n```\n\nWhen `\"n\"` is not a registered decorator, `lookupProperty(decorators, \"n\")` returns `undefined`. The expression immediately attempts to call `undefined` as a function, producing:\n\n```\nTypeError: lookupProperty(...) is not a function\n```\n\nBecause 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.\n\nThis inconsistency is notable: references to unregistered **helpers** produce a clean `\"Missing helper: ...\"` error, while references to unregistered **decorators** cause a hard crash.\n\n**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.\n\n## Proof of Concept\n\n```javascript\nconst Handlebars = require('handlebars'); // Handlebars 4.7.8, Node.js v22.x\n\n// Any of these payloads crash the process\nHandlebars.compile('{{*n}}')({});\nHandlebars.compile('{{*decorator}}')({});\nHandlebars.compile('{{*constructor}}')({});\n```\n\nExpected crash output:\n```\nTypeError: lookupProperty(...) is not a function\n    at Function.eval [as decorator] (eval at compile (...javascript-compiler.js:134:36))\n```\n\n## Workarounds\n\n- **Wrap compilation and rendering in `try/catch`:**\n  ```javascript\n  try {\n    const result = Handlebars.compile(userInput)(context);\n    res.send(result);\n  } catch (err) {\n    res.status(400).send('Invalid template');\n  }\n  ```\n- **Validate template input** before passing it to `compile()`. Reject templates containing  decorator syntax (`{{*...}}`) if decorators are not used in your application.\n- **Use the pre-compilation workflow:** compile templates at build time and serve only pre-compiled  templates; do not call `compile()` at request time.","status":"published","published":"2026-03-27T18:21:15Z","modified":"2026-03-30T20:08:14Z","cvss":[{"version":"3.1","score":7.5,"vector":"CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H","level":"high"}],"cwes":["CWE-754"],"updated_at":"2026-11-02T14:39:46.119458Z"}],"nvd":[{"id":"CVE-2026-33939","description":"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.","status":"published","published":"2026-03-27T22:16:20.857Z","modified":"2026-10-26T22:10:00.163Z","cvss":[{"version":"3.1","score":7.5,"vector":"CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H","level":"high","assessor":"secondary"},{"version":"3.1","score":7.5,"vector":"CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H","level":"high","assessor":"secondary"}],"cwes":["CWE-754","CWE-248"],"updated_at":"2026-11-02T14:12:11.678711Z"}],"osv":[{"id":"CVE-2026-33939","title":"Handlebars.js has Denial of Service via Malformed Decorator Syntax in Template Compilation","description":"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.","status":"published","published":"2026-03-27T21:08:24.664Z","modified":"2026-10-28T02:30:51.360321154Z","cvss":[{"version":"3.1","score":7.5,"vector":"CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H","level":"high"}],"cwes":["CWE-754"],"updated_at":"2026-11-02T15:45:01.896044Z"},{"id":"DEBIAN-CVE-2026-33939","description":"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.","status":"published","published":"2026-03-27T22:16:20.857Z","modified":"2026-10-27T10:00:58.186454812Z","cvss":[{"version":"3.1","score":7.5,"vector":"CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H","level":"high"}],"updated_at":"2026-11-02T15:45:54.587575Z"},{"id":"GHSA-442j-39wm-28r2","title":"Handlebars.js has a Property Access Validation Bypass in container.lookup","description":"## Summary\n\nIn `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.\n\nOnly relevant when the **compat** compile option is enabled (`{compat: true}`), which activates `depthedLookup` in `lib/handlebars/compiler/javascript-compiler.js`.\n\n## Description\n\nThe vulnerable code in `lib/handlebars/runtime.js` (lines 137–144):\n\n```javascript\nlookup: function (depths, name) {\n  const len = depths.length;\n  for (let i = 0; i \u003c len; i++) {\n    let result = depths[i] \u0026\u0026 container.lookupProperty(depths[i], name);\n    if (result != null) {\n      return depths[i][name];  // BUG: should be `return result;`\n    }\n  }\n},\n```\n\n`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.\n\n## Workarounds\n\n- Avoid enabling `{ compat: true }` when rendering templates that include untrusted data.\n- Ensure context data objects are plain JSON (no Proxies, no getter-based accessor properties).","status":"published","published":"2026-03-29T15:16:37Z","modified":"2026-09-10T03:50:36.874716263Z","cvss":[{"version":"3.1","score":3.7,"vector":"CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:U/C:L/I:N/A:N","level":"low"}],"cwes":["CWE-367"],"updated_at":"2026-11-02T15:46:36.434231Z"},{"id":"GHSA-7rx3-28cr-v5wh","title":"Handlebars.js has a Prototype Method Access Control Gap via Missing __lookupSetter__ Blocklist Entry","description":"## Summary\n\nThe 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.\n\n`4.6.0` is the version that introduced `protoAccessControl` and the `allowProtoMethodsByDefault` runtime option.\n\n## Description\n\nIn `lib/handlebars/internal/proto-access.js`:\n\n```javascript\nconst methodWhiteList = Object.create(null);\nmethodWhiteList['constructor']      = false;\nmethodWhiteList['__defineGetter__'] = false;\nmethodWhiteList['__defineSetter__'] = false;\nmethodWhiteList['__lookupGetter__'] = false;\n// __lookupSetter__ intentionally blocked in CVE-2021-23383,\n// but omitted here — creating an asymmetric blocklist\n```\n\nAll 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.\n\nWhen `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.\n\n## Workarounds\n\n- Do **not** set `allowProtoMethodsByDefault: true`. The default configuration is not affected.\n- If `allowProtoMethodsByDefault` must be enabled, ensure templates do not reference  `__lookupSetter__` through untrusted input.","status":"published","published":"2026-03-29T15:17:15Z","modified":"2026-09-10T03:50:38.084132596Z","cvss":[{"version":"3.1","score":4.8,"vector":"CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:U/C:L/I:L/A:N","level":"medium"}],"cwes":["CWE-1321"],"updated_at":"2026-11-02T15:46:41.349637Z"},{"id":"GHSA-9cx6-37pm-9jff","title":"Handlebars.js has Denial of Service via Malformed Decorator Syntax in Template Compilation","description":"## Summary\n\nWhen 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.\n\n## Description\n\nIn `lib/handlebars/compiler/javascript-compiler.js`, the code generated for a decorator invocation looks like:\n\n```javascript\nfn = lookupProperty(decorators, \"n\")(fn, props, container, options) || fn;\n```\n\nWhen `\"n\"` is not a registered decorator, `lookupProperty(decorators, \"n\")` returns `undefined`. The expression immediately attempts to call `undefined` as a function, producing:\n\n```\nTypeError: lookupProperty(...) is not a function\n```\n\nBecause 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.\n\nThis inconsistency is notable: references to unregistered **helpers** produce a clean `\"Missing helper: ...\"` error, while references to unregistered **decorators** cause a hard crash.\n\n**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.\n\n## Proof of Concept\n\n```javascript\nconst Handlebars = require('handlebars'); // Handlebars 4.7.8, Node.js v22.x\n\n// Any of these payloads crash the process\nHandlebars.compile('{{*n}}')({});\nHandlebars.compile('{{*decorator}}')({});\nHandlebars.compile('{{*constructor}}')({});\n```\n\nExpected crash output:\n```\nTypeError: lookupProperty(...) is not a function\n    at Function.eval [as decorator] (eval at compile (...javascript-compiler.js:134:36))\n```\n\n## Workarounds\n\n- **Wrap compilation and rendering in `try/catch`:**\n  ```javascript\n  try {\n    const result = Handlebars.compile(userInput)(context);\n    res.send(result);\n  } catch (err) {\n    res.status(400).send('Invalid template');\n  }\n  ```\n- **Validate template input** before passing it to `compile()`. Reject templates containing  decorator syntax (`{{*...}}`) if decorators are not used in your application.\n- **Use the pre-compilation workflow:** compile templates at build time and serve only pre-compiled  templates; do not call `compile()` at request time.","status":"published","published":"2026-03-27T18:21:15Z","modified":"2026-09-10T03:51:00.150731044Z","cvss":[{"version":"3.1","score":7.5,"vector":"CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H","level":"high"}],"cwes":["CWE-754"],"updated_at":"2026-11-02T15:46:43.524801Z"},{"id":"ROOT-APP-NPM-CVE-2026-33939","title":"CVE-2026-33939 in handlebars - Patched by Root","description":"Root has patched CVE-2026-33939 in the handlebars package for Root:npm. Multiple fixed versions available.","status":"published","published":"2026-10-15T16:35:43Z","modified":"2026-10-15T17:15:04.313863122Z","cvss":[{"version":"3.1","score":7.5,"vector":"CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H","level":"high"}],"updated_at":"2026-11-02T15:53:27.649662Z"},{"id":"ROOT-APP-NPM-GHSA-7rx3-28cr-v5wh","title":"GHSA-7rx3-28cr-v5wh in handlebars - Patched by Root","description":"Root has patched GHSA-7rx3-28cr-v5wh in the handlebars package for Root:npm. Multiple fixed versions available.","status":"published","published":"2026-10-15T16:35:43Z","modified":"2026-10-15T17:15:03.265448164Z","cvss":[{"version":"3.1","score":4.8,"vector":"CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:U/C:L/I:L/A:N","level":"medium"}],"updated_at":"2026-11-02T15:53:27.940619Z"},{"id":"UBUNTU-CVE-2026-33939","description":"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.","status":"published","published":"2026-03-27T22:16:00Z","modified":"2026-10-17T12:58:51.082032622Z","cvss":[{"version":"3.1","score":7.5,"vector":"CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H","level":"high"},{"version":"3.1","score":7.5,"vector":"CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H","level":"high"}],"updated_at":"2026-11-02T16:56:16.036833Z"},{"id":"CLSA-2026-1782349135","title":"TuxCare security update for handlebars (8 CVEs)","description":"TuxCare rebuilt handlebars to address 8 CVEs. Fixed in 4.7.7-tuxcare.1.","status":"published","published":"2026-08-04T14:52:39Z","modified":"2026-10-15T09:47:10.129115848Z","updated_at":"2026-11-02T15:43:45.794021Z"},{"id":"CLSA-2026-1782435546","title":"TuxCare security update for handlebars (8 CVEs)","description":"TuxCare rebuilt handlebars to address 8 CVEs. Fixed in 4.7.8-tuxcare.1.","status":"published","published":"2026-08-04T14:52:39Z","modified":"2026-10-15T09:47:10.153121357Z","updated_at":"2026-11-02T15:43:45.794021Z"},{"id":"CLSA-2026-1792139237","title":"TuxCare security update for handlebars (7 CVEs)","description":"TuxCare rebuilt handlebars to address 7 CVEs. Fixed in 4.5.3-tuxcare.3.","status":"published","published":"2026-10-16T08:27:17Z","modified":"2026-10-16T12:15:03.193874365Z","updated_at":"2026-11-02T15:43:50.949147Z"}]}}
