CVE-2026-115897: CVE-2026-115897: Cross-Site Scripting via Function Body Boundary Bypass in serialize-javascript
CVE-2026-115897: Cross-Site Scripting via Function Body Boundary Bypass in serialize-javascript
> Vulnerability ID: CVE-2026-115897
> CVSS Score: 2.1
> Published: 2026-10-23
CVE-2026-115897 (also tracked as GHSA-m5mm-p8h7-m29v and aliased as CVE-2026-115754) is a Cross-Site Scripting (XSS) vulnerability in the Yahoo serialize-javascript npm package prior to version 7.1.3. The flaw exists in the regular expression used by escapeFunctionBody() to neutralize HTML script closing tags within serialized JavaScript functions. Because function bodies are sanitized in isolation before structural formatting is applied, a function whose string representation terminates directly with the sequence '</script' bypasses the positive lookahead check. When combined with serialization formatting options that introduce whitespace delimiters and a subsequent property that supplies a closing bracket, an attacker can prematurely terminate an enclosing HTML <script> block and inject arbitrary HTML or JavaScript into the rendered document.
TL;DR
Versions of the serialize-javascript npm package prior to 7.1.3 fail to neutralize the bare string '</script' when it appears at the exact end of a serialized function body. If an application serializes attacker-influenced function representations with formatting options enabled, the surrounding serialization structure can supply the necessary HTML tag delimiter and closing angle bracket, resulting in Cross-Site Scripting (XSS) when the output is embedded in an HTML <script> element.
---
⚠️ Exploit Status: POC
Technical Details
- Vulnerability Type: Cross-Site Scripting (CWE-79)
- Affected Component: serialize-javascript (< 7.1.3) escapeFunctionBody()
- CVSS v4.0 Score: 2.1 Low (CVSS:4.0/AV:N/AC:H/AT:P/PR:L/UI:P/VC:L/VI:L/VA:N/SC:L/SI:L/SA:N)
- Attack Vector: Network (HTML <script> breakout via serialized function boundary)
- Exploit Status: Proof-of-Concept (Unit test fixtures available)
- CISA KEV Status: Not Listed
- Patched Version: 7.1.3
Affected Systems
- serialize-javascript (npm package)
- serialize-javascript: < 7.1.3 (Fixed in: 7.1.3)
Code Analysis
Commit: 2864b3c
fix: escape '</script' at the end of a serialized function body (#235)
diff --git a/index.js b/index.js
--- a/index.js
+++ b/index.js
@@ -26,7 +26,11 @@ var UNSAFE_CHARS_REGEXP = /[<>\/\u2028\u2029]/g;
// stays in script data, so only these need neutralizing. The bare-prefix form
// matters because the matching `>` could be supplied by a different
// serialized value later in the output, so escaping stops there without
-// waiting for a closing `>`. A trailing backslash is not a delimiter here
+// waiting for a closing `>`. For the same reason the bare form also matches
+// at the very end of the string: each function body is escaped on its own, so
+// a body ending in `</script` can't see the delimiter (e.g. the newline added
+// by the `space` option) that the surrounding output supplies next
+// (PSECBUGS-118415). A trailing backslash is not a delimiter here
// (that's a JS-level concern, not an HTML one), so this doesn't affect tagged
// template literals like `String.raw`.
//
@@ -38,7 +42,7 @@ var UNSAFE_CHARS_REGEXP = /[<>\/\u2028\u2029]/g;
// longer contain a second `<`, every `</script` in the source is either the
// start of its own match or is followed by a non-delimiter — and the latter
// the tokenizer never treats as an end tag.
-var SCRIPT_CLOSE_REGEXP = /<\/script[^<>]*>|<\/script(?=[\t\n\f\r \/>])/gi;
+var SCRIPT_CLOSE_REGEXP = /<\/script[^<>]*>|<\/script(?=$|[\t\n\f\r \/>])/gi;
var RESERVED_SYMBOLS = ['*', 'async'];
Mitigation Strategies
- Upgrade serialize-javascript to version 7.1.3 or later across all direct and transitive dependencies.
- Disable function serialization by passing { ignoreFunction: true } to serialize() when function persistence is not required.
- Avoid using the 'space' formatting option when serializing objects destined for inline HTML <script> tags.
- Never construct JavaScript Function objects or allow custom .toString() overrides from untrusted user input.
- Deploy a strict Content Security Policy (CSP) that disallows unsafe inline event handlers and requires nonces or hashes for script execution.
Remediation Steps:
1. Run 'npm ls serialize-javascript' (or equivalent yarn/pnpm command) to identify all installed versions of serialize-javascript in the dependency tree.
2. Update direct dependencies to 'serialize-javascript@^7.1.3' in package.json.
3. If serialize-javascript is pulled in transitively, use the 'overrides' field in package.json (npm), 'resolutions' (Yarn), or 'pnpm.overrides' (pnpm) to force version '>=7.1.3'.
4. Verify the resolved version in package-lock.json, yarn.lock, or pnpm-lock.yaml and redeploy the application.
References
- GitHub Security Advisory GHSA-m5mm-p8h7-m29v
- Pull Request #235: fix: escape '</script' at the end of a serialized function body
- Patch Commit 2864b3c6260a3bfd52d2db3e70d1a079de108a61
- serialize-javascript v7.1.3 Release Notes
- NVD - CVE-2026-115897
- CVE.org Record - CVE-2026-115897
- CVE List V5 JSON Record - CVE-2026-115897
---
Read the full report for CVE-2026-115897 on our website for more details including interactive diagrams and full exploit analysis.
Mentions
CVE-2026-115897: CVE-2026-115897: Cross-Site Scripting via Function Body Boundary Bypass in serialize-javascript CVE-2026-115897: Cross-Site Scripting via Function Body Boundary Bypass in serialize-javascript > Vulnerability ID: CVE-2026-115897 > CVSS Score: 2.1 > Published: 2026-10-23 CVE-2026-115897 (also tracked as GHSA-m5mm-p8h7-m29v and aliased as CVE-2026-115754) is a Cross-Site Scripting (XSS) vulnerability in the Yahoo serialize-javascript npm package prior to version 7.1.3. The flaw exists in the regular expression used by escapeFunctionBody() to neutralize HTML script closing tags within serialized JavaScript functions. Because function bodies are sanitized in isolation before structural formatting is applied, a function whose string representation terminates directly with the sequence '</script' bypasses the positive lookahead check. When combined with serialization formatting options that introduce whitespace delimiters and a subsequent property that supplies a closing bracket, an attacker can prematurely terminate an enclosing HTML <script> block and inject arbitrary HTML or JavaScript into the rendered document. TL;DR Versions of the serialize-javascript npm package prior to 7.1.3 fail to neutralize the bare string '</script' when it appears at the exact end of a serialized function body. If an application serializes attacker-influenced function representations with formatting options enabled, the surrounding serialization structure can supply the necessary HTML tag delimiter and closing angle bracket, resulting in Cross-Site Scripting (XSS) when the output is embedded in an HTML <script> element. --- ⚠️ Exploit Status: POC Technical Details - Vulnerability Type: Cross-Site Scripting (CWE-79) - Affected Component: serialize-javascript (< 7.1.3) escapeFunctionBody() - CVSS v4.0 Score: 2.1 Low (CVSS:4.0/AV:N/AC:H/AT:P/PR:L/UI:P/VC:L/VI:L/VA:N/SC:L/SI:L/SA:N) - Attack Vector: Network (HTML <script> breakout via serialized function boundary) - Exploit Status: Proof-of-Concept (Unit test fixtures available) - CISA KEV Status: Not Listed - Patched Version: 7.1.3 Affected Systems - serialize-javascript (npm package) - serialize-javascript: < 7.1.3 (Fixed in: 7.1.3) Code Analysis Commit: 2864b3c fix: escape '</script' at the end of a serialized function body (#235) diff --git a/index.js b/index.js --- a/index.js +++ b/index.js @@ -26,7 +26,11 @@ var UNSAFE_CHARS_REGEXP = /[<>\/\u2028\u2029]/g; // stays in script data, so only these need neutralizing. The bare-prefix form // matters because the matching `>` could be supplied by a different // serialized value later in the output, so escaping stops there without -// waiting for a closing `>`. A trailing backslash is not a delimiter here +// waiting for a closing `>`. For the same reason the bare form also matches +// at the very end of the string: each function body is escaped on its own, so +// a body ending in `</script` can't see the delimiter (e.g. the newline added +// by the `space` option) that the surrounding output supplies next +// (PSECBUGS-118415). A trailing backslash is not a delimiter here // (that's a JS-level concern, not an HTML one), so this doesn't affect tagged // template literals like `String.raw`. // @@ -38,7 +42,7 @@ var UNSAFE_CHARS_REGEXP = /[<>\/\u2028\u2029]/g; // longer contain a second `<`, every `</script` in the source is either the // start of its own match or is followed by a non-delimiter — and the latter // the tokenizer never treats as an end tag. -var SCRIPT_CLOSE_REGEXP = /<\/script[^<>]*>|<\/script(?=[\t\n\f\r \/>])/gi; +var SCRIPT_CLOSE_REGEXP = /<\/script[^<>]*>|<\/script(?=$|[\t\n\f\r \/>])/gi; var RESERVED_SYMBOLS = ['*', 'async']; Mitigation Strategies - Upgrade serialize-javascript to version 7.1.3 or later across all direct and transitive dependencies. - Disable function serialization by passing { ignoreFunction: true } to serialize() when function persistence is not required. - Avoid using the 'space' formatting option when serializing objects destined for inline HTML <script> tags. - Never construct JavaScript Function objects or allow custom .toString() overrides from untrusted user input. - Deploy a strict Content Security Policy (CSP) that disallows unsafe inline event handlers and requires nonces or hashes for script execution. Remediation Steps: 1. Run 'npm ls serialize-javascript' (or equivalent yarn/pnpm command) to identify all installed versions of serialize-javascript in the dependency tree. 2. Update direct dependencies to 'serialize-javascript@^7.1.3' in package.json. 3. If serialize-javascript is pulled in transitively, use the 'overrides' field in package.json (npm), 'resolutions' (Yarn), or 'pnpm.overrides' (pnpm) to force version '>=7.1.3'. 4. Verify the resolved version in package-lock.json, yarn.lock, or pnpm-lock.yaml and redeploy the application. References - GitHub Security Advisory GHSA-m5mm-p8h7-m29v - Pull Request #235: fix: escape '</script' at the end of a serialized function body - Patch Commit 2864b3c6260a3bfd52d2db3e70d1a079de108a61 - serialize-javascript v7.1.3 Release Notes - NVD - CVE-2026-115897 - CVE.org Record - CVE-2026-115897 - CVE List V5 JSON Record - CVE-2026-115897 --- Read the full report for CVE-2026-115897 on our website for more details including interactive diagrams and full exploit analysis.