chore: bump up js-yaml version to v4.3.0 [SECURITY] (#15298)

This PR contains the following updates:

| Package | Change |
[Age](https://docs.renovatebot.com/merge-confidence/) |
[Confidence](https://docs.renovatebot.com/merge-confidence/) |
|---|---|---|---|
| [js-yaml](https://redirect.github.com/nodeca/js-yaml) | [`4.2.0` →
`4.3.0`](https://renovatebot.com/diffs/npm/js-yaml/4.2.0/4.3.0) |
![age](https://developer.mend.io/api/mc/badges/age/npm/js-yaml/4.3.0?slim=true)
|
![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/js-yaml/4.2.0/4.3.0?slim=true)
|

---

### JS-YAML: Quadratic-complexity DoS in merge key handling via repeated
aliases
[CVE-2026-53550](https://nvd.nist.gov/vuln/detail/CVE-2026-53550) /
[GHSA-h67p-54hq-rp68](https://redirect.github.com/advisories/GHSA-h67p-54hq-rp68)

<details>
<summary>More information</summary>

#### 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
-
[https://github.com/nodeca/js-yaml/security/advisories/GHSA-h67p-54hq-rp68](https://redirect.github.com/nodeca/js-yaml/security/advisories/GHSA-h67p-54hq-rp68)
-
[https://nvd.nist.gov/vuln/detail/CVE-2026-53550](https://nvd.nist.gov/vuln/detail/CVE-2026-53550)
-
[https://github.com/advisories/GHSA-h67p-54hq-rp68](https://redirect.github.com/advisories/GHSA-h67p-54hq-rp68)

This data is provided by the [GitHub Advisory
Database](https://redirect.github.com/advisories/GHSA-h67p-54hq-rp68)
([CC-BY
4.0](https://redirect.github.com/github/advisory-database/blob/main/LICENSE.md)).
</details>

---

### js-yaml: YAML merge-key chains can force quadratic CPU consumption
[CVE-2026-59869](https://nvd.nist.gov/vuln/detail/CVE-2026-59869) /
[GHSA-52cp-r559-cp3m](https://redirect.github.com/advisories/GHSA-52cp-r559-cp3m)

<details>
<summary>More information</summary>

#### Details
##### Impact

js-yaml can spend quadratic CPU time parsing a document whose size grows
only linearly. The issue is triggered by a chain of mappings where each
mapping merges the previous one:

```yaml
a0: &a0 { k0: 0 }
a1: &a1 { <<: *a0, k1: 1 }
a2: &a2 { <<: *a1, k2: 2 }
a3: &a3 { <<: *a2, k3: 3 }
...
b: *aN
```

For each new mapping, the loader has to enumerate the keys inherited
from the previous mapping. With N chained mappings, this results in
roughly 1 + 2 + ... + N merged-key visits, i.e., O(N^2) work for O(N)
input size.

##### PoC

From N = 4000 delay become > 1s (doc size < 100K)

```js
import { performance } from 'node:perf_hooks'
import { Buffer } from 'node:buffer'
import { load, YAML11_SCHEMA } from 'js-yaml'

const n = Number(process.argv[2] || 4000)

function makeMergeChain (count) {
  const lines = ['a0: &a0 { k0: 0 }']

  for (let i = 1; i < count; i++) {
    lines.push(`a${i}: &a${i} { <<: *a${i - 1}, k${i}: ${i} }`)
  }

  lines.push(`b: *a${count - 1}`)
  return `${lines.join('\n')}\n`
}

const source = makeMergeChain(n)

console.log(source.split('\n').slice(0, 8).join('\n'))
console.log('...')
console.log(source.split('\n').slice(-4).join('\n'))
console.log()
console.log(`N: ${n}`)
console.log(`YAML size: ${Buffer.byteLength(source)} bytes`)

const started = performance.now()
const result = load(source, { schema: YAML11_SCHEMA })
const elapsed = performance.now() - started

console.log(`parse time: ${elapsed.toFixed(1)} ms`)
console.log(`top-level keys: ${Object.keys(result).length}`)
console.log(`b keys: ${Object.keys(result.b).length}`)
```

##### Patches

Fix released. The most robust protection is to limit the total number of
merged keys per parse call. This should close all past and future edge
cases with merge. The default 10K-key limit should be okay in most
cases.

#### 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
-
[https://github.com/nodeca/js-yaml/security/advisories/GHSA-52cp-r559-cp3m](https://redirect.github.com/nodeca/js-yaml/security/advisories/GHSA-52cp-r559-cp3m)
-
[https://nvd.nist.gov/vuln/detail/CVE-2026-59869](https://nvd.nist.gov/vuln/detail/CVE-2026-59869)
-
[https://github.com/nodeca/js-yaml/commit/24f13e79ee1343a7e30bd6f6c9d9cdbf0ac9b2b7](https://redirect.github.com/nodeca/js-yaml/commit/24f13e79ee1343a7e30bd6f6c9d9cdbf0ac9b2b7)
-
[https://github.com/nodeca/js-yaml/commit/59423c6f8cdc78742ac00e25a4dd39ef16b702e4](https://redirect.github.com/nodeca/js-yaml/commit/59423c6f8cdc78742ac00e25a4dd39ef16b702e4)
-
[https://github.com/nodeca/js-yaml/releases/tag/3.15.0](https://redirect.github.com/nodeca/js-yaml/releases/tag/3.15.0)
-
[https://github.com/nodeca/js-yaml/releases/tag/4.3.0](https://redirect.github.com/nodeca/js-yaml/releases/tag/4.3.0)
-
[https://github.com/advisories/GHSA-52cp-r559-cp3m](https://redirect.github.com/advisories/GHSA-52cp-r559-cp3m)

This data is provided by the [GitHub Advisory
Database](https://redirect.github.com/advisories/GHSA-52cp-r559-cp3m)
([CC-BY
4.0](https://redirect.github.com/github/advisory-database/blob/main/LICENSE.md)).
</details>

---

### Release Notes

<details>
<summary>nodeca/js-yaml (js-yaml)</summary>

###
[`v4.3.0`](https://redirect.github.com/nodeca/js-yaml/compare/4.2.0...33d05b5d29a8c21360f620f7e1c1706e24522eda)

[Compare
Source](https://redirect.github.com/nodeca/js-yaml/compare/4.2.0...4.3.0)

</details>

---

### 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.

---

- [ ] <!-- rebase-check -->If you want to rebase/retry this PR, check
this box

---

This PR was generated by [Mend Renovate](https://mend.io/renovate/).
View the [repository job
log](https://developer.mend.io/github/toeverything/AFFiNE).

<!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiI0My4yNzIuNCIsInVwZGF0ZWRJblZlciI6IjQzLjI3Mi40IiwidGFyZ2V0QnJhbmNoIjoiY2FuYXJ5IiwibGFiZWxzIjpbImRlcGVuZGVuY2llcyJdfQ==-->

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
This commit is contained in:
renovate[bot]
2026-07-21 13:26:30 +08:00
committed by GitHub
parent b1abd8db54
commit bd3fc7c78e
+6 -6
View File
@@ -26404,25 +26404,25 @@ __metadata:
linkType: hard
"js-yaml@npm:^3.13.1, js-yaml@npm:^3.14.1":
version: 3.14.2
resolution: "js-yaml@npm:3.14.2"
version: 3.15.0
resolution: "js-yaml@npm:3.15.0"
dependencies:
argparse: "npm:^1.0.7"
esprima: "npm:^4.0.0"
bin:
js-yaml: bin/js-yaml.js
checksum: 10/172e0b6007b0bf0fc8d2469c94424f7dd765c64a047d2b790831fecef2204a4054eabf4d911eb73ab8c9a3256ab8ba1ee8d655b789bf24bf059c772acc2075a1
checksum: 10/2fdf3a1453ed93a8e06d6ca8054c0bec145cf40ab51f305d1071736a03668b95e40f47cfd0239d7d50019b4780a18cdaca3c935def935594c9876964c49f1185
languageName: node
linkType: hard
"js-yaml@npm:^4.2.0":
version: 4.2.0
resolution: "js-yaml@npm:4.2.0"
version: 4.3.0
resolution: "js-yaml@npm:4.3.0"
dependencies:
argparse: "npm:^2.0.1"
bin:
js-yaml: bin/js-yaml.js
checksum: 10/51de2067a2b44b07ba5206132e56005f8b568ff279bb4d2f645068958c56fa4827d40a6841c983234671fa0a134bf094d0b0717873c2a3d319185297af145a6d
checksum: 10/2bcec3a8118d7f744badeb04e14366578d234a736f353d41fe35d2305e4ce2409a8e041d277f07cd6bbc8aaa12128d650a68ce43247072519bede20962d2126f
languageName: node
linkType: hard