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-116693

CVE-2026-116693: Regular Expression Denial of Service in Datadog Node.js Tracer (dd-trace)

Alon Barad
Alon Barad
Software Engineer

Oct 28, 2026·10 min read·3 visits

Executive Summary (TL;DR)

An inefficient default regular expression used by the Datadog Node.js APM tracer (dd-trace) to redact sensitive parameters from URL query strings allows unauthenticated attackers to trigger catastrophic backtracking via crafted HTTP requests, blocking the Node.js single-threaded event loop and causing a full application denial of service.

CVE-2026-116693 is a high-severity Regular Expression Denial of Service (ReDoS) vulnerability affecting the official Datadog Application Performance Monitoring (APM) client library for Node.js, dd-trace. The defect resides in the default regular expression defined by the DD_TRACE_OBFUSCATION_QUERY_STRING_REGEXP configuration parameter, which is used to sanitize incoming and outgoing HTTP URL query strings prior to recording trace span metadata. Due to overlapping sub-patterns and unanchored repetition blocks in the JSON Web Token (JWT) and URL-encoded string matching branches, the V8 JavaScript engine's regular expression subsystem (Irregexp) can be forced into catastrophic or high-degree polynomial backtracking. Because regular expression replacement occurs synchronously on the primary Node.js event loop, an unauthenticated remote attacker can send crafted HTTP requests with malicious query strings to consume 100% of the process CPU core, stalling concurrent request processing and rendering the application unavailable.

Vulnerability Overview

CVE-2026-116693 (also tracked as GHSA-x94g-w73q-hpcw) is an algorithmic complexity vulnerability classified under CWE-1333 (Inefficient Regular Expression Complexity) in dd-trace, the Datadog Application Performance Monitoring (APM) library for Node.js. The dd-trace package provides automatic and manual instrumentation for Node.js runtime environments, hooking into standard web frameworks (including Express, Fastify, Koa, Hapi, and Connect) as well as core Node.js networking modules (http, https, and http2).

During the lifecycle of an instrumented HTTP transaction, dd-trace intercepts the request or response to populate APM span tags, specifically the http.url tag. Because raw URLs frequently contain sensitive secrets, session tokens, or personally identifiable information inside query parameters, the tracer automatically runs a sanitization routine over the query string before queuing the span for transmission to the Datadog Agent. This redaction step is enabled by default whenever HTTP tracing and query string capture are active.

The sanitization logic relies on a global, case-insensitive regular expression configured via the DD_TRACE_OBFUSCATION_QUERY_STRING_REGEXP option. In versions >= 2.0.0, < 5.131.1 and >= 6.0.0, < 6.20.1, this default regular expression contains multiple structural ambiguities and unanchored repetition groups. Because Node.js executes JavaScript and regular expression evaluations synchronously on a single-threaded event loop, any input that induces non-linear evaluation time directly blocks the execution thread.

An unauthenticated remote adversary with network access to any HTTP endpoint instrumented by dd-trace can supply a crafted query string in a standard GET or POST request. The tracer evaluates this query string prior to or alongside application routing logic, causing the V8 engine to enter catastrophic backtracking. This results in immediate CPU exhaustion and complete starvation of the Node.js event loop, denying service to all legitimate clients connected to the affected process.

Root Cause Analysis

The root cause of CVE-2026-116693 lies in the construction of the default 626-character regular expression assigned to DD_TRACE_OBFUSCATION_QUERY_STRING_REGEXP, combined with the backtracking behavior of V8's non-backtracking-unaware NFA engine (Irregexp). The pattern is designed to detect a broad range of credential formats in URL query strings, including key-value pairs (password=, secret=, api_key=), Bearer tokens, GitHub personal access tokens, JSON Web Tokens (JWTs), PEM-encoded private keys, and SSH public keys.

(?:p(?:ass)?w(?:or)?d|pass(?:_?phrase)?|secret|(?:api_?|private_?|public_?|access_?|secret_?)key(?:_?id)?|token|consumer_?(?:id|key|secret)|sign(?:ed|ature)?|auth(?:entication|orization)?)(?:(?:\s|%20)*(?:=|%3D)[^&]+|(?:"|%22)(?:\s|%20)*(?::|%3A)(?:\s|%20)*(?:"|%22)(?:%2[^2]|%[^2]|[^"%])+(?:"|%22))|bearer(?:\s|%20)+[a-z0-9\._\-]+|token(?::|%3A)[a-z0-9]{13}|gh[opsu]_[0-9a-zA-Z]{36}|ey[I-L](?:[\w=-]|%3D)+\.ey[I-L](?:[\w=-]|%3D)+(?:\.(?:[\w.+\/=-]|%3D|%2F|%2B)+)?|[\-]{5}BEGIN(?:[a-z\s]|%20)+PRIVATE(?:\s|%20)KEY[\-]{5}[^\-]+[\-]{5}END(?:[a-z\s]|%20)+PRIVATE(?:\s|%20)KEY|ssh-rsa(?:\s|%20)*(?:[a-z0-9\/\.+]|%2F|%5C|%2B){100,}

The primary backtracking hotspot occurs in the JWT detection branch: ey[I-L](?:[\w=-]|%3D)+\.ey[I-L](?:[\w=-]|%3D)+(?:\.(?:[\w.+\/=-]|%3D|%2F|%2B)+)?. First, this sub-pattern lacks a leading boundary anchor or lookbehind assertion (such as ^ or a non-word delimiter), allowing the engine to initiate a match attempt at any arbitrary offset within a long string where the substring ey followed by I, J, K, or L appears. Second, the repeated alternation group (?:[\w=-]|%3D)+ introduces ambiguity when processing URL-encoded sequences or strings containing 3 and D characters, alongside repeated dot (.) delimiters across the three JWT segments.

When a query string contains multiple segments starting with eyJ followed by base64url-compatible characters and dots, but fails to satisfy the trailing segment requirements or triggers repeated sub-match attempts across the string, the NFA engine must explore an exponential or high-degree polynomial number of paths before abandoning the match at each starting offset. Because the g (global) flag is set on the compiled RegExp object, String.prototype.replace() advances character by character and re-evaluates the pattern across the remaining substring.

A secondary hotspot exists in the JSON-encoded value matching branch: (?:%2[^2]|%[^2]|[^"%])+. Here, three alternatives are wrapped inside a greedy + quantifier to match characters up to a closing quote (" or %22). When an attacker supplies a sequence of percent-encoded characters starting with % or %2 that is never terminated by a closing quote (" or %22), the engine backtracks through the overlapping character classes across the length of the input.

Code Analysis

The vulnerable code path resides in packages/dd-trace/src/plugins/util/url.js and packages/dd-trace/src/config/supported-configurations.json. When dd-trace initializes its HTTP instrumentation plugins, getQsObfuscator(config) compiles the regular expression string from config.queryStringObfuscation (populated by default from DD_TRACE_OBFUSCATION_QUERY_STRING_REGEXP) into a cached RegExp instance with the gi flags.

During request processing, obfuscateQs(config, url) slices the query string after the first ? delimiter and executes qs.replace(queryStringObfuscation, '<redacted>'). Prior to the patch in commits 5eeee790c93036a50549056fc890028cb4c86b1b (v6 branch) and cf4e68a45fa1442c9850f2086c81901258e821b8 (v5 branch), url.js performed a static string replacement without accounting for boundary capture groups:

// Vulnerable implementation in packages/dd-trace/src/plugins/util/url.js
function obfuscateQs (config, url) {
  // ... validation and index lookup for '?' ...
  let qs = url.slice(i + 1)
 
  // Synchronous execution of vulnerable regex on main thread
  qs = qs.replace(queryStringObfuscation, '<redacted>')
 
  return `${path}?${qs}`
}

To remediate the vulnerability in Pull Request #10675, Datadog modified both the regular expression definition and the replacement logic in url.js. In the updated regular expression, the JWT branch was anchored to a preceding delimiter using a capturing group ^|[^\w%-]|%[0-9a-f]{2}, and the character classes for the JWT header and payload were tightened from (?:[\w=-]|%3D)+ to [\w-]+(?:=|%3D)*. Separating the base64url body characters ([\w-]+) from the optional padding characters ((?:=|%3D)*) eliminates the quantifier nesting ambiguity and enforces strict token boundaries.

// Patched implementation in packages/dd-trace/src/plugins/util/url.js
const { defaults } = require('../../config/defaults')
// ...
function obfuscateQs (config, url) {
  // ...
  let qs = url.slice(i + 1)
 
  // Group 1 of the default regex captures the delimiter preceding a JWT.
  // If the default obfuscator is active, preserve Group 1 ($1) during replacement.
  // If a custom user-provided regex is active, redact the entire match to avoid leaking Group 1.
  const replacement = queryStringObfuscation === defaultQsObfuscator ? '$1<redacted>' : '<redacted>'
  qs = qs.replace(queryStringObfuscation, replacement)
 
  return `${path}?${qs}`
}
 
const qsObfuscatorCache = new Map()
let defaultQsObfuscator
 
function getQsObfuscator (config) {
  // ...
  } else if (obfuscator !== '.*') {
    try {
      compiled = new RegExp(obfuscator, 'gi')
      // Track reference to the compiled default regex
      if (obfuscator === defaults.DD_TRACE_OBFUSCATION_QUERY_STRING_REGEXP) defaultQsObfuscator = compiled
    } catch (err) {
      log.error('Error getting qs obfuscator', err)
    }
  }
}

> [!NOTE] > Assessment of Fix Completeness: The patch effectively neutralizes the JWT backtracking vector by anchoring the match start and decoupling the padding quantifier (=|%3D)* from the body [\w-]+. It also hardens the SSH key matching branch ((?:ssh-(?:rsa|dss)|ecdsa-[a-z0-9]+-[a-z0-9]+)...). However, the JSON value matching sub-branch (?:%2[^2]|%[^2]|[^"%])+ remains present in the default pattern. While its alternatives (%2[^2], %[^2], and [^"%]) are mutually exclusive at the first character or second character lookahead level—preventing exponential $O(2^n)$ backtracking within that specific group—the overarching regular expression still relies on V8's backtracking engine rather than a linear-time automaton.

Exploitation

Exploiting CVE-2026-116693 requires no authentication, valid session state, or knowledge of the target application's internal route structure. Because dd-trace hooks into the lowest-level Node.js HTTP server events (specifically the request event emitted by http.Server or http2.Http2Server), the tracer processes the request URL even if the target path returns a 404 Not Found or 401 Unauthorized response at the application layer.

To trigger the denial of service, an attacker constructs an HTTP request containing a query string specifically structured to maximize backtracking transitions in the default DD_TRACE_OBFUSCATION_QUERY_STRING_REGEXP pattern. The attack targets either the unanchored JWT sub-pattern or the compound key-value alternations.

  1. Target Identification: The attacker identifies a Node.js web service instrumented with dd-trace (versions 2.0.0 through 5.131.0 or 6.0.0 through 6.20.0).
  2. Payload Construction: The attacker generates a query string parameter containing repeated sequences matching the prefix eyJ followed by word characters, hyphens, and ambiguous = or %3D sequences separated by dots (.), terminated by a character that invalidates the third JWT segment (such as & or %).
  3. Request Transmission: The attacker sends the HTTP request over the network to any exposed endpoint on the server. Standard HTTP servers typically permit URL lengths between 4 KB and 8 KB by default (Node.js maxHeaderSize defaults to 16 KB in modern releases), providing ample payload space within a single request.
  4. Event Loop Exhaustion: Upon request completion or span finalization, obfuscateQs() invokes qs.replace() on the malicious query string. The main Node.js execution thread stalls inside C++ V8 Irregexp execution. By sending a low-rate stream of requests (a few requests per second), a single attacker can keep a multi-worker or clustered deployment continuously saturated.

Impact Assessment

The primary impact of CVE-2026-116693 is a complete denial of service against the affected Node.js process, reflected in the CVSS v4.0 base score of 8.7 (High) with vector CVSS:4.0/AV:N/AC:L/AT:N/PR:N/UI:N/VC:N/VI:N/VA:H/SC:N/SI:N/SA:N. Because Confidentiality (VC:N) and Integrity (VI:N) are unaffected, the risk is strictly confined to system Availability (VA:H).

In the Node.js runtime architecture, all I/O operations, timers, promise resolutions, and incoming HTTP connections are multiplexed onto a single main thread via libuv. When CPU-bound synchronous work such as catastrophic regular expression backtracking executes on this thread, the event loop cannot advance to the poll phase. Consequently, active sockets stop receiving data, database connection pools time out, and health check probes (such as Kubernetes liveness and readiness checks) fail to receive responses.

In containerized orchestration environments (such as Kubernetes or Amazon ECS), sustained failure of liveness probes caused by event loop starvation will prompt the orchestrator to terminate and restart the container. If the attacker maintains a minimal request rate across load-balanced replicas, the entire service tier can be forced into a continuous crash-loop state (Application Exhaustion Flood, MITRE ATT&CK T1499.004).

According to current threat intelligence, CVE-2026-116693 is not listed in the CISA Known Exploited Vulnerabilities (KEV) catalog, and no public standalone Proof-of-Concept (PoC) scripts have been published on ExploitDB or GitHub. However, because the exact diff between the vulnerable and fixed regular expressions is publicly visible in the repository commit history, deriving a triggering string requires minimal effort for a skilled adversary.

Remediation

Organizations utilizing dd-trace in Node.js applications should upgrade to a patched release immediately. Datadog has resolved this issue in versions 5.131.1 (for the v5.x release line and earlier v2.x-v4.x users upgrading to v5) and 6.20.1 (for the v6.x release line).

# Upgrade to the latest patched v6 release
npm install dd-trace@^6.20.1
 
# Or upgrade to the latest patched v5 release
npm install dd-trace@^5.131.1

For environments where upgrading the dd-trace package dependency and redeploying the build artifact cannot be performed immediately, administrators can apply an immediate hotfix via environment configuration. By overriding the DD_TRACE_OBFUSCATION_QUERY_STRING_REGEXP environment variable with a hardened regular expression that uses lookbehind assertions (?:(?<![\w-])|(?<=%[0-9a-f]{2})) instead of capturing groups, the ReDoS vector is mitigated without altering the underlying url.js replacement code:

export DD_TRACE_OBFUSCATION_QUERY_STRING_REGEXP='(?:(?:"|%22)?)(?:(?:old[-_]?|new[-_]?)?p(?:ass)?w(?:or)?d(?:1|2)?|pass(?:[-_]?phrase)?|secret|(?:api[-_]?|private[-_]?|public[-_]?|access[-_]?|secret[-_]?|app(?:lication)?[-_]?)key(?:[-_]?id)?|token|consumer[-_]?(?:id|key|secret)|sign(?:ed|ature)?|auth(?:entication|orization)?)(?:(?:\s|%20)*(?:=|%3D)[^&]+|(?:"|%22)(?:\s|%20)*(?::|%3A)(?:\s|%20)*(?:"|%22)(?:%2[^2]|%[^2]|[^"%])+(?:"|%22))|(?:bearer(?:\s|%20)+[a-z0-9._\-]+|token(?::|%3A)[a-z0-9]{13}|gh[opsu]_[0-9a-zA-Z]{36}|(?:(?<![\w-])|(?<=%[0-9a-f]{2}))ey[I-L][\w-]+(?:=|%3D)*\.ey[I-L][\w-]+(?:=|%3D)*(?:\.(?:[\w.+/=-]|%3D|%2F|%2B)+)?|-{5}BEGIN(?:[a-z\s]|%20)+PRIVATE(?:\s|%20)KEY-{5}[^\-]+-{5}END(?:[a-z\s]|%20)+PRIVATE(?:\s|%20)KEY(?:-{5})?(?:\n|%0A)?|(?:ssh-(?:rsa|dss)|ecdsa-[a-z0-9]+-[a-z0-9]+)(?:\s|%20|%09)+(?:[a-z0-9/.+]|%2F|%5C|%2B){100,}(?:=|%3D)*(?:(?:\s|%20|%09)+[a-z0-9._-]+)?)'

> [!NOTE] > When applying the environment variable workaround on unpatched versions of dd-trace, you must use the non-capturing lookbehind syntax (?:(?<![\w-])|(?<=%[0-9a-f]{2})) shown above rather than the capturing group (^|[^\w%-]|%[0-9a-f]{2}) used in the v5.131.1/v6.20.1 source code. Unpatched versions replace the entire match with <redacted> rather than $1<redacted>, which would otherwise strip the delimiter character preceding a JWT.

Alternatively, if query string parameters are not needed in APM trace metadata, teams can bypass the regular expression engine entirely either by setting DD_TRACE_OBFUSCATION_QUERY_STRING_REGEXP='.*' (which triggers a fast-path boolean redaction of the entire query string in getQsObfuscator) or by disabling query string collection in the tracer initialization options.

Official Patches

DatadogPull Request #10675: fix(http): update default query string obfuscation regex
Datadogdd-trace Release v5.131.1
Datadogdd-trace Release v6.20.1

Fix Analysis (2)

Technical Appendix

CVSS Score
8.7/ 10
CVSS:4.0/AV:N/AC:L/AT:N/PR:N/UI:N/VC:N/VI:N/VA:H/SC:N/SI:N/SA:N

Affected Systems

Datadog Node.js APM Tracer (dd-trace) >= 2.0.0, < 5.131.1Datadog Node.js APM Tracer (dd-trace) >= 6.0.0, < 6.20.1

Affected Versions Detail

Product
Affected Versions
Fixed Version
dd-trace
Datadog
>= 2.0.0, < 5.131.15.131.1
dd-trace
Datadog
>= 6.0.0, < 6.20.16.20.1
AttributeDetail
CVE IDCVE-2026-116693 (GHSA-x94g-w73q-hpcw)
Vulnerability ClassCWE-1333: Inefficient Regular Expression Complexity (ReDoS)
Affected Componentdd-trace (npm) URL Query String Obfuscator (obfuscateQs)
Attack VectorNetwork (Unauthenticated HTTP/HTTPS Requests)
CVSS v4.0 Score8.7 High (AV:N/AC:L/AT:N/PR:N/UI:N/VC:N/VI:N/VA:H/SC:N/SI:N/SA:N)
Security ImpactNode.js Event Loop Starvation / Application Denial of Service
Patched Versions5.131.1, 6.20.1
CISA KEV StatusNot Listed

MITRE ATT&CK Mapping

T1499Endpoint Denial of Service
Impact
T1499.004Application Exhaustion Flood
Impact
CWE-1333
Inefficient Regular Expression Complexity

The product uses a regular expression that can take an exponential or polynomial amount of time to evaluate relative to the size of the input, enabling Regular Expression Denial of Service (ReDoS).

Vulnerability Timeline

Fix Pull Request #10675 created and merged into DataDog/dd-trace-js.
2026-10-07
Patched versions v5.131.1 and v6.20.1 tagged and published to npm.
2026-10-08
GitHub Security Advisory GHSA-x94g-w73q-hpcw and CVE-2026-116693 publicly disclosed.
2026-10-27

References & Sources

  • [1]GitHub Security Advisory GHSA-x94g-w73q-hpcw
  • [2]Official CVE Record: CVE-2026-116693
  • [3]NVD Vulnerability Detail: CVE-2026-116693
  • [4]GitHub Pull Request #10675: fix(http): update default query string obfuscation regex
  • [5]Fix Commit (v6 branch - 5eeee790c93036a50549056fc890028cb4c86b1b)
  • [6]Fix Commit (v5 branch - cf4e68a45fa1442c9850f2086c81901258e821b8)
  • [7]Datadog dd-trace Release v5.131.1
  • [8]Datadog dd-trace Release v6.20.1

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

•about 2 hours ago•CVE-2026-116692
9.8

CVE-2026-116692: Remote Code Execution in MLflow via Third-Party Scorer Deserialization

CVE-2026-116692 (GHSA-26p8-2jq9-3vq9) is a remote code execution vulnerability in MLflow affecting versions 3.12.0rc0 prior to 3.17.0. The flaw stems from an overly permissive module prefix check during the deserialization of third-party GenAI evaluation scorers in mlflow/genai/scorers/base.py. By setting an experiment's artifact root to a local package directory within the Python module search path and uploading a crafted Python file as a run artifact, an attacker can invoke the /ajax-api/3.0/mlflow/scorer/invoke endpoint to dynamically import and execute arbitrary code on the MLflow tracking server.

Amit Schendel
Amit Schendel
5 views•9 min read
•about 3 hours ago•CVE-2026-116691
6.5

CVE-2026-116691: Cleartext LLM Provider API Key Disclosure in MLflow CrewAI Autologging

CVE-2026-116691 (GHSA-j7qq-vr8c-xvw3) is a sensitive credential disclosure vulnerability in the MLflow platform affecting versions 2.19.0 through 3.16.x. When CrewAI autologging is enabled via mlflow.crewai.autolog(), the tracing instrumentation fails to sanitize nested CrewAI LLM objects before serializing them into OpenTelemetry trace spans. Consequently, plaintext LLM provider API keys are extracted from object dictionaries and string representations, then transmitted and stored in MLflow tracking servers or external OpenTelemetry Protocol (OTLP) telemetry backends.

Alon Barad
Alon Barad
4 views•12 min read
•about 4 hours ago•CVE-2026-116690
7.5

CVE-2026-116690: Arbitrary File Read via Prompt Model Version Source in MLflow

MLflow versions 3.10.0 through 3.16.1 contain a path traversal vulnerability (CWE-22) in the model version creation handler. Specifically, the prompt-specific execution branch in `_create_model_version()` fails to validate schemeless relative paths and evaluates the `mlflow.prompt.is_prompt` tag based on key presence rather than value. An unauthenticated remote attacker on default deployments, or an authenticated low-privilege user on basic-auth deployments, can register a model version with a relative local path as its artifact source and subsequently retrieve arbitrary files from the server filesystem via the `/api/2.0/mlflow/model-versions/get-artifact` endpoint.

Alon Barad
Alon Barad
10 views•9 min read
•about 5 hours ago•CVE-2026-109383
7.4

CVE-2026-109383: Improper Certificate Validation in Node.js Undici Agent Dispatcher

CVE-2026-109383 (GHSA-2m5v-pch6-74hx) is an improper certificate validation vulnerability (CWE-295) in undici, the official HTTP/1.1 and HTTP/2 client library for Node.js. In affected versions, the Agent constructor clones configuration options using a JSON-based deep clone function (util.deepClone), which executes JSON.parse(JSON.stringify(options)). Because JSON serialization omits function properties, custom certificate validation callbacks passed via the tls configuration option—such as tls.checkServerIdentity—are silently stripped before being passed to origin connection pools. Consequently, connections fall back to standard Node.js TLS validation, bypassing custom certificate pinning or hostname verification rules and allowing an Adversary-in-the-Middle (AitM) with a CA-trusted certificate to intercept and modify traffic.

Alon Barad
Alon Barad
6 views•10 min read
•about 6 hours ago•CVE-2026-109829
7.4

CVE-2026-109829: Persistent Cache Poisoning and Cross-User Information Disclosure in Node.js Undici

A cache key origin desynchronization and intermediate Cache-Control suppression vulnerability exists in the Node.js Undici HTTP client library. When an originless Agent composes the redirect and cache interceptors in the order compose(redirect(), cache()) with a shared cache store, cross-origin responses and sensitive redirected resources are stored under the initial request's cache key.

Alon Barad
Alon Barad
8 views•11 min read
•about 7 hours ago•CVE-2026-109855
7.5

CVE-2026-109855: Denial of Service via Unhandled Stream Error in Node.js Undici HTTP/2 WebSockets

CVE-2026-109855 is a high-severity Denial of Service (DoS) vulnerability in undici, the primary HTTP/1.1 and HTTP/2 client library for Node.js maintained under the OpenJS Foundation. In versions 8.11.0 and 8.11.1, the WebSocket client fails to properly terminate underlying ClientHttp2Stream instances when an HTTP/2 WebSocket handshake fails validation. When the remote server subsequently closes or resets the stream, Node.js emits an unhandled error event on the orphaned stream, crashing the client process.

Alon Barad
Alon Barad
9 views•9 min read