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-39320
7.50.04%

CVE-2026-39320: Unauthenticated ReDoS in Signal K Server WebSocket Subscriptions

Amit Schendel
Amit Schendel
Senior Security Researcher

Apr 22, 2026·6 min read·3 visits

PoC Available

Executive Summary (TL;DR)

Unauthenticated attackers can send crafted WebSocket messages containing nested regex quantifiers to Signal K Server, triggering a ReDoS condition that blocks the Node.js event loop and causes 100% CPU exhaustion.

Signal K Server prior to version 2.25.0 contains a Regular Expression Denial of Service (ReDoS) vulnerability in its WebSocket subscription handling module. The application dynamically compiles unvalidated user input into regular expressions, allowing unauthenticated remote attackers to trigger catastrophic backtracking in the Node.js V8 engine. This results in complete resource exhaustion and immediate denial of service.

Vulnerability Overview

Signal K Server operates as a central data hub for marine vessels, heavily utilizing WebSockets for real-time telemetry streaming. The application processes client subscription requests to specific data paths using the SubscriptionManager component. Clients define their areas of interest using a context parameter, which the server translates into an internal filtering mechanism.

CVE-2026-39320 represents a Regular Expression Denial of Service (ReDoS) vulnerability in this subscription filtering logic. The application dynamically constructs regular expressions from unauthenticated, user-supplied context and path parameters. A failure to safely escape regex metacharacters allows attackers to inject malicious execution patterns.

Because Signal K Server runs on the Node.js runtime, it relies on a single-threaded event loop for JavaScript execution. When the V8 JavaScript engine evaluates an injected, highly complex regular expression against standard system identifiers, it enters a state of catastrophic backtracking. This synchronous computational operation halts all concurrent processing, resulting in an immediate and sustained denial of service.

Root Cause Analysis

The root cause lies in src/subscriptionmanager.ts, specifically within the contextMatcher and pathMatcher functions. These functions are responsible for converting wildcard-based string queries into native RegExp objects. The intended design allows simple wildcard filtering, translating paths like vessels.* into a matching regex pattern.

To achieve this behavior, the legacy implementation applied a naive string replacement strategy. It converted period characters to literal periods and asterisks to .* catch-all matchers. The implementation completely omitted sanitization for all other regular expression control characters, including grouping parentheses, alternation pipes, and repetition quantifiers.

This logic omission permits an attacker to supply a context string containing nested quantifiers. When the server concatenates this unsanitized input into the RegExp constructor, it creates a compiled pattern capable of exponential backtracking. The engine attempts to match the payload against long internal strings, typically the server's own 36-character UUID.

As the V8 regex engine evaluates the string, the nested groups cause it to compute every possible combination of character matches before ultimately failing. The computational time required scales exponentially with the length of the input string. This synchronous evaluation process blocks the Node.js event loop entirely.

Code Analysis

The vulnerable implementation relied on manual, incomplete string replacement logic. By examining the source code prior to version 2.25.0, the failure to escape standard metacharacters is evident. The replacement sequence only accounted for two specific characters, leaving the rest of the regex syntax fully accessible to the end user.

// Vulnerable implementation in src/subscriptionmanager.ts
function contextMatcher(context: string) {
  const pattern = context
    .replace(/\./g, '\\.')
    .replace(/\*/g, '.*');
  return new RegExp(`^${pattern}$`);
}

The patch introduced in commit 215d81eb700d5419c3396a0fbf23f2e246dfac2d addresses the flaw by integrating an external, robust regex escaping library. Rather than attempting to maintain a blocklist of dangerous characters, the fix employs an allowlist-like approach. It neutralizes the entire input string before selectively restoring the intended wildcard functionality.

// Patched implementation
import escapeStringRegexp from 'escape-string-regexp';
 
function contextMatcher(context: string) {
  // Properly escape all metacharacters first
  let pattern = escapeStringRegexp(context);
  // Safely restore the intended wildcard behavior
  pattern = pattern.replace(/\\\*/g, '.*');
  return new RegExp(`^${pattern}$`);
}

This architectural change ensures that any user-supplied parentheses, brackets, or plus signs are treated strictly as string literals by the regex engine. Consequently, the attacker loses the ability to define capturing groups or dynamic quantifiers, completely mitigating the catastrophic backtracking vector.

Exploitation Methodology

Exploitation requires no prior authentication and minimal network interaction. An attacker only needs TCP access to the target Signal K Server's WebSocket endpoint, typically exposed on port 3000. The attack initiates via a standard WebSocket upgrade request, followed by the transmission of a single crafted JSON payload.

The payload specifically targets the context field of a subscription request. The attacker structures the context to include a nested repetition pattern, followed by a character guaranteed not to exist at the end of the server's internal evaluation string. This suffix forces the worst-case time complexity path within the regex engine.

{
  "context": "vessels.([a-z0-9:-]+)+!",
  "subscribe": [
    {
      "path": "navigation.position",
      "period": 1000
    }
  ]
}

Upon receiving this frame, the server maps the string ([a-z0-9:-]+)+! into a RegExp object. It then attempts to validate an incoming vessel identifier against it. When matching a standard vessel URN (e.g., urn:mrn:signalk:uuid:c0d79334-4e25-4245-8892-54e8ccc8021d), the engine matches the alphanumeric characters but fails at the literal exclamation mark boundary. The engine continuously backtracks through the overlapping plus quantifiers, locking the thread.

Impact Assessment

The successful execution of this attack results in a total denial of service for the target application. The underlying Node.js runtime operates concurrently using an asynchronous event loop, but native regex evaluations execute synchronously on the main thread. The catastrophic backtracking consumes 100% of the CPU core allocated to the Signal K process.

While the thread remains locked in the regex evaluation sequence, the server cannot process any pending or incoming network I/O. All subsequent REST API requests, WebSocket messages, and internal timers queue indefinitely. Existing client connections eventually drop as application-layer keep-alive mechanisms fail, rendering the system entirely unresponsive.

The CVSS v3.1 base score of 7.5 reflects the severity of this availability impact. The exploit execution requires low attack complexity, demands no privileges, and functions without any user interaction. System confidentiality and data integrity remain unaffected, as the vulnerability exclusively exhausts computational resources.

The recovery process requires manual administrative intervention or automated orchestration restarts. The affected process will not recover gracefully, as the regex evaluation time for a 36-character string with nested quantifiers can exceed multiple years of compute time. Administrators must forcefully terminate the process (SIGKILL) and allow a supervisor daemon to restart it.

Remediation and Workarounds

The primary remediation strategy requires upgrading the Signal K Server software to version 2.25.0 or later. This release contains the complete cryptographic neutralization of user input prior to regex compilation, alongside new rate-limiting structures. Administrators must verify their package versions using npm or their container orchestrator management interfaces.

In environments where an immediate software upgrade is impossible, administrators can deploy Web Application Firewall (WAF) rules or reverse proxy filters to inspect WebSocket traffic. WAF signatures should be configured to aggressively drop any WebSocket frames containing repetitive regex metacharacters, specifically targeting patterns containing ( followed by + in the context JSON field.

Network-level restrictions provide an additional, effective layer of defense. By isolating the WebSocket endpoint behind a strict reverse proxy configuration or VPN gateway, administrators can restrict access to known, trusted client IP addresses. Implementing pre-connection authentication at the load balancer level completely removes the unauthenticated remote attack vector.

Official Patches

Signal K GitHubPull Request #2568: Fix ReDoS in subscription manager
Signal K GitHubCommit 215d81eb700d5419c3396a0fbf23f2e246dfac2d
Signal K GitHubRelease v2.25.0 containing the fix

Fix Analysis (1)

Technical Appendix

CVSS Score
7.5/ 10
CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H
EPSS Probability
0.04%
Top 87% most exploited

Affected Systems

Signal K Server < 2.25.0

Affected Versions Detail

Product
Affected Versions
Fixed Version
Signal K Server
Signal K
< 2.25.02.25.0
AttributeDetail
CVSS v3.17.5 (High)
CWE IDsCWE-1333, CWE-400
Attack VectorNetwork (Unauthenticated)
ImpactDenial of Service (100% CPU exhaustion)
EPSS Score0.00041 (12.57th percentile)
Exploit StatusProof of Concept (PoC) available
CISA KEVNot Listed

MITRE ATT&CK Mapping

T1499Endpoint Denial of Service
Impact
CWE-1333
Inefficient Regular Expression Complexity

Inefficient Regular Expression Complexity

Known Exploits & Detection

Vulnerability Context PayloadJSON payload containing nested quantifier targeting the context parameter

Vulnerability Timeline

Version 2.25.0 officially released with patch.
2026-04-21
Vulnerability publicly disclosed and CVE assigned.
2026-04-21

References & Sources

  • [1]NVD Record for CVE-2026-39320
  • [2]GitHub Security Advisory GHSA-7gcj-phff-2884
  • [3]CVE.org Record for CVE-2026-39320
  • [4]Tenable Analysis for CVE-2026-39320

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.