Skip to content

Commit e78e783

Browse files
committed
reject __proto__ since it could break the object
1 parent 0ff708a commit e78e783

File tree

2 files changed

+29
-2
lines changed

2 files changed

+29
-2
lines changed

src/Decoder.ts

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

67-
Object.defineProperty(this, 'name', {
67+
Object.defineProperty(this, "name", {
6868
configurable: true,
6969
enumerable: false,
7070
value: this.constructor.name,
@@ -413,6 +413,9 @@ export class Decoder<ContextType> {
413413
if (!isValidMapKeyType(object)) {
414414
throw new DecodeError("The type of key must be string or number but " + typeof object);
415415
}
416+
if (object === "__proto__") {
417+
throw new DecodeError("The key __proto__ is not allowed");
418+
}
416419

417420
state.key = object;
418421
state.type = State.MAP_VALUE;
@@ -498,7 +501,9 @@ export class Decoder<ContextType> {
498501

499502
private decodeUtf8String(byteLength: number, headerOffset: number): string {
500503
if (byteLength > this.maxStrLength) {
501-
throw new DecodeError(`Max length exceeded: UTF-8 byte length (${byteLength}) > maxStrLength (${this.maxStrLength})`);
504+
throw new DecodeError(
505+
`Max length exceeded: UTF-8 byte length (${byteLength}) > maxStrLength (${this.maxStrLength})`,
506+
);
502507
}
503508

504509
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)