Handlebars.js has Prototype Pollution Leading to XSS through Partial Template Injection
Collected exploitation and prediction evidence
Risk source coverageCISA KEV is observed exploitation evidence. FIRST EPSS is a dated prediction of exploitation in the next 30 days. Missing scores are unknown. This collector requests predictions only for explicit CVE aliases in the public NuGet archive; Microsoft release views retain their existing prediction scope.
No collected risk observation for these identifiers. This does not establish absence of exploitation or a zero probability.
cve-program · CVE-2026-33916
PublishedHandlebars 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.
- Source published
- 27 Mar 2026 21:00:48 UTC
- Source modified
- 30 Mar 2026 15:41:36 UTC
- Observed here
- 23 Oct 2026 15:48:27 UTC
- Source terms
- CVE Program Terms of Use
Original source record · Cite this exact observation · Complete original publisher JSON
This view projects the publisher's source fields for reading; the original JSON retains additional fields and CVE enrichment containers. Attribution: cve-program · CVE Program Terms of Use. Source text is retained; field grouping and change labels are provided by ChangeIntel.
CVSS 3.1 · 4.7 CVSS:3.1/AV:N/AC:H/PR:N/UI:R/S:C/C:L/I:L/A:N
euvd · EUVD-2026-16847
PublishedHandlebars 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.
EUVD source date text has no stated timezone and is retained without inventing a UTC instant. Related bulletin membership is not an alias, common cause or applicability claim. A missing vector with a zero score is treated as unrated. Complete vendor/product and underlying source evidence remains in the original JSON.
Original publisher date fields
datePublished: Mar 27, 2026, 9:00:48 PM
dateUpdated: Mar 30, 2026, 3:41:36 PM
3 related source bulletins · separate from aliases
WID-SEC-W-2026-3046: IBM Concert: Mehrere Schwachstellen
CVE-2019-19921 · CVE-2021-23337 · CVE-2024-3651 · CVE-2024-39338 · CVE-2024-45590 · CVE-2025-13465 · CVE-2025-15284 · CVE-2025-15599 · CVE-2025-22874 · CVE-2025-47273 · CVE-2025-47907 · CVE-2025-52881 · CVE-2025-53643 · CVE-2025-55184 · CVE-2025-58056 · CVE-2025-58188 · CVE-2025-58189 · CVE-2025-61723 · CVE-2025-61730 · CVE-2025-64649 · CVE-2025-64756 · CVE-2025-67221 · CVE-2025-68121 · CVE-2025-68146 · CVE-2026-0540 · CVE-2026-2327 · CVE-2026-23490 · CVE-2026-23897 · CVE-2026-2391 · CVE-2026-23949 · CVE-2026-24486 · CVE-2026-25528 · CVE-2026-25547 · CVE-2026-25639 · CVE-2026-25990 · CVE-2026-26007 · CVE-2026-26019 · CVE-2026-26996 · CVE-2026-27142 · CVE-2026-27212 · CVE-2026-27699 · CVE-2026-27903 · CVE-2026-27904 · CVE-2026-28684 · CVE-2026-29063 · CVE-2026-29181 · CVE-2026-2950 · CVE-2026-31808 · CVE-2026-31900 · CVE-2026-32274 · CVE-2026-32288 · CVE-2026-32597 · CVE-2026-32630 · CVE-2026-32887 · CVE-2026-32952 · CVE-2026-33186 · CVE-2026-33532 · CVE-2026-33750 · CVE-2026-33814 · CVE-2026-33816 · CVE-2026-33916 · CVE-2026-34043 · CVE-2026-34073 · CVE-2026-34077 · CVE-2026-3520 · CVE-2026-35469 · CVE-2026-35515 · CVE-2026-3627 · CVE-2026-39823 · CVE-2026-39825 · CVE-2026-39826 · CVE-2026-39892 · CVE-2026-39984 · CVE-2026-40175 · CVE-2026-40179 · CVE-2026-40181 · CVE-2026-40190 · CVE-2026-40347 · CVE-2026-41066 · CVE-2026-41182 · CVE-2026-41238 · CVE-2026-41239 · CVE-2026-41240 · CVE-2026-41305 · CVE-2026-41324 · CVE-2026-41425 · CVE-2026-41481 · CVE-2026-41488 · CVE-2026-41602 · CVE-2026-41636 · CVE-2026-42151 · CVE-2026-42154 · CVE-2026-42198 · CVE-2026-42211 · CVE-2026-42338 · CVE-2026-42342 · CVE-2026-42561 · CVE-2026-42577 · CVE-2026-43870 · CVE-2026-44405 · CVE-2026-44431 · CVE-2026-44432 · CVE-2026-44486 · CVE-2026-44487 · CVE-2026-44488 · CVE-2026-44492 · CVE-2026-44494 · CVE-2026-44496 · CVE-2026-44728 · CVE-2026-4539 · CVE-2026-45409 · CVE-2026-45736 · CVE-2026-46625 · CVE-2026-4800 · CVE-2026-4923 · CVE-2026-4926 · CVE-2026-7246 · CVE-2026-8723
WID-SEC-W-2026-1407: IBM App Connect Enterprise Certified Container: Mehrere Schwachstellen
CVE-2026-26013 · CVE-2026-27142 · CVE-2026-28277 · CVE-2026-28684 · CVE-2026-32288 · CVE-2026-33151 · CVE-2026-33349 · CVE-2026-33532 · CVE-2026-33891 · CVE-2026-33894 · CVE-2026-33895 · CVE-2026-33896 · CVE-2026-33916 · CVE-2026-34601 · CVE-2026-35469 · CVE-2026-39406 · CVE-2026-39407 · CVE-2026-39408 · CVE-2026-39409 · CVE-2026-39410 · CVE-2026-39983 · CVE-2026-40175 · CVE-2026-40347 · CVE-2026-40895 · CVE-2026-41238 · CVE-2026-41239 · CVE-2026-41240 · CVE-2026-4923 · CVE-2026-4926
msrc_CVE-2026-33916: Handlebars.js has Prototype Pollution Leading to XSS through Partial Template Injection
CVE-2026-33916
- Source published
- Mar 27, 2026, 9:00:48 PM (timezone not stated)
- Source modified
- Mar 30, 2026, 3:41:36 PM (timezone not stated)
- Observed here
- 1 Nov 2026 06:04:56 UTC
- Source terms
- ENISA EUVD · source terms and attribution apply
Original source record · Cite this exact observation · Complete original publisher JSON
This view projects the publisher's source fields for reading; the original JSON retains additional fields and CVE enrichment containers. Attribution: euvd · ENISA EUVD · source terms and attribution apply. Source text is retained; field grouping and change labels are provided by ChangeIntel.
EUVD CVSS 3.1 · 4.7 CVSS:3.1/AV:N/AC:H/PR:N/UI:R/S:C/C:L/I:L/A:N
nvd · CVE-2026-33916
PublishedHandlebars 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.
NVD analysis and CPE criteria are source context, not proof that a package or your environment is affected. Complete affected data, logical configurations and SSVC are retained in the original JSON.
Source analysis status: Analyzed
Weakness classifications: CWE-79 · CWE-1321
Original publisher date fields
published: 2026-03-27T21:17:27.237
lastModified: 2026-10-26T22:10:00.163
1 source CPE criteria · context only
- cpe:2.3:a:handlebarsjs:handlebars:*:*:*:*:*:node.js:*:*
The original JSON retains the logical configuration operators, exclusions and version bounds.
- Source published
- 27 Mar 2026 21:17:27 UTC
- Source modified
- 26 Oct 2026 22:10:00 UTC
- Observed here
- 27 Oct 2026 09:03:00 UTC
- Source terms
- NIST NVD usage terms; underlying source attribution retained
Original source record · Cite this exact observation · Complete original publisher JSON
This view projects the publisher's source fields for reading; the original JSON retains additional fields and CVE enrichment containers. Attribution: nvd · NIST NVD usage terms; underlying source attribution retained. Source text is retained; field grouping and change labels are provided by ChangeIntel.
CVSS 3.1 · [email protected] · Secondary · 4.7 CVSS:3.1/AV:N/AC:H/PR:N/UI:R/S:C/C:L/I:L/A:N
CVSS 3.1 · [email protected] · Primary · 4.7 CVSS:3.1/AV:N/AC:H/PR:N/UI:R/S:C/C:L/I:L/A:N
osv · GHSA-2qvq-rjwj-gvw9
Published## Summary `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. ## Description The root cause is in `lib/handlebars/runtime.js` inside `resolvePartial()` and `invokePartial()`: ```javascript // Vulnerable: plain bracket access traverses Object.prototype partial = options.partials[options.name]; ``` `hasOwnProperty` is never checked, so if `Object.prototype` has been seeded with a key whose name matches a partial reference in the template (e.g. `widget`), the lookup succeeds and the polluted string is returned. The runtime emits a prototype-access warning, but the partial is still resolved and its content is inserted into the rendered output unescaped. This contradicts the documented security model and is distinct from CVE-2021-23369 and CVE-2021-23383, which addressed data property access rather than partial template resolution. **Prerequisites for exploitation:** 1. The target application must be vulnerable to prototype pollution (e.g. via `qs`, `minimist`, or any querystring/JSON merge sink). 2. The attacker must know or guess the name of a partial reference used in a template. ## Proof of Concept ```javascript const Handlebars = require('handlebars'); // Step 1: Prototype pollution (via qs, minimist, or another vector) Object.prototype.widget = '<img src=x onerror="alert(document.domain)">'; // Step 2: Normal template that references a partial const template = Handlebars.compile('<div>Welcome! {{> widget}}</div>'); // Step 3: Render — XSS payload injected unescaped const output = template({}); // Output: <div>Welcome! <img src=x onerror="alert(document.domain)"></div> ``` > The runtime prints a prototype access warning claiming "access has been denied," but the partial still resolves and returns the polluted value. ## Workarounds - Apply `Object.freeze(Object.prototype)` early in application startup to prevent prototype pollution. Note: this may break other libraries. - Use the Handlebars runtime-only build (`handlebars/runtime`), which does not compile templates and reduces the attack surface.
- Source published
- 26 Mar 2026 22:20:51 UTC
- Source modified
- 10 Sep 2026 03:50:36 UTC
- Observed here
- 24 Oct 2026 13:17:17 UTC
- Source terms
- GitHub Advisory Database · CC-BY-4.0
Original source record · Cite this exact observation · Complete original publisher JSON
This view projects the publisher's source fields for reading; the original JSON retains additional fields and CVE enrichment containers. Attribution: osv · GitHub Advisory Database · CC-BY-4.0. Source text is retained; field grouping and change labels are provided by ChangeIntel.
CVSS_V3 · CVSS:3.1/AV:N/AC:H/PR:N/UI:R/S:C/C:L/I:L/A:N
Publisher rating · MODERATE