Prevent Prototype Pollution
Prototype pollution is a vulnerability that occurs when an attacker can modify the prototype of a base object, such as Object.prototype in JavaScript. This can create attributes that exist on every object or replace critical attributes with malicious ones.
Mitigations: Freeze prototypes with Object.freeze(Object.prototype), use Object.create(null), block __proto__ and constructor keys, or use Map instead of objects.
Incorrect (JavaScript - dynamic property assignment from user input):
app.get('/test/:id', (req, res) => {
let id = req.params.id;
let items = req.session.todos[id];
if (!items) {
items = req.session.todos[id] = {};
}
items[req.query.name] = req.query.text;
res.end(200);
});Correct (JavaScript - validate keys and use null-prototype objects):
const DANGEROUS_KEYS = new Set(['__proto__', 'constructor', 'prototype']);
app.post('/test/:id', (req, res) => {
const id = req.params.id;
const name = req.query.name;
if (DANGEROUS_KEYS.has(id) || DANGEROUS_KEYS.has(name)) {
return res.status(400).end();
}
let items = req.session.todos[id];
if (!items) {
items = req.session.todos[id] = Object.create(null);
}
items[name] = req.query.text;
res.end(200);
});Incorrect (JavaScript - nested property assignment in loop):
function setNestedValue(obj, props, value) {
props = props.split('.');
var lastProp = props.pop();
while ((thisProp = props.shift())) {
if (typeof obj[thisProp] == 'undefined') {
obj[thisProp] = {};
}
obj = obj[thisProp];
}
obj[lastProp] = value;
}Correct (JavaScript - use numeric index or Map):
function safeIteration(name) {
let config = this.config;
name = name.split('.');
for (let i = 0; i < name.length; i++) {
config = config[i];
}
return this;
}Incorrect (JavaScript - Object.assign with user input):
function controller(req, res) {
const defaultData = {foo: true}
let data = Object.assign(defaultData, req.body)
doSmthWith(data)
}Correct (JavaScript - use trusted data sources):
function controller(req, res) {
const defaultData = {foo: {bar: true}}
let data = Object.assign(defaultData, {foo: getTrustedFoo()})
doSmthWith(data)
}References:
- CWE-915: Improperly Controlled Modification of Dynamically-Determined Object Attributes
- OWASP Mass Assignment Cheat Sheet