Prototype-polluting merge call¶
ID: js/prototype-pollution
Kind: path-problem
Security severity: 6.1
Severity: error
Precision: high
Tags:
- security
- external/cwe/cwe-078
- external/cwe/cwe-079
- external/cwe/cwe-094
- external/cwe/cwe-400
- external/cwe/cwe-471
- external/cwe/cwe-915
Query suites:
- javascript-code-scanning.qls
- javascript-security-extended.qls
- javascript-security-and-quality.qls
Click to see the query in the CodeQL repository
Most JavaScript objects inherit the properties of the built-in Object.prototype
object. Prototype pollution is a type of vulnerability in which an attacker is able to modify Object.prototype
. Since most objects inherit from the compromised Object.prototype
, the attacker can use this to tamper with the application logic, and often escalate to remote code execution or cross-site scripting.
One way to cause prototype pollution is through use of an unsafe merge or extend function to recursively copy properties from an untrusted source object. Such a call can modify any object reachable from the destination object, and the built-in Object.prototype
is usually reachable through the special properties __proto__
and constructor.prototype
. An attacker can abuse this by sending an object with these property names and thereby modify Object.prototype
.
Recommendation¶
Update your library dependencies in order to use a safe version of the merge or extend function. If your library has no fixed version, switch to another library.
Example¶
In the example below, the untrusted value req.query.prefs
is parsed as JSON and then copied into a new object:
app.get('/news', (req, res) => {
let prefs = lodash.merge({}, JSON.parse(req.query.prefs));
})
Prior to lodash 4.17.11 this would be vulnerable to prototype pollution. An attacker could send the following GET request:
GET /news?prefs={"constructor":{"prototype":{"xxx":true}}}
This causes the xxx
property to be injected on Object.prototype
. Fix this by updating the lodash version:
{
"dependencies": {
"lodash": "^4.17.12"
}
}
Note that some web frameworks, such as Express, parse query parameters using extended URL-encoding by default. When this is the case, the application may be vulnerable even if not using JSON.parse
. The example below would also be susceptible to prototype pollution:
app.get('/news', (req, res) => {
let config = lodash.merge({}, {
prefs: req.query.prefs
});
})
In the above example, an attacker can cause prototype pollution by sending the following GET request:
GET /news?prefs[constructor][prototype][xxx]=true
References¶
Prototype pollution attacks: lodash, jQuery, extend, just-extend, merge.recursive.
Express: urlencoded()
Common Weakness Enumeration: CWE-78.
Common Weakness Enumeration: CWE-79.
Common Weakness Enumeration: CWE-94.
Common Weakness Enumeration: CWE-400.
Common Weakness Enumeration: CWE-471.
Common Weakness Enumeration: CWE-915.