-
Notifications
You must be signed in to change notification settings - Fork 8
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
Feature proposal: Mitigation for Client-Side Prototype Pollution #33
Comments
I don't have a strong opinion about the solution, other than to note that Document Policy seems like a reasonable place to put a control like this one. I've asked some folks who know more about JavaScript internals than I to (and developer expectations regarding things like I have a few questions:
I'll see if I can find folks with (informed) opinions to weigh in. |
https://github.com/tc39/proposal-freeze-prototype is an early-stage proposal for freezing prototypes. It achieved Stage 1 in 2019. If it were to progress further and become a standard, it sounds like this particular document policy feature proposal could be nicely built on top. cc @bakkot |
Well, the For the others:
There is no way that behavior could work with ECMAScript. The prototype of
As written, that can't work without a fairly significant change to ECMAScript, since currently Of course, doing that would break substantially all webpages, so I don't know how feasible it would be for anyone to use. |
Not sure 🙁
The hard part of this problem is that, while we can use
Yes, this seem difficult to implement currently (both spec and browser implementation). However, this is probably useful in the future too. For example, many developers are bypassing
Given @bakkot's feedback, maybe it's better to just introduce WDYT? |
Oh, I should mention also that doing Object.freeze(Object.prototype);
let x = {};
x.toString = 0;
console.log(x.toString === 0); // false. writing to an own property fails if the object inherits that property from its prototype and its prototype has that property as non-writeable. So it would probably have to be something slightly different. For example, |
I think this is the behavior that we want (or at least it's good from security perspective). Because if we have a method where it allows overwrite of existing property, those might be still vulnerable to PP if developers called However, if it turns out that |
I promise you that it will not work in real applications; there's no need to run the experiment. The code snippet I wrote is very, very common. (Note that it's not attempting to change the value of |
Got it. So maybe we expose 2 keywords?
Maybe doing experiment with those 2 would work? For Object, all built-in properties are functions, so However, if we decide to do the same for Array, Array has |
I don't really understand what the function-vs-data distinction has to do with prototype pollution. |
Oh, yeah 😊
Not sure if I understand this. Polyfill will just be
Attacker's entry point is method like |
I mean, people will want to polyfill new JS language features, not this feature. That is, when JS adds a new method to |
I think that's a tradeoff that developers/security engineers has to make 😊 But if they are calling @terjanq, do you think something like #33 (comment) might work in production? @clelland, how does new addition to document policy look like in terms of spec? |
I'm not clear on why this needs to be a document policy instead of being done programmatically, if the behavior is equivalent to calling #33 (comment) suggests it has to do with a better debugging experience, which I don't quite understand either. What is a report-only mode? |
Please see: But to elaborate, you are right that these can be programmatically done (at least for the proposal in #33 (comment)). However, for a real-world application to enable such code programmatically, they would first write a tool to scan all of dependencies and verify that the code change doesn't affect the application in any way (and scan for each application). That might be an expensive cost for a mitigation. But if we can roll out a report-only mode, we get benefit of:
|
That seems as the best solution for global Prototype Pollution. That would still have to apply to any other native types such as Function, String, Array, since it's easy to reference those prototypes as well. Not only For the local pollution, as mentioned, this is only concern for a specific application and the application can prevent themselves in multiple ways (for example passing an object with frozen But per my understanding the |
Can such a report-only mode be built in devtools instead of a document-policy header? |
We need a signal from website to opt-in to the mitigation. Devtools' warning would only make sense if we decide to disable PP by default.
Agreed. But seems like it requires a lot of changes to ECMAScript, which I'm not willing to take currently 😊 But once we know what works, we might be able to come back to this solution.
I'm planning to experiment first with Object, as we know that's a problem. If you know of many PP with any of above native types, we can include that, but I thinking we can do that later once we have a solid mitigation for Object.
Right. After getting feedback, I suggested the following mitigation, which should work both on global and local objects.
|
IMO, this feature should be split into two. delete
|
Client-Side Prototype Pollution (will refer as PP) are increasing. For example, this shows many libraries are vulnerable to PP just by parsing
location.search
.But essentially, a PP bug can be introduced if a JS application has a custom function to merge/clone objects, where an object is controlled by an attacker.
For example, following is a vulnerable code:
Proposal
Create a Document Policy to stop PP.
Name:
restrict-prototype
(bikeshed).Keywords:
globalObject
,allObjects
, and (if possible)objectsIfImplicit
(all bikeshed).Note: I'm still unsure if Arrays should be protected. But if so, we can add same keywords for Arrays.
globalObject
This allows developers to set prototype of local objects, but not for the global Object.
For example:
This way, prototype addition/modification only affects a local object but not all other objects.
allObjects
This ignores prototype modification of all objects. Which is equivalent of
Object.freeze(Object.prototype)
;For example:
objectsIfImplicit
This allows prototype modification only when explicitly specified.
Explicit prototype modification is defined by property set with the dot notation property accessor. Setting prototype other than the dot notation will be ignored (such as bracket notation).
For example:
I'm not sure how technically feasible this option is (in terms of browser implementation), but it seems possible at least in Chromium.
This option is beneficial because most (if not all) of PP bugs are introduced with the code which accesses prototype with bracket notation (obviously this is unintentional). This option looks like a best way to eliminate PP while allowing developers to intentionally modify object prototypes.
Special thanks to @koto for some ideas.
CC: @mikewest and @arturjanc
The text was updated successfully, but these errors were encountered: