CVE-2026-53550

ADVISORY - github

Summary

Summary

A crafted YAML document can trigger algorithmic CPU exhaustion in js-yaml merge-key processing (<<) by repeating the same alias many times in a merge sequence.
This causes quadratic parse-time behavior relative to input size and can block a Node.js worker/event loop for seconds with a relatively small payload (tens of KB), resulting in denial of service.

Details

The issue is in merge handling inside lib/loader.js:

  • storeMappingPair(...) iterates every element of a merge sequence when key tag is tag:yaml.org,2002:merge.
  • For each element, it calls mergeMappings(...).
  • mergeMappings(...) computes Object.keys(source) and performs _hasOwnProperty.call(destination, key) checks for each key.

When input is of the form:

a: &a {k0:0, k1:0, ..., kK:0} b: {<<: [*a, *a, *a, ... repeated M times ...]} all *a entries refer to the same anchored object. After the first merge, subsequent merges are semantically no-ops, but the parser still reprocesses all keys each time. Resulting work is O(K * M), while input size is O(K + M), giving quadratic scaling as payload grows. Relevant code path: lib/loader.js in storeMappingPair(...) merge branch (keyTag === 'tag:yaml.org,2002:merge') lib/loader.js mergeMappings(...)

Root cause

File: lib/loader.js Function: storeMappingPair(state, _result, overridableKeys, keyTag, keyNode, valueNode, startLine, startLineStart, startPos) Lines: ~359-366

if (keyTag === 'tag:yaml.org,2002:merge') {
  if (Array.isArray(valueNode)) {
    for (index = 0, quantity = valueNode.length; index < quantity; index += 1) {
      mergeMappings(state, _result, valueNode[index], overridableKeys);
    }
  } else {
    mergeMappings(state, _result, valueNode, overridableKeys);
  }
}

When the merge value is a sequence (YAML 1.1 <<: [ *a, *a, ... ]), each element is handed to mergeMappings() without deduplication. mergeMappings() then does

sourceKeys = Object.keys(source);
for (index = 0; index < sourceKeys.length; index += 1) {
  key = sourceKeys[index];
  if (!_hasOwnProperty.call(destination, key)) {
    setProperty(destination, key, source[key]);
    overridableKeys[key] = true;
  }
}

Every alias reference in the sequence resolves (by design) to the SAME object via state.anchorMap. After the first merge, every subsequent merge of that same reference is a pure no-op semantically, but still performs:

  • one Object.keys(source) call (O(K))
  • K _hasOwnProperty.call checks on the destination

Total: M * K hasOwnProperty checks + M Object.keys allocations, while the final object and all observable side effects are identical to a single merge.

YAML semantics for <<: are idempotent and commutative over duplicate sources, so collapsing duplicates preserves behavior exactly; this isn't a spec trade-off.

PoC

Environment: js-yaml version: 4.1.1 Node.js: v24.5.0 Platform: arm64 macOS (reproduced consistently) Reproduction script: Create many keys in one anchored map (&a). Merge that same alias repeatedly via <<: [*a, *a, ...]. Measure parse time and compare with control payload using single merge (<<: *a). Observed repeated runs (same machine): K=M=1000, input 9,909 bytes: ~33–36 ms K=M=2000, input 20,909 bytes: ~121–123 ms K=M=4000, input 42,909 bytes: ~524–537 ms K=M=6000, input 64,909 bytes: ~1,608–1,829 ms K=M=8000, input 86,909 bytes: ~3,395–3,565 ms Control (single merge, similar key counts): K=2000: ~1–2 ms K=4000: ~3 ms K=8000: ~5 ms Also verified: repeated-merge output equals single-merge output (same key count and same JSON), confirming excess time is redundant computation.

Impact

This is a denial-of-service vulnerability (CPU exhaustion / algorithmic complexity). Any service parsing untrusted YAML with js-yaml can be impacted, including API backends, CI tools, config processors, and automation services. An attacker can submit crafted YAML to significantly increase CPU time and reduce availability.

Suggested fix:

Dedupe the merge source list by reference before invoking mergeMappings. Any of the following are minimal and preserve YAML 1.1 merge semantics:

dedupe in storeMappingPair:

if (keyTag === 'tag:yaml.org,2002:merge') {
  if (Array.isArray(valueNode)) {
    var seen = new Set();
    for (index = 0, quantity = valueNode.length; index < quantity; index += 1) {
      var src = valueNode[index];
      if (seen.has(src)) continue;   // idempotent; skip redundant alias
      seen.add(src);
      mergeMappings(state, _result, src, overridableKeys);
    }
  } else {
    mergeMappings(state, _result, valueNode, overridableKeys);
  }
}

Common Weakness Enumeration (CWE)

ADVISORY - github

Inefficient Algorithmic Complexity


GitHub

CREATED

UPDATED

EXPLOITABILITY SCORE

3.9

EXPLOITS FOUND
-
COMMON WEAKNESS ENUMERATION (CWE)

CVSS SCORE

5.3medium
PackageTypeOS NameOS VersionAffected RangesFix Versions
js-yamlnpm--<=4.1.14.2.0

CVSS:3 Severity and metrics

The CVSS metrics represent different qualitative aspects of a vulnerability that impact the overall score, as defined by the CVSS Specification.

The vulnerable component is bound to the network stack, but the attack is limited at the protocol level to a logically adjacent topology. This can mean an attack must be launched from the same shared physical (e.g., Bluetooth or IEEE 802.11) or logical (e.g., local IP subnet) network, or from within a secure or otherwise limited administrative domain (e.g., MPLS, secure VPN to an administrative network zone). One example of an Adjacent attack would be an ARP (IPv4) or neighbor discovery (IPv6) flood leading to a denial of service on the local LAN segment (e.g., CVE-2013-6014).

Specialized access conditions or extenuating circumstances do not exist. An attacker can expect repeatable success when attacking the vulnerable component.

The attacker is unauthorized prior to attack, and therefore does not require any access to settings or files of the vulnerable system to carry out an attack.

The vulnerable system can be exploited without interaction from any user.

An exploited vulnerability can only affect resources managed by the same security authority. In this case, the vulnerable component and the impacted component are either the same, or both are managed by the same security authority.

There is no loss of confidentiality.

There is no loss of trust or accuracy within the impacted component.

Performance is reduced or there are interruptions in resource availability. Even if repeated exploitation of the vulnerability is possible, the attacker does not have the ability to completely deny service to legitimate users. The resources in the impacted component are either partially available all of the time, or fully available only some of the time, but overall there is no direct, serious consequence to the impacted component.

Chainguard

CREATED

UPDATED

ADVISORY ID

CGA-hxp5-835r-fjv4

EXPLOITABILITY SCORE

-

EXPLOITS FOUND
-
COMMON WEAKNESS ENUMERATION (CWE)-
RATING UNAVAILABLE FROM ADVISORY

minimos

CREATED

UPDATED

ADVISORY ID

MINI-272r-8h37-wjj7

EXPLOITABILITY SCORE

-

EXPLOITS FOUND
-
COMMON WEAKNESS ENUMERATION (CWE)-
RATING UNAVAILABLE FROM ADVISORY

minimos

CREATED

UPDATED

ADVISORY ID

MINI-364m-8wpj-xm89

EXPLOITABILITY SCORE

-

EXPLOITS FOUND
-
COMMON WEAKNESS ENUMERATION (CWE)-
RATING UNAVAILABLE FROM ADVISORY

minimos

CREATED

UPDATED

ADVISORY ID

MINI-7qfg-7mpw-rf3v

EXPLOITABILITY SCORE

-

EXPLOITS FOUND
-
COMMON WEAKNESS ENUMERATION (CWE)-
RATING UNAVAILABLE FROM ADVISORY

minimos

CREATED

UPDATED

ADVISORY ID

MINI-888p-c7xg-5wx7

EXPLOITABILITY SCORE

-

EXPLOITS FOUND
-
COMMON WEAKNESS ENUMERATION (CWE)-
RATING UNAVAILABLE FROM ADVISORY

minimos

CREATED

UPDATED

ADVISORY ID

MINI-8qmv-8f9f-5w8v

EXPLOITABILITY SCORE

-

EXPLOITS FOUND
-
COMMON WEAKNESS ENUMERATION (CWE)-
RATING UNAVAILABLE FROM ADVISORY

minimos

CREATED

UPDATED

ADVISORY ID

MINI-9g35-c55q-6pp7

EXPLOITABILITY SCORE

-

EXPLOITS FOUND
-
COMMON WEAKNESS ENUMERATION (CWE)-
RATING UNAVAILABLE FROM ADVISORY

minimos

CREATED

UPDATED

ADVISORY ID

MINI-gppc-q7x2-vvc9

EXPLOITABILITY SCORE

-

EXPLOITS FOUND
-
COMMON WEAKNESS ENUMERATION (CWE)-
RATING UNAVAILABLE FROM ADVISORY

minimos

CREATED

UPDATED

ADVISORY ID

MINI-gvw3-65xm-2q4v

EXPLOITABILITY SCORE

-

EXPLOITS FOUND
-
COMMON WEAKNESS ENUMERATION (CWE)-
RATING UNAVAILABLE FROM ADVISORY

minimos

CREATED

UPDATED

ADVISORY ID

MINI-m4pr-jrc6-pwfg

EXPLOITABILITY SCORE

-

EXPLOITS FOUND
-
COMMON WEAKNESS ENUMERATION (CWE)-
RATING UNAVAILABLE FROM ADVISORY

minimos

CREATED

UPDATED

ADVISORY ID

MINI-mcgr-2qcc-rrw8

EXPLOITABILITY SCORE

-

EXPLOITS FOUND
-
COMMON WEAKNESS ENUMERATION (CWE)-
RATING UNAVAILABLE FROM ADVISORY

minimos

CREATED

UPDATED

ADVISORY ID

MINI-q3wh-9pw7-xxhx

EXPLOITABILITY SCORE

-

EXPLOITS FOUND
-
COMMON WEAKNESS ENUMERATION (CWE)-
RATING UNAVAILABLE FROM ADVISORY

minimos

CREATED

UPDATED

ADVISORY ID

MINI-v6cr-h2ch-jqrh

EXPLOITABILITY SCORE

-

EXPLOITS FOUND
-
COMMON WEAKNESS ENUMERATION (CWE)-
RATING UNAVAILABLE FROM ADVISORY

minimos

CREATED

UPDATED

ADVISORY ID

MINI-x3hq-j2f7-m3p5

EXPLOITABILITY SCORE

-

EXPLOITS FOUND
-
COMMON WEAKNESS ENUMERATION (CWE)-
RATING UNAVAILABLE FROM ADVISORY