Skip to content

chore(deps): update dependency js-yaml@<3.15.0 to v4 [security] - #2271

Open
renovate[bot] wants to merge 1 commit into
mainfrom
renovate/npm-js-yaml-3.15.0-vulnerability
Open

chore(deps): update dependency js-yaml@<3.15.0 to v4 [security]#2271
renovate[bot] wants to merge 1 commit into
mainfrom
renovate/npm-js-yaml-3.15.0-vulnerability

Conversation

@renovate

@renovate renovate Bot commented Aug 12, 2026

Copy link
Copy Markdown
Contributor

This PR contains the following updates:

Package Change Age Confidence
js-yaml@<3.15.0 ^3.15.0^4.3.1 age confidence

JS-YAML: Quadratic CPU consumption in !!omap resolution (3.x and 4.x) — CVE-2026-59870 fix not backported

GHSA-5p4m-2wfm-xmqj

More information

Details

Quadratic CPU consumption in !!omap resolution (js-yaml 3.x and 4.x)
Summary

resolveYamlOmap() enforces key uniqueness for !!omap sequences with a linear
scan (objectKeys.indexOf(...)) inside the per-element loop, making resolution
O(n²) in the number of entries. A modestly sized YAML document therefore
consumes disproportionate CPU inside yaml.load(), giving a denial of service
against any consumer that parses untrusted YAML.

!!omap is registered in the default schema
(lib/schema/default.jsrequire('../type/omap')), so a plain
yaml.load(untrustedInput) with no options is affected — no custom schema or
non-default configuration is required.

This is the same weakness as CVE-2026-59870 / GHSA-724g-mxrg-4qvm, which was
fixed in the 5.x line in 5.2.1. That fix was never backported: both currently
maintained legacy lines still carry the original implementation.

Affected versions
Line Latest tested Status
3.x 3.15.0 Affected — objectKeys.indexOf(pairKey) at lib/type/omap.js:29
4.x 4.3.0 Affected — objectKeys.indexOf(pairKey) at lib/type/omap.js:30
5.x 5.2.2 Not affected — fixed in 5.2.1 (uses a Set)

Both figures are the newest release of each line at the time of writing, so
this is not a "you are on an old version" issue.

Details

lib/type/omap.js (js-yaml 4.3.0):

if (objectKeys.indexOf(pairKey) === -1) objectKeys.push(pairKey)
else return false

objectKeys grows by one element per entry, and Array.prototype.indexOf is a
linear scan, so resolving an n-entry !!omap performs roughly
1 + 2 + … + n comparisons — quadratic in n. The work happens synchronously
inside yaml.load(), blocking the event loop for its whole duration.

The 5.x line already solves exactly this by tracking seen keys in a Set
(src/tag/sequence/omap.ts):

if (carrier.seen.has(key)) return 'duplicate key in ordered map'
carrier.seen.add(key)
Proof of concept
// poc.js  —  node poc.js
const yaml = require('js-yaml');
const doc = n => '!!omap\n' + Array.from({length: n}, (_, i) => `- k${i}: ${i}`).join('\n') + '\n';

for (const n of [10000, 20000, 40000, 80000]) {
  const d = doc(n), t = Date.now();
  yaml.load(d);                      // default schema, no options
  console.log(`n=${n} bytes=${d.length} load=${Date.now() - t}ms`);
}
Measured (node v20.20.2, default heap, no flags)

js-yaml 4.3.0

n=10000  bytes=137787   load=54ms
n=20000  bytes=297787   load=169ms
n=40000  bytes=617787   load=646ms
n=80000  bytes=1257787  load=2607ms

js-yaml 3.15.0

n=10000  bytes=137787   load=53ms
n=20000  bytes=297787   load=166ms
n=40000  bytes=617787   load=641ms
n=80000  bytes=1257787  load=2567ms

Runtime grows by a factor of ~4 for each doubling of n, which is the
signature of O(n²) (linear growth would be ~2×).

Scaling further: a 2.48 MB document with 150,000 entries blocked
yaml.load() for 10.8 seconds.

Impact

Any service that parses attacker-influenced YAML with js-yaml 3.x or 4.x can be
stalled with a small input. Because the loop is synchronous, a single request
blocks the Node.js event loop and stalls every other request in the process —
so the amplification is per-process, not just per-request.

Suggested severity: consistent with CVE-2026-59870 (the same weakness in
5.x), i.e. Availability-only impact, network attack vector, no privileges or
user interaction required.

Suggested fix

Mirror the 5.x fix — replace the linear scan with a Set:

// lib/type/omap.js
const seen = new Set()
// ...
if (seen.has(pairKey)) return false
seen.add(pairKey)

This preserves the existing duplicate-key rejection semantics exactly while
making resolution O(n). A maxOmapLength-style cap would also work, but the
Set matches what 5.x already ships and requires no new option.

References
  • CVE-2026-59870 / GHSA-724g-mxrg-4qvm — same weakness in 5.0.0–5.2.0, fixed in 5.2.1
  • lib/type/omap.js (3.x, 4.x) — the affected resolver
  • lib/schema/default.js — registers !!omap in the default schema
Discovery

Found by an automated static-analysis and executed-proof-of-concept scanner run
against js-yaml 4.2.0, then manually verified against 3.15.0 and 4.3.0 by
executing the proof of concept above. All timings in this report were measured
on the current releases of each line, not on the version originally scanned.

Severity

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

References

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


Release Notes

nodeca/js-yaml (js-yaml@<3.15.0)

v4.3.1

Compare Source

v4.3.0

Compare Source

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.

v4.1.0

Compare Source

Added
  • Types are now exported as yaml.types.XXX.
  • Every type now has options property with original arguments kept as they were
    (see yaml.types.int.options as an example).
Changed
  • Schema.extend() now keeps old type order in case of conflicts
    (e.g. Schema.extend([ a, b, c ]).extend([ b, a, d ]) is now ordered as abcd instead of cbad).

v4.0.0

Compare Source

Changed
  • Check migration guide in docs for details of all breaking changes.
  • Breaking: "unsafe" tags !!js/function, !!js/regexp, !!js/undefined are
    moved to js-yaml-js-types package.
  • Breaking: removed safe* functions. Use load, loadAll, dump
    instead which are all now safe by default.
  • yaml.DEFAULT_SAFE_SCHEMA and yaml.DEFAULT_FULL_SCHEMA are removed, use
    yaml.DEFAULT_SCHEMA instead.
  • yaml.Schema.create(schema, tags) is removed, use schema.extend(tags) instead.
  • !!binary now always mapped to Uint8Array on load.
  • Reduced nesting of /lib folder.
  • Parse numbers according to YAML 1.2 instead of YAML 1.1 (01234 is now decimal,
    0o1234 is octal, 1:23 is parsed as string instead of base60).
  • dump() no longer quotes :, [, ], (, ) except when necessary, #​470, #​557.
  • Line and column in exceptions are now formatted as (X:Y) instead of
    at line X, column Y (also present in compact format), #​332.
  • Code snippet created in exceptions now contains multiple lines with line numbers.
  • dump() now serializes undefined as null in collections and removes keys with
    undefined in mappings, #​571.
  • dump() with skipInvalid=true now serializes invalid items in collections as null.
  • Custom tags starting with ! are now dumped as !tag instead of !<!tag>, #​576.
  • Custom tags starting with tag:yaml.org,2002: are now shorthanded using !!, #​258.
Added
  • Added .mjs (es modules) support.
  • Added quotingType and forceQuotes options for dumper to configure
    string literal style, #​290, #​529.
  • Added styles: { '!!null': 'empty' } option for dumper
    (serializes { foo: null } as "foo: "), #​570.
  • Added replacer option (similar to option in JSON.stringify), #​339.
  • Custom Tag can now handle all tags or multiple tags with the same prefix, #​385.
Fixed
  • Astral characters are no longer encoded by dump(), #​587.
  • "duplicate mapping key" exception now points at the correct column, #​452.
  • Extra commas in flow collections (e.g. [foo,,bar]) now throw an exception
    instead of producing null, #​321.
  • __proto__ key no longer overrides object prototype, #​164.
  • Removed bower.json.
  • Tags are now url-decoded in load() and url-encoded in dump()
    (previously usage of custom non-ascii tags may have led to invalid YAML that can't be parsed).
  • Anchors now work correctly with empty nodes, #​301.
  • Fix incorrect parsing of invalid block mapping syntax, #​418.
  • Throw an error if block sequence/mapping indent contains a tab, #​80.

v3.15.1

Compare Source


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 becomes conflicted, 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 requested a review from a team as a code owner August 12, 2026 07:01
@changeset-bot

changeset-bot Bot commented Aug 12, 2026

Copy link
Copy Markdown

⚠️ No Changeset found

Latest commit: 04cedab

Merging this PR will not cause a version bump for any packages. If these changes should not result in a new version, you're good to go. If these changes should result in a version bump, you need to add a changeset.

This PR includes no changesets

When changesets are added to this PR, you'll see the packages that this PR includes changesets for and the associated semver types

Click here to learn what changesets are, and how to add one.

Click here if you're a maintainer who wants to add a changeset to this PR

devin-ai-integration[bot]

This comment was marked as resolved.

@renovate
renovate Bot force-pushed the renovate/npm-js-yaml-3.15.0-vulnerability branch from 4bfb5da to ec1b8ed Compare August 12, 2026 07:50
@renovate renovate Bot changed the title chore(deps): update dependency js-yaml@<3.15.0 to v4 [security] chore(deps): update dependency js-yaml@<3.15.0 to v5 [security] Aug 12, 2026

@devin-ai-integration devin-ai-integration Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Devin Review found 2 new potential issues.

View 1 additional finding in Devin Review.

Open in Devin Review

Comment thread pnpm-workspace.yaml
@@ -35,7 +37,7 @@ overrides:
'lodash@<4.18.0': ^4.18.0
'protobufjs@<7.6.5': ^7.6.5
'ws@>=8.0.0 <8.21.0': ^8.21.0

@devin-ai-integration devin-ai-integration Bot Aug 12, 2026

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔴 Release/versioning tooling crashes because an old dependency is forced onto an incompatible YAML library major version

Every dependency that asked for the old 3.x YAML library is now forced onto version 4 ('js-yaml@<3.15.0': ^4.3.1 at pnpm-workspace.yaml:41), but one of those dependencies calls a function that version 4 removed, so the workspace's changeset/versioning commands fail with a runtime error.
Impact: Running the repo's release tooling (changesets version/status) breaks in CI and locally.

Mechanism: read-yaml-file@1.1.0 uses the removed yaml.safeLoad API

pnpm-lock.yaml resolves read-yaml-file@1.1.0 (a dependency of @manypkg/get-packages@1.1.3, itself used by @changesets/*) with js-yaml: 4.3.1 (pnpm-lock.yaml:9014-9019). read-yaml-file@1.1.0/index.js is:

const yaml = require('js-yaml')
const parse = data => yaml.safeLoad(stripBom(data))

safeLoad was removed in js-yaml 4.0.0 (see the 4.0.0 breaking-change notes in the PR body: "removed safe* functions"). So any code path that reads pnpm-workspace.yaml through @manypkg/get-packages throws TypeError: yaml.safeLoad is not a function. Previously the override pinned ^3.15.0, which kept safeLoad available.

Before this change the same override range resolved to js-yaml 3.15.0, which still exposes safeLoad, so the breakage is introduced by widening the override to ^4.3.1.

Open in Devin Review

Was this helpful? React with 👍 or 👎 to provide feedback.

Comment thread pnpm-workspace.yaml
@renovate
renovate Bot force-pushed the renovate/npm-js-yaml-3.15.0-vulnerability branch from ec1b8ed to c13f51e Compare August 12, 2026 08:35
@renovate renovate Bot changed the title chore(deps): update dependency js-yaml@<3.15.0 to v5 [security] chore(deps): update dependency js-yaml@<3.15.0 to v4 [security] Aug 12, 2026
@renovate renovate Bot changed the title chore(deps): update dependency js-yaml@<3.15.0 to v4 [security] chore(deps): update dependency js-yaml@<3.15.0 to v5 [security] Aug 12, 2026
@renovate
renovate Bot force-pushed the renovate/npm-js-yaml-3.15.0-vulnerability branch from c13f51e to 8ce9ee3 Compare August 12, 2026 09:22
@renovate renovate Bot changed the title chore(deps): update dependency js-yaml@<3.15.0 to v5 [security] chore(deps): update dependency js-yaml@<3.15.0 to v4 [security] Aug 12, 2026
@renovate
renovate Bot force-pushed the renovate/npm-js-yaml-3.15.0-vulnerability branch from 8ce9ee3 to c071304 Compare August 12, 2026 09:26
devin-ai-integration[bot]

This comment was marked as resolved.

@renovate
renovate Bot force-pushed the renovate/npm-js-yaml-3.15.0-vulnerability branch from c071304 to b9242e8 Compare August 12, 2026 09:33
@renovate renovate Bot changed the title chore(deps): update dependency js-yaml@<3.15.0 to v4 [security] chore(deps): update dependency js-yaml@<3.15.0 to v5 [security] Aug 12, 2026
@renovate renovate Bot changed the title chore(deps): update dependency js-yaml@<3.15.0 to v5 [security] chore(deps): update dependency js-yaml@<3.15.0 to v4 [security] Aug 12, 2026
@renovate
renovate Bot force-pushed the renovate/npm-js-yaml-3.15.0-vulnerability branch from b9242e8 to 62962f3 Compare August 12, 2026 10:01
devin-ai-integration[bot]

This comment was marked as resolved.

@renovate renovate Bot changed the title chore(deps): update dependency js-yaml@<3.15.0 to v4 [security] chore(deps): update dependency js-yaml@<3.15.0 to v5 [security] Aug 12, 2026
@renovate
renovate Bot force-pushed the renovate/npm-js-yaml-3.15.0-vulnerability branch from 62962f3 to a9487ea Compare August 12, 2026 10:20
devin-ai-integration[bot]

This comment was marked as resolved.

@renovate renovate Bot changed the title chore(deps): update dependency js-yaml@<3.15.0 to v5 [security] chore(deps): update dependency js-yaml@<3.15.0 to v4 [security] Aug 12, 2026
@renovate
renovate Bot force-pushed the renovate/npm-js-yaml-3.15.0-vulnerability branch from a9487ea to 30a97cd Compare August 12, 2026 11:11
devin-ai-integration[bot]

This comment was marked as resolved.

@renovate renovate Bot changed the title chore(deps): update dependency js-yaml@<3.15.0 to v4 [security] chore(deps): update dependency js-yaml@<3.15.0 to v5 [security] Aug 12, 2026
@renovate
renovate Bot force-pushed the renovate/npm-js-yaml-3.15.0-vulnerability branch from 30a97cd to 7aaf1b7 Compare August 12, 2026 12:44
devin-ai-integration[bot]

This comment was marked as resolved.

@renovate renovate Bot changed the title chore(deps): update dependency js-yaml@<3.15.0 to v5 [security] chore(deps): update dependency js-yaml@<3.15.0 to v4 [security] Aug 12, 2026
@renovate
renovate Bot force-pushed the renovate/npm-js-yaml-3.15.0-vulnerability branch from 7aaf1b7 to b1b41e8 Compare August 12, 2026 12:46
devin-ai-integration[bot]

This comment was marked as resolved.

@renovate
renovate Bot force-pushed the renovate/npm-js-yaml-3.15.0-vulnerability branch 2 times, most recently from 18aa444 to 321e1e4 Compare August 13, 2026 11:34
@renovate renovate Bot changed the title chore(deps): update dependency js-yaml@<3.15.0 to v4 [security] chore(deps): update dependency js-yaml@<3.15.0 to v5 [security] Aug 13, 2026
@renovate renovate Bot changed the title chore(deps): update dependency js-yaml@<3.15.0 to v5 [security] chore(deps): update dependency js-yaml@<3.15.0 to v4 [security] Aug 13, 2026
@renovate
renovate Bot force-pushed the renovate/npm-js-yaml-3.15.0-vulnerability branch from 321e1e4 to df542e9 Compare August 13, 2026 11:37
devin-ai-integration[bot]

This comment was marked as resolved.

@renovate renovate Bot changed the title chore(deps): update dependency js-yaml@<3.15.0 to v4 [security] chore(deps): update dependency js-yaml@<3.15.0 to v5 [security] Aug 13, 2026
@renovate
renovate Bot force-pushed the renovate/npm-js-yaml-3.15.0-vulnerability branch from df542e9 to fadffcb Compare August 13, 2026 12:51
devin-ai-integration[bot]

This comment was marked as resolved.

@renovate renovate Bot changed the title chore(deps): update dependency js-yaml@<3.15.0 to v5 [security] chore(deps): update dependency js-yaml@<3.15.0 to v4 [security] Aug 13, 2026
@renovate
renovate Bot force-pushed the renovate/npm-js-yaml-3.15.0-vulnerability branch from fadffcb to 7cb7f40 Compare August 13, 2026 21:06
devin-ai-integration[bot]

This comment was marked as resolved.

@renovate
renovate Bot force-pushed the renovate/npm-js-yaml-3.15.0-vulnerability branch from 7cb7f40 to 76d0dd7 Compare August 14, 2026 12:59
@renovate renovate Bot changed the title chore(deps): update dependency js-yaml@<3.15.0 to v4 [security] chore(deps): update dependency js-yaml@<3.15.0 to v5 [security] Aug 14, 2026
devin-ai-integration[bot]

This comment was marked as resolved.

@renovate renovate Bot changed the title chore(deps): update dependency js-yaml@<3.15.0 to v5 [security] chore(deps): update dependency js-yaml@<3.15.0 to v4 [security] Aug 14, 2026
@renovate
renovate Bot force-pushed the renovate/npm-js-yaml-3.15.0-vulnerability branch from 76d0dd7 to 5fe9fb1 Compare August 14, 2026 13:23
devin-ai-integration[bot]

This comment was marked as resolved.

@renovate renovate Bot changed the title chore(deps): update dependency js-yaml@<3.15.0 to v4 [security] chore(deps): update dependency js-yaml@<3.15.0 to v5 [security] Aug 14, 2026
@renovate
renovate Bot force-pushed the renovate/npm-js-yaml-3.15.0-vulnerability branch from 5fe9fb1 to a8cd4cd Compare August 14, 2026 15:07
@renovate renovate Bot changed the title chore(deps): update dependency js-yaml@<3.15.0 to v5 [security] chore(deps): update dependency js-yaml@<3.15.0 to v4 [security] Aug 14, 2026
@renovate
renovate Bot force-pushed the renovate/npm-js-yaml-3.15.0-vulnerability branch from a8cd4cd to 306c81c Compare August 14, 2026 15:09
devin-ai-integration[bot]

This comment was marked as resolved.

@renovate renovate Bot changed the title chore(deps): update dependency js-yaml@<3.15.0 to v4 [security] chore(deps): update dependency js-yaml@<3.15.0 to v5 [security] Aug 14, 2026
@renovate
renovate Bot force-pushed the renovate/npm-js-yaml-3.15.0-vulnerability branch from 306c81c to f5459b8 Compare August 14, 2026 15:18
devin-ai-integration[bot]

This comment was marked as resolved.

@renovate renovate Bot changed the title chore(deps): update dependency js-yaml@<3.15.0 to v5 [security] chore(deps): update dependency js-yaml@<3.15.0 to v4 [security] Aug 14, 2026
@renovate
renovate Bot force-pushed the renovate/npm-js-yaml-3.15.0-vulnerability branch from f5459b8 to 04cedab Compare August 14, 2026 16:03

@devin-ai-integration devin-ai-integration Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Devin Review found 1 new potential issue.

View 2 additional findings in Devin Review.

Open in Devin Review

Comment thread pnpm-workspace.yaml
'protobufjs@<7.6.5': ^7.6.5
'ws@>=8.0.0 <8.21.0': ^8.21.0
'js-yaml@<3.15.0': ^3.15.0
'js-yaml@<3.15.0': ^4.3.1

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟨 Advisory being patched remains unfixed for most YAML library consumers pinned to 4.3.0

The PR bumps only the <3.15.0 override to ^4.3.1, while the sibling override 'js-yaml@>=4.0.0 <4.3.0': ^4.3.0 (pnpm-workspace.yaml:43) still resolves to js-yaml 4.3.0 in pnpm-lock.yaml:8457-8459, which is the version the referenced advisory (GHSA-5p4m-2wfm-xmqj, quadratic !!omap resolution) explicitly lists as affected. ESLint and the changesets tooling continue to load js-yaml 4.3.0 (pnpm-lock.yaml:5768, 5978, 7893), so the intended security update is only partially applied.

Open in Devin Review

Was this helpful? React with 👍 or 👎 to provide feedback.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

0 participants