CVE-2026-84375 Overview
CVE-2026-84375 is a resource exhaustion vulnerability [CWE-400] in js-yaml, a widely used JavaScript YAML parser and dumper maintained by the nodeca project. The flaw affects versions from 3.0.0 up to (but not including) 3.15.2 and 4.3.2. The maxTotalMergeKeys guard in lib/js-yaml/loader.js and lib/loader.js fails to count empty mapping sources during YAML merge key (<<) processing. An attacker can craft a small YAML document that aliases a large sequence of empty mappings into many merge targets, driving O(N * K) work while totalMergeKeys never advances toward the configured limit.
Critical Impact
A small, attacker-controlled YAML document can trigger prolonged CPU consumption in any application that parses untrusted YAML with js-yaml, since merge processing is enabled by default on the affected release lines.
Affected Products
- js-yaml versions 3.0.0 through 3.15.1
- js-yaml versions 4.0.0 through 4.3.1
- Node.js applications and build tooling that parse untrusted YAML using vulnerable js-yaml releases
Discovery Timeline
- 2026-09-01 - CVE-2026-84375 published to NVD
- 2026-09-02 - Last updated in NVD database
Technical Details for CVE-2026-84375
Vulnerability Analysis
The vulnerability is an algorithmic complexity flaw in the YAML merge key implementation. YAML supports a merge key operator (<<) that folds keys from one or more source mappings into a target mapping. js-yaml implements a maxTotalMergeKeys guard intended to bound the total merge work per document by counting keys folded into targets. Because the counter only increments per source key, a source that contributes zero keys costs nothing against the budget while still consuming per-source processing time.
By aliasing a single sequence of many empty mappings and reusing that alias as the merge source in many target mappings, an attacker forces js-yaml to iterate every source for every target. Processing scales as O(N * K) where N is the number of empty sources and K is the number of merge targets, yet totalMergeKeys remains at zero. The parser proceeds until the event loop is starved.
Root Cause
The root cause is that mergeMappings (and the TypeScript mergeKeys in the v5 line) only charged the totalMergeKeys counter inside the per-key loop. Empty source mappings never entered that loop, so their per-source processing cost was invisible to the resource limit.
Attack Vector
Exploitation is network-reachable and requires no privileges or user interaction. Any endpoint that deserializes attacker-controlled YAML through js-yaml.load or js-yaml.safeLoad is exposed. Typical exposure includes configuration ingestion APIs, CI/CD systems, Kubernetes-adjacent tooling, and web services accepting YAML payloads.
// Patch: lib/js-yaml/loader.js (backport from v5.4.1)
// Adds chargeMergeWork() so the source mapping itself
// is counted against maxTotalMergeKeys, bounding empty sources.
function chargeMergeWork(state) {
state.totalMergeKeys += 1;
if (state.maxTotalMergeKeys !== -1 && state.totalMergeKeys > state.maxTotalMergeKeys) {
throwError(state, 'merge keys exceeded maxTotalMergeKeys (' + state.maxTotalMergeKeys + ')');
}
}
function mergeMappings(state, destination, source, overridableKeys) {
var sourceKeys, key, index, quantity;
if (!common.isObject(source)) {
throwError(state, 'cannot merge mappings; the provided source object is unacceptable');
}
// Count the source mapping itself to bound sequences of empty mappings.
chargeMergeWork(state);
sourceKeys = Object.keys(source);
for (index = 0, quantity = sourceKeys.length; index < quantity; index += 1) {
key = sourceKeys[index];
chargeMergeWork(state);
// ...
}
}
Source: GitHub Commit 3485bc0
Detection Methods for CVE-2026-84375
Indicators of Compromise
- Node.js processes hosting YAML-parsing services showing sustained single-thread CPU saturation shortly after receiving a small request payload.
- Elevated request latency or event-loop lag correlated with inbound YAML content containing the merge key token << and repeated aliases (for example *x).
- Application logs showing timeouts or watchdog kills of workers that recently invoked js-yaml.load on untrusted input.
Detection Strategies
- Inventory dependencies using npm ls js-yaml or lockfile scans to identify direct and transitive usage of vulnerable versions.
- Add software composition analysis rules that flag js-yaml < 3.15.2 and js-yaml >= 4.0.0 < 4.3.2 in application manifests and container images.
- Instrument YAML parsing paths to record input size, wall-clock parse duration, and merge key counts, then alert on outliers where parse time is disproportionate to payload size.
Monitoring Recommendations
- Track per-endpoint CPU time and Node.js event-loop delay metrics for services that accept YAML input.
- Log and rate-limit requests whose bodies contain YAML merge keys (<<) combined with anchors (&) and aliases (*).
- Correlate build system and CI job failures against YAML inputs to catch exploitation attempts against pipeline tooling.
How to Mitigate CVE-2026-84375
Immediate Actions Required
- Upgrade js-yaml to 3.15.2 on the v3 line or 4.3.2 on the v4 line across all applications, build systems, and container images.
- Audit transitive dependencies with npm audit or yarn audit and force resolutions on packages that pin older js-yaml versions.
- Impose request size limits, parse timeouts, and worker isolation on any service that deserializes untrusted YAML.
Patch Information
The fix is delivered in js-yaml 3.15.2 and js-yaml 4.3.2. The patches introduce a chargeMergeWork helper that charges one unit against maxTotalMergeKeys for every source mapping processed, including empty ones. See the GitHub Security Advisory GHSA-2883-xcg3-v3hh and Pull Request 797 for the full change set.
Workarounds
- Where upgrading is not immediately possible, reject YAML documents containing merge keys (<<) before invoking the parser.
- Lower the configured maxTotalMergeKeys value and enforce a strict wall-clock timeout around js-yaml.load calls processing untrusted input.
- Run YAML parsing in a short-lived worker thread or child process so a runaway parse can be terminated without impacting the main event loop.
# Upgrade js-yaml to a fixed release
npm install js-yaml@3.15.2 # v3.x line
npm install js-yaml@4.3.2 # v4.x line
# Verify installed versions across the dependency tree
npm ls js-yaml
# Force a resolution for transitive dependencies (package.json)
# "overrides": { "js-yaml": "4.3.2" }
Disclaimer: This content was generated using AI. While we strive for accuracy, please verify critical information with official sources.

