Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Remove Object.prototype.__proto__ #4341

Merged
merged 5 commits into from
Mar 15, 2020
Merged

Conversation

kitsonk
Copy link
Contributor

@kitsonk kitsonk commented Mar 13, 2020

Fixes #4324

This PR removes Object.prototype.__proto__. This legacy property can be exploited when deserialising inguarded external input. The most common exploit would be a denial of service attack causing code to throw in unexpected ways.

Prior to this patch, the following code:

const payload = `{ "__proto__": null }`;
const obj = {};
console.log("Before: " + obj);
Object.assign(obj, JSON.parse(payload));
console.log("After: " + obj);

Would result in the following output from Deno:

$ deno cli/tests/proto_exploit.js
Before: [object Object]
error: Uncaught TypeError: Cannot convert object to primitive value
► /deno/cli/tests/proto_exploit.js:5:23

5 console.log("After: " + obj);
                        ^

    at file:///Users/kkelly/github/deno/cli/tests/proto_exploit.js:5:23

With this patch, the output is:

Before: [object Object]
After: [object Object]

TypeScript already claims that Object.prototype.__proto__ doesn't exist, so there is nothing to correct there.

An alternative approach was to "throw" on attempting to access __proto__, effectively though that would be the same situation, in that someone attempting to exploit unguarded serialised input to "attack" __proto__ would be successful. The "best" situation is really to not have __proto__ in the prototype for Objects and exploits would not have any impact on the code.

#4324 also mentions freezing built ins. This has a potentially much bigger consequences and it is debatable about what builtins we would actually want to freeze, we should tackle that as a seperate issue IMO.

cli/js/runtime_main.ts Outdated Show resolved Hide resolved
deno_typescript/lib.rs Outdated Show resolved Hide resolved
deno_typescript/lib.rs Outdated Show resolved Hide resolved
//
// eslint-disable-next-line @typescript-eslint/no-explicit-any
delete (Object.prototype as any).__proto__;

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍

Copy link
Member

@bartlomieju bartlomieju left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

@bartlomieju bartlomieju merged commit 2f4be6e into denoland:master Mar 15, 2020
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.

security: disallow __proto__ / freeze builtins
3 participants