CVE-2025-69873
JavaScript vulnerability analysis and mitigation

Overview

CVE-2025-69873 is a Regular Expression Denial of Service (ReDoS) vulnerability in ajv (Another JSON Schema Validator) that affects all versions up to and including 8.17.1 (v8 branch) and 6.12.6 (v6 branch). The flaw is triggered when the $data option is enabled, allowing an attacker to inject a malicious regex pattern via the pattern keyword that causes catastrophic backtracking in the JavaScript engine. The vulnerability was discovered on 2025-12-17 by Ethan Taebeom Kim of Cremit, with CVE assignment and publication occurring on 2026-02-11. The CVSS v3.1 base score is 2.9 (Low) per NVD, though the researcher and GitHub Advisory Database assign it a higher severity of 5.5 (Moderate, CVSS v4) and 7.5 (High) respectively, reflecting the real-world network-exploitable denial-of-service impact (GitHub Advisory, Researcher Disclosure).

Technical details

The root cause is classified as CWE-400 (Uncontrolled Resource Consumption) and CWE-1333 (Inefficient Regular Expression Complexity). When $data: true is configured in ajv, the pattern keyword can reference runtime data via JSON Pointer syntax (e.g., pattern: { $data: '1/pattern' }), and this user-supplied value is passed directly to the JavaScript RegExp() constructor in lib/vocabularies/validation/pattern.ts without any validation, sanitization, or complexity check. In contrast, statically defined patterns are pre-compiled at schema compilation time and are safe. An attacker who controls both the pattern field and the input value can supply a catastrophically backtracking regex such as ^(a|a)*$ paired with a crafted string (e.g., 30 a characters followed by X), causing O(2^n) evaluation time. Because Node.js is single-threaded, this blocks the entire event loop. A public proof-of-concept is available in the researcher's disclosure (Researcher Disclosure, GitHub Advisory).

Impact

Successful exploitation results in complete denial of service of the affected Node.js application. A single HTTP request containing a malicious payload (31 characters) can block the event loop for approximately 44 seconds, with each additional character doubling execution time — making sustained unavailability trivially achievable with one request per minute. Health checks fail during the blocking period, which can trigger cascading failures in load-balanced or auto-scaled environments as instances are marked unhealthy and traffic shifts to other potentially vulnerable nodes. There is no confidentiality or integrity impact; the vulnerability is purely an availability issue. The exposure is significant given ajv's position as a foundational dependency with over 170 million weekly npm downloads and 10,000+ dependent packages, though only deployments with $data: true and user-controlled pattern input are at risk (Researcher Disclosure).

Exploitability

A working proof-of-concept is publicly available in the researcher's GitHub disclosure repository, demonstrating the attack with measured timing results (Researcher Disclosure). The EPSS score is approximately 0.086% (0.000860), indicating a low but non-negligible probability of exploitation in the wild within 30 days (GitHub Advisory). No in-the-wild exploitation or threat actor attribution has been reported. The vulnerability is not listed in the CISA KEV catalog. Exploitation requires no authentication and no privileges, but does require the target application to have explicitly enabled the $data: true option and to expose an endpoint where user-controlled data influences the pattern keyword — a non-default but documented configuration.

Exploitation steps

  1. Reconnaissance: Identify API endpoints of Node.js applications that use ajv for JSON Schema validation. Look for endpoints that accept JSON payloads with fields that may be used as dynamic validation patterns (e.g., form builders, configuration APIs, multi-tenant SaaS platforms).
  2. Confirm $data usage: Probe the target API by submitting a JSON payload where a field contains a simple regex string. If the application validates the value field against a pattern field from the same payload, $data is likely enabled.
  3. Craft malicious payload: Construct a JSON body with a catastrophically backtracking regex as the pattern and a crafted input string:
{
  "pattern": "^(a|a)*$",
  "value": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaX"
}
  1. Send the attack request: Submit a single HTTP POST request with the malicious payload to the target endpoint:
POST /api/validate HTTP/1.1
Content-Type: application/json
{"pattern": "^(a|a)*$", "value": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaX"}
  1. Observe denial of service: The Node.js event loop blocks for 44+ seconds per request. Sending one request per minute is sufficient to keep the service permanently unavailable. Health check failures will cause load balancers to route traffic away from the affected instance, potentially cascading to other instances (Researcher Disclosure).

Indicators of compromise

  • Network: Repeated HTTP POST requests to validation endpoints containing JSON bodies with fields matching regex patterns like ^(a|a)*$, (a+)+, ([a-zA-Z]+)*, or other known ReDoS patterns; unusually long response times (>10 seconds) or timeouts on API endpoints that normally respond quickly.
  • Logs: Application logs showing requests that never complete or time out; Node.js process logs indicating event loop lag or unresponsiveness; load balancer logs showing health check failures coinciding with specific inbound requests.
  • Process: Node.js process consuming 99% CPU for extended periods (tens of seconds to minutes) on a single core; process appearing hung or unresponsive to signals during the blocking period.
  • Application Behavior: API endpoints returning 503/504 errors or timing out immediately after a specific request is received; health check endpoints becoming unresponsive in patterns consistent with periodic attack requests (Researcher Disclosure).

Mitigation and workarounds

The primary remediation is to upgrade ajv to version 8.18.0 (v8 branch) or 6.14.0 (v6 branch), both released in February 2026 (ajv v6.14.0 Release, GitHub Advisory). For applications that cannot immediately upgrade, the following workarounds are available in order of preference:

  1. Disable $data: Remove $data: true from ajv configuration if dynamic pattern references are not required — this eliminates the attack surface entirely.
  2. Use the RE2 engine: Configure ajv v8 to use Google's RE2 regex engine, which guarantees linear-time evaluation: new Ajv({ $data: true, code: { regExp: (pattern, flags) => new RE2(pattern, flags) } }).
  3. Pre-validate patterns with safe-regex: Before passing user-supplied patterns to ajv, validate them using the safe-regex npm package to reject potentially catastrophic patterns.
  4. Input validation: Restrict which fields can influence the pattern keyword via $data references, ensuring only trusted, pre-approved patterns are used (Researcher Disclosure). Multiple IBM products incorporating ajv have also released patches addressing this CVE (IBM Advisory).

Community reactions

The vulnerability generated notable community activity on GitHub, with the fix PR for v6 (backport) receiving 33 thumbs-up reactions and significant engagement from downstream maintainers including ESLint, AWS CDK, and Tauri, all of whom issued dependency updates (ajv PR #2588, ajv PR #2590). The ajv maintainer (epoberezkin) responded promptly, merging the v6 fix and releasing 6.14.0 within days of the PR submission. Some community members noted that the v6 fix (try/catch approach) does not fully eliminate ReDoS risk and that users must opt into the RE2 engine for comprehensive protection. IBM issued over 20 security bulletins across its product portfolio acknowledging the vulnerability in bundled ajv components, reflecting the library's broad enterprise adoption (IBM Advisory). Microsoft also acknowledged the CVE in its Security Response Center update guide.

Additional resources

Linux Distribution fix status

Fix availability across major Linux distributions and their releases.

Debian

Fixed

bookworm

node-ajv

Affected

sid

node-ajv: 8.18.0~ds+~cs6.1.1-1

Fixed

trixie

node-ajv

Affected

Ubuntu

Unknown

bionic (esm-apps)

node-ajv

Unknown

devel

node-ajv

Unknown

focal (esm-apps)

node-ajv

Unknown

jammy

node-ajv

Unknown

jammy (esm-apps)

node-ajv

Unknown

noble

node-ajv

Unknown

noble (esm-apps)

node-ajv

Unknown

resolute

node-ajv

Unknown

RHEL / CentOS

Fixed

OpenShift

el9:openshift4/ose-monitoring-plugin-rhel8-0:v4.14.0

Fixed

RHEL 8

Not Affected

RHEL 9

Not Affected

RHEL 10

Not Affected

SourceThis report was generated using AI

Related JavaScript vulnerabilities:

CVE ID

Severity

Score

Technologies

Component name

CISA KEV exploit

Has fix

Published date

CVE-2026-54504HIGH8.8
  • JavaScript logoJavaScript
  • @andrea9293/mcp-documentation-server
NoYesSep 17, 2026
CVE-2026-77615HIGH8.7
  • JavaScript logoJavaScript
  • paella-core
NoYesSep 17, 2026
CVE-2026-91127HIGH8.2
  • JavaScript logoJavaScript
  • @file-viewer/doc
NoYesSep 18, 2026
CVE-2026-77301HIGH7.5
  • JavaScript logoJavaScript
  • adm-zip
NoYesSep 18, 2026
CVE-2026-84992MEDIUM6.1
  • JavaScript logoJavaScript
  • md-editor-v3
NoYesSep 18, 2026

Free Vulnerability Assessment

Benchmark your Cloud Security Posture

Evaluate your cloud security practices across 9 security domains to benchmark your risk level and identify gaps in your defenses.

Request assessment

Get a personalized demo

Ready to see Wiz in action?

"Best User Experience I have ever seen, provides full visibility to cloud workloads."
David EstlickCISO
"Wiz provides a single pane of glass to see what is going on in our cloud environments."
Adam FletcherChief Security Officer
"We know that if Wiz identifies something as critical, it actually is."
Greg PoniatowskiHead of Threat and Vulnerability Management