Prototype Pollution vulnerabilities allow to inject new properties into the built-in ``++Object.prototype++`` object. Since most objects inherit from this prototype, it can result in unexpected behavior, e.g., crashes or more severe vulnerabilities.


In the past, it has led to the following vulnerabilities:

* http://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2019-10744[CVE-2019-10744]
* http://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2019-11358[CVE-2019-11358]


== Noncompliant Code Example

For merge functions:

[source,javascript]
----
function for_in_merge(dst, src) {
    for (let key in src) {
        if (dst[key]) {
            for_in_merge(dst[key], src[key]);
        } else {
            dst[key] = src[key];
        }
    }
}

let obj1 = {};
for_in_merge(obj1, req.query.obj2); // Noncompliant
----

For set-path functions:

[source,javascript]
----
function for_set(target, path, value) {
    let keys = path.split('.');
    for (let i = 0; i < keys.length; ++i) {
        let key = keys[i];
        if (i < keys.length - 1) {
            if (!target[key]) {
                target[key] = {};
            }
            target = target[key];
        } else {
            target[key] = value;
        }
    }
}

for_set(req.query.path, req.query.val); // Noncompliant
----


== Compliant Solution

For merge functions:

[source,javascript]
----
function for_in_merge(dst, src) {
    for (let key in src) {
        // Recommended Secure Coding Practices: prevent sensible keys
        if (key === "constructor" || key === "prototype" || key === "__proto__") {
            continue;
        }

        if (dst[key]) {
            for_in_merge(dst[key], src[key]);
        } else {
            dst[key] = src[key];
        }
    }
}

let obj1 = {};
for_in_merge(obj1, req.query.obj2); // Compliant
----

For set-path functions:

[source,javascript]
----
function for_set(target, path, value) {
    let keys = path.split('.');
    for (let i = 0; i < keys.length; ++i) {
        let key = keys[i];
        // Recommended Secure Coding Practices: prevent sensible keys
        if (key === "constructor" || key === "prototype" || key === "__proto__") {
            break;
        }
        if (i < keys.length - 1) {
            if (!target[key]) {
                target[key] = {};
            }
            target = target[key];
        } else {
            target[key] = value;
        }
    }
}

for_set(req.query.path, req.query.val); // Compliant
----


== See

* https://github.com/HoLyVieR/prototype-pollution-nsec18/blob/master/paper/JavaScript_prototype_pollution_attack_in_NodeJS.pdf[Prototype pollution attack in NodeJS application - Olivier Arteau]
* https://cwe.mitre.org/data/definitions/1321[MITRE, CWE-1321] - Improperly Controlled Modification of Object Prototype Attributes ('Prototype Pollution')

