[GHSA-mwv9-gp5h-frr4] Sveltejs devalue's devalue.parse and devalue.unflatten emit objects with __proto__ own properties#7464
Conversation
|
Hi there @elliott-with-the-longest-name-on-github! A community member has suggested an improvement to your security advisory. If approved, this change will affect the global advisory listed at github.com/advisories. It will not affect the version listed in your project repository. This change will be reviewed by our Security Curation Team. If you have thoughts or feedback, please share them in a comment here! If this PR has already been closed, you can start a new community contribution for this advisory |
| "CWE-1321" | ||
| ], | ||
| "severity": "LOW", | ||
| "severity": "MODERATE", |
There was a problem hiding this comment.
We do not accept this modification. For reference, JSON.stringify works this way by design -- it will emit objects with __proto__ own properties if they exist in the source objects. We implemented this change purely as a hardening effort. We may decide to allow devalue to support own-property __proto__ in the future (there is no work planned for this currently, as we know of no valid use cases). This is not a vulnerability in devalue itself. We released this advisory as just that: An advisory.
In some circumstances,
devalue.parseanddevalue.unflattencould emit objects with__proto__own properties. This in and of itself is not a security vulnerability
(emphasis added)
| "severity": "MODERATE", | |
| "severity": "LOW", |
There was a problem hiding this comment.
Hi @elliott-with-the-longest-name-on-github, thanks for the quick response! Please see my comment below about the CVSS changes. This was not intentional and I agree that the severity should not be changed.
There was a problem hiding this comment.
Yeah, sorry, I meant to submit both of my comments as one review. Looks like GHSA assigned a "ghost string" or something on the backend; we didn't even give it a CVSS score in the first place. Thanks for fixing the starting version!
There was a problem hiding this comment.
No problem at all! I don’t think I’m able to directly modify those files in the PR, so please feel free to make those changes. If the starting version looks good to you, feel free to merge the PR after fixing the CVSS issue. Thank you for looking at this so quickly!
|
Note: the GHSA improvement form rejects the original CVSS v4 vector with — the error reproduces on the unchanged vector (CVSS:4.0/AV:N/AC:L/AT:N/PR:N/UI:N/VC:N/VI:L/VA:N/SC:N/SI:N/SA:N/E:U), so the form won't let me submit without dropping the /E:U suffix. Dropping |
| "severity": [ | ||
| { | ||
| "type": "CVSS_V4", | ||
| "score": "CVSS:4.0/AV:N/AC:L/AT:N/PR:N/UI:N/VC:N/VI:L/VA:N/SC:N/SI:N/SA:N/E:U" |

Updates
Comments
The advisory identifies
parseandunflattenas the relevant sinks. These functions can produce objects in which__proto__is preserved as an own property, creating a prototype-pollution hazard when downstream code later performs unsafe merges such asObject.assign(target, result)on the parsed output.Neither sink existed before
4.0.0. The1.x,2.x, and3.xlines ofdevaluewere serialization-only: they exposed a single function that converted a JavaScript value into a string. Those releases had no deserialization path, no string-to-object parser, and no opportunity for__proto__handling to introduce this bug class.Version
4.0.0is the first release that introduced deserialization as part of a broader API redesign. Its entireindex.jsis:This release renamed the former
devalueserializer tounevaland introducedparseas the corresponding deserialization entry point.unflattenwas exported later in the5.xline, but both advisory-listed sinks trace back to the4.0.0restructuring that first added the vulnerable API surface.The following 14 versions are currently included in the advisory’s affected range even though they do not expose the vulnerable API surface and should therefore be excluded:
1.0.0,1.0.1,1.0.2,1.0.3,1.0.4,1.1.0,1.1.12.0.0,2.0.13.0.1,3.1.0,3.1.1,3.1.2,3.1.3All fourteen are serializer-only releases.
Evidence
1.0.0,1.1.1,2.0.1,3.1.3,4.0.0,5.6.3,5.6.4ripgrepforparse|unflatten|hydratein1.x,2.x, and3.xmain bundles returns zero matches3.1.3types/devalue.d.tsexposes onlyexport function devalue(value: any): string;4.0.0types/index.d.tsaddsexport { parse } from './src/parse.js', marking the first appearance of the sink4.0.0index.jsexplicitly throws from the legacydevalueexport, confirming that the API was restructured rather than merely extended1.xthrough3.xis expected, because the PoC importsparseorunflatten, which are undefined in those versionsConclusion
The affected range should begin at
4.0.0, not in the1.xline. Versions1.x,2.x, and3.xdo not containparse,unflatten, or any comparable deserialization sink, so including them produces false positives.