CVE-2015-8861
Medium · 6.1CVSS
6.1
EPSS
2.6%
Published
Jan 23, 2017
CISA due date
—
Cloudanix analysis
A vulnerable template library can let attackers make a trusted web page run their code in a user’s browser if the page displays unsafe input.
- Exploitation
- Requires User Interaction
- Attacker needs
- None
- Complexity
- Low
- Impact
- Data Tampering
- Component
- Library
- Class
- XSS
- Remediation
- Upgrade
- Effort
- Medium
- Patch risk
- Medium
What it actually does
Handlebars versions before 4.0.0 can incorrectly escape data when a template places attacker-controlled content into an unquoted HTML attribute. Because the attribute boundary is not protected by quotes, crafted input can break out of the intended value and introduce additional HTML attributes or script-capable event handlers. The result is reflected or stored cross-site scripting when vulnerable templates render untrusted data into a browser. Exploitation requires a victim to view the affected rendered page, but it can allow execution of attacker-controlled JavaScript in the victim’s browser within the security context of the affected application.
Why it matters to the business
Successful exploitation can lead to session theft, account impersonation, unauthorized actions performed as users, phishing inside a trusted application, or exposure of sensitive information visible in the browser. The issue is old and not listed in CISA KEV, and the provided EPSS score indicates relatively low observed exploitation likelihood, but any internet-facing application or documentation/UI component that renders untrusted content with vulnerable Handlebars templates remains at risk. Organizations using the affected Chainguard or Wolfi docker-cli, docker-cli-compat, or docker-cli-doc packages should update to the fixed 24.0.6-r2 builds to remove the vulnerable dependency chain.
How an attack unfolds
An attacker first identifies a page or component that renders user-controlled data through a Handlebars template into an HTML attribute without surrounding quotation marks, such as an href, title, class, data-* attribute, or similar field. The attacker submits input containing whitespace and an additional attribute, often an event handler such as onmouseover or onerror, or a JavaScript URL where the browser will interpret it as executable behavior. When the application renders the template using a vulnerable Handlebars version, the generated HTML treats the attacker’s input as markup rather than inert text. A victim then visits the page or opens the affected UI, causing the injected JavaScript to execute in the victim’s browser. From there, the attacker may steal tokens or page data, issue authenticated requests, redirect the user to credential-harvesting content, or perform actions using the victim’s session.
How to fix it
Upgrade all affected packages and dependencies so that Handlebars is version 4.0.0 or later. For the listed Chainguard and Wolfi packages, update to the fixed builds: docker-cli 24.0.6-r2, docker-cli-compat 24.0.6-r2, and docker-cli-doc 24.0.6-r2. Rebuild and redeploy any container images, application bundles, or documentation artifacts that include the vulnerable package. As defense in depth, review templates and quote all HTML attribute values, avoid inserting untrusted data into executable contexts, use context-aware escaping, sanitize rich HTML input with a maintained sanitizer, and deploy a restrictive Content Security Policy that limits inline script execution.
How to confirm the fix worked
Confirm dependency versions using package manifests, lockfiles, software composition analysis, and container image scans. Validate that no deployed artifact contains Handlebars versions earlier than 4.0.0 and that the affected Chainguard or Wolfi packages are at 24.0.6-r2 or later. Review compiled or source templates for unquoted attributes containing Handlebars expressions, such as attr={{value}}, and correct them to quoted form, such as attr="{{value}}". In a non-production test environment, attempt to render benign XSS test strings in suspected fields and verify they are escaped as text rather than interpreted as HTML or JavaScript. Also confirm that browser-side protections such as CSP are present and do not allow unrestricted inline scripts.
Typical attack path
- Find an application or generated UI that uses Handlebars before 4.0.0.
- Identify a template that places untrusted data inside an unquoted HTML attribute.
- Submit crafted input that closes or escapes the intended attribute value and injects a new attribute or script-capable payload.
- Cause the victim to view the rendered page, for example by sending a link, creating stored content, or waiting for normal application use.
- Execute JavaScript in the victim’s browser under the affected application’s origin.
- Use the victim’s session or browser context to read accessible data, perform unauthorized actions, or redirect the user to attacker-controlled content.
How to detect it
To determine whether this was already exploited, review HTTP access logs, WAF logs, application request logs, and audit trails for suspicious input submitted to parameters that are later rendered in Handlebars templates. Focus on payloads containing HTML event handlers, JavaScript URLs, encoded angle brackets, attribute-breaking whitespace, or attempts to inject new attributes into values. For stored-XSS scenarios, inspect user-generated content records, comments, profile fields, labels, names, descriptions, documentation metadata, or other rendered fields for script-like content. Review browser telemetry, CSP violation reports, and endpoint logs for unexpected outbound connections initiated from affected pages shortly after users viewed attacker-controlled content. Look for follow-on signs such as unusual authenticated actions, session reuse from unfamiliar IP addresses, unexpected account setting changes, or requests to sensitive endpoints immediately after a suspicious page view. There are no unique malware indicators for this vulnerability; detection is primarily based on exploit-pattern searches and correlation with user activity.
- onerror=
- onload=
- onmouseover=
- onclick=
- onfocus=
- javascript:
- data:text/html
- <script
- </script>
- <script
- %3Cscript
- %22%20onerror%3D
- %22%20onload%3D
- %27%20onerror%3D
- %27%20onload%3D
- alert(1)
- prompt(1)
- confirm(1)
- document.cookie
- localStorage
- sessionStorage
- new Image().src
- fetch(
- XMLHttpRequest
- Handlebars.VERSION = "3.
- handlebars@3.
- "handlebars": "3.
- "handlebars":"3.
What your security team should do
- Prioritize upgrading affected docker-cli, docker-cli-compat, and docker-cli-doc packages to 24.0.6-r2 or later in all base images and build pipelines.
- Run SCA and container image scans to identify any remaining Handlebars versions earlier than 4.0.0, including transitive dependencies.
- Search application templates for unquoted Handlebars expressions in HTML attributes and correct them even after upgrading.
- Invalidate or rebuild cached static documentation, generated UIs, and container layers that may still contain vulnerable dependencies.
- Review web access logs, application logs, and WAF events for XSS payloads submitted to fields rendered by Handlebars-backed pages.
- Apply or tighten Content Security Policy to reduce impact if another template injection or XSS flaw exists.
- Because this is not currently in KEV and has low EPSS, handle it as routine-priority patching unless the vulnerable component is internet-facing or processes untrusted user-generated content, in which case accelerate remediation.
The record
The handlebars package before 4.0.0 for Node.js allows remote attackers to conduct cross-site scripting (XSS) attacks by leveraging a template with an attribute that is not quoted.
Affected packages
| Ecosystem | Package | Introduced | Fixed |
|---|---|---|---|
| npm | handlebars | 0 | 4.0.0 |
| 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 |
| Debian:10 | mustache.js | 0 | No fix |
| Debian:11 | mustache.js | 0 | No fix |
| Debian:12 | mustache.js | 0 | No fix |
| Debian:13 | mustache.js | 0 | No fix |
| Ubuntu:18.04:LTS | node-handlebars | 0 | 3:4.0.10-5 |
| 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