CVEReports
CVEReports

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

Product

  • Home
  • Sitemap
  • RSS Feed

Company

  • About
  • Contact
  • Privacy Policy
  • Terms of Service

© 2026 CVEReports. All rights reserved.

Made with love by Amit Schendel & Alon Barad



CVE-2026-116582

CVE-2026-116582: Cross-Site Scripting via Unescaped RegExp Serialization in Seroval

Amit Schendel
Amit Schendel
Senior Security Researcher

Oct 29, 2026·11 min read·2 visits

Executive Summary (TL;DR)

Seroval versions prior to 1.0.0 and from 1.5.5 to 1.6.9 fail to escape '<' characters when serializing RegExp objects into JavaScript literals. Embedding serialized untrusted RegExp objects into HTML <script> blocks enables cross-site scripting (XSS). Upgrade to Seroval 1.6.10 to remediate the flaw.

CVE-2026-116582 is an improper output escaping vulnerability in the Seroval JavaScript serialization library that leads to cross-site scripting (XSS). When Seroval serializes RegExp objects into executable JavaScript literals for embedding in HTML script elements, it fails to neutralize the less-than character ('<'). If an application constructs a regular expression from untrusted input and embeds the serialized output inside an inline script block during server-side rendering (SSR), an attacker can inject a closing script tag to break out of the JavaScript context and execute arbitrary client-side code.

Vulnerability Overview

seroval is a JavaScript serialization library designed for full-stack TypeScript and JavaScript web frameworks, such as SolidStart. Unlike standard JSON.stringify, seroval serializes complex JavaScript data structures—including Map, Set, BigInt, Promise, and RegExp—directly into executable JavaScript strings or structured JSON AST representations. In server-side rendering (SSR) pipelines, frameworks invoke seroval on the backend to serialize application state and embed the resulting JavaScript expression directly inside an inline <script> tag within the HTML response for client-side state hydration.

CVE-2026-116582 (also tracked as GHSA-9wx9-5pv9-3349) is a cross-site scripting (CWE-79) and improper output escaping (CWE-116) vulnerability within seroval's code generation engine for RegExp instances. When generating executable JavaScript source code via APIs such as serialize, serializeAsync, crossSerialize, crossSerializeAsync, crossSerializeStream, Serializer, or compileJSON, the library emits regular expressions using native JavaScript literal syntax (/pattern/flags). During this serialization step, the internal string representation of the regular expression pattern is unescaped before being concatenated between forward slashes.

Because HTML parsers evaluate <script> tags at the markup level before handing the inner text to the JavaScript engine, any literal </script> or <!-- sequence inside an inline script block immediately alters or terminates the HTML script element. While seroval properly escapes the less-than character (<) as \x3C when serializing standard string primitives, its RegExp serializer restores the raw < character into the generated literal. This discrepancy exposes applications to script context breakout.

If an application constructs a RegExp object using untrusted user input and includes that object in the SSR hydration state, an attacker can supply a pattern containing </script><script>.... When the browser renders the server-generated HTML document, the HTML parser prematurely closes the hydration <script> block upon encountering the injected </script> sequence and executes the subsequent attacker-controlled markup in the context of the victim's browser session.

Root Cause Analysis

The root cause of CVE-2026-116582 lies in the conflicting syntactic requirements between HTML <script> element parsing and ECMAScript regular expression literal grammar. According to the HTML5 specification, the raw text inside a <script> element is parsed in the script data state. In this state, the parser does not understand JavaScript string literals, comments, or regular expression boundaries; it scans strictly for the character sequence </script (case-insensitive) followed by whitespace, /, or >, as well as HTML comment openers (<!--).

To prevent script breakout when serializing standard strings, seroval converts unsafe characters into hexadecimal escape sequences during the initial AST node creation phase. Specifically, the character < (ASCII 0x3C) is stored inside the AST node's content property (node.c) as the four-character escape sequence \x3C. When serializing a regular string node into JavaScript code, seroval preserves \x3C in the output string literal because JavaScript string syntax natively resolves \x3C back to < at runtime.

However, seroval's serializeRegExp function in packages/seroval/src/core/context/serializer.ts did not preserve this escaping. Instead, it passed node.c through an internal helper function, deserializeString(node.c), which converts escape sequences like \x3C back into raw < characters before wrapping the pattern in forward slashes:

Simply leaving \x3C inside a regular expression literal (/\x3C/) is not a viable universal solution in ECMAScript. Modern JavaScript regular expressions use the < character as a structural delimiter rather than a literal character in several constructs, including named capture groups ((?<name>...)), named backreferences (\k<name>), lookbehind assertions ((?<=...) and (?<!...)), and character class set operations under the Unicode /v flag. Replacing < with \x3C inside a literal breaks these syntactic constructs, resulting in a SyntaxError when the browser evaluates the script.

Because the serializeRegExp implementation prioritized valid RegExp literal syntax by calling deserializeString(node.c), any raw < character present in the regular expression source was emitted verbatim into the serialized JavaScript output. This affected all releases prior to 1.0.0 (the v0.x branch) and versions 1.5.5 through 1.6.9.

Code Analysis

The vulnerability is located in packages/seroval/src/core/context/serializer.ts within the serializeRegExp function. In vulnerable versions up to 1.6.9, the function checks whether the Feature.RegExp bitmask is enabled in the serialization context and unconditionally emits a regular expression literal by invoking deserializeString on node.c.

// Vulnerable implementation prior to 1.6.10
function serializeRegExp(
  ctx: SerializationContext,
  node: SerovalRegExpNode,
): string {
  if (ctx.base.features & Feature.RegExp) {
    // BUG: deserializeString converts '\x3C' back into raw '<'
    return '/' + deserializeString(node.c) + '/' + node.m;
  }
  throw new SerovalUnsupportedNodeError(node);
}

In commit f94ee0b63936dae954ff50d5b5e8ea7cb9b284e6, the maintainer resolved the issue by inspecting node.c prior to deserialization. Because node.c already holds the string-escaped representation of the regular expression source (where < is encoded as \x3C), checking node.c.includes('\\x3C') reliably detects whether the original pattern contained a < character.

--- a/packages/seroval/src/core/context/serializer.ts
+++ b/packages/seroval/src/core/context/serializer.ts
@@ -879,6 +879,13 @@ function serializeRegExp(
   node: SerovalRegExpNode,
 ): string {
   if (ctx.base.features & Feature.RegExp) {
+    // A literal would put the source's `<` back into the output, so `</script>`
+    // could close the page's script element. Escaping it inside a literal
+    // breaks named groups and lookbehinds, so the escaped source goes through
+    // the constructor instead.
+    if (node.c.includes('\\x3C')) {
+      return 'new RegExp("' + node.c + '","' + node.m + '")';
+    }
     return '/' + deserializeString(node.c) + '/' + node.m;
   }
   throw new SerovalUnsupportedNodeError(node);
 }

When node.c contains \x3C, serializeRegExp bypasses the literal format (/.../) and emits a new RegExp("...") constructor invocation instead. Because the first argument to the RegExp constructor is a standard JavaScript string literal, the \x3C escape sequence inside node.c is evaluated by the JavaScript string parser before the resulting string is compiled by the regular expression engine. When the JavaScript engine parses "(?\x3Cname>a)", it resolves the string in memory to "(?<name>a)" and passes that resolved string to new RegExp(), preserving full compatibility with named groups, lookbehinds, and /v mode while guaranteeing that no raw < character is written to the HTML document.

Fix Completeness Assessment

The patch in commit f94ee0b63936dae954ff50d5b5e8ea7cb9b284e6 is complete and addresses all three code generation paths in seroval: synchronous/asynchronous direct serialization (serialize), cross-reference serialization (crossSerialize), and JSON AST compilation (compileJSON). The regression test suite added in packages/seroval/test/regexp-script-safety.test.ts verifies that patterns containing </script>, case-insensitive </SCRIPT>, HTML comment openers (<!--), named capture groups ((?<name>a)\k<name>), lookbehind assertions ((?<=a)b(?<!c)), and Unicode sets ([<"\\]/v) never emit a raw < character while deserializing back into functionally identical RegExp instances.

Exploitation

Exploiting CVE-2026-116582 requires a specific application architecture where user-controlled input is incorporated into a RegExp object on the server, serialized via seroval, and injected directly into an inline HTML <script> element without additional encoding. This pattern occurs in SSR frameworks when applications persist search filters, routing matchers, or client-side validation rules across the server-client boundary.

Proof-of-Concept Scenario

Consider a server-side rendered route handler that accepts a query parameter pattern, compiles it into a RegExp instance for shared server/client filtering, and hydrates the state into the HTML response using seroval:

import { serialize } from 'seroval';
 
export function renderSearchPage(userPattern: string): string {
  const filterRegex = new RegExp(userPattern, 'i');
  const serializedState = serialize({
    activeFilter: filterRegex,
  });
 
  return `<!DOCTYPE html>
<html>
  <head>
    <script>
      window.__INITIAL_STATE__ = ${serializedState};
    </script>
  </head>
  <body>Search Results</body>
</html>`;
}

To trigger the vulnerability while ensuring the server-side new RegExp(userPattern, 'i') call does not throw a SyntaxError prior to serialization, the attacker wraps the HTML breakout payload inside a valid regular expression character class ([...]) or non-capturing group:

[</script><script>alert(document.domain)//]

When renderSearchPage executes on a vulnerable version of seroval (such as 1.6.9), new RegExp("[</script><script>alert(document.domain)//]", "i") succeeds because the brackets form a valid character class and the forward slashes inside </script> are automatically escaped by the JavaScript engine's RegExp.prototype.source getter as \/. seroval then serializes the state into the HTML template as follows:

<!DOCTYPE html>
<html>
  <head>
    <script>
      window.__INITIAL_STATE__ = {activeFilter:/[<\/script><script>alert(document.domain)\/\/]/i};
    </script>
  </head>
  <body>Search Results</body>
</html>

Notice that in RegExp.prototype.source, forward slashes are escaped with a backslash (<\/script>), which would normally prevent HTML tag termination. However, if the attacker constructs the RegExp or AST via paths where / is not preceded by \, or injects an unclosed HTML comment sequence (<!--) combined with subsequent user-controlled strings, or if the pattern is processed through compileJSON with crafted AST nodes, raw </script> or <!-- sequences reach the HTML parser. Moreover, in environments or transformations where node.c contains unescaped slashes (as verified directly by the upstream test case /[</script><script>alert(1)//]/ in regexp-script-safety.test.ts), deserializeString(node.c) emits the exact substring </script><script>alert(1)//. The browser's HTML parser closes the first <script> block at </script> and immediately executes alert(1) inside the newly opened <script> element.

Impact Assessment

CVE-2026-116582 is rated as Medium severity with a CVSS v3.1 base score of 4.7 (CVSS:3.1/AV:N/AC:H/PR:N/UI:R/S:C/C:L/I:L/A:N). The High Attack Complexity (AC:H) metric reflects the prerequisite that the target application must explicitly construct a RegExp object from untrusted input on the server and pass it through seroval's JavaScript serializer into an HTML <script> context. Most web applications pass user input as standard strings rather than RegExp instances.

When these prerequisites are met, the vulnerability results in stored or reflected Cross-Site Scripting (XSS), changing the security scope (S:C) from the server-side serialization routine to the victim's client-side browser environment. Requiring no privileges (PR:N) and relying on user interaction (UI:R) where a victim visits a crafted URL or views a page containing stored regex filters, an attacker achieves arbitrary JavaScript execution within the origin of the vulnerable web application.

Concrete impacts of successful exploitation include:

  • Confidentiality Impact (C:L): The attacker's script can read non-HttpOnly session cookies, extract bearer tokens or sensitive state stored in localStorage and sessionStorage, and exfiltrate private user data rendered within the DOM or window.__INITIAL_STATE__ object.
  • Integrity Impact (I:L): The attacker can perform arbitrary state-changing requests (Cross-Site Request Forgery via same-origin fetch/XMLHttpRequest), manipulate the rendered DOM to present phishing forms, or hijack the user's account session.
  • Availability Impact (A:N): The flaw does not impact the availability of the underlying Node.js server infrastructure.

According to FIRST.org Exploit Prediction Scoring System (EPSS) telemetry, CVE-2026-116582 carries an EPSS score of 0.00188 (0.19% probability of exploitation in the next 30 days, placing it in the 8.36th percentile). The vulnerability is not listed in the CISA Known Exploited Vulnerabilities (KEV) catalog, and no active in-the-wild exploitation has been observed.

Remediation

The primary remediation is to upgrade seroval (and seroval-plugins if used in lockstep) to version 1.6.10 or later. Version 1.6.10 modifies serializeRegExp to emit new RegExp(...) constructor calls with hexadecimal-escaped string arguments whenever a < character (\x3C) is present in the pattern, eliminating the possibility of <script> tag termination.

# Upgrade using npm
npm install seroval@^1.6.10
 
# Upgrade using pnpm
pnpm update seroval@^1.6.10
 
# Upgrade using yarn
yarn upgrade seroval@^1.6.10

> [!NOTE] > If seroval is included as a transitive dependency via an SSR meta-framework (such as SolidStart or Vinxi), inspect your lockfile (package-lock.json, pnpm-lock.yaml, or yarn.lock) to verify the resolved version of seroval. Use overrides (npm/pnpm) or resolutions (yarn) in package.json to force version >=1.6.10 if the upstream framework has not yet bumped its dependency range.

Defense-in-Depth & Workarounds

For environments where immediate dependency upgrades are blocked, apply the following mitigations:

  1. Avoid Serializing Untrusted RegExp Instances: Do not pass user-supplied strings into new RegExp() prior to SSR state serialization. Instead, pass the raw filter string inside the state object (which seroval safely escapes using \x3C) and instantiate the RegExp object on the client side after hydration completes.
  2. Input Validation on Regular Expression Patterns: If server-side RegExp instantiation is strictly required, validate the input string before constructing the regular expression and reject any input containing the < character.
  3. Enforce Strict Content Security Policy (CSP): Configure a Content Security Policy header that uses cryptographic nonces (script-src 'nonce-<random>') rather than 'unsafe-inline'. Even if an attacker injects </script><script>...</script> to break out of a legitimate nonce-bearing hydration script tag, the browser will refuse to execute the newly opened <script> tag because it lacks the required nonce attribute.
  4. Use Non-Executable JSON Hydration: Where supported by the architecture, serialize state using seroval's toJSON API, embed the output inside a non-executable <script type="application/json"> block (escaping < as \u003c during JSON.stringify), and parse it on the client via fromJSON(JSON.parse(el.textContent)).

Official Patches

lxsmnsyc (GitHub)Official release seroval@1.6.10 containing the security patch
lxsmnsyc (GitHub)GitHub Security Advisory GHSA-9wx9-5pv9-3349
lxsmnsyc (GitHub)Upstream patch commit in lxsmnsyc/seroval

Fix Analysis (1)

Technical Appendix

CVSS Score
4.7/ 10
CVSS:3.1/AV:N/AC:H/PR:N/UI:R/S:C/C:L/I:L/A:N
EPSS Probability
0.19%
Top 92% most exploited

Affected Systems

serovalseroval-plugins

Affected Versions Detail

Product
Affected Versions
Fixed Version
seroval
lxsmnsyc
< 1.0.01.6.10
seroval
lxsmnsyc
>= 1.5.5, < 1.6.101.6.10
seroval-plugins
lxsmnsyc
< 1.0.01.6.10
seroval-plugins
lxsmnsyc
>= 1.5.5, < 1.6.101.6.10
AttributeDetail
CVE IDCVE-2026-116582 (GHSA-9wx9-5pv9-3349)
Weakness ClassCWE-79 (Cross-Site Scripting) / CWE-116 (Improper Output Escaping)
CVSS v3.1 Score4.7 Medium (CVSS:3.1/AV:N/AC:H/PR:N/UI:R/S:C/C:L/I:L/A:N)
EPSS Score0.19% (8.36th Percentile)
Attack VectorNetwork (SSR HTML <script> Breakout via RegExp Literal)
Affected Versionsseroval < 1.0.0 and >= 1.5.5, < 1.6.10
Patched Versionseroval 1.6.10
CISA KEV StatusNot Listed

MITRE ATT&CK Mapping

T1189Drive-by Compromise
Initial Access
T1185Browser Session Hijacking
Collection
CWE-79
Improper Neutralization of Input During Web Page Generation ('Cross-site Scripting')

The software does not neutralize or incorrectly neutralizes user-controllable input before it is placed in output that is used as a web page that is served to other users.

Vulnerability Timeline

Fix commit f94ee0b63936dae954ff50d5b5e8ea7cb9b284e6 authored in lxsmnsyc/seroval
2026-10-18
CVE-2026-116582 and GitHub Security Advisory GHSA-9wx9-5pv9-3349 published
2026-10-26
NVD and OSV vulnerability records updated with CVSS v3.1 assessment
2026-10-28

References & Sources

  • [1]GitHub Security Advisory GHSA-9wx9-5pv9-3349
  • [2]Patch Commit: fix: keep RegExp sources from closing the script element
  • [3]GitHub Release: seroval@1.6.10
  • [4]National Vulnerability Database (NVD) - CVE-2026-116582
  • [5]CVE Project cvelistV5 Record - CVE-2026-116582
  • [6]CVE.org Official Record - CVE-2026-116582

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.

More Reports

•24 minutes ago•CVE-2026-116581
7.5

CVE-2026-116581: Unauthenticated Event-Loop Denial of Service via Unvalidated Sequence Indices in Seroval

Seroval, a JavaScript serialization library used for transferring complex structures across network boundaries, contains an input validation vulnerability in versions prior to 1.6.8. The `fromJSON` and `fromCrossJSON` deserializers fail to validate array element lists and the termination boundaries (`done` and `throw` indices) of sequence nodes. By supplying out-of-bounds indices or forged array-like structures, an unauthenticated remote attacker can construct an iterator with an unreachable exit condition or trigger excessive loop iterations, halting the single-threaded JavaScript event loop and causing a denial of service.

Amit Schendel
Amit Schendel
2 views•10 min read
•about 2 hours ago•CVE-2026-116583
5.3

CVE-2026-116583: Code Injection via TypedArray Constructor Property Spoofing in Seroval

CVE-2026-116583 (GHSA-f86p-h4j2-7qgj) is a code injection and cross-site scripting (XSS) vulnerability in Seroval, a JavaScript object serialization library. In versions 1.6.0 prior to 1.6.11, Seroval derives the constructor name of a TypedArray directly from the `current.constructor.name` property expression during serialization. If an attacker supplies untrusted properties that are merged onto a TypedArray instance, an own `constructor` property overrides the prototype property and gets emitted unescaped after the `new` keyword in the generated JavaScript output. Evaluating or rendering this output in a browser or JavaScript runtime results in arbitrary code execution.

Alon Barad
Alon Barad
3 views•8 min read
•about 3 hours ago•GHSA-JF75-Q64Q-G65R
6.5

GHSA-jf75-q64q-g65r: NoSQL Query Manipulation and Partial Authentication Bypass in Waline Server

An improper input validation and NoSQL query construction vulnerability exists in the Waline comment system server (@waline/vercel) version 1.40.3 and earlier. When MongoDB is used as the backend storage engine, the POST /api/token authentication endpoint fails to validate that the user-supplied email parameter is a string. Supplying a JSON object or array operator causes the MongoDB storage adapter to omit the email filter or construct an unintended match-all query, returning all user records and allowing unauthenticated attackers to target the site administrator account directly without knowing the administrator's email address.

Alon Barad
Alon Barad
2 views•10 min read
•about 4 hours ago•GHSA-2HW4-C9M4-F2FJ
6.5

CVE-2026-54462: Unbounded Request-Body Memory Exhaustion in Knative Admission Webhooks

An uncontrolled resource consumption vulnerability in the knative.dev/pkg/webhook package allows network-adjacent attackers within a Kubernetes cluster to trigger Out-Of-Memory (OOM) terminations of admission controller pods. The admission webhook HTTP server processes incoming AdmissionReview requests through an io.TeeReader and json.Decoder pipeline without enforcing an upper bound on request body size. Due to internal buffer reallocation mechanics, incoming payloads experience a 4.5x memory amplification factor. Because knative.dev/pkg provides the shared webhook server foundation for numerous cloud-native projects—including Knative Serving, Knative Eventing, Tekton, KEDA, Sigstore Policy Controller, and Kpack—exploitation can halt resource admission across entire Kubernetes clusters or bypass critical security validation policies.

Alon Barad
Alon Barad
3 views•10 min read
•about 5 hours ago•CVE-2026-115923
6.5

CVE-2026-115923: Path Traversal and Catalog Rule Bypass in Backstage Catalog Backend

CVE-2026-115923 (GHSA-w658-mh9p-ww8f) is a path traversal and access control bypass vulnerability in Spotify's Backstage developer portal framework, specifically within the @backstage/plugin-catalog-backend package. Prior to patched versions, DefaultCatalogRulesEnforcer evaluated user-supplied URL catalog locations against configured catalog.rules patterns using raw, uncanonicalized strings. Because downstream URL readers canonicalize URLs and resolve dot segments before fetching resources, an authenticated attacker with location registration permissions can supply percent-encoded traversal sequences (such as %2e%2e) to bypass location restrictions and register untrusted catalog entities.

Amit Schendel
Amit Schendel
5 views•9 min read
•about 6 hours ago•CVE-2026-116576
7.8

CVE-2026-116576: OS Command Injection via Unicode Quotation Marks in Node.js systeminformation

CVE-2026-116576 (GHSA-3f7j-7jwc-fxfj) is an OS Command Injection vulnerability (CWE-78) in the Node.js systeminformation library prior to version 5.33.16 on Microsoft Windows. The services() API function dynamically constructs a PowerShell Get-CimInstance command using caller-supplied service names passed through sanitizeShellString(). While the sanitizer strips standard ASCII quotation marks, it permits Unicode typographic quotation marks (U+2018 through U+201E). Because the Windows PowerShell tokenizer recognizes Unicode quotation marks as valid string literal delimiters, an attacker who controls the service name input can break out of the CIM filter string and execute arbitrary PowerShell commands within the security context of the Node.js process.

Alon Barad
Alon Barad
6 views•11 min read