CodeQL documentation

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)=>{letprefs=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)=>{letconfig=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

close