JS: Add PrototypePollutionUtility query

This commit is contained in:
Asger F
2019-10-31 12:59:07 +00:00
committed by Asger Feldthaus
parent 52cec25035
commit 654f145772
9 changed files with 1950 additions and 0 deletions

View File

@@ -0,0 +1 @@
Security/CWE-400/PrototypePollutionUtility.ql

View File

@@ -0,0 +1,211 @@
import dummy from 'somewhere';
function copyUsingForIn(dst, src) {
for (let key in src) {
if (dst[key]) {
copyUsingForIn(dst[key], src[key]);
} else {
dst[key] = src[key]; // NOT OK
}
}
}
function copyUsingKeys(dst, src) {
Object.keys(src).forEach(key => {
if (dst[key]) {
copyUsingKeys(dst[key], src[key]);
} else {
dst[key] = src[key]; // NOT OK
}
});
}
function copyRest(dst, ...sources) {
for (let source of sources) {
for (let key in source) {
copyRestAux(dst, source[key], key);
}
}
}
function copyRestAux(dst, value, key) {
let dstValue = dst[key];
if (dstValue) {
copyRest(dstValue, value);
} else {
dst[key] = value; // NOT OK
}
}
function copyProtoGuarded(dst, src) {
for (let key in src) {
if (key === "__proto__") continue;
if (dst[key]) {
copyProtoGuarded(dst[key], src[key]);
} else {
dst[key] = src[key]; // NOT OK
}
}
}
function copyCtorGuarded(dst, src) {
for (let key in src) {
if (key === "constructor") continue;
if (dst[key]) {
copyCtorGuarded(dst[key], src[key]);
} else {
dst[key] = src[key]; // NOT OK
}
}
}
function copyDoubleGuarded(dst, src) {
for (let key in src) {
if (key === "constructor" || key === "__proto__") continue;
if (dst[key]) {
copyDoubleGuarded(dst[key], src[key]);
} else {
dst[key] = src[key]; // OK
}
}
}
function isSafe(key) {
return key !== "__proto__" && key !== "constructor" && key !== "prototype";
}
function copyComplex(dst, src) {
for (let key in src) {
if (isSafe(key)) {
if (dst[key]) {
copyComplex(dst[key], src[key]);
} else {
dst[key] = src[key]; // OK
}
}
}
}
function copyHasOwnProperty(dst, src) {
for (let key in src) {
// Guarding the recursive case by dst.hasOwnProperty is safe,
// since '__proto__' and 'constructor' are not own properties of the destination object.
if (dst.hasOwnProperty(key)) {
copyHasOwnProperty(dst[key], src[key]);
} else {
dst[key] = src[key]; // OK
}
}
}
function copyHasOwnPropertyBad(dst, src) {
for (let key in src) {
// Guarding using src.hasOwnProperty is *not* effective,
// since '__proto__' and 'constructor' are own properties in the payload.
if (!src.hasOwnProperty(key)) continue; // Not safe
if (dst[key]) {
copyHasOwnPropertyBad(dst[key], src[key]);
} else {
dst[key] = src[key]; // NOT OK
}
}
}
let _hasOwnProp = Object.prototype.hasOwnProperty;
function copyHasOwnPropertyTearOff(dst, src) {
for (let key in src) {
if (_hasOwnProp.call(dst, key)) {
copyHasOwnPropertyTearOff(dst[key], src[key]);
} else {
dst[key] = src[key]; // OK
}
}
}
function shallowExtend(dst, src) {
for (let key in src) {
dst[key] = src[key]; // OK
}
}
function transform(src, fn) {
if (typeof src !== 'object') return fn(src);
for (let key in src) {
src[key] = transform(src[key], fn); // OK
}
return src;
}
function clone(src) {
if (typeof src !== 'object') return src;
let result = {};
for (let key in src) {
result[key] = clone(src[key]); // OK
}
return result;
}
function higherOrderRecursion(dst, src, callback) {
for (let key in src) {
if (dst[key]) {
callback(dst, src, key);
} else {
dst[key] = src[key]; // NOT OK
}
}
}
function higherOrderRecursionEntry(dst, src) {
higherOrderRecursion(dst, src, (dst, src, key) => {
higherOrderRecursionEntry(dst[key], src[key]);
});
}
function instanceofObjectGuard(dst, src) {
for (let key in src) {
let dstValue = dst[key];
if (typeof dstValue === 'object' && dstValue instanceof Object) {
instanceofObjectGuard(dstValue, src[key]);
} else {
dst[key] = src[key]; // OK
}
}
}
let blacklist = ["__proto__", "constructor"];
function copyWithBlacklist(dst, src) {
for (let key in src) {
if (blacklist.indexOf(key) >= 0) continue;
if (dst[key]) {
copyWithBlacklist(dst[key], src[key]);
} else {
dst[key] = src[key]; // OK
}
}
}
function copyUsingPlainForLoop(dst, src) {
let keys = Object.keys(src);
for (let i = 0; i < keys.length; ++i) {
let key = keys[i];
if (dst[key]) {
copyUsingPlainForLoop(dst[key], src[key]);
} else {
dst[key] = src[key]; // NOT OK
}
}
}
function copyUsingPlainForLoopNoAlias(dst, src) {
// Like copyUsingPlainForLoop, but with keys[i] duplicated at every use-site
let keys = Object.keys(src);
for (let i = 0; i < keys.length; ++i) {
if (dst[key]) {
copyUsingPlainForLoopNoAlias(dst[keys[i]], src[keys[i]]);
} else {
dst[keys[i]] = src[keys[i]]; // NOT OK - but not flagged
}
}
}