GHSA-xw65-4hp5-5hc7

Suggest an improvement
Source
https://github.com/advisories/GHSA-xw65-4hp5-5hc7
Import Source
https://github.com/github/advisory-database/blob/main/advisories/github-reviewed/2026/10/GHSA-xw65-4hp5-5hc7/GHSA-xw65-4hp5-5hc7.json
JSON Data
https://api.osv.dev/v1/vulns/GHSA-xw65-4hp5-5hc7
Aliases
Published
2026-10-08T17:52:37Z
Modified
2026-10-08T18:00:09Z
Severity
  • 4.7 (Medium) CVSS_V3 - CVSS:3.1/AV:N/AC:H/PR:N/UI:R/S:C/C:L/I:L/A:N CVSS Calculator
Summary
Handlebars: JavaScript Injection via Unsafe Inline Embedding of Precompiled Templates
Details

Summary

Handlebars.precompile() generates JavaScript source that is commonly embedded in browser <script> elements. Before the fix, static template text containing </script> was emitted unchanged. HTML parsers recognize </script> even inside a JavaScript string literal, closing the surrounding script element and allowing following attacker-controlled markup to be parsed and executed.

This affects applications that precompile attacker-controlled templates and embed the generated source directly in an HTML <script> element. It does not affect ordinary server-side rendering or precompiled templates delivered as external JavaScript files.

Details

Static text is serialized by quotedString() in lib/handlebars/compiler/code-gen.js. The generated JavaScript is valid, but JavaScript quoting alone does not make it safe to embed in HTML. In HTML script data, the sequence </script> terminates the element regardless of JavaScript string context.

On affected releases, this template:

safe</script><script>alert("XSS")</script><script>

could produce generated source containing:

return 'safe</script><script>alert("XSS")</script><script>';

When included inline in an HTML document, the first </script> closes the script containing the precompiled template. The next <script> element is then parsed as HTML and executes.

Proof of Concept

const Handlebars = require('handlebars');

const template = 'safe</script><script>alert("XSS")</script><script>';
const output = Handlebars.precompile(template);

console.log(output.includes('</script>'));

Affected versions print true. Embedding output directly in an inline <script> element allows the injected script tag to be parsed by the browser.

Workarounds

  • Do not inline precompiled output from untrusted templates into HTML documents.
  • Serve generated precompiled templates as external JavaScript files where practical.

Credits

Reported by Curly-Haired-Baboon Aka Laplas

Database specific
{
    "cwe_ids": [
        "CWE-116"
    ],
    "github_reviewed": true,
    "github_reviewed_at": "2026-10-08T17:52:37Z",
    "nvd_published_at": "2026-10-06T20:17:26Z",
    "severity": "MODERATE"
}
References

Affected packages

npm / handlebars

Package

Affected ranges

Type
SEMVER
Events
Introduced
4.0.0
Fixed
4.7.10

Database specific

last_known_affected_version_range
"<= 4.7.9"
source
"https://github.com/github/advisory-database/blob/main/advisories/github-reviewed/2026/10/GHSA-xw65-4hp5-5hc7/GHSA-xw65-4hp5-5hc7.json"