javascript.lang.security.audit.prototype-pollution.prototype-pollution-assignment.prototype-pollution-assignment

Author
137
Download Count*
License
Possibility of prototype polluting assignment detected. By adding or modifying attributes of an object prototype, it is possible to create attributes that exist on every object, or replace critical attributes with malicious ones. This can be problematic if the software depends on existence or non-existence of certain attributes, or uses pre-defined attributes of object prototype (such as hasOwnProperty, toString or valueOf). Possible mitigations might be: freezing the object prototype, using an object without prototypes (via Object.create(null) ), blocking modifications of attributes that resolve to object prototype, using Map instead of object.
Run Locally
Run in CI
Defintion
rules:
- id: prototype-pollution-assignment
message: "Possibility of prototype polluting assignment detected. By adding or
modifying attributes of an object prototype, it is possible to create
attributes that exist on every object, or replace critical attributes with
malicious ones. This can be problematic if the software depends on
existence or non-existence of certain attributes, or uses pre-defined
attributes of object prototype (such as hasOwnProperty, toString or
valueOf). Possible mitigations might be: freezing the object prototype,
using an object without prototypes (via Object.create(null) ), blocking
modifications of attributes that resolve to object prototype, using Map
instead of object."
metadata:
cwe:
- "CWE-915: Improperly Controlled Modification of Dynamically-Determined
Object Attributes"
owasp:
- A08:2021 - Software and Data Integrity Failures
category: security
references:
- https://github.com/HoLyVieR/prototype-pollution-nsec18/blob/master/paper/JavaScript_prototype_pollution_attack_in_NodeJS.pdf
technology:
- javascript
subcategory:
- audit
likelihood: LOW
impact: LOW
confidence: LOW
license: Commons Clause License Condition v1.0[LGPL-2.1-only]
languages:
- javascript
- typescript
severity: WARNING
patterns:
- pattern: |
$X[$B] = ...
- pattern-not: |
$X[$B] = '...'
- pattern-inside: |
$X = $SMTH[$A]
...
- pattern-not-inside: |
if (<...'constructor' ...>) {
...
}
...
- pattern-not-inside: |
if (<...'__proto__' ...>) {
...
}
...
- pattern-not-inside: |
for(var $B = $S; ...; ...) {...}
- pattern-not-inside: |
for($B = $S; ...; ...) {...}
- pattern-not-inside: |
$X.forEach(function $NAME($OBJ, $B,...) {...})
- metavariable-pattern:
patterns:
- pattern-not: '"..."'
- pattern-not: |
`...${...}...`
- pattern-not: |
($A: float)
metavariable: $A
- metavariable-pattern:
patterns:
- pattern-not: '"..."'
- pattern-not: |
`...${...}...`
- pattern-not: |
($B: float)
metavariable: $B
Examples
prototype-pollution-assignment.js
app.get('/test/:id', (req, res) => {
let id = req.params.id;
let items = req.session.todos[id];
if (!items) {
items = req.session.todos[id] = {};
}
// ruleid: prototype-pollution-assignment
items[req.query.name] = req.query.text;
res.end(200);
});
app.post('/testOk/:id', (req, res) => {
let id = req.params.id;
if (id !== 'constructor' && id !== '__proto__') {
let items = req.session.todos[id];
if (!items) {
items = req.session.todos[id] = {};
}
// ok: prototype-pollution-assignment
items[req.query.name] = req.query.text;
}
res.end(200);
});
function ok1(req, res) {
let items = req.session.todos["id"];
if (!items) {
items = req.session.todos["id"] = {};
}
// ok: prototype-pollution-assignment
items[req.query.name] = req.query.text;
res.end(200);
}
function ok2(req, res) {
let id = req.params.id;
let items = req.session.todos[id];
if (!items) {
items = req.session.todos[id] = {};
}
// ok: prototype-pollution-assignment
items["name"] = req.query.text;
res.end(200);
}
function ok3(req, res) {
let items = req.session.todos["id"];
if (!items) {
items = req.session.todos["id"] = {};
}
// ok: prototype-pollution-assignment
items["name"] = req.query.text;
res.end(200);
}
function ok4(req, res) {
let id = req.params.id;
let items = req.session.todos[id];
// ok: prototype-pollution-assignment
items[0] = req.query.text;
res.end(200);
}
app.get('/testOk5/:id', (req, res) => {
let id = req.params.id;
let items = req.session.todos[id];
if (!items) {
items = req.session.todos[id] = [];
}
// ok: prototype-pollution-assignment
for (let i = 0; i < items.length; i++) {
items[i] = req.query.text;
}
res.end(200);
});
Short Link: https://sg.run/N8AA