Skip to main content

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 · NVD
View

Vulnerability Assessment

Weakness
CWE
OWASP Top 10:2025
A05:2025 - Injection
ASVS 5.0
V1 - Encoding and Sanitization Output encoding, context-aware escaping
MITRE ATT&CK

2 techniques across 2 tactics: Initial Access, Execution

The technique list with ATT&CK links and the kill-chain view is part of the Basic plan and up.

Impact

The CVSS score of 4.7 (Medium, CVSS:3.1/AV:N/AC:H/PR:N/UI:R/S:C/C:L/I:L/A:N) reflects moderate severity: the attack vector is network-accessible and unauthenticated, but attack complexity is high and user interaction is required. The scope is changed (server-rendered output affects client context), and impact is limited to confidentiality and integrity (no availability impact). However, real-world risk depends heavily on the presence of a separate prototype pollution vulnerability in the target application-this is not a direct remote code execution vector but rather a secondary exploitation technique. The proof-of-concept code exists and is publicly available, confirming reproducibility. No CISA KEV status is indicated in the input data, meaning active exploitation in the wild has not been confirmed at the time of analysis. The combination of high attack complexity (requires both prototype pollution and template knowledge), user interaction requirement (reflected XSS variant), and the need for a precursor vulnerability suggests this is a lower-priority issue than the CVSS score alone implies, though applications using Handlebars in combination with known prototype pollution sinks (qs, minimist, etc.) should be prioritized for patching. Organizations should weigh this against their specific dependency landscape.

Exploit ScenarioDerived

An attacker identifies that a web application uses Handlebars templates with a partial named 'widget' and discovers a prototype pollution vulnerability in the application's use of the qs library for query string parsing. The attacker crafts a malicious URL containing ?widget=<img src=x onerror="alert(document.domain)"> which is parsed by qs, polluting Object.prototype. When the application renders its Handlebars template containing {{> widget}}, the resolvePartial() function retrieves the polluted Object.prototype.widget string instead of the intended partial template, and the unescaped HTML payload is rendered to the victim's browser, executing the JavaScript and stealing session cookies or performing account takeover. This requires user interaction (the victim must click the malicious link) and knowledge or guessing of partial names, but no authentication and only network access.

This Month Plan within 30 days. Why: MEDIUM severity (CVSS 4.0-6.9).
Patch available 0.0% exploitation probability (EPSS)

Get an e-mail when this CVE is exploited, patched or re-scored. Free account.

Alert me

AnalysisAIv1 – Mar 26, 2026

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.

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.

Affected Packages

npm handlebars fix: 4.7.9

Source: OSV (Open Source Vulnerabilities)

Affects your stack

Affects 1 package in npm

Checking this CVE against your own stacks and servers is part of the Basic plan and up.

Technical ContextAI · show details

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.

Know when the next one hits your stack

  • Watch products and get an email when something new is published
  • Check this CVE against your own stack and servers
  • Exploit and PoC references, threat intelligence from 22 sources

No credit card · 7-day full trial

Severity by source

NVD 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

Primary rating from NVD.

CVSS VectorNVD

Attack Vector
Network
Attack Complexity
High
Privileges Required
None
User Interaction
Required
Scope
Changed
Confidentiality
Low
Integrity
Low
Availability
None

Lifecycle Timeline

2
Patch released
Mar 26, 2026 - 22:31 nvd
Patch available
CVE Published
Mar 26, 2026 - 22:20 nvd
MEDIUM 4.7

DescriptionNVD

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.

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.

Executive ViewAI

Why It Matters

CVE-2026-33916 presents moderate security risk, a cross-site scripting vulnerability rated CVSS 4.7. Attackers could inject scripts to steal sessions or perform actions as authenticated users. A patch is available and should be applied during regular vulnerability management.

Business Impact: Low
Compensating Controls

Apply vendor patch. If patching is delayed: implement CSP headers, enable HttpOnly cookies, deploy WAF XSS rules.

Threat Intelligence Overview

EPSS Score
0.0%
Top 92% exploitable
Data Quality
7 sources
Confidence: High
NVD CVE.org EPSS Vulnrichment Vendor GitHub VulDB

How this decision was reached

The engine reads each signal below and applies a fixed list of rules from top to bottom. The first rule that matches sets the recommended action – like a statement, every line is shown.

SignalValue
Severity MEDIUM
CISA KEV No
Public POC No
EPSS 0.0%
Patch available Yes
Active threat No
Deciding rule
MEDIUM severity (CVSS 4.0-6.9)
What every action level means
Emergency Immediate action required. Criteria: CRITICAL + in CISA KEV (actively exploited) without patch, OR CRITICAL + EPSS > 30% without patch, OR CRITICAL + active threat signals without patch.
Act Now Prioritize within 24-48h. Criteria: in KEV with patch available, OR CRITICAL + public POC, OR HIGH + EPSS > 10%, OR CRITICAL + active threat, OR any CRITICAL severity.
This Week Schedule remediation this week. Criteria: HIGH severity (CVSS 7.0-8.9). Patch within normal change window.
This Month Plan within 30 days. Criteria: MEDIUM severity (CVSS 4.0-6.9), lower exploitation probability. Include in regular patch cycle.
Monitor Track and reassess. Criteria: LOW severity (CVSS 0.1-3.9), minimal exploitation risk. No immediate action needed.

SSVC AssessmentENISA

SSVC Decision
Scheduled
Exploitation
Poc
System Exposure· derived
Open
Automatable
No
Human Impact
Low
Technical Impact
Partial

Priority Score

24
Low Medium High Critical
KEV: 0
EPSS: 0
CVSS: +24
PoC: 0
Weaponized: 0
Threat intel: 0
Gov advisory: 0

Attack Technique

Cross-Site Scripting occurs when an application accepts untrusted data and sends it to a web browser without proper validation or encoding.

Affected Products (CPE)NVD

pkg:npm/handlebars

Vendor StatusVendor

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