Skip to content

[GHSA-mwv9-gp5h-frr4] Sveltejs devalue's devalue.parse and devalue.unflatten emit objects with __proto__ own properties#7464

Open
Wenxin-Jiang wants to merge 1 commit intoWenxin-Jiang/advisory-improvement-7464from
Wenxin-Jiang-GHSA-mwv9-gp5h-frr4
Open

[GHSA-mwv9-gp5h-frr4] Sveltejs devalue's devalue.parse and devalue.unflatten emit objects with __proto__ own properties#7464
Wenxin-Jiang wants to merge 1 commit intoWenxin-Jiang/advisory-improvement-7464from
Wenxin-Jiang-GHSA-mwv9-gp5h-frr4

Conversation

@Wenxin-Jiang
Copy link
Copy Markdown

Updates

  • Affected products
  • CVSS v4
  • Severity

Comments
The advisory identifies parse and unflatten as 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 as Object.assign(target, result) on the parsed output.

Neither sink existed before 4.0.0. The 1.x, 2.x, and 3.x lines of devalue were 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.0 is the first release that introduced deserialization as part of a broader API redesign. Its entire index.js is:

export { uneval } from './src/uneval.js';
export { parse } from './src/parse.js';
export { stringify } from './src/stringify.js';

export function devalue() {
  throw new Error('The `devalue` export has been removed. Use `uneval` instead');
}

This release renamed the former devalue serializer to uneval and introduced parse as the corresponding deserialization entry point. unflatten was exported later in the 5.x line, but both advisory-listed sinks trace back to the 4.0.0 restructuring 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.1
  • 2.0.0, 2.0.1
  • 3.0.1, 3.1.0, 3.1.1, 3.1.2, 3.1.3

All fourteen are serializer-only releases.

Evidence

  • npm registry tarballs inspected: 1.0.0, 1.1.1, 2.0.1, 3.1.3, 4.0.0, 5.6.3, 5.6.4
  • ripgrep for parse|unflatten|hydrate in 1.x, 2.x, and 3.x main bundles returns zero matches
  • 3.1.3 types/devalue.d.ts exposes only export function devalue(value: any): string;
  • 4.0.0 types/index.d.ts adds export { parse } from './src/parse.js', marking the first appearance of the sink
  • 4.0.0 index.js explicitly throws from the legacy devalue export, confirming that the API was restructured rather than merely extended
  • Backend PoC non-exploitation on 1.x through 3.x is expected, because the PoC imports parse or unflatten, which are undefined in those versions

Conclusion

The affected range should begin at 4.0.0, not in the 1.x line. Versions 1.x, 2.x, and 3.x do not contain parse, unflatten, or any comparable deserialization sink, so including them produces false positives.

@github
Copy link
Copy Markdown
Collaborator

github commented Apr 20, 2026

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

@github-actions github-actions bot changed the base branch from main to Wenxin-Jiang/advisory-improvement-7464 April 20, 2026 16:26
"CWE-1321"
],
"severity": "LOW",
"severity": "MODERATE",

Choose a reason for hiding this comment

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

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.parse and devalue.unflatten could emit objects with __proto__ own properties. This in and of itself is not a security vulnerability

(emphasis added)

Suggested change
"severity": "MODERATE",
"severity": "LOW",

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

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.

Choose a reason for hiding this comment

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

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!

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

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!

@Wenxin-Jiang
Copy link
Copy Markdown
Author

Note: the GHSA improvement form rejects the original CVSS v4 vector with

The entered vector string contains an error and cannot populate a score.

— 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 E:U is not intentional — it's only to get past the validator. Please revert the CVSS vector back to the original (with /E:U) when merging. The only substantive change in this PR is the introduced version bump from 0 to 4.0.0.

"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"

Choose a reason for hiding this comment

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

I'm not actually sure why there's a CVSS string here in the first place; it is not present in the original advisory:

Image

We purposefully statically scored this as a LOW as we do not consider it to be an actual security issue.

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.

3 participants