Skip to main content

js-yaml CVE-2026-53550

| EUVDEUVD-2026-38256 MEDIUM
Inefficient Algorithmic Complexity (CWE-407)
2026-06-15 https://github.com/nodeca/js-yaml GHSA-h67p-54hq-rp68
5.3
CVSS 3.1 · Vendor: https://github.com/nodeca/js-yaml
Share

Severity by source

Vendor (https://github.com/nodeca/js-yaml) PRIMARY
5.3 MEDIUM
AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:L
vuln.today AI
7.5 HIGH

No auth or configuration prerequisites; a single small payload blocks the entire Node.js event loop for 3+ seconds, constituting high availability impact rather than the NVD-assigned low.

3.1 AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H
4.0 AV:N/AC:L/AT:N/PR:N/UI:N/VC:N/VI:N/VA:H/SC:N/SI:N/SA:N
SUSE
MEDIUM
qualitative
Red Hat
5.3 MEDIUM
qualitative

Primary rating from Vendor (https://github.com/nodeca/js-yaml).

CVSS VectorVendor: https://github.com/nodeca/js-yaml

CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:L
Attack Vector
Network
Attack Complexity
Low
Privileges Required
None
User Interaction
None
Scope
Unchanged
Confidentiality
None
Integrity
None
Availability
Low

Lifecycle Timeline

3
Source Code Evidence Fetched
Jun 15, 2026 - 17:32 vuln.today
Analysis Generated
Jun 15, 2026 - 17:32 vuln.today
CVE Published
Jun 15, 2026 - 17:15 github-advisory
MEDIUM 5.3

Blast Radius

ecosystem impact
† from your stack dependencies † transitive graph · vuln.today resolves 4-path depth
  • 6,011 npm packages depend on js-yaml (139 direct, 5,885 indirect)

Ecosystem-wide dependent count for version 4.0.0.

DescriptionCVE.org

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); } }

AnalysisAI

Quadratic CPU exhaustion in js-yaml (npm) versions 4.1.1 and earlier allows unauthenticated remote attackers to block a Node.js event loop for multiple seconds using a crafted YAML payload under 100 KB, resulting in denial of service. The flaw lies in the merge-key parser's failure to deduplicate repeated alias references before invoking per-key processing, producing O(K×M) work from O(K+M) input. A detailed proof-of-concept with reproducible timing benchmarks is publicly available via GitHub Security Advisory GHSA-h67p-54hq-rp68; no active exploitation is confirmed in CISA KEV at time of analysis.

Technical ContextAI

js-yaml (pkg:npm/js-yaml) is a widely deployed JavaScript/Node.js YAML 1.1 parser. The vulnerability (CWE-407: Inefficient Algorithmic Complexity) is rooted in lib/loader.js in the storeMappingPair() function, which handles the YAML 1.1 merge key tag tag:yaml.org,2002:merge (commonly <<:). When a merge value is a sequence - <<: [*a, *a, ...*a] - the function iterates each element and calls mergeMappings() without first deduplicating alias references. Each mergeMappings() call performs an Object.keys(source) allocation of O(K) and K hasOwnProperty checks against the destination object. Because all M aliases resolve to the same anchored object in state.anchorMap, every call after the first is a semantic no-op, yet the computation is repeated in full. Total work is O(K×M), while input size is only O(K+M), yielding quadratic scaling. YAML 1.1 merge semantics are explicitly idempotent and commutative over duplicate sources, so deduplication is a lossless fix with no spec trade-off.

RemediationAI

Upgrade js-yaml to version 4.2.0 or later, which introduces reference deduplication in storeMappingPair() via a Set-based seen-check before invoking mergeMappings(), preserving full YAML 1.1 merge semantics. The advisory is at https://github.com/nodeca/js-yaml/security/advisories/GHSA-h67p-54hq-rp68. If an immediate upgrade is not feasible, apply an upstream payload size limit - for example, reject YAML inputs exceeding a configurable byte threshold (e.g., 16 KB for most use cases) before passing them to the parser; note this may reject legitimate large documents and requires careful threshold tuning. A second compensating control is to restrict YAML parsing to trusted internal sources only and prevent untrusted input from reaching any code path that calls js-yaml. There is no configuration flag in js-yaml itself to disable merge-key processing without modifying the library. Generic input sanitization at the application layer is not sufficient, as the malicious complexity is hidden in syntactically valid YAML.

CVE-2024-55591 CRITICAL POC
9.8 Jan 14

FortiOS and FortiProxy contain an authentication bypass via the Node.js websocket module allowing unauthenticated remote

CVE-2014-7205 CRITICAL POC
10.0 Oct 08

Eval injection vulnerability in the internals.batch function in lib/batch.js in the bassmaster plugin before 1.5.2 for t

CVE-2025-59528 CRITICAL POC
10.0 Sep 22

Flowise version 3.0.5 contains a remote code execution vulnerability in the CustomMCP node. The mcpServerConfig paramete

CVE-2017-14849 HIGH POC
7.5 Sep 28

Node.js 8.5.0 before 8.6.0 allows remote attackers to access unintended files, because a change to ".." handling was inc

CVE-2017-5941 CRITICAL POC
9.8 Feb 09

An issue was discovered in the node-serialize package 0.0.4 for Node.js. Rated critical severity (CVSS 9.8), this vulner

CVE-2014-3744 HIGH POC
7.5 Oct 23

Directory traversal vulnerability in the st module before 0.2.5 for Node.js allows remote attackers to read arbitrary fi

CVE-2014-9566 HIGH POC
7.5 Mar 10

Multiple SQL injection vulnerabilities in the Manage Accounts page in the AccountManagement.asmx service in the Solarwin

CVE-2013-4660 MEDIUM POC
6.8 Jun 28

The JS-YAML module before 2.0.5 for Node.js parses input without properly considering the unsafe !!js/function tag, whic

CVE-2015-5688 MEDIUM POC
5.0 Sep 04

Directory traversal vulnerability in lib/app/index.js in Geddy before 13.0.8 for Node.js allows remote attackers to read

CVE-2026-45321 CRITICAL POC
9.6 May 12

Credential-harvesting malware compromised 84 versions of 42 TanStack npm packages on 2026-05-11 via chained GitHub Actio

CVE-2014-7192 CRITICAL POC
10.0 Dec 11

Eval injection vulnerability in index.js in the syntax-error package before 1.1.1 for Node.js 0.10.x, as used in IBM Rat

CVE-2013-4450 MEDIUM POC
5.0 Oct 21

The HTTP server in Node.js 0.10.x before 0.10.21 and 0.8.x before 0.8.26 allows remote attackers to cause a denial of se

Vendor StatusVendor

SUSE

Severity: Moderate
Product Status
SUSE Linux Enterprise Desktop 15 SP7 Affected
SUSE Linux Enterprise High Performance Computing 12 Affected
SUSE Linux Enterprise High Performance Computing 15 SP7 Affected
SUSE Linux Enterprise High Performance Computing 15 SP7 Affected
SUSE Linux Enterprise High Performance Computing 15 SP7 Affected

Share

CVE-2026-53550 vulnerability details – vuln.today

This site uses cookies essential for authentication and security. No tracking or analytics cookies are used. Privacy Policy