GHSA-g9r4-xpmj-mj65
NoneCVSS
—
EPSS
—
Published
Sep 4, 2020
CISA due date
—
Cloudanix analysis
A commonly used template library could let malicious input change how an application behaves unless the library is updated.
- Exploitation
- Remote Unauthenticated
- Attacker needs
- None
- Complexity
- Moderate
- Impact
- Data Tampering
- Component
- Library
- Class
- Improper Input Validation
- Remediation
- Upgrade
- Effort
- Medium
- Patch risk
- Low
What it actually does
Handlebars contains a prototype pollution flaw in vulnerable 3.x and 4.x releases before 3.0.8 and 4.5.3. When untrusted template input or attacker-influenced data is processed, an attacker may be able to assign properties such as __proto__, constructor, or prototype and modify Object.prototype or other shared JavaScript prototypes. This can alter application behavior across the Node.js process, potentially causing authorization bypasses, logic manipulation, denial of service, or unsafe interaction with other code paths that trust inherited object properties.
Why it matters to the business
Applications using vulnerable Handlebars versions may behave unpredictably if they compile or render attacker-controlled templates or data. The most likely business impacts are service disruption, incorrect application decisions, and potential compromise of application logic. Because Handlebars is a common npm dependency and may be pulled in transitively by other packages, organizations should check both direct and indirect dependency trees even if developers did not intentionally include it.
How an attack unfolds
An attacker first finds an application feature, API, build pipeline, CMS, email-template system, or server-side rendering workflow that processes attacker-controlled Handlebars templates or template data using a vulnerable package version. The attacker then submits a crafted template or payload that targets prototype-related properties such as __proto__, constructor, or prototype. If the vulnerable code path accepts and processes the payload, the JavaScript prototype chain can be polluted for objects created later in the same runtime. The attacker then leverages the polluted property to change downstream application behavior, for example by making security checks evaluate incorrectly, forcing crashes, or influencing options passed to other libraries. Practical impact depends heavily on how the host application uses Handlebars and whether polluted properties reach sensitive logic.
How to fix it
Upgrade Handlebars to a fixed version: use handlebars 3.0.8 or later for the 3.x line, or handlebars 4.5.3 or later for the 4.x line. Prefer upgrading to the latest supported Handlebars release compatible with the application. Regenerate lockfiles after upgrading and verify transitive dependencies no longer resolve to vulnerable versions. If immediate upgrade is not possible, do not compile or render untrusted templates, strictly validate and sanitize template input and data keys, reject dangerous property names such as __proto__, prototype, and constructor, and isolate template rendering in a restricted process with minimal privileges.
How to confirm the fix worked
Confirm that package manifests and lockfiles resolve handlebars to 3.0.8 or later in the 3.x branch, 4.5.3 or later in the 4.x branch, or a newer maintained release. Use dependency inspection tools such as npm ls handlebars, npm audit, yarn why handlebars, pnpm why handlebars, or software composition analysis tooling to identify direct and transitive copies. Validate deployed artifacts as well as source repositories, because bundled or vendored JavaScript may still contain older vulnerable versions. Regression test any code path that compiles or renders templates with user-controllable input and add negative tests that reject keys such as __proto__, constructor, and prototype.
Typical attack path
- Identify an application or service using a vulnerable Handlebars npm version before 3.0.8 or 4.5.3.
- Locate a feature that accepts user-controlled template content or data rendered through Handlebars.
- Submit a crafted payload containing prototype pollution keys such as __proto__, constructor, or prototype.
- Trigger template compilation or rendering so the vulnerable Handlebars code processes the payload.
- Cause shared JavaScript object prototypes to receive attacker-controlled properties.
- Leverage the polluted property in later application logic to cause denial of service, bypass checks, or manipulate behavior.
How to detect it
Review application, API gateway, WAF, and server logs for requests containing prototype pollution property names submitted to endpoints that create, edit, preview, or render templates, emails, pages, reports, CMS content, or other dynamic content. Search for unusual rendering errors, spikes in template compilation failures, application crashes, or unexpected changes in authorization and configuration behavior shortly after requests containing __proto__, constructor, or prototype. In Node.js environments, inspect process crash logs, uncaught exception logs, and APM traces for Handlebars parsing or rendering stack traces near suspicious request parameters. Also review package deployment history to determine whether vulnerable Handlebars versions were present during the suspected activity window.
- __proto__
- constructor.prototype
- prototype.polluted
- Handlebars.compile
- Handlebars.template
- Error: Parse error on line
- TypeError: Cannot convert undefined or null to object
- TypeError: Cannot read property
- TypeError: Cannot set property
- npm ls handlebars
- node_modules/handlebars/package.json
What your security team should do
- Inventory all applications, services, build tools, and packaged front-end/server-side assets that include the handlebars npm package.
- Prioritize upgrades where Handlebars is used server-side or where users can influence templates, template partials, helpers, or rendering data.
- Upgrade to handlebars 3.0.8, 4.5.3, or preferably the latest compatible maintained version, and regenerate lockfiles.
- Search dependency trees for transitive vulnerable versions and force/resolution-pin patched versions where necessary.
- Add input validation controls that reject prototype pollution keys in template data and configuration objects.
- Review application logic for security decisions that rely on inherited object properties; prefer Object.hasOwn, hasOwnProperty.call, Maps, or null-prototype objects where appropriate.
- Monitor application logs for malformed template payloads and repeated rendering errors that include prototype-pollution-related property names.
The record
Prototype Pollution in handlebars
Affected packages
| Ecosystem | Package | Introduced | Fixed |
|---|---|---|---|
| npm | handlebars | 0 | 3.0.8 |
| npm | handlebars | 4.0.0 | 4.5.3 |
| Chainguard | code-server | 0 | 0 |
| Chainguard | code-server-compat | 0 | 0 |
| Chainguard | gitlab-rails-ce-18.1 | 0 | 0 |
| Chainguard | gitlab-rails-ce-18.2 | 0 | 0 |
| Chainguard | gitlab-rails-ce-18.3 | 0 | 0 |
| Chainguard | gitlab-rails-ce-18.4 | 0 | 0 |
| Chainguard | gitlab-rails-ce-18.5 | 0 | 0 |
| Chainguard | gitlab-rails-ce-18.6 | 0 | 0 |
| Chainguard | gitlab-rails-ce-18.7 | 0 | 0 |
| Chainguard | gitlab-rails-ce-assets-18.1 | 0 | 0 |
| Chainguard | gitlab-rails-ce-assets-18.2 | 0 | 0 |
| Chainguard | gitlab-rails-ce-assets-18.3 | 0 | 0 |
| Chainguard | gitlab-rails-ce-assets-18.4 | 0 | 0 |
| Chainguard | gitlab-rails-ce-assets-18.5 | 0 | 0 |
| Chainguard | gitlab-rails-ce-assets-18.6 | 0 | 0 |
| Chainguard | gitlab-rails-ce-assets-18.7 | 0 | 0 |
| Chainguard | gitlab-rails-ce-assets-18.8 | 0 | 0 |
| Chainguard | gitlab-rails-ce-assets-18.9 | 0 | 0 |
| Chainguard | gitlab-rails-ce-assets-fips-18.1 | 0 | 0 |
| Chainguard | gitlab-rails-ce-assets-fips-18.2 | 0 | 0 |
| Chainguard | gitlab-rails-ce-assets-fips-18.3 | 0 | 0 |
| Chainguard | gitlab-rails-ce-assets-fips-18.4 | 0 | 0 |
| Chainguard | gitlab-rails-ce-assets-fips-18.5 | 0 | 0 |
| Chainguard | gitlab-rails-ce-assets-fips-18.6 | 0 | 0 |
| Chainguard | gitlab-rails-ce-assets-fips-18.7 | 0 | 0 |
| Chainguard | gitlab-rails-ce-assets-fips-18.8 | 0 | 0 |
| Chainguard | gitlab-rails-ce-assets-fips-18.9 | 0 | 0 |
| Chainguard | gitlab-rails-ce-doc-18.1 | 0 | 0 |
| Chainguard | gitlab-rails-ce-doc-18.2 | 0 | 0 |
| Chainguard | gitlab-rails-ce-doc-18.3 | 0 | 0 |
| Chainguard | gitlab-rails-ce-doc-18.4 | 0 | 0 |
| Chainguard | gitlab-rails-ce-doc-18.5 | 0 | 0 |
| Chainguard | gitlab-rails-ce-doc-18.6 | 0 | 0 |
| Chainguard | gitlab-rails-ce-doc-18.7 | 0 | 0 |
| Chainguard | gitlab-rails-ce-doc-fips-18.1 | 0 | 0 |
| Chainguard | gitlab-rails-ce-doc-fips-18.2 | 0 | 0 |
| Chainguard | gitlab-rails-ce-doc-fips-18.3 | 0 | 0 |
| Chainguard | gitlab-rails-ce-doc-fips-18.4 | 0 | 0 |
| Chainguard | gitlab-rails-ce-doc-fips-18.5 | 0 | 0 |
| Chainguard | gitlab-rails-ce-doc-fips-18.6 | 0 | 0 |
| Chainguard | gitlab-rails-ce-doc-fips-18.7 | 0 | 0 |
| Chainguard | gitlab-rails-ce-fips-18.1 | 0 | 0 |
| Chainguard | gitlab-rails-ce-fips-18.2 | 0 | 0 |
| Chainguard | gitlab-rails-ce-fips-18.3 | 0 | 0 |
| Chainguard | gitlab-rails-ce-fips-18.4 | 0 | 0 |
| Chainguard | gitlab-rails-ce-fips-18.5 | 0 | 0 |
| Chainguard | gitlab-rails-ce-fips-18.6 | 0 | 0 |
| Chainguard | gitlab-rails-ce-fips-18.7 | 0 | 0 |
| Chainguard | gitlab-rails-ee-17.0 | 0 | 0 |
| Chainguard | gitlab-rails-ee-17.1 | 0 | 0 |
| Chainguard | gitlab-rails-ee-17.10 | 0 | 0 |
| Chainguard | gitlab-rails-ee-17.11 | 0 | 0 |
| Chainguard | gitlab-rails-ee-17.2 | 0 | 0 |
| Chainguard | gitlab-rails-ee-17.3 | 0 | 0 |
| Chainguard | gitlab-rails-ee-17.4 | 0 | 0 |
| Chainguard | gitlab-rails-ee-17.6 | 0 | 0 |
| Chainguard | gitlab-rails-ee-17.7 | 0 | 0 |
| Chainguard | gitlab-rails-ee-17.8 | 0 | 0 |
| Chainguard | gitlab-rails-ee-17.9 | 0 | 0 |
| Chainguard | gitlab-rails-ee-assets-17.10 | 0 | 0 |
| Chainguard | gitlab-rails-ee-assets-17.11 | 0 | 0 |
| Chainguard | gitlab-rails-ee-assets-17.2 | 0 | 0 |
| Chainguard | gitlab-rails-ee-assets-17.3 | 0 | 0 |
| Chainguard | gitlab-rails-ee-assets-17.4 | 0 | 0 |
| Chainguard | gitlab-rails-ee-assets-17.6 | 0 | 0 |
| Chainguard | gitlab-rails-ee-assets-17.7 | 0 | 0 |
| Chainguard | gitlab-rails-ee-assets-17.8 | 0 | 0 |
| Chainguard | gitlab-rails-ee-assets-17.9 | 0 | 0 |
| Chainguard | gitlab-rails-ee-assets-fips-17.10 | 0 | 0 |
| Chainguard | gitlab-rails-ee-assets-fips-17.11 | 0 | 0 |
| Chainguard | gitlab-rails-ee-assets-fips-17.2 | 0 | 0 |
| Chainguard | gitlab-rails-ee-assets-fips-17.3 | 0 | 0 |
| Chainguard | gitlab-rails-ee-assets-fips-17.4 | 0 | 0 |
| Chainguard | gitlab-rails-ee-assets-fips-17.6 | 0 | 0 |
| Chainguard | gitlab-rails-ee-assets-fips-17.7 | 0 | 0 |
| Chainguard | gitlab-rails-ee-assets-fips-17.8 | 0 | 0 |
| Chainguard | gitlab-rails-ee-assets-fips-17.9 | 0 | 0 |
| Chainguard | gitlab-rails-ee-doc-17.10 | 0 | 0 |
| Chainguard | gitlab-rails-ee-doc-17.11 | 0 | 0 |
| Chainguard | gitlab-rails-ee-doc-17.2 | 0 | 0 |
| Chainguard | gitlab-rails-ee-doc-17.3 | 0 | 0 |
| Chainguard | gitlab-rails-ee-doc-17.4 | 0 | 0 |
| Chainguard | gitlab-rails-ee-doc-17.6 | 0 | 0 |
| Chainguard | gitlab-rails-ee-doc-17.7 | 0 | 0 |
| Chainguard | gitlab-rails-ee-doc-17.8 | 0 | 0 |
| Chainguard | gitlab-rails-ee-doc-17.9 | 0 | 0 |
| Chainguard | gitlab-rails-ee-doc-fips-17.10 | 0 | 0 |
| Chainguard | gitlab-rails-ee-doc-fips-17.11 | 0 | 0 |
| Chainguard | gitlab-rails-ee-doc-fips-17.2 | 0 | 0 |
| Chainguard | gitlab-rails-ee-doc-fips-17.3 | 0 | 0 |
| Chainguard | gitlab-rails-ee-doc-fips-17.4 | 0 | 0 |
| Chainguard | gitlab-rails-ee-doc-fips-17.6 | 0 | 0 |
| Chainguard | gitlab-rails-ee-doc-fips-17.7 | 0 | 0 |
| Chainguard | gitlab-rails-ee-doc-fips-17.8 | 0 | 0 |
| Chainguard | gitlab-rails-ee-doc-fips-17.9 | 0 | 0 |
| Chainguard | gitlab-rails-ee-fips-17.0 | 0 | 0 |
| Chainguard | gitlab-rails-ee-fips-17.1 | 0 | 0 |
| Chainguard | gitlab-rails-ee-fips-17.10 | 0 | 0 |
| Chainguard | gitlab-rails-ee-fips-17.11 | 0 | 0 |
| Chainguard | gitlab-rails-ee-fips-17.2 | 0 | 0 |
| Chainguard | gitlab-rails-ee-fips-17.3 | 0 | 0 |
| Chainguard | gitlab-rails-ee-fips-17.4 | 0 | 0 |
| Chainguard | gitlab-rails-ee-fips-17.6 | 0 | 0 |
| Chainguard | gitlab-rails-ee-fips-17.7 | 0 | 0 |
| Chainguard | gitlab-rails-ee-fips-17.8 | 0 | 0 |
| Chainguard | gitlab-rails-ee-fips-17.9 | 0 | 0 |
| Wolfi | code-server | 0 | 0 |
| Wolfi | code-server-compat | 0 | 0 |
Related vulnerabilities
- GHSA-7rx3-28cr-v5wh Handlebars.js has a Prototype Method Access Control Gap via Missing __lookupSetter__… Also affects handlebars
- GHSA-442j-39wm-28r2 Handlebars.js has a Property Access Validation Bypass in container.lookup Also affects handlebars
- CVE-2026-33940 Handlebars provides the power necessary to let users build semantic templates. Also affects handlebars
- CVE-2026-33941 Handlebars provides the power necessary to let users build semantic templates. Also affects handlebars
- CVE-2026-33939 Handlebars provides the power necessary to let users build semantic templates. Also affects handlebars
- CVE-2026-33937 Handlebars provides the power necessary to let users build semantic templates. Also affects handlebars
- CVE-2026-33938 Handlebars provides the power necessary to let users build semantic templates. Also affects handlebars
- CVE-2026-33916 Handlebars provides the power necessary to let users build semantic templates. Also affects handlebars