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:
function isObject(obj) {
return obj !== null && typeof obj === 'object';
}
function merge(a, b) {
for (let key in b) {
if (isObject(a[key]) && isObject(b[key])) {
merge(a[key], b[key]);
} else {
a[key] = b[key];
}
}
return a;
}
const internalObj = {a: 1, b: 2};
const userSuppliedObj = JSON.parse('{"__proto__":{"polluted": 1}}');
merge(internalObj, userSuppliedObj);
const newObj = {};
console.log(newObj.polluted); // 1
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:
let obj = {};
obj.__proto__.test = 1;
obj.test; // 1
Object.test; // undefined
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:
let obj = {};
obj.__proto__.test = 1;
obj.test; // undefined
Object.test; // undefined
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:
let obj = {};
obj["__proto__"]["test"] = 1;
obj.test; // undefined
Object.test; // undefined
obj.__proto__.test = 1;
obj.test; // 1
Object.test; // 1
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
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