Skip to content

fix: guard __proto__ keys in OpenStep and binary parsers (CVE-2022-22912) - #188

Open
icguner wants to merge 2 commits into
TooTallNate:masterfrom
icguner:fix/proto-pollution-openstep-binary
Open

icguner wants to merge 2 commits into
TooTallNate:masterfrom
icguner:fix/proto-pollution-openstep-binary

Conversation

@icguner

@icguner icguner commented Nov 8, 2026

Copy link
Copy Markdown

What

The __proto__ dictionary-key guard added for CVE-2022-22912 only covers the XML parser. The OpenStep parser (added in 5.0.0) and the binary parser have no such guard, and parse() dispatches to them automatically based on the input shape — so plist.parse(untrusted) is exploitable again even when the caller expects XML.

Why

  • src/parse.ts guards <key>__proto__</key>, but only for XML.
  • parse() routes Buffer/Uint8Array/ArrayBuffer and bplist-prefixed strings to the binary parser, and any string starting with { or ( to the OpenStep parser. Both assign obj[key] = value with no check.
  • OpenStep PoC (verified against 5.0.0):
    const r = plist.parse('{ __proto__ = { isAdmin = YES; }; }');
    // r has no own keys, but Object.getPrototypeOf(r) is attacker-controlled:
    r.isAdmin;    // "YES"
    String(r);    // throws "Cannot convert object to primitive value"
    This is the same type-confusion / DoS class as the original CVE. _ is a valid unquoted OpenStep character, so no quoting is needed.
  • Binary: a crafted bplist00 payload whose dict carries a __proto__ key reaches the same sink via parseBinary.

Like the original CVE, this replaces the returned object's prototype; it does not reach the global Object.prototype.

Fix

A shared assertSafeKey helper, used by both the OpenStep and binary parsers. It rejects __proto__, and also rejects non-string keys so the check cannot be bypassed by an OpenStep array key ( ) or a binary key ref that happens to coerce to "__proto__".

Tests

Added __proto__ cases to test/parse-openstep.test.ts and test/parse-binary.test.ts, mirroring the existing XML test at test/parse.test.ts. I was unable to run the suite in my environment, so I'd appreciate CI confirming it.

@changeset-bot

changeset-bot Bot commented Nov 8, 2026 •

Copy link
Copy Markdown

🦋 Changeset detected

Latest commit: 259a1b2

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 1 package
Name Type
plist Patch

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

@vercel

vercel Bot commented Nov 8, 2026

Copy link
Copy Markdown

@icguner is attempting to deploy a commit to the TooTallNate's Team Team on Vercel.

A member of the Team first needs to authorize it.

This branch has not been deployed

No deployments
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.

1 participant