Skip to content

Fix prototype replacement when array key value is __proto__ - #322

Merged
keichi merged 1 commit into
masterfrom
fix-array-key-proto
Oct 18, 2026
Merged

keichi merged 1 commit into
masterfrom
fix-array-key-proto

Conversation

@keichi

@keichi keichi commented Oct 18, 2026

Copy link
Copy Markdown
Owner

Problem

An array with the key option builds its result as lhs = {} and assigns entries with lhs[item.key] = item. When the key value comes from parsed input and equals "__proto__", the assignment triggers the __proto__ setter and replaces the hash's prototype with the parsed item instead of adding an entry. The entry vanishes from Object.keys(), and missing properties on the hash resolve to attacker-controlled data.

Repro

const parser = new Parser().array("a", {
  type: new Parser().uint8("l").string("k", { length: "l" }).uint8("evil"),
  lengthInBytes: 11,
  key: "k",
});
const r = parser.parse(Buffer.from([9, ...Buffer.from("__proto__"), 1]));
Object.keys(r.a); // []
r.a.evil;         // 1

Fix

Use Object.defineProperty (enumerable, writable, configurable) for the assignment, so every key, "__proto__" included, becomes an own data property.

I picked this over Object.create(null) because the result stays a plain object with Object.prototype. Existing users can still call hasOwnProperty/toString on it, and strict deep equality (e.g. toStrictEqual, which compares prototypes) keeps working, so existing tests and user code see no change.

A regression test is added in test/composite_parser.ts.

@keichi
keichi merged commit a8bd676 into master Oct 18, 2026
8 checks passed
@keichi
keichi deleted the fix-array-key-proto branch October 18, 2026 13:54
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