fix(encoding/jsonc): avoid prototype pollution in Node.js and Browser (#3077)

This commit is contained in:
ayame113 2023-01-13 16:13:35 +09:00 committed by GitHub
parent 46e2251ab3
commit 329d164bb4
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 35 additions and 1 deletions

View File

@ -271,7 +271,12 @@ class JSONCParser {
}
const token3 = this.#getNext();
target[key] = this.#parseJSONValue(token3);
Object.defineProperty(target, key, {
value: this.#parseJSONValue(token3),
writable: true,
enumerable: true,
configurable: true,
});
const token4 = this.#getNext();
if (token4.type === tokenType.endObject) {

View File

@ -2,6 +2,7 @@
import * as JSONC from "./jsonc.ts";
import {
assert,
assertEquals,
assertStrictEquals,
assertThrows,
@ -171,3 +172,31 @@ Deno.test({
assertValidParse(' ["foo\\\\\\\\", "bar"]', ["foo\\\\", "bar"]);
},
});
Deno.test({
name: "[jsonc] use Object.defineProperty when setting object property",
async fn() {
// Tests if the value is set using `Object.defineProperty(target, key, {value})`
// instead of `target[key] = value` when parsing the object.
// This makes a difference in behavior when __proto__ is set in Node.js and browsers.
// Using `Object.defineProperty` avoids prototype pollution in Node.js and browsers.
// reference: https://github.com/advisories/GHSA-9c47-m6qq-7p4h (CVE-2022-46175)
const testCode = `
Object.defineProperty(Object.prototype, "__proto__", {
set() {
throw new Error("Don't try to set the value directly to the key __proto__.")
}
});
import { parse } from "${import.meta.resolve("./jsonc.ts")}";
parse('{"__proto__": {"isAdmin": true}}');
`;
const command = new Deno.Command(Deno.execPath(), {
stdout: "inherit",
stderr: "inherit",
args: ["eval", testCode],
});
const { success } = await command.output();
assert(success);
},
});