Skip to content

Update dependency js-yaml to v4.2.0 [SECURITY]#222

Merged
wbaldoumas merged 1 commit into
mainfrom
renovate/npm-js-yaml-vulnerability
Jun 28, 2026
Merged

Update dependency js-yaml to v4.2.0 [SECURITY]#222
wbaldoumas merged 1 commit into
mainfrom
renovate/npm-js-yaml-vulnerability

Conversation

@renovate

@renovate renovate Bot commented Nov 15, 2025

Copy link
Copy Markdown
Contributor

This PR contains the following updates:

Package Change Age Confidence
js-yaml 4.1.04.2.0 age confidence

js-yaml has prototype pollution in merge (<<)

CVE-2025-64718 / GHSA-mh29-5h37-fv8m

More information

Details

Impact

In js-yaml 4.1.0, 4.0.0, and 3.14.1 and below, it's possible for an attacker to modify the prototype of the result of a parsed yaml document via prototype pollution (__proto__). All users who parse untrusted yaml documents may be impacted.

Patches

Problem is patched in js-yaml 4.1.1 and 3.14.2.

Workarounds

You can protect against this kind of attack on the server by using node --disable-proto=delete or deno (in Deno, pollution protection is on by default).

References

https://cheatsheetseries.owasp.org/cheatsheets/Prototype_Pollution_Prevention_Cheat_Sheet.html

Severity

  • CVSS Score: 5.3 / 10 (Medium)
  • Vector String: CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:L/A:N

References

This data is provided by the GitHub Advisory Database (CC-BY 4.0).


JS-YAML: Quadratic-complexity DoS in merge key handling via repeated aliases

CVE-2026-53550 / GHSA-h67p-54hq-rp68

More information

Details

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

Severity

  • CVSS Score: 5.3 / 10 (Medium)
  • Vector String: CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:L

References

This data is provided by the GitHub Advisory Database (CC-BY 4.0).


Release Notes

nodeca/js-yaml (js-yaml)

v4.2.0

Compare Source

Added
  • Added docs/safety.md with notes about processing untrusted YAML.
  • Added maxDepth (100) loader option. Not a problem, but gives a better
    exception instead of RangeError on stack overflow.
  • Added maxMergeSeqLength (20) loader option. Not a problem after merge fix,
    but an additional restriction for safety.
  • Added sourcemaps to dist/ builds.
Changed
  • Stop resolving numbers with underscores as numeric scalars, #​627.
  • Switched dev toolchains to Vite / neostandard.
  • Updated demo.
  • Reorganized tests.
  • dist/ files are no longer kept in the repository.
Fixed
  • Fix parsing of properties on the first implicit block mapping key, #​62.
  • Fix trailing whitespace handling when folding flow scalar lines, #​307.
  • Reject top-level block scalars without content indentation, #​280.
  • Ensure numbers survive round-trip, #​737.
  • Fix test coverage for issue #​221.
  • Fix flow scalar trailing whitespace folding, #​307.
  • Fix digits in YAML named tag handles.
Security
  • Fix potential DoS via quadratic complexity in merge - deduplicate repeated
    elements (makes sense for malformed files > 10K).

v4.1.1

Compare Source

Security
  • Fix prototype pollution issue in yaml merge (<<) operator.

Configuration

📅 Schedule: (UTC)

  • Branch creation
    • At any time (no schedule defined)
  • Automerge
    • At any time (no schedule defined)

🚦 Automerge: Disabled by config. Please merge this manually once you are satisfied.

Rebasing: Whenever PR is behind base branch, or you tick the rebase/retry checkbox.

🔕 Ignore: Close this PR and you won't be reminded about this update again.


  • If you want to rebase/retry this PR, check this box

This PR was generated by Mend Renovate. View the repository job log.

@renovate renovate Bot added dependencies Pull requests that update a dependency file renovate labels Nov 15, 2025
@codecov

codecov Bot commented Nov 15, 2025

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 100.00%. Comparing base (ecb76ea) to head (5f202d2).

Additional details and impacted files
@@            Coverage Diff            @@
##              main      #222   +/-   ##
=========================================
  Coverage   100.00%   100.00%           
=========================================
  Files            7         7           
  Lines          112       112           
  Branches        13        13           
=========================================
  Hits           112       112           

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@renovate renovate Bot force-pushed the renovate/npm-js-yaml-vulnerability branch from 54bfdd1 to 4802168 Compare November 21, 2025 06:01
@renovate renovate Bot force-pushed the renovate/npm-js-yaml-vulnerability branch from 4802168 to 296ef9e Compare November 28, 2025 05:49
@renovate renovate Bot force-pushed the renovate/npm-js-yaml-vulnerability branch from 296ef9e to 41c4050 Compare December 12, 2025 10:01
@renovate renovate Bot force-pushed the renovate/npm-js-yaml-vulnerability branch from 41c4050 to 90d3bff Compare January 16, 2026 05:04
@renovate renovate Bot force-pushed the renovate/npm-js-yaml-vulnerability branch from 90d3bff to 209bf51 Compare January 23, 2026 05:31
@renovate renovate Bot force-pushed the renovate/npm-js-yaml-vulnerability branch from 209bf51 to 2b9ec63 Compare February 2, 2026 17:28
@renovate renovate Bot force-pushed the renovate/npm-js-yaml-vulnerability branch from 2b9ec63 to 5a543d2 Compare February 13, 2026 05:44
@renovate renovate Bot force-pushed the renovate/npm-js-yaml-vulnerability branch from 5a543d2 to fe1efac Compare February 20, 2026 04:39
@renovate renovate Bot force-pushed the renovate/npm-js-yaml-vulnerability branch from fe1efac to 7983469 Compare February 27, 2026 05:13
@renovate renovate Bot force-pushed the renovate/npm-js-yaml-vulnerability branch from 7983469 to 98ed2d6 Compare March 13, 2026 06:16
@renovate renovate Bot force-pushed the renovate/npm-js-yaml-vulnerability branch from 98ed2d6 to b07641b Compare March 13, 2026 09:54
@renovate renovate Bot force-pushed the renovate/npm-js-yaml-vulnerability branch from b07641b to 8f31159 Compare March 20, 2026 05:39
@renovate renovate Bot changed the title Update dependency js-yaml to v4.1.1 [SECURITY] Update dependency js-yaml to v4.1.1 [SECURITY] - autoclosed Mar 27, 2026
@renovate renovate Bot closed this Mar 27, 2026
@renovate renovate Bot changed the title Update dependency js-yaml to v4.1.1 [SECURITY] - autoclosed Update dependency js-yaml to v4.1.1 [SECURITY] Mar 30, 2026
@renovate renovate Bot reopened this Mar 30, 2026
@renovate renovate Bot force-pushed the renovate/npm-js-yaml-vulnerability branch 2 times, most recently from 8f31159 to 023194a Compare March 30, 2026 17:50
@renovate renovate Bot force-pushed the renovate/npm-js-yaml-vulnerability branch from 023194a to d249b45 Compare April 10, 2026 05:12
@renovate renovate Bot force-pushed the renovate/npm-js-yaml-vulnerability branch from d249b45 to 499c746 Compare May 1, 2026 12:52
@renovate renovate Bot force-pushed the renovate/npm-js-yaml-vulnerability branch from 499c746 to be6411e Compare May 8, 2026 08:55
@renovate renovate Bot force-pushed the renovate/npm-js-yaml-vulnerability branch from be6411e to 2b62a0e Compare May 15, 2026 04:30
@renovate renovate Bot force-pushed the renovate/npm-js-yaml-vulnerability branch from 2b62a0e to 2c541db Compare May 22, 2026 04:35
@renovate renovate Bot force-pushed the renovate/npm-js-yaml-vulnerability branch from 2c541db to ad493ee Compare May 29, 2026 07:14
@renovate renovate Bot force-pushed the renovate/npm-js-yaml-vulnerability branch from ad493ee to fd73118 Compare June 12, 2026 05:09
github-actions[bot]
github-actions Bot previously approved these changes Jun 12, 2026
@renovate renovate Bot changed the title Update dependency js-yaml to v4.1.1 [SECURITY] Update dependency js-yaml to v4.2.0 [SECURITY] Jun 22, 2026
@renovate renovate Bot force-pushed the renovate/npm-js-yaml-vulnerability branch from fd73118 to 95e2ca4 Compare June 22, 2026 11:10
@renovate renovate Bot force-pushed the renovate/npm-js-yaml-vulnerability branch from 95e2ca4 to c763806 Compare June 22, 2026 17:56
@renovate renovate Bot force-pushed the renovate/npm-js-yaml-vulnerability branch from c763806 to 5f202d2 Compare June 26, 2026 08:03
@wbaldoumas wbaldoumas merged commit 6b9e1f2 into main Jun 28, 2026
9 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

dependencies Pull requests that update a dependency file renovate

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant