devalue vulnerable to denial of service due to memory/CPU exhaustion in devalue.parse
Description
Svelte devalue is a JavaScript library that serializes values into strings when JSON.stringify isn't sufficient for the job. From 5.1.0 to 5.6.1, certain inputs can cause devalue.parse to consume excessive CPU time and/or memory, potentially leading to denial of service in systems that parse input from untrusted sources. This affects applications using devalue.parse on externally-supplied data. The root cause is the ArrayBuffer hydration expecting base64 encoded strings as input, but not checking the assumption before decoding the input. This vulnerability is fixed in 5.6.2.
Affected packages
Versions sourced from the GitHub Security Advisory.
| Package | Affected versions | Patched versions |
|---|---|---|
devaluenpm | >= 5.1.0, < 5.6.2 | 5.6.2 |
Affected products
1Patches
111755849fa06Merge commit from fork
4 files changed · +61 −3
.changeset/slow-banks-love.md+5 −0 added@@ -0,0 +1,5 @@ +--- +"devalue": patch +--- + +fix: validate input for `ArrayBuffer` parsing
.changeset/tender-cities-check.md+5 −0 added@@ -0,0 +1,5 @@ +--- +"devalue": patch +--- + +fix: more helpful errors for inputs causing stack overflows
src/parse.js+28 −1 modified@@ -33,6 +33,13 @@ export function unflatten(parsed, revivers) { const hydrated = Array(values.length); + /** + * A set of values currently being hydrated with custom revivers, + * used to detect invalid cyclical dependencies + * @type {Set<number> | null} + */ + let hydrating = null; + /** * @param {number} index * @returns {any} @@ -70,7 +77,18 @@ export function unflatten(parsed, revivers) { // so we need to munge it into the format expected by a custom reviver i = values.push(value[1]) - 1; } - return (hydrated[index] = reviver(hydrate(i))); + + hydrating ??= new Set(); + + if (hydrating.has(i)) { + throw new Error('Invalid circular reference'); + } + + hydrating.add(i); + hydrated[index] = reviver(hydrate(i)); + hydrating.delete(i); + + return hydrated[index]; } switch (type) { @@ -125,6 +143,12 @@ export function unflatten(parsed, revivers) { case 'Float64Array': case 'BigInt64Array': case 'BigUint64Array': { + if (values[value[1]][0] !== 'ArrayBuffer') { + // without this, if we receive malformed input we could + // end up trying to hydrate in a circle + throw new Error('Invalid data'); + } + const TypedArrayConstructor = globalThis[type]; const buffer = hydrate(value[1]); if (!(buffer instanceof ArrayBuffer)) { @@ -142,6 +166,9 @@ export function unflatten(parsed, revivers) { case 'ArrayBuffer': { const base64 = value[1]; + if (typeof base64 !== 'string') { + throw new Error('Invalid ArrayBuffer encoding'); + } const arraybuffer = decode64(base64); hydrated[index] = arraybuffer; break;
test/test.js+23 −2 modified@@ -745,6 +745,11 @@ const invalid = [ json: '[["Int8Array", 1], { "length": 2 }, 1000000000]', message: 'Invalid input, expected ArrayBuffer but got object' }, + { + name: 'ArrayBuffer with non-string value', + json: '[["ArrayBuffer", { "length": 100 }]]', + message: 'Invalid ArrayBuffer encoding' + }, { name: 'empty string', json: '', @@ -802,13 +807,29 @@ const invalid = [ name: 'bad index', json: '[{"0":1,"toString":"push"},"hello"]', message: 'Invalid input' + }, + { + name: 'TypedArray self-reference', + json: '[["Uint8Array", 0]]', + message: 'Invalid data' + }, + { + name: 'custom reviver self-reference', + json: '[["Custom", 0]]', + revivers: { Custom: (v) => v }, + message: 'Invalid circular reference' + }, + { + name: 'mutual TypedArray reference', + json: '[["Uint8Array", 1], ["Uint8Array", 0]]', + message: 'Invalid data' } ]; -for (const { name, json, message } of invalid) { +for (const { name, json, message, revivers } of invalid) { uvu.test(`parse error: ${name}`, () => { assert.throws( - () => parse(json), + () => parse(json, revivers), (error) => { const match = error.message === message; if (!match) {
Vulnerability mechanics
Generated by null/stub on May 9, 2026. Inputs: CWE entries + fix-commit diffs from this CVE's patches. Citations validated against bundle.
References
5- github.com/advisories/GHSA-g2pg-6438-jwpfghsaADVISORY
- nvd.nist.gov/vuln/detail/CVE-2026-22775ghsaADVISORY
- github.com/sveltejs/devalue/commit/11755849fa0634ae294a15ec0aef2f43efcad7c4ghsax_refsource_MISCWEB
- github.com/sveltejs/devalue/releases/tag/v5.6.2ghsax_refsource_MISCWEB
- github.com/sveltejs/devalue/security/advisories/GHSA-g2pg-6438-jwpfghsax_refsource_CONFIRMWEB
News mentions
0No linked articles in our index yet.