Skip to content

Commit 1a15754

Browse files
authored
Merge pull request #166 from msgpack/reject_proto
reject __proto__ since it could break the object
2 parents 0ff708a + c31a76e commit 1a15754

File tree

2 files changed

+34
-3
lines changed

2 files changed

+34
-3
lines changed

src/Decoder.ts

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -64,10 +64,14 @@ export class DecodeError extends Error {
6464
constructor(message: string) {
6565
super(message);
6666

67-
Object.defineProperty(this, 'name', {
67+
// fix the prototype chain in a cross-platform way
68+
const proto = Object.create(DecodeError.prototype);
69+
Object.setPrototypeOf(this, proto);
70+
71+
Object.defineProperty(this, "name", {
6872
configurable: true,
6973
enumerable: false,
70-
value: this.constructor.name,
74+
value: DecodeError.name,
7175
});
7276
}
7377
}
@@ -413,6 +417,9 @@ export class Decoder<ContextType> {
413417
if (!isValidMapKeyType(object)) {
414418
throw new DecodeError("The type of key must be string or number but " + typeof object);
415419
}
420+
if (object === "__proto__") {
421+
throw new DecodeError("The key __proto__ is not allowed");
422+
}
416423

417424
state.key = object;
418425
state.type = State.MAP_VALUE;
@@ -498,7 +505,9 @@ export class Decoder<ContextType> {
498505

499506
private decodeUtf8String(byteLength: number, headerOffset: number): string {
500507
if (byteLength > this.maxStrLength) {
501-
throw new DecodeError(`Max length exceeded: UTF-8 byte length (${byteLength}) > maxStrLength (${this.maxStrLength})`);
508+
throw new DecodeError(
509+
`Max length exceeded: UTF-8 byte length (${byteLength}) > maxStrLength (${this.maxStrLength})`,
510+
);
502511
}
503512

504513
if (this.bytes.byteLength < this.pos + headerOffset + byteLength) {

test/prototype-pollution.test.ts

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
import { throws } from "assert";
2+
import { encode, decode, DecodeError } from "@msgpack/msgpack";
3+
4+
describe("prototype pollution", () => {
5+
context("__proto__ exists as a map key", () => {
6+
it("raises DecodeError in decoding", () => {
7+
const o = {
8+
foo: "bar",
9+
};
10+
// override __proto__ as an enumerable property
11+
Object.defineProperty(o, "__proto__", {
12+
value: new Date(0),
13+
enumerable: true,
14+
});
15+
const encoded = encode(o);
16+
17+
throws(() => {
18+
decode(encoded);
19+
}, DecodeError);
20+
});
21+
});
22+
});

0 commit comments

Comments
 (0)