Skip to main content

Red Hat CVE-2026-33916

MEDIUM
Cross-site Scripting (XSS) (CWE-79)
2026-03-26 https://github.com/handlebars-lang/handlebars.js
4.7
CVSS 3.1 · GitHub Advisory
Share

Severity by source

GitHub Advisory PRIMARY
4.7 MEDIUM
AV:N/AC:H/PR:N/UI:R/S:C/C:L/I:L/A:N
Red Hat
4.7 MEDIUM
qualitative

Primary rating from GitHub Advisory.

CVSS VectorGitHub Advisory

CVSS:3.1/AV:N/AC:H/PR:N/UI:R/S:C/C:L/I:L/A:N
Attack Vector
Network
Attack Complexity
High
Privileges Required
None
User Interaction
Required
Scope
Changed
Confidentiality
Low
Integrity
Low
Availability
None

Lifecycle Timeline

3
Analysis Generated
Mar 26, 2026 - 22:31 vuln.today
Patch released
Mar 26, 2026 - 22:31 nvd
Patch available
CVE Published
Mar 26, 2026 - 22:20 nvd
MEDIUM 4.7

Blast Radius

ecosystem impact
† from your stack dependencies † transitive graph · vuln.today resolves 4-path depth
  • 3 npm packages depend on handlebars (1 direct, 2 indirect)

Ecosystem-wide dependent count for version 4.0.0.

DescriptionGitHub Advisory

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).

  1. 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.

AnalysisAI

Handlebars template engine fails to guard prototype-chain access when resolving partial templates, allowing unauthenticated remote attackers to inject unescaped HTML and JavaScript through prototype pollution. When Object.prototype is polluted with a string value matching a partial name referenced in a template, the malicious string is rendered without HTML escaping, resulting in reflected or stored XSS. Exploitation requires a separate prototype pollution vulnerability in the target application (such as via qs or minimist libraries) combined with knowledge of partial names used in templates; publicly available proof-of-concept code demonstrates the attack. The vulnerability affects npm package handlebars (pkg:npm/handlebars) across multiple versions and is distinct from earlier prototype-access issues CVE-2021-23369 and CVE-2021-23383.

Technical ContextAI

Handlebars is a popular JavaScript templating engine (npm package: pkg:npm/handlebars) that supports partial template inclusion via the {{> partial_name}} syntax. The vulnerability resides in the resolvePartial() and invokePartial() functions in lib/handlebars/runtime.js, which perform property lookup on options.partials using plain bracket notation without checking hasOwnProperty(). This allows traversal of the JavaScript prototype chain-specifically Object.prototype-to resolve partial names. The root cause is classified under CWE-79 (Cross-site Scripting) and represents a case of unsafe prototype chain traversal combined with missing output encoding. When a polluted Object.prototype property matches a partial reference in a template, the string value is retrieved and inserted into the rendered output without HTML entity encoding, bypassing the security model that should isolate data from template logic.

RemediationAI

Upgrade handlebars to version 4.7.9 or later immediately (see vendor advisory at https://github.com/handlebars-lang/handlebars.js/security/advisories/GHSA-2qvq-rjwj-gvw9 and release notes at https://github.com/handlebars-lang/handlebars.js/releases/tag/v4.7.9). This release includes the fix commit 68d8df5a88e0a26fe9e6084c5c6aaebe67b07da2 that guards partial resolution against prototype-chain traversal. Until patching is possible, apply Object.freeze(Object.prototype) early in application startup to prevent prototype pollution, though this is a temporary mitigation and may cause compatibility issues with other libraries. Additionally, audit all dependencies for prototype pollution vulnerabilities (particularly qs, minimist, and other querystring/JSON parsing libraries) and upgrade or replace those packages. For defense-in-depth, use Content Security Policy (CSP) headers to restrict script execution and validate all data sources before template rendering. Consider using the Handlebars runtime-only build (handlebars/runtime) if your application does not require dynamic template compilation, reducing attack surface.

Vendor StatusVendor

Share

CVE-2026-33916 vulnerability details – vuln.today

This site uses cookies essential for authentication and security. No tracking or analytics cookies are used. Privacy Policy