From 52cec25035c6757d5e1c5d4ebdc6a133272e0028 Mon Sep 17 00:00:00 2001 From: Asger F Date: Fri, 8 Nov 2019 10:46:23 +0000 Subject: [PATCH 01/17] JS: Build access paths for array accesses --- .../semmle/javascript/GlobalAccessPaths.qll | 33 +++++++++++++++++++ 1 file changed, 33 insertions(+) diff --git a/javascript/ql/src/semmle/javascript/GlobalAccessPaths.qll b/javascript/ql/src/semmle/javascript/GlobalAccessPaths.qll index b19a19482d1..77defbed7d1 100644 --- a/javascript/ql/src/semmle/javascript/GlobalAccessPaths.qll +++ b/javascript/ql/src/semmle/javascript/GlobalAccessPaths.qll @@ -3,6 +3,7 @@ */ import javascript +private import semmle.javascript.dataflow.InferredTypes deprecated module GlobalAccessPath { @@ -80,6 +81,35 @@ module AccessPath { result = base + "." + prop } + /** + * Holds if `variable` is compared to the `length` property of something, indicating + * that, if used as a dynamic property name, it represents an array index. + */ + private predicate isLikelyArrayIndex(SsaVariable variable) { + exists(RelationalComparison cmp, DataFlow::PropRead length, Expr lengthUse | + length.getPropertyName() = "length" and + length.flowsToExpr(lengthUse) and + cmp.hasOperands(variable.getAUse(), lengthUse) + ) + or + isLikelyArrayIndex(variable.getDefinition().(SsaRefinementNode).getAnInput()) + } + + /** + * Holds if `prop` likely accesses a non-constant array element. + */ + private predicate isLikelyDynamicArrayAccess(DataFlow::PropRead prop) { + // The implicit PropRead in a for-of loop is represented by its lvalue node + prop = DataFlow::lvalueNode(any(ForOfStmt stmt).getLValue()) + or + // Match an index access x[i] where `i` is likely an array index variable. + not exists(prop.getPropertyName()) and + exists(SsaVariable indexVar | + isLikelyArrayIndex(indexVar) and + prop.getPropertyNameExpr() = indexVar.getAUse() + ) + } + /** * Gets the access path relative to `root` referred to by `node`. * @@ -115,6 +145,9 @@ module AccessPath { not node.accessesGlobal(_) and exists(DataFlow::PropRead prop | node = prop | result = join(fromReference(prop.getBase(), root), prop.getPropertyName()) + or + isLikelyDynamicArrayAccess(prop) and + result = join(fromReference(prop.getBase(), root), "[number]") ) or exists(Closure::ClosureNamespaceAccess acc | node = acc | From 654f145772efd9ce004c3c8cda463efa5a0446bf Mon Sep 17 00:00:00 2001 From: Asger F Date: Thu, 31 Oct 2019 12:59:07 +0000 Subject: [PATCH 02/17] JS: Add PrototypePollutionUtility query --- javascript/config/suites/javascript/security | 1 + .../CWE-400/PrototypePollutionUtility.qhelp | 71 + .../CWE-400/PrototypePollutionUtility.ql | 365 +++++ .../examples/PrototypePollutionUtility.js | 10 + .../PrototypePollutionUtility_fixed.js | 10 + .../PrototypePollutionUtility_fixed2.js | 11 + .../PrototypePollutionUtility.expected | 1270 +++++++++++++++++ .../CWE-400/PrototypePollutionUtility.qlref | 1 + .../PrototypePollutionUtility/tests.js | 211 +++ 9 files changed, 1950 insertions(+) create mode 100644 javascript/ql/src/Security/CWE-400/PrototypePollutionUtility.qhelp create mode 100644 javascript/ql/src/Security/CWE-400/PrototypePollutionUtility.ql create mode 100644 javascript/ql/src/Security/CWE-400/examples/PrototypePollutionUtility.js create mode 100644 javascript/ql/src/Security/CWE-400/examples/PrototypePollutionUtility_fixed.js create mode 100644 javascript/ql/src/Security/CWE-400/examples/PrototypePollutionUtility_fixed2.js create mode 100644 javascript/ql/test/query-tests/Security/CWE-400/PrototypePollutionUtility.expected create mode 100644 javascript/ql/test/query-tests/Security/CWE-400/PrototypePollutionUtility.qlref create mode 100644 javascript/ql/test/query-tests/Security/CWE-400/PrototypePollutionUtility/tests.js diff --git a/javascript/config/suites/javascript/security b/javascript/config/suites/javascript/security index d3501346458..301cfc8ed05 100644 --- a/javascript/config/suites/javascript/security +++ b/javascript/config/suites/javascript/security @@ -31,6 +31,7 @@ + semmlecode-javascript-queries/Security/CWE-352/MissingCsrfMiddleware.ql: /Security/CWE/CWE-352 + semmlecode-javascript-queries/Security/CWE-400/RemotePropertyInjection.ql: /Security/CWE/CWE-400 + semmlecode-javascript-queries/Security/CWE-400/PrototypePollution.ql: /Security/CWE/CWE-400 ++ semmlecode-javascript-queries/Security/CWE-400/PrototypePollutionUtility.ql: /Security/CWE/CWE-400 + semmlecode-javascript-queries/Security/CWE-502/UnsafeDeserialization.ql: /Security/CWE/CWE-502 + semmlecode-javascript-queries/Security/CWE-506/HardcodedDataInterpretedAsCode.ql: /Security/CWE/CWE-506 + semmlecode-javascript-queries/Security/CWE-601/ClientSideUrlRedirect.ql: /Security/CWE/CWE-601 diff --git a/javascript/ql/src/Security/CWE-400/PrototypePollutionUtility.qhelp b/javascript/ql/src/Security/CWE-400/PrototypePollutionUtility.qhelp new file mode 100644 index 00000000000..387d438922b --- /dev/null +++ b/javascript/ql/src/Security/CWE-400/PrototypePollutionUtility.qhelp @@ -0,0 +1,71 @@ + + + + +

+ 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 one object to another. + Such a function has the potential to 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. +

+
+ + +

+ The most effective place to guard against this is in the function that performs + the recursive copy. +

+ +

+ Only merge a property recursively when it is an own property of the destination object. + Alternatively, blacklist the property names __proto__ and constructor + from being merged. +

+
+ + +

+ This function recursively copies properties from src to dst: +

+ + + +

+ However, if src is the object {"__proto__": {"xxx": true}}, + it will inject the property xxx: true in in Object.prototype. +

+ +

+ The issue can be fixed by ensuring that only own properties of the destination object + are merged recursively: +

+ + + +

+ Alternatively, blacklist the __proto__ and constructor properties: +

+ + +
+ + +
  • Prototype pollution attacks: + lodash, + jQuery, + extend, + just-extend, + merge.recursive. +
  • +
    +
    diff --git a/javascript/ql/src/Security/CWE-400/PrototypePollutionUtility.ql b/javascript/ql/src/Security/CWE-400/PrototypePollutionUtility.ql new file mode 100644 index 00000000000..8fb9ae89af4 --- /dev/null +++ b/javascript/ql/src/Security/CWE-400/PrototypePollutionUtility.ql @@ -0,0 +1,365 @@ +/** + * @name Prototype pollution in utility function + * @description Recursively copying properties between objects may cause + accidental modification of a built-in prototype object. + * @kind path-problem + * @problem.severity warning + * @precision high + * @id js/prototype-pollution-utility + * @tags security + * external/cwe/cwe-079 + * external/cwe/cwe-116 + */ + +import javascript +import DataFlow +import PathGraph +import semmle.javascript.dataflow.InferredTypes + +/** + * Gets a node that refers to an element of `array`, likely obtained + * as a result of enumerating the elements of the array. + */ +SourceNode getAnEnumeratedArrayElement(SourceNode array) { + exists(MethodCallNode call, string name | + call = array.getAMethodCall(name) and + (name = "forEach" or name = "map") and + result = call.getCallback(0).getParameter(0) + ) + or + exists(DataFlow::PropRead read | + read = array.getAPropertyRead() and + not exists(read.getPropertyName()) and + not read.getPropertyNameExpr().analyze().getAType() = TTString() and + result = read + ) +} + +/** + * A data flow node that refers to the name of a property obtained by enumerating + * the properties of some object. + */ +class EnumeratedPropName extends DataFlow::Node { + DataFlow::Node object; + + EnumeratedPropName() { + exists(ForInStmt stmt | + this = DataFlow::lvalueNode(stmt.getLValue()) and + object = stmt.getIterationDomain().flow() + ) + or + exists(CallNode call, string name | + call = globalVarRef("Object").getAMemberCall(name) and + (name = "keys" or name = "getOwnPropertyNames") and + object = call.getArgument(0) and + this = getAnEnumeratedArrayElement(call) + ) + } + + /** + * Gets the object whose properties are being enumerated. + * + * For example, gets `src` in `for (var key in src)`. + */ + Node getSourceObject() { result = object } + + /** + * Gets a local reference of the source object. + */ + SourceNode getASourceObjectRef() { + exists(SourceNode root, string path | + getSourceObject() = AccessPath::getAReferenceTo(root, path) and + result = AccessPath::getAReferenceTo(root, path) + ) + or + result = getSourceObject().getALocalSource() + } + + /** + * Gets a property read that accesses the corresponding property value in the source object. + * + * For example, gets `src[key]` in `for (var key in src) { src[key]; }`. + */ + PropRead getASourceProp() { + result = getASourceObjectRef().getAPropertyRead() and + result.getPropertyNameExpr().flow().getImmediatePredecessor*() = this + } +} + +/** + * Holds if the properties of `node` are enumerated locally. + */ +predicate arePropertiesEnumerated(DataFlow::SourceNode node) { + node = any(EnumeratedPropName name).getASourceObjectRef() +} + +/** + * A dynamic property access that is not obviously an array access. + */ +class DynamicPropRead extends DataFlow::SourceNode, DataFlow::ValueNode { + // Use IndexExpr instead of PropRead as we're not interested in implicit accesses like + // rest-patterns and for-of loops. + override IndexExpr astNode; + + DynamicPropRead() { + not exists(astNode.getPropertyName()) and + // Exclude obvious array access + astNode.getPropertyNameExpr().analyze().getAType() = TTString() + } + + /** Gets the base of the dynamic read. */ + DataFlow::Node getBase() { result = astNode.getBase().flow() } +} + +/** + * Holds if there is a dynamic property assignment of form `base[prop] = rhs` + * which might act as the writing operation in a recursive merge function. + * + * Only assignments to pre-existing objects are of interest, so object/array literals + * are not included. + * + * Additionally, we ignore cases where the properties of `base` are enumerated, as this + * would typically not happen in a merge function. + */ +predicate dynamicPropWrite(DataFlow::Node base, DataFlow::Node prop, DataFlow::Node rhs) { + exists(AssignExpr write, IndexExpr index | + index = write.getLhs() and + base = index.getBase().flow() and + prop = index.getPropertyNameExpr().flow() and + rhs = write.getRhs().flow() and + not exists(prop.getStringValue()) and + not arePropertiesEnumerated(base.getALocalSource()) + ) +} + +/** Gets the name of a property that can lead to `Object.prototype`. */ +string unsafePropName() { + result = "__proto__" + or + result = "constructor" +} + +/** + * Flow label representing an unsafe property name, or an object obtained + * by using such a property in a dynamic read. + */ +class UnsafePropLabel extends FlowLabel { + UnsafePropLabel() { this = unsafePropName() } +} + +/** + * Tracks data from property enumerations to dynamic property writes. + * + * The intent is to find code of the general form: + * ```js + * function merge(dst, src) { + * for (var key in src) + * if (...) + * merge(dst[key], src[key]) + * else + * dst[key] = src[key] + * } + * ``` + * + * This configuration is used to find four separate data flow paths originating + * from a property enumeration, all leading to the same dynamic property write. + * + * In particular, the base, property name, and rhs of the property write should all + * depend on the enumerated property name (`key`) and the right-hand side should + * additionally depend on the source object (`src`), while allowing steps of form + * `x -> x[p]` and `p -> x[p]`. + * + * Note that in the above example, the flow from `key` to the base of the write (`dst`) + * requires stepping through the recursive call. + * Such a path would be absent for a shallow copying operation. + */ +class PropNameTracking extends DataFlow::Configuration { + PropNameTracking() { this = "PropNameTracking" } + + override predicate isSource(DataFlow::Node node, FlowLabel label) { + label instanceof UnsafePropLabel and + exists(EnumeratedPropName prop | + node = prop + or + node = prop.getASourceProp() + ) + } + + override predicate isSink(DataFlow::Node node, FlowLabel label) { + label instanceof UnsafePropLabel and + ( + dynamicPropWrite(node, _, _) or + dynamicPropWrite(_, node, _) or + dynamicPropWrite(_, _, node) + ) + } + + override predicate isAdditionalFlowStep( + DataFlow::Node pred, DataFlow::Node succ, FlowLabel predlbl, FlowLabel succlbl + ) { + predlbl instanceof UnsafePropLabel and + succlbl = predlbl and + ( + // Step through `p -> x[p]` + exists(PropRead read | + pred = read.getPropertyNameExpr().flow() and + succ = read + ) + or + // Step through `x -> x[p]` + exists(DynamicPropRead read | + pred = read.getBase() and + succ = read + ) + ) + } + + override predicate isBarrierGuard(DataFlow::BarrierGuardNode node) { + node instanceof EqualityGuard or + node instanceof HasOwnPropertyGuard or + node instanceof InstanceOfGuard or + node instanceof TypeofGuard or + node instanceof ArrayInclusionGuard + } +} + +/** + * Sanitizer guard of form `x === "__proto__"` or `x === "constructor"`. + */ +class EqualityGuard extends DataFlow::LabeledBarrierGuardNode, ValueNode { + override EqualityTest astNode; + string propName; + + EqualityGuard() { + astNode.getAnOperand().getStringValue() = propName and + propName = unsafePropName() + } + + override predicate blocks(boolean outcome, Expr e, FlowLabel label) { + e = astNode.getAnOperand() and + outcome = astNode.getPolarity().booleanNot() and + label = propName + } +} + +/** + * Sanitizer guard for calls to `Object.prototype.hasOwnProperty`. + * + * A malicious source object will have `__proto__` and/or `constructor` as own properties, + * but the destination object generally doesn't. It is therefore only a sanitizer when + * used on the destination object. + */ +class HasOwnPropertyGuard extends DataFlow::BarrierGuardNode, CallNode { + HasOwnPropertyGuard() { + // Make sure we handle reflective calls since libraries love to do that. + getCalleeNode().getALocalSource().(DataFlow::PropRead).getPropertyName() = "hasOwnProperty" and + exists(getReceiver()) and + // Try to avoid `src.hasOwnProperty` by requiring that the receiver + // does not locally have its properties enumerated. Typically there is no + // reason to enumerate the properties of the destination object. + not arePropertiesEnumerated(getReceiver().getALocalSource()) + } + + override predicate blocks(boolean outcome, Expr e) { + e = getArgument(0).asExpr() and outcome = true + } +} + +/** + * Sanitizer guard for `instanceof` expressions. + * + * `Object.prototype instanceof X` is never true, so this blocks the `__proto__` label. + * + * It is still possible to get to `Function.prototype` through `constructor.constructor.prototype` + * so we do not block the `constructor` label. + */ +class InstanceOfGuard extends DataFlow::LabeledBarrierGuardNode, DataFlow::ValueNode { + override InstanceOfExpr astNode; + + override predicate blocks(boolean outcome, Expr e, DataFlow::FlowLabel label) { + e = astNode.getLeftOperand() and outcome = true and label = "__proto__" + } +} + +/** + * Sanitizer guard of form `typeof x === "object"` or `typeof x === "function"`. + * + * The former blocks the `constructor` label as that payload must pass through a function, + * and the latter blocks the `__proto__` label as that only passes through objects. + */ +class TypeofGuard extends DataFlow::LabeledBarrierGuardNode, DataFlow::ValueNode { + override EqualityTest astNode; + TypeofExpr typeof; + string typeofStr; + + TypeofGuard() { + typeof = astNode.getAnOperand() and + typeofStr = astNode.getAnOperand().getStringValue() + } + + override predicate blocks(boolean outcome, Expr e, DataFlow::FlowLabel label) { + e = typeof.getOperand() and + outcome = astNode.getPolarity() and + ( + typeofStr = "object" and + label = "constructor" + or + typeofStr = "function" and + label = "__proto__" + ) + } +} + +/** + * A check of form `["__proto__"].includes(x)` or similar. + */ +class ArrayInclusionGuard extends DataFlow::LabeledBarrierGuardNode, InclusionTest { + UnsafePropLabel label; + + ArrayInclusionGuard() { + exists(DataFlow::ArrayCreationNode array | + array.getAnElement().getStringValue() = label and + array.flowsTo(getContainerNode()) + ) + } + + override predicate blocks(boolean outcome, Expr e, DataFlow::FlowLabel lbl) { + outcome = getPolarity().booleanNot() and + e = getContainedNode().asExpr() and + label = lbl + } +} + +/** + * Gets a meaningful name for `node` if possible. + */ +string getExprName(DataFlow::Node node) { + result = node.asExpr().(Identifier).getName() + or + result = node.asExpr().(DotExpr).getPropertyName() +} + +/** + * Gets a name to display for `node`. + */ +string deriveExprName(DataFlow::Node node) { + result = getExprName(node) + or + not exists(getExprName(node)) and + result = "this object" +} + +from + PropNameTracking cfg, DataFlow::PathNode source, DataFlow::PathNode sink, EnumeratedPropName enum, + Node base, Node prop, Node rhs +where + cfg.hasFlowPath(source, sink) and + dynamicPropWrite(base, prop, rhs) and + sink.getNode() = base and + source.getNode() = enum and + cfg.hasFlow(enum, prop) and + cfg.hasFlow(enum, rhs) and + cfg.hasFlow(enum.getASourceProp(), rhs) +select base, source, sink, + "Properties are copied from $@ to $@ without guarding against prototype pollution.", + enum.getSourceObject(), deriveExprName(enum.getSourceObject()), base, deriveExprName(base) diff --git a/javascript/ql/src/Security/CWE-400/examples/PrototypePollutionUtility.js b/javascript/ql/src/Security/CWE-400/examples/PrototypePollutionUtility.js new file mode 100644 index 00000000000..1953ba57f00 --- /dev/null +++ b/javascript/ql/src/Security/CWE-400/examples/PrototypePollutionUtility.js @@ -0,0 +1,10 @@ +function merge(dst, src) { + for (let key in src) { + if (!src.hasOwnProperty(key)) continue; + if (isObject(dst[key])) { + merge(dst[key], src[key]); + } else { + dst[key] = src[key]; + } + } +} diff --git a/javascript/ql/src/Security/CWE-400/examples/PrototypePollutionUtility_fixed.js b/javascript/ql/src/Security/CWE-400/examples/PrototypePollutionUtility_fixed.js new file mode 100644 index 00000000000..d1b762fb43c --- /dev/null +++ b/javascript/ql/src/Security/CWE-400/examples/PrototypePollutionUtility_fixed.js @@ -0,0 +1,10 @@ +function merge(dst, src) { + for (let key in src) { + if (!src.hasOwnProperty(key)) continue; + if (dst.hasOwnProperty(key) && isObject(dst[key])) { + merge(dst[key], src[key]); + } else { + dst[key] = src[key]; + } + } +} diff --git a/javascript/ql/src/Security/CWE-400/examples/PrototypePollutionUtility_fixed2.js b/javascript/ql/src/Security/CWE-400/examples/PrototypePollutionUtility_fixed2.js new file mode 100644 index 00000000000..a4e108a4bd0 --- /dev/null +++ b/javascript/ql/src/Security/CWE-400/examples/PrototypePollutionUtility_fixed2.js @@ -0,0 +1,11 @@ +function merge(dst, src) { + for (let key in src) { + if (!src.hasOwnProperty(key)) continue; + if (key === "__proto__" || key === "constructor") continue; + if (isObject(dst[key])) { + merge(dst[key], src[key]); + } else { + dst[key] = src[key]; + } + } +} diff --git a/javascript/ql/test/query-tests/Security/CWE-400/PrototypePollutionUtility.expected b/javascript/ql/test/query-tests/Security/CWE-400/PrototypePollutionUtility.expected new file mode 100644 index 00000000000..1c911a35bbe --- /dev/null +++ b/javascript/ql/test/query-tests/Security/CWE-400/PrototypePollutionUtility.expected @@ -0,0 +1,1270 @@ +nodes +| PrototypePollutionUtility/tests.js:3:25:3:27 | dst | +| PrototypePollutionUtility/tests.js:3:25:3:27 | dst | +| PrototypePollutionUtility/tests.js:3:30:3:32 | src | +| PrototypePollutionUtility/tests.js:3:30:3:32 | src | +| PrototypePollutionUtility/tests.js:4:14:4:16 | key | +| PrototypePollutionUtility/tests.js:4:14:4:16 | key | +| PrototypePollutionUtility/tests.js:4:14:4:16 | key | +| PrototypePollutionUtility/tests.js:6:28:6:30 | dst | +| PrototypePollutionUtility/tests.js:6:28:6:30 | dst | +| PrototypePollutionUtility/tests.js:6:28:6:35 | dst[key] | +| PrototypePollutionUtility/tests.js:6:28:6:35 | dst[key] | +| PrototypePollutionUtility/tests.js:6:28:6:35 | dst[key] | +| PrototypePollutionUtility/tests.js:6:28:6:35 | dst[key] | +| PrototypePollutionUtility/tests.js:6:32:6:34 | key | +| PrototypePollutionUtility/tests.js:6:32:6:34 | key | +| PrototypePollutionUtility/tests.js:6:38:6:40 | src | +| PrototypePollutionUtility/tests.js:6:38:6:40 | src | +| PrototypePollutionUtility/tests.js:6:38:6:45 | src[key] | +| PrototypePollutionUtility/tests.js:6:38:6:45 | src[key] | +| PrototypePollutionUtility/tests.js:6:38:6:45 | src[key] | +| PrototypePollutionUtility/tests.js:6:38:6:45 | src[key] | +| PrototypePollutionUtility/tests.js:6:38:6:45 | src[key] | +| PrototypePollutionUtility/tests.js:6:42:6:44 | key | +| PrototypePollutionUtility/tests.js:6:42:6:44 | key | +| PrototypePollutionUtility/tests.js:8:13:8:15 | dst | +| PrototypePollutionUtility/tests.js:8:13:8:15 | dst | +| PrototypePollutionUtility/tests.js:8:13:8:15 | dst | +| PrototypePollutionUtility/tests.js:8:17:8:19 | key | +| PrototypePollutionUtility/tests.js:8:17:8:19 | key | +| PrototypePollutionUtility/tests.js:8:17:8:19 | key | +| PrototypePollutionUtility/tests.js:8:24:8:26 | src | +| PrototypePollutionUtility/tests.js:8:24:8:26 | src | +| PrototypePollutionUtility/tests.js:8:24:8:31 | src[key] | +| PrototypePollutionUtility/tests.js:8:24:8:31 | src[key] | +| PrototypePollutionUtility/tests.js:8:24:8:31 | src[key] | +| PrototypePollutionUtility/tests.js:8:24:8:31 | src[key] | +| PrototypePollutionUtility/tests.js:8:24:8:31 | src[key] | +| PrototypePollutionUtility/tests.js:8:24:8:31 | src[key] | +| PrototypePollutionUtility/tests.js:8:28:8:30 | key | +| PrototypePollutionUtility/tests.js:8:28:8:30 | key | +| PrototypePollutionUtility/tests.js:13:24:13:26 | dst | +| PrototypePollutionUtility/tests.js:13:24:13:26 | dst | +| PrototypePollutionUtility/tests.js:13:29:13:31 | src | +| PrototypePollutionUtility/tests.js:13:29:13:31 | src | +| PrototypePollutionUtility/tests.js:14:30:14:32 | key | +| PrototypePollutionUtility/tests.js:14:30:14:32 | key | +| PrototypePollutionUtility/tests.js:14:30:14:32 | key | +| PrototypePollutionUtility/tests.js:16:27:16:29 | dst | +| PrototypePollutionUtility/tests.js:16:27:16:29 | dst | +| PrototypePollutionUtility/tests.js:16:27:16:34 | dst[key] | +| PrototypePollutionUtility/tests.js:16:27:16:34 | dst[key] | +| PrototypePollutionUtility/tests.js:16:27:16:34 | dst[key] | +| PrototypePollutionUtility/tests.js:16:27:16:34 | dst[key] | +| PrototypePollutionUtility/tests.js:16:31:16:33 | key | +| PrototypePollutionUtility/tests.js:16:31:16:33 | key | +| PrototypePollutionUtility/tests.js:16:37:16:39 | src | +| PrototypePollutionUtility/tests.js:16:37:16:39 | src | +| PrototypePollutionUtility/tests.js:16:37:16:44 | src[key] | +| PrototypePollutionUtility/tests.js:16:37:16:44 | src[key] | +| PrototypePollutionUtility/tests.js:16:37:16:44 | src[key] | +| PrototypePollutionUtility/tests.js:16:37:16:44 | src[key] | +| PrototypePollutionUtility/tests.js:16:37:16:44 | src[key] | +| PrototypePollutionUtility/tests.js:16:41:16:43 | key | +| PrototypePollutionUtility/tests.js:16:41:16:43 | key | +| PrototypePollutionUtility/tests.js:18:13:18:15 | dst | +| PrototypePollutionUtility/tests.js:18:13:18:15 | dst | +| PrototypePollutionUtility/tests.js:18:13:18:15 | dst | +| PrototypePollutionUtility/tests.js:18:17:18:19 | key | +| PrototypePollutionUtility/tests.js:18:17:18:19 | key | +| PrototypePollutionUtility/tests.js:18:17:18:19 | key | +| PrototypePollutionUtility/tests.js:18:24:18:26 | src | +| PrototypePollutionUtility/tests.js:18:24:18:26 | src | +| PrototypePollutionUtility/tests.js:18:24:18:31 | src[key] | +| PrototypePollutionUtility/tests.js:18:24:18:31 | src[key] | +| PrototypePollutionUtility/tests.js:18:24:18:31 | src[key] | +| PrototypePollutionUtility/tests.js:18:24:18:31 | src[key] | +| PrototypePollutionUtility/tests.js:18:24:18:31 | src[key] | +| PrototypePollutionUtility/tests.js:18:24:18:31 | src[key] | +| PrototypePollutionUtility/tests.js:18:28:18:30 | key | +| PrototypePollutionUtility/tests.js:18:28:18:30 | key | +| PrototypePollutionUtility/tests.js:23:19:23:21 | dst | +| PrototypePollutionUtility/tests.js:23:19:23:21 | dst | +| PrototypePollutionUtility/tests.js:25:18:25:20 | key | +| PrototypePollutionUtility/tests.js:25:18:25:20 | key | +| PrototypePollutionUtility/tests.js:25:18:25:20 | key | +| PrototypePollutionUtility/tests.js:26:25:26:27 | dst | +| PrototypePollutionUtility/tests.js:26:25:26:27 | dst | +| PrototypePollutionUtility/tests.js:26:30:26:40 | source[key] | +| PrototypePollutionUtility/tests.js:26:30:26:40 | source[key] | +| PrototypePollutionUtility/tests.js:26:30:26:40 | source[key] | +| PrototypePollutionUtility/tests.js:26:37:26:39 | key | +| PrototypePollutionUtility/tests.js:26:37:26:39 | key | +| PrototypePollutionUtility/tests.js:26:43:26:45 | key | +| PrototypePollutionUtility/tests.js:26:43:26:45 | key | +| PrototypePollutionUtility/tests.js:31:22:31:24 | dst | +| PrototypePollutionUtility/tests.js:31:22:31:24 | dst | +| PrototypePollutionUtility/tests.js:31:27:31:31 | value | +| PrototypePollutionUtility/tests.js:31:27:31:31 | value | +| PrototypePollutionUtility/tests.js:31:34:31:36 | key | +| PrototypePollutionUtility/tests.js:31:34:31:36 | key | +| PrototypePollutionUtility/tests.js:32:9:32:27 | dstValue | +| PrototypePollutionUtility/tests.js:32:9:32:27 | dstValue | +| PrototypePollutionUtility/tests.js:32:20:32:22 | dst | +| PrototypePollutionUtility/tests.js:32:20:32:22 | dst | +| PrototypePollutionUtility/tests.js:32:20:32:27 | dst[key] | +| PrototypePollutionUtility/tests.js:32:20:32:27 | dst[key] | +| PrototypePollutionUtility/tests.js:32:24:32:26 | key | +| PrototypePollutionUtility/tests.js:32:24:32:26 | key | +| PrototypePollutionUtility/tests.js:34:18:34:25 | dstValue | +| PrototypePollutionUtility/tests.js:34:18:34:25 | dstValue | +| PrototypePollutionUtility/tests.js:36:9:36:11 | dst | +| PrototypePollutionUtility/tests.js:36:9:36:11 | dst | +| PrototypePollutionUtility/tests.js:36:9:36:11 | dst | +| PrototypePollutionUtility/tests.js:36:13:36:15 | key | +| PrototypePollutionUtility/tests.js:36:13:36:15 | key | +| PrototypePollutionUtility/tests.js:36:13:36:15 | key | +| PrototypePollutionUtility/tests.js:36:20:36:24 | value | +| PrototypePollutionUtility/tests.js:36:20:36:24 | value | +| PrototypePollutionUtility/tests.js:36:20:36:24 | value | +| PrototypePollutionUtility/tests.js:40:27:40:29 | dst | +| PrototypePollutionUtility/tests.js:40:32:40:34 | src | +| PrototypePollutionUtility/tests.js:40:32:40:34 | src | +| PrototypePollutionUtility/tests.js:41:14:41:16 | key | +| PrototypePollutionUtility/tests.js:41:14:41:16 | key | +| PrototypePollutionUtility/tests.js:44:30:44:32 | dst | +| PrototypePollutionUtility/tests.js:44:30:44:37 | dst[key] | +| PrototypePollutionUtility/tests.js:44:30:44:37 | dst[key] | +| PrototypePollutionUtility/tests.js:44:34:44:36 | key | +| PrototypePollutionUtility/tests.js:44:40:44:42 | src | +| PrototypePollutionUtility/tests.js:44:40:44:42 | src | +| PrototypePollutionUtility/tests.js:44:40:44:47 | src[key] | +| PrototypePollutionUtility/tests.js:44:40:44:47 | src[key] | +| PrototypePollutionUtility/tests.js:44:40:44:47 | src[key] | +| PrototypePollutionUtility/tests.js:44:40:44:47 | src[key] | +| PrototypePollutionUtility/tests.js:44:40:44:47 | src[key] | +| PrototypePollutionUtility/tests.js:44:44:44:46 | key | +| PrototypePollutionUtility/tests.js:46:13:46:15 | dst | +| PrototypePollutionUtility/tests.js:46:13:46:15 | dst | +| PrototypePollutionUtility/tests.js:46:17:46:19 | key | +| PrototypePollutionUtility/tests.js:46:17:46:19 | key | +| PrototypePollutionUtility/tests.js:46:24:46:26 | src | +| PrototypePollutionUtility/tests.js:46:24:46:26 | src | +| PrototypePollutionUtility/tests.js:46:24:46:31 | src[key] | +| PrototypePollutionUtility/tests.js:46:24:46:31 | src[key] | +| PrototypePollutionUtility/tests.js:46:24:46:31 | src[key] | +| PrototypePollutionUtility/tests.js:46:24:46:31 | src[key] | +| PrototypePollutionUtility/tests.js:46:24:46:31 | src[key] | +| PrototypePollutionUtility/tests.js:46:24:46:31 | src[key] | +| PrototypePollutionUtility/tests.js:46:28:46:30 | key | +| PrototypePollutionUtility/tests.js:51:26:51:28 | dst | +| PrototypePollutionUtility/tests.js:51:31:51:33 | src | +| PrototypePollutionUtility/tests.js:51:31:51:33 | src | +| PrototypePollutionUtility/tests.js:52:14:52:16 | key | +| PrototypePollutionUtility/tests.js:52:14:52:16 | key | +| PrototypePollutionUtility/tests.js:55:29:55:31 | dst | +| PrototypePollutionUtility/tests.js:55:29:55:36 | dst[key] | +| PrototypePollutionUtility/tests.js:55:29:55:36 | dst[key] | +| PrototypePollutionUtility/tests.js:55:33:55:35 | key | +| PrototypePollutionUtility/tests.js:55:39:55:41 | src | +| PrototypePollutionUtility/tests.js:55:39:55:41 | src | +| PrototypePollutionUtility/tests.js:55:39:55:46 | src[key] | +| PrototypePollutionUtility/tests.js:55:39:55:46 | src[key] | +| PrototypePollutionUtility/tests.js:55:39:55:46 | src[key] | +| PrototypePollutionUtility/tests.js:55:39:55:46 | src[key] | +| PrototypePollutionUtility/tests.js:55:39:55:46 | src[key] | +| PrototypePollutionUtility/tests.js:55:43:55:45 | key | +| PrototypePollutionUtility/tests.js:57:13:57:15 | dst | +| PrototypePollutionUtility/tests.js:57:13:57:15 | dst | +| PrototypePollutionUtility/tests.js:57:17:57:19 | key | +| PrototypePollutionUtility/tests.js:57:17:57:19 | key | +| PrototypePollutionUtility/tests.js:57:24:57:26 | src | +| PrototypePollutionUtility/tests.js:57:24:57:26 | src | +| PrototypePollutionUtility/tests.js:57:24:57:31 | src[key] | +| PrototypePollutionUtility/tests.js:57:24:57:31 | src[key] | +| PrototypePollutionUtility/tests.js:57:24:57:31 | src[key] | +| PrototypePollutionUtility/tests.js:57:24:57:31 | src[key] | +| PrototypePollutionUtility/tests.js:57:24:57:31 | src[key] | +| PrototypePollutionUtility/tests.js:57:24:57:31 | src[key] | +| PrototypePollutionUtility/tests.js:57:28:57:30 | key | +| PrototypePollutionUtility/tests.js:62:33:62:35 | src | +| PrototypePollutionUtility/tests.js:62:33:62:35 | src | +| PrototypePollutionUtility/tests.js:66:41:66:43 | src | +| PrototypePollutionUtility/tests.js:66:41:66:43 | src | +| PrototypePollutionUtility/tests.js:66:41:66:48 | src[key] | +| PrototypePollutionUtility/tests.js:66:41:66:48 | src[key] | +| PrototypePollutionUtility/tests.js:66:41:66:48 | src[key] | +| PrototypePollutionUtility/tests.js:66:41:66:48 | src[key] | +| PrototypePollutionUtility/tests.js:66:41:66:48 | src[key] | +| PrototypePollutionUtility/tests.js:68:24:68:26 | src | +| PrototypePollutionUtility/tests.js:68:24:68:26 | src | +| PrototypePollutionUtility/tests.js:68:24:68:31 | src[key] | +| PrototypePollutionUtility/tests.js:68:24:68:31 | src[key] | +| PrototypePollutionUtility/tests.js:68:24:68:31 | src[key] | +| PrototypePollutionUtility/tests.js:68:24:68:31 | src[key] | +| PrototypePollutionUtility/tests.js:68:24:68:31 | src[key] | +| PrototypePollutionUtility/tests.js:68:24:68:31 | src[key] | +| PrototypePollutionUtility/tests.js:77:27:77:29 | src | +| PrototypePollutionUtility/tests.js:77:27:77:29 | src | +| PrototypePollutionUtility/tests.js:81:39:81:41 | src | +| PrototypePollutionUtility/tests.js:81:39:81:41 | src | +| PrototypePollutionUtility/tests.js:81:39:81:46 | src[key] | +| PrototypePollutionUtility/tests.js:81:39:81:46 | src[key] | +| PrototypePollutionUtility/tests.js:81:39:81:46 | src[key] | +| PrototypePollutionUtility/tests.js:81:39:81:46 | src[key] | +| PrototypePollutionUtility/tests.js:81:39:81:46 | src[key] | +| PrototypePollutionUtility/tests.js:83:28:83:30 | src | +| PrototypePollutionUtility/tests.js:83:28:83:30 | src | +| PrototypePollutionUtility/tests.js:83:28:83:35 | src[key] | +| PrototypePollutionUtility/tests.js:83:28:83:35 | src[key] | +| PrototypePollutionUtility/tests.js:83:28:83:35 | src[key] | +| PrototypePollutionUtility/tests.js:83:28:83:35 | src[key] | +| PrototypePollutionUtility/tests.js:83:28:83:35 | src[key] | +| PrototypePollutionUtility/tests.js:83:28:83:35 | src[key] | +| PrototypePollutionUtility/tests.js:89:34:89:36 | src | +| PrototypePollutionUtility/tests.js:89:34:89:36 | src | +| PrototypePollutionUtility/tests.js:90:14:90:16 | key | +| PrototypePollutionUtility/tests.js:90:14:90:16 | key | +| PrototypePollutionUtility/tests.js:90:14:90:16 | key | +| PrototypePollutionUtility/tests.js:94:42:94:44 | src | +| PrototypePollutionUtility/tests.js:94:42:94:44 | src | +| PrototypePollutionUtility/tests.js:94:42:94:49 | src[key] | +| PrototypePollutionUtility/tests.js:94:42:94:49 | src[key] | +| PrototypePollutionUtility/tests.js:94:42:94:49 | src[key] | +| PrototypePollutionUtility/tests.js:94:42:94:49 | src[key] | +| PrototypePollutionUtility/tests.js:94:42:94:49 | src[key] | +| PrototypePollutionUtility/tests.js:96:17:96:19 | key | +| PrototypePollutionUtility/tests.js:96:17:96:19 | key | +| PrototypePollutionUtility/tests.js:96:17:96:19 | key | +| PrototypePollutionUtility/tests.js:96:24:96:26 | src | +| PrototypePollutionUtility/tests.js:96:24:96:26 | src | +| PrototypePollutionUtility/tests.js:96:24:96:31 | src[key] | +| PrototypePollutionUtility/tests.js:96:24:96:31 | src[key] | +| PrototypePollutionUtility/tests.js:96:24:96:31 | src[key] | +| PrototypePollutionUtility/tests.js:96:24:96:31 | src[key] | +| PrototypePollutionUtility/tests.js:96:24:96:31 | src[key] | +| PrototypePollutionUtility/tests.js:96:24:96:31 | src[key] | +| PrototypePollutionUtility/tests.js:96:28:96:30 | key | +| PrototypePollutionUtility/tests.js:96:28:96:30 | key | +| PrototypePollutionUtility/tests.js:101:32:101:34 | dst | +| PrototypePollutionUtility/tests.js:101:32:101:34 | dst | +| PrototypePollutionUtility/tests.js:101:37:101:39 | src | +| PrototypePollutionUtility/tests.js:101:37:101:39 | src | +| PrototypePollutionUtility/tests.js:102:14:102:16 | key | +| PrototypePollutionUtility/tests.js:102:14:102:16 | key | +| PrototypePollutionUtility/tests.js:102:14:102:16 | key | +| PrototypePollutionUtility/tests.js:107:35:107:37 | dst | +| PrototypePollutionUtility/tests.js:107:35:107:37 | dst | +| PrototypePollutionUtility/tests.js:107:35:107:42 | dst[key] | +| PrototypePollutionUtility/tests.js:107:35:107:42 | dst[key] | +| PrototypePollutionUtility/tests.js:107:35:107:42 | dst[key] | +| PrototypePollutionUtility/tests.js:107:35:107:42 | dst[key] | +| PrototypePollutionUtility/tests.js:107:39:107:41 | key | +| PrototypePollutionUtility/tests.js:107:39:107:41 | key | +| PrototypePollutionUtility/tests.js:107:45:107:47 | src | +| PrototypePollutionUtility/tests.js:107:45:107:47 | src | +| PrototypePollutionUtility/tests.js:107:45:107:52 | src[key] | +| PrototypePollutionUtility/tests.js:107:45:107:52 | src[key] | +| PrototypePollutionUtility/tests.js:107:45:107:52 | src[key] | +| PrototypePollutionUtility/tests.js:107:45:107:52 | src[key] | +| PrototypePollutionUtility/tests.js:107:45:107:52 | src[key] | +| PrototypePollutionUtility/tests.js:107:49:107:51 | key | +| PrototypePollutionUtility/tests.js:107:49:107:51 | key | +| PrototypePollutionUtility/tests.js:109:13:109:15 | dst | +| PrototypePollutionUtility/tests.js:109:13:109:15 | dst | +| PrototypePollutionUtility/tests.js:109:13:109:15 | dst | +| PrototypePollutionUtility/tests.js:109:17:109:19 | key | +| PrototypePollutionUtility/tests.js:109:17:109:19 | key | +| PrototypePollutionUtility/tests.js:109:17:109:19 | key | +| PrototypePollutionUtility/tests.js:109:24:109:26 | src | +| PrototypePollutionUtility/tests.js:109:24:109:26 | src | +| PrototypePollutionUtility/tests.js:109:24:109:31 | src[key] | +| PrototypePollutionUtility/tests.js:109:24:109:31 | src[key] | +| PrototypePollutionUtility/tests.js:109:24:109:31 | src[key] | +| PrototypePollutionUtility/tests.js:109:24:109:31 | src[key] | +| PrototypePollutionUtility/tests.js:109:24:109:31 | src[key] | +| PrototypePollutionUtility/tests.js:109:24:109:31 | src[key] | +| PrototypePollutionUtility/tests.js:109:28:109:30 | key | +| PrototypePollutionUtility/tests.js:109:28:109:30 | key | +| PrototypePollutionUtility/tests.js:116:41:116:43 | src | +| PrototypePollutionUtility/tests.js:116:41:116:43 | src | +| PrototypePollutionUtility/tests.js:117:14:117:16 | key | +| PrototypePollutionUtility/tests.js:117:14:117:16 | key | +| PrototypePollutionUtility/tests.js:117:14:117:16 | key | +| PrototypePollutionUtility/tests.js:119:49:119:51 | src | +| PrototypePollutionUtility/tests.js:119:49:119:51 | src | +| PrototypePollutionUtility/tests.js:119:49:119:56 | src[key] | +| PrototypePollutionUtility/tests.js:119:49:119:56 | src[key] | +| PrototypePollutionUtility/tests.js:119:49:119:56 | src[key] | +| PrototypePollutionUtility/tests.js:119:49:119:56 | src[key] | +| PrototypePollutionUtility/tests.js:119:49:119:56 | src[key] | +| PrototypePollutionUtility/tests.js:121:17:121:19 | key | +| PrototypePollutionUtility/tests.js:121:17:121:19 | key | +| PrototypePollutionUtility/tests.js:121:17:121:19 | key | +| PrototypePollutionUtility/tests.js:121:24:121:26 | src | +| PrototypePollutionUtility/tests.js:121:24:121:26 | src | +| PrototypePollutionUtility/tests.js:121:24:121:31 | src[key] | +| PrototypePollutionUtility/tests.js:121:24:121:31 | src[key] | +| PrototypePollutionUtility/tests.js:121:24:121:31 | src[key] | +| PrototypePollutionUtility/tests.js:121:24:121:31 | src[key] | +| PrototypePollutionUtility/tests.js:121:24:121:31 | src[key] | +| PrototypePollutionUtility/tests.js:121:24:121:31 | src[key] | +| PrototypePollutionUtility/tests.js:121:28:121:30 | key | +| PrototypePollutionUtility/tests.js:121:28:121:30 | key | +| PrototypePollutionUtility/tests.js:127:14:127:16 | key | +| PrototypePollutionUtility/tests.js:127:14:127:16 | key | +| PrototypePollutionUtility/tests.js:127:14:127:16 | key | +| PrototypePollutionUtility/tests.js:128:13:128:15 | key | +| PrototypePollutionUtility/tests.js:128:13:128:15 | key | +| PrototypePollutionUtility/tests.js:128:13:128:15 | key | +| PrototypePollutionUtility/tests.js:128:20:128:27 | src[key] | +| PrototypePollutionUtility/tests.js:128:20:128:27 | src[key] | +| PrototypePollutionUtility/tests.js:128:20:128:27 | src[key] | +| PrototypePollutionUtility/tests.js:128:20:128:27 | src[key] | +| PrototypePollutionUtility/tests.js:128:24:128:26 | key | +| PrototypePollutionUtility/tests.js:128:24:128:26 | key | +| PrototypePollutionUtility/tests.js:140:16:140:18 | src | +| PrototypePollutionUtility/tests.js:143:14:143:16 | key | +| PrototypePollutionUtility/tests.js:143:14:143:16 | key | +| PrototypePollutionUtility/tests.js:143:14:143:16 | key | +| PrototypePollutionUtility/tests.js:144:16:144:18 | key | +| PrototypePollutionUtility/tests.js:144:16:144:18 | key | +| PrototypePollutionUtility/tests.js:144:16:144:18 | key | +| PrototypePollutionUtility/tests.js:144:23:144:37 | clone(src[key]) | +| PrototypePollutionUtility/tests.js:144:23:144:37 | clone(src[key]) | +| PrototypePollutionUtility/tests.js:144:23:144:37 | clone(src[key]) | +| PrototypePollutionUtility/tests.js:144:23:144:37 | clone(src[key]) | +| PrototypePollutionUtility/tests.js:144:29:144:31 | src | +| PrototypePollutionUtility/tests.js:144:29:144:36 | src[key] | +| PrototypePollutionUtility/tests.js:144:29:144:36 | src[key] | +| PrototypePollutionUtility/tests.js:144:29:144:36 | src[key] | +| PrototypePollutionUtility/tests.js:144:29:144:36 | src[key] | +| PrototypePollutionUtility/tests.js:144:33:144:35 | key | +| PrototypePollutionUtility/tests.js:144:33:144:35 | key | +| PrototypePollutionUtility/tests.js:149:31:149:33 | dst | +| PrototypePollutionUtility/tests.js:149:31:149:33 | dst | +| PrototypePollutionUtility/tests.js:149:31:149:33 | dst | +| PrototypePollutionUtility/tests.js:149:31:149:33 | dst | +| PrototypePollutionUtility/tests.js:149:36:149:38 | src | +| PrototypePollutionUtility/tests.js:149:36:149:38 | src | +| PrototypePollutionUtility/tests.js:149:36:149:38 | src | +| PrototypePollutionUtility/tests.js:149:36:149:38 | src | +| PrototypePollutionUtility/tests.js:150:14:150:16 | key | +| PrototypePollutionUtility/tests.js:150:14:150:16 | key | +| PrototypePollutionUtility/tests.js:150:14:150:16 | key | +| PrototypePollutionUtility/tests.js:152:22:152:24 | dst | +| PrototypePollutionUtility/tests.js:152:22:152:24 | dst | +| PrototypePollutionUtility/tests.js:152:22:152:24 | dst | +| PrototypePollutionUtility/tests.js:152:22:152:24 | dst | +| PrototypePollutionUtility/tests.js:152:27:152:29 | src | +| PrototypePollutionUtility/tests.js:152:27:152:29 | src | +| PrototypePollutionUtility/tests.js:152:27:152:29 | src | +| PrototypePollutionUtility/tests.js:152:27:152:29 | src | +| PrototypePollutionUtility/tests.js:152:32:152:34 | key | +| PrototypePollutionUtility/tests.js:152:32:152:34 | key | +| PrototypePollutionUtility/tests.js:154:13:154:15 | dst | +| PrototypePollutionUtility/tests.js:154:13:154:15 | dst | +| PrototypePollutionUtility/tests.js:154:13:154:15 | dst | +| PrototypePollutionUtility/tests.js:154:13:154:15 | dst | +| PrototypePollutionUtility/tests.js:154:13:154:15 | dst | +| PrototypePollutionUtility/tests.js:154:17:154:19 | key | +| PrototypePollutionUtility/tests.js:154:17:154:19 | key | +| PrototypePollutionUtility/tests.js:154:17:154:19 | key | +| PrototypePollutionUtility/tests.js:154:24:154:26 | src | +| PrototypePollutionUtility/tests.js:154:24:154:26 | src | +| PrototypePollutionUtility/tests.js:154:24:154:26 | src | +| PrototypePollutionUtility/tests.js:154:24:154:26 | src | +| PrototypePollutionUtility/tests.js:154:24:154:31 | src[key] | +| PrototypePollutionUtility/tests.js:154:24:154:31 | src[key] | +| PrototypePollutionUtility/tests.js:154:24:154:31 | src[key] | +| PrototypePollutionUtility/tests.js:154:24:154:31 | src[key] | +| PrototypePollutionUtility/tests.js:154:24:154:31 | src[key] | +| PrototypePollutionUtility/tests.js:154:24:154:31 | src[key] | +| PrototypePollutionUtility/tests.js:154:24:154:31 | src[key] | +| PrototypePollutionUtility/tests.js:154:24:154:31 | src[key] | +| PrototypePollutionUtility/tests.js:154:28:154:30 | key | +| PrototypePollutionUtility/tests.js:154:28:154:30 | key | +| PrototypePollutionUtility/tests.js:159:36:159:38 | dst | +| PrototypePollutionUtility/tests.js:159:36:159:38 | dst | +| PrototypePollutionUtility/tests.js:159:36:159:38 | dst | +| PrototypePollutionUtility/tests.js:159:36:159:38 | dst | +| PrototypePollutionUtility/tests.js:159:41:159:43 | src | +| PrototypePollutionUtility/tests.js:159:41:159:43 | src | +| PrototypePollutionUtility/tests.js:159:41:159:43 | src | +| PrototypePollutionUtility/tests.js:159:41:159:43 | src | +| PrototypePollutionUtility/tests.js:160:26:160:28 | dst | +| PrototypePollutionUtility/tests.js:160:26:160:28 | dst | +| PrototypePollutionUtility/tests.js:160:26:160:28 | dst | +| PrototypePollutionUtility/tests.js:160:26:160:28 | dst | +| PrototypePollutionUtility/tests.js:160:31:160:33 | src | +| PrototypePollutionUtility/tests.js:160:31:160:33 | src | +| PrototypePollutionUtility/tests.js:160:31:160:33 | src | +| PrototypePollutionUtility/tests.js:160:31:160:33 | src | +| PrototypePollutionUtility/tests.js:160:37:160:39 | dst | +| PrototypePollutionUtility/tests.js:160:37:160:39 | dst | +| PrototypePollutionUtility/tests.js:160:37:160:39 | dst | +| PrototypePollutionUtility/tests.js:160:37:160:39 | dst | +| PrototypePollutionUtility/tests.js:160:42:160:44 | src | +| PrototypePollutionUtility/tests.js:160:42:160:44 | src | +| PrototypePollutionUtility/tests.js:160:42:160:44 | src | +| PrototypePollutionUtility/tests.js:160:42:160:44 | src | +| PrototypePollutionUtility/tests.js:160:47:160:49 | key | +| PrototypePollutionUtility/tests.js:160:47:160:49 | key | +| PrototypePollutionUtility/tests.js:160:47:160:49 | key | +| PrototypePollutionUtility/tests.js:160:47:160:49 | key | +| PrototypePollutionUtility/tests.js:161:35:161:37 | dst | +| PrototypePollutionUtility/tests.js:161:35:161:37 | dst | +| PrototypePollutionUtility/tests.js:161:35:161:37 | dst | +| PrototypePollutionUtility/tests.js:161:35:161:37 | dst | +| PrototypePollutionUtility/tests.js:161:35:161:42 | dst[key] | +| PrototypePollutionUtility/tests.js:161:35:161:42 | dst[key] | +| PrototypePollutionUtility/tests.js:161:35:161:42 | dst[key] | +| PrototypePollutionUtility/tests.js:161:35:161:42 | dst[key] | +| PrototypePollutionUtility/tests.js:161:39:161:41 | key | +| PrototypePollutionUtility/tests.js:161:39:161:41 | key | +| PrototypePollutionUtility/tests.js:161:39:161:41 | key | +| PrototypePollutionUtility/tests.js:161:39:161:41 | key | +| PrototypePollutionUtility/tests.js:161:45:161:47 | src | +| PrototypePollutionUtility/tests.js:161:45:161:47 | src | +| PrototypePollutionUtility/tests.js:161:45:161:47 | src | +| PrototypePollutionUtility/tests.js:161:45:161:47 | src | +| PrototypePollutionUtility/tests.js:161:45:161:52 | src[key] | +| PrototypePollutionUtility/tests.js:161:45:161:52 | src[key] | +| PrototypePollutionUtility/tests.js:161:45:161:52 | src[key] | +| PrototypePollutionUtility/tests.js:161:45:161:52 | src[key] | +| PrototypePollutionUtility/tests.js:161:49:161:51 | key | +| PrototypePollutionUtility/tests.js:161:49:161:51 | key | +| PrototypePollutionUtility/tests.js:161:49:161:51 | key | +| PrototypePollutionUtility/tests.js:161:49:161:51 | key | +| PrototypePollutionUtility/tests.js:165:37:165:39 | src | +| PrototypePollutionUtility/tests.js:165:37:165:39 | src | +| PrototypePollutionUtility/tests.js:166:14:166:16 | key | +| PrototypePollutionUtility/tests.js:166:14:166:16 | key | +| PrototypePollutionUtility/tests.js:166:14:166:16 | key | +| PrototypePollutionUtility/tests.js:169:45:169:47 | src | +| PrototypePollutionUtility/tests.js:169:45:169:47 | src | +| PrototypePollutionUtility/tests.js:169:45:169:52 | src[key] | +| PrototypePollutionUtility/tests.js:169:45:169:52 | src[key] | +| PrototypePollutionUtility/tests.js:169:45:169:52 | src[key] | +| PrototypePollutionUtility/tests.js:169:45:169:52 | src[key] | +| PrototypePollutionUtility/tests.js:169:45:169:52 | src[key] | +| PrototypePollutionUtility/tests.js:169:49:169:51 | key | +| PrototypePollutionUtility/tests.js:169:49:169:51 | key | +| PrototypePollutionUtility/tests.js:171:17:171:19 | key | +| PrototypePollutionUtility/tests.js:171:17:171:19 | key | +| PrototypePollutionUtility/tests.js:171:17:171:19 | key | +| PrototypePollutionUtility/tests.js:171:24:171:26 | src | +| PrototypePollutionUtility/tests.js:171:24:171:26 | src | +| PrototypePollutionUtility/tests.js:171:24:171:31 | src[key] | +| PrototypePollutionUtility/tests.js:171:24:171:31 | src[key] | +| PrototypePollutionUtility/tests.js:171:24:171:31 | src[key] | +| PrototypePollutionUtility/tests.js:171:24:171:31 | src[key] | +| PrototypePollutionUtility/tests.js:171:24:171:31 | src[key] | +| PrototypePollutionUtility/tests.js:171:24:171:31 | src[key] | +| PrototypePollutionUtility/tests.js:171:28:171:30 | key | +| PrototypePollutionUtility/tests.js:171:28:171:30 | key | +| PrototypePollutionUtility/tests.js:178:33:178:35 | src | +| PrototypePollutionUtility/tests.js:178:33:178:35 | src | +| PrototypePollutionUtility/tests.js:182:41:182:43 | src | +| PrototypePollutionUtility/tests.js:182:41:182:43 | src | +| PrototypePollutionUtility/tests.js:182:41:182:48 | src[key] | +| PrototypePollutionUtility/tests.js:182:41:182:48 | src[key] | +| PrototypePollutionUtility/tests.js:182:41:182:48 | src[key] | +| PrototypePollutionUtility/tests.js:182:41:182:48 | src[key] | +| PrototypePollutionUtility/tests.js:182:41:182:48 | src[key] | +| PrototypePollutionUtility/tests.js:184:24:184:26 | src | +| PrototypePollutionUtility/tests.js:184:24:184:26 | src | +| PrototypePollutionUtility/tests.js:184:24:184:31 | src[key] | +| PrototypePollutionUtility/tests.js:184:24:184:31 | src[key] | +| PrototypePollutionUtility/tests.js:184:24:184:31 | src[key] | +| PrototypePollutionUtility/tests.js:184:24:184:31 | src[key] | +| PrototypePollutionUtility/tests.js:184:24:184:31 | src[key] | +| PrototypePollutionUtility/tests.js:184:24:184:31 | src[key] | +| PrototypePollutionUtility/tests.js:189:32:189:34 | dst | +| PrototypePollutionUtility/tests.js:189:32:189:34 | dst | +| PrototypePollutionUtility/tests.js:189:37:189:39 | src | +| PrototypePollutionUtility/tests.js:189:37:189:39 | src | +| PrototypePollutionUtility/tests.js:192:13:192:25 | key | +| PrototypePollutionUtility/tests.js:192:13:192:25 | key | +| PrototypePollutionUtility/tests.js:192:19:192:25 | keys[i] | +| PrototypePollutionUtility/tests.js:192:19:192:25 | keys[i] | +| PrototypePollutionUtility/tests.js:192:19:192:25 | keys[i] | +| PrototypePollutionUtility/tests.js:194:35:194:37 | dst | +| PrototypePollutionUtility/tests.js:194:35:194:37 | dst | +| PrototypePollutionUtility/tests.js:194:35:194:42 | dst[key] | +| PrototypePollutionUtility/tests.js:194:35:194:42 | dst[key] | +| PrototypePollutionUtility/tests.js:194:35:194:42 | dst[key] | +| PrototypePollutionUtility/tests.js:194:35:194:42 | dst[key] | +| PrototypePollutionUtility/tests.js:194:39:194:41 | key | +| PrototypePollutionUtility/tests.js:194:39:194:41 | key | +| PrototypePollutionUtility/tests.js:194:45:194:47 | src | +| PrototypePollutionUtility/tests.js:194:45:194:47 | src | +| PrototypePollutionUtility/tests.js:194:45:194:52 | src[key] | +| PrototypePollutionUtility/tests.js:194:45:194:52 | src[key] | +| PrototypePollutionUtility/tests.js:194:45:194:52 | src[key] | +| PrototypePollutionUtility/tests.js:194:45:194:52 | src[key] | +| PrototypePollutionUtility/tests.js:194:45:194:52 | src[key] | +| PrototypePollutionUtility/tests.js:194:49:194:51 | key | +| PrototypePollutionUtility/tests.js:194:49:194:51 | key | +| PrototypePollutionUtility/tests.js:196:13:196:15 | dst | +| PrototypePollutionUtility/tests.js:196:13:196:15 | dst | +| PrototypePollutionUtility/tests.js:196:13:196:15 | dst | +| PrototypePollutionUtility/tests.js:196:17:196:19 | key | +| PrototypePollutionUtility/tests.js:196:17:196:19 | key | +| PrototypePollutionUtility/tests.js:196:17:196:19 | key | +| PrototypePollutionUtility/tests.js:196:24:196:26 | src | +| PrototypePollutionUtility/tests.js:196:24:196:26 | src | +| PrototypePollutionUtility/tests.js:196:24:196:31 | src[key] | +| PrototypePollutionUtility/tests.js:196:24:196:31 | src[key] | +| PrototypePollutionUtility/tests.js:196:24:196:31 | src[key] | +| PrototypePollutionUtility/tests.js:196:24:196:31 | src[key] | +| PrototypePollutionUtility/tests.js:196:24:196:31 | src[key] | +| PrototypePollutionUtility/tests.js:196:24:196:31 | src[key] | +| PrototypePollutionUtility/tests.js:196:28:196:30 | key | +| PrototypePollutionUtility/tests.js:196:28:196:30 | key | +| PrototypePollutionUtility/tests.js:201:39:201:41 | dst | +| PrototypePollutionUtility/tests.js:201:39:201:41 | dst | +| PrototypePollutionUtility/tests.js:201:44:201:46 | src | +| PrototypePollutionUtility/tests.js:201:44:201:46 | src | +| PrototypePollutionUtility/tests.js:206:42:206:44 | dst | +| PrototypePollutionUtility/tests.js:206:42:206:44 | dst | +| PrototypePollutionUtility/tests.js:206:42:206:53 | dst[keys[i]] | +| PrototypePollutionUtility/tests.js:206:42:206:53 | dst[keys[i]] | +| PrototypePollutionUtility/tests.js:206:42:206:53 | dst[keys[i]] | +| PrototypePollutionUtility/tests.js:206:42:206:53 | dst[keys[i]] | +| PrototypePollutionUtility/tests.js:206:46:206:52 | keys[i] | +| PrototypePollutionUtility/tests.js:206:46:206:52 | keys[i] | +| PrototypePollutionUtility/tests.js:206:46:206:52 | keys[i] | +| PrototypePollutionUtility/tests.js:206:56:206:58 | src | +| PrototypePollutionUtility/tests.js:206:56:206:58 | src | +| PrototypePollutionUtility/tests.js:206:56:206:67 | src[keys[i]] | +| PrototypePollutionUtility/tests.js:206:56:206:67 | src[keys[i]] | +| PrototypePollutionUtility/tests.js:206:56:206:67 | src[keys[i]] | +| PrototypePollutionUtility/tests.js:206:56:206:67 | src[keys[i]] | +| PrototypePollutionUtility/tests.js:206:56:206:67 | src[keys[i]] | +| PrototypePollutionUtility/tests.js:206:60:206:66 | keys[i] | +| PrototypePollutionUtility/tests.js:206:60:206:66 | keys[i] | +| PrototypePollutionUtility/tests.js:206:60:206:66 | keys[i] | +| PrototypePollutionUtility/tests.js:208:13:208:15 | dst | +| PrototypePollutionUtility/tests.js:208:13:208:15 | dst | +| PrototypePollutionUtility/tests.js:208:13:208:15 | dst | +| PrototypePollutionUtility/tests.js:208:17:208:23 | keys[i] | +| PrototypePollutionUtility/tests.js:208:17:208:23 | keys[i] | +| PrototypePollutionUtility/tests.js:208:17:208:23 | keys[i] | +| PrototypePollutionUtility/tests.js:208:17:208:23 | keys[i] | +| PrototypePollutionUtility/tests.js:208:28:208:30 | src | +| PrototypePollutionUtility/tests.js:208:28:208:30 | src | +| PrototypePollutionUtility/tests.js:208:28:208:39 | src[keys[i]] | +| PrototypePollutionUtility/tests.js:208:28:208:39 | src[keys[i]] | +| PrototypePollutionUtility/tests.js:208:28:208:39 | src[keys[i]] | +| PrototypePollutionUtility/tests.js:208:28:208:39 | src[keys[i]] | +| PrototypePollutionUtility/tests.js:208:28:208:39 | src[keys[i]] | +| PrototypePollutionUtility/tests.js:208:28:208:39 | src[keys[i]] | +| PrototypePollutionUtility/tests.js:208:32:208:38 | keys[i] | +| PrototypePollutionUtility/tests.js:208:32:208:38 | keys[i] | +| PrototypePollutionUtility/tests.js:208:32:208:38 | keys[i] | +edges +| PrototypePollutionUtility/tests.js:3:25:3:27 | dst | PrototypePollutionUtility/tests.js:6:28:6:30 | dst | +| PrototypePollutionUtility/tests.js:3:25:3:27 | dst | PrototypePollutionUtility/tests.js:6:28:6:30 | dst | +| PrototypePollutionUtility/tests.js:3:25:3:27 | dst | PrototypePollutionUtility/tests.js:8:13:8:15 | dst | +| PrototypePollutionUtility/tests.js:3:25:3:27 | dst | PrototypePollutionUtility/tests.js:8:13:8:15 | dst | +| PrototypePollutionUtility/tests.js:3:25:3:27 | dst | PrototypePollutionUtility/tests.js:8:13:8:15 | dst | +| PrototypePollutionUtility/tests.js:3:25:3:27 | dst | PrototypePollutionUtility/tests.js:8:13:8:15 | dst | +| PrototypePollutionUtility/tests.js:3:30:3:32 | src | PrototypePollutionUtility/tests.js:6:38:6:40 | src | +| PrototypePollutionUtility/tests.js:3:30:3:32 | src | PrototypePollutionUtility/tests.js:6:38:6:40 | src | +| PrototypePollutionUtility/tests.js:3:30:3:32 | src | PrototypePollutionUtility/tests.js:8:24:8:26 | src | +| PrototypePollutionUtility/tests.js:3:30:3:32 | src | PrototypePollutionUtility/tests.js:8:24:8:26 | src | +| PrototypePollutionUtility/tests.js:4:14:4:16 | key | PrototypePollutionUtility/tests.js:6:32:6:34 | key | +| PrototypePollutionUtility/tests.js:4:14:4:16 | key | PrototypePollutionUtility/tests.js:6:32:6:34 | key | +| PrototypePollutionUtility/tests.js:4:14:4:16 | key | PrototypePollutionUtility/tests.js:6:32:6:34 | key | +| PrototypePollutionUtility/tests.js:4:14:4:16 | key | PrototypePollutionUtility/tests.js:6:32:6:34 | key | +| PrototypePollutionUtility/tests.js:4:14:4:16 | key | PrototypePollutionUtility/tests.js:6:42:6:44 | key | +| PrototypePollutionUtility/tests.js:4:14:4:16 | key | PrototypePollutionUtility/tests.js:6:42:6:44 | key | +| PrototypePollutionUtility/tests.js:4:14:4:16 | key | PrototypePollutionUtility/tests.js:6:42:6:44 | key | +| PrototypePollutionUtility/tests.js:4:14:4:16 | key | PrototypePollutionUtility/tests.js:6:42:6:44 | key | +| PrototypePollutionUtility/tests.js:4:14:4:16 | key | PrototypePollutionUtility/tests.js:8:17:8:19 | key | +| PrototypePollutionUtility/tests.js:4:14:4:16 | key | PrototypePollutionUtility/tests.js:8:17:8:19 | key | +| PrototypePollutionUtility/tests.js:4:14:4:16 | key | PrototypePollutionUtility/tests.js:8:17:8:19 | key | +| PrototypePollutionUtility/tests.js:4:14:4:16 | key | PrototypePollutionUtility/tests.js:8:17:8:19 | key | +| PrototypePollutionUtility/tests.js:4:14:4:16 | key | PrototypePollutionUtility/tests.js:8:17:8:19 | key | +| PrototypePollutionUtility/tests.js:4:14:4:16 | key | PrototypePollutionUtility/tests.js:8:17:8:19 | key | +| PrototypePollutionUtility/tests.js:4:14:4:16 | key | PrototypePollutionUtility/tests.js:8:17:8:19 | key | +| PrototypePollutionUtility/tests.js:4:14:4:16 | key | PrototypePollutionUtility/tests.js:8:28:8:30 | key | +| PrototypePollutionUtility/tests.js:4:14:4:16 | key | PrototypePollutionUtility/tests.js:8:28:8:30 | key | +| PrototypePollutionUtility/tests.js:4:14:4:16 | key | PrototypePollutionUtility/tests.js:8:28:8:30 | key | +| PrototypePollutionUtility/tests.js:4:14:4:16 | key | PrototypePollutionUtility/tests.js:8:28:8:30 | key | +| PrototypePollutionUtility/tests.js:6:28:6:30 | dst | PrototypePollutionUtility/tests.js:6:28:6:35 | dst[key] | +| PrototypePollutionUtility/tests.js:6:28:6:30 | dst | PrototypePollutionUtility/tests.js:6:28:6:35 | dst[key] | +| PrototypePollutionUtility/tests.js:6:28:6:35 | dst[key] | PrototypePollutionUtility/tests.js:3:25:3:27 | dst | +| PrototypePollutionUtility/tests.js:6:28:6:35 | dst[key] | PrototypePollutionUtility/tests.js:3:25:3:27 | dst | +| PrototypePollutionUtility/tests.js:6:28:6:35 | dst[key] | PrototypePollutionUtility/tests.js:3:25:3:27 | dst | +| PrototypePollutionUtility/tests.js:6:28:6:35 | dst[key] | PrototypePollutionUtility/tests.js:3:25:3:27 | dst | +| PrototypePollutionUtility/tests.js:6:32:6:34 | key | PrototypePollutionUtility/tests.js:6:28:6:35 | dst[key] | +| PrototypePollutionUtility/tests.js:6:32:6:34 | key | PrototypePollutionUtility/tests.js:6:28:6:35 | dst[key] | +| PrototypePollutionUtility/tests.js:6:38:6:40 | src | PrototypePollutionUtility/tests.js:6:38:6:45 | src[key] | +| PrototypePollutionUtility/tests.js:6:38:6:40 | src | PrototypePollutionUtility/tests.js:6:38:6:45 | src[key] | +| PrototypePollutionUtility/tests.js:6:38:6:45 | src[key] | PrototypePollutionUtility/tests.js:3:30:3:32 | src | +| PrototypePollutionUtility/tests.js:6:38:6:45 | src[key] | PrototypePollutionUtility/tests.js:3:30:3:32 | src | +| PrototypePollutionUtility/tests.js:6:38:6:45 | src[key] | PrototypePollutionUtility/tests.js:3:30:3:32 | src | +| PrototypePollutionUtility/tests.js:6:38:6:45 | src[key] | PrototypePollutionUtility/tests.js:3:30:3:32 | src | +| PrototypePollutionUtility/tests.js:6:38:6:45 | src[key] | PrototypePollutionUtility/tests.js:3:30:3:32 | src | +| PrototypePollutionUtility/tests.js:6:38:6:45 | src[key] | PrototypePollutionUtility/tests.js:3:30:3:32 | src | +| PrototypePollutionUtility/tests.js:6:42:6:44 | key | PrototypePollutionUtility/tests.js:6:38:6:45 | src[key] | +| PrototypePollutionUtility/tests.js:6:42:6:44 | key | PrototypePollutionUtility/tests.js:6:38:6:45 | src[key] | +| PrototypePollutionUtility/tests.js:8:24:8:26 | src | PrototypePollutionUtility/tests.js:8:24:8:31 | src[key] | +| PrototypePollutionUtility/tests.js:8:24:8:26 | src | PrototypePollutionUtility/tests.js:8:24:8:31 | src[key] | +| PrototypePollutionUtility/tests.js:8:24:8:26 | src | PrototypePollutionUtility/tests.js:8:24:8:31 | src[key] | +| PrototypePollutionUtility/tests.js:8:24:8:26 | src | PrototypePollutionUtility/tests.js:8:24:8:31 | src[key] | +| PrototypePollutionUtility/tests.js:8:24:8:31 | src[key] | PrototypePollutionUtility/tests.js:8:24:8:31 | src[key] | +| PrototypePollutionUtility/tests.js:8:28:8:30 | key | PrototypePollutionUtility/tests.js:8:24:8:31 | src[key] | +| PrototypePollutionUtility/tests.js:8:28:8:30 | key | PrototypePollutionUtility/tests.js:8:24:8:31 | src[key] | +| PrototypePollutionUtility/tests.js:8:28:8:30 | key | PrototypePollutionUtility/tests.js:8:24:8:31 | src[key] | +| PrototypePollutionUtility/tests.js:8:28:8:30 | key | PrototypePollutionUtility/tests.js:8:24:8:31 | src[key] | +| PrototypePollutionUtility/tests.js:13:24:13:26 | dst | PrototypePollutionUtility/tests.js:16:27:16:29 | dst | +| PrototypePollutionUtility/tests.js:13:24:13:26 | dst | PrototypePollutionUtility/tests.js:16:27:16:29 | dst | +| PrototypePollutionUtility/tests.js:13:24:13:26 | dst | PrototypePollutionUtility/tests.js:18:13:18:15 | dst | +| PrototypePollutionUtility/tests.js:13:24:13:26 | dst | PrototypePollutionUtility/tests.js:18:13:18:15 | dst | +| PrototypePollutionUtility/tests.js:13:24:13:26 | dst | PrototypePollutionUtility/tests.js:18:13:18:15 | dst | +| PrototypePollutionUtility/tests.js:13:24:13:26 | dst | PrototypePollutionUtility/tests.js:18:13:18:15 | dst | +| PrototypePollutionUtility/tests.js:13:29:13:31 | src | PrototypePollutionUtility/tests.js:16:37:16:39 | src | +| PrototypePollutionUtility/tests.js:13:29:13:31 | src | PrototypePollutionUtility/tests.js:16:37:16:39 | src | +| PrototypePollutionUtility/tests.js:13:29:13:31 | src | PrototypePollutionUtility/tests.js:18:24:18:26 | src | +| PrototypePollutionUtility/tests.js:13:29:13:31 | src | PrototypePollutionUtility/tests.js:18:24:18:26 | src | +| PrototypePollutionUtility/tests.js:14:30:14:32 | key | PrototypePollutionUtility/tests.js:16:31:16:33 | key | +| PrototypePollutionUtility/tests.js:14:30:14:32 | key | PrototypePollutionUtility/tests.js:16:31:16:33 | key | +| PrototypePollutionUtility/tests.js:14:30:14:32 | key | PrototypePollutionUtility/tests.js:16:31:16:33 | key | +| PrototypePollutionUtility/tests.js:14:30:14:32 | key | PrototypePollutionUtility/tests.js:16:31:16:33 | key | +| PrototypePollutionUtility/tests.js:14:30:14:32 | key | PrototypePollutionUtility/tests.js:16:41:16:43 | key | +| PrototypePollutionUtility/tests.js:14:30:14:32 | key | PrototypePollutionUtility/tests.js:16:41:16:43 | key | +| PrototypePollutionUtility/tests.js:14:30:14:32 | key | PrototypePollutionUtility/tests.js:16:41:16:43 | key | +| PrototypePollutionUtility/tests.js:14:30:14:32 | key | PrototypePollutionUtility/tests.js:16:41:16:43 | key | +| PrototypePollutionUtility/tests.js:14:30:14:32 | key | PrototypePollutionUtility/tests.js:18:17:18:19 | key | +| PrototypePollutionUtility/tests.js:14:30:14:32 | key | PrototypePollutionUtility/tests.js:18:17:18:19 | key | +| PrototypePollutionUtility/tests.js:14:30:14:32 | key | PrototypePollutionUtility/tests.js:18:17:18:19 | key | +| PrototypePollutionUtility/tests.js:14:30:14:32 | key | PrototypePollutionUtility/tests.js:18:17:18:19 | key | +| PrototypePollutionUtility/tests.js:14:30:14:32 | key | PrototypePollutionUtility/tests.js:18:17:18:19 | key | +| PrototypePollutionUtility/tests.js:14:30:14:32 | key | PrototypePollutionUtility/tests.js:18:17:18:19 | key | +| PrototypePollutionUtility/tests.js:14:30:14:32 | key | PrototypePollutionUtility/tests.js:18:17:18:19 | key | +| PrototypePollutionUtility/tests.js:14:30:14:32 | key | PrototypePollutionUtility/tests.js:18:28:18:30 | key | +| PrototypePollutionUtility/tests.js:14:30:14:32 | key | PrototypePollutionUtility/tests.js:18:28:18:30 | key | +| PrototypePollutionUtility/tests.js:14:30:14:32 | key | PrototypePollutionUtility/tests.js:18:28:18:30 | key | +| PrototypePollutionUtility/tests.js:14:30:14:32 | key | PrototypePollutionUtility/tests.js:18:28:18:30 | key | +| PrototypePollutionUtility/tests.js:16:27:16:29 | dst | PrototypePollutionUtility/tests.js:16:27:16:34 | dst[key] | +| PrototypePollutionUtility/tests.js:16:27:16:29 | dst | PrototypePollutionUtility/tests.js:16:27:16:34 | dst[key] | +| PrototypePollutionUtility/tests.js:16:27:16:34 | dst[key] | PrototypePollutionUtility/tests.js:13:24:13:26 | dst | +| PrototypePollutionUtility/tests.js:16:27:16:34 | dst[key] | PrototypePollutionUtility/tests.js:13:24:13:26 | dst | +| PrototypePollutionUtility/tests.js:16:27:16:34 | dst[key] | PrototypePollutionUtility/tests.js:13:24:13:26 | dst | +| PrototypePollutionUtility/tests.js:16:27:16:34 | dst[key] | PrototypePollutionUtility/tests.js:13:24:13:26 | dst | +| PrototypePollutionUtility/tests.js:16:31:16:33 | key | PrototypePollutionUtility/tests.js:16:27:16:34 | dst[key] | +| PrototypePollutionUtility/tests.js:16:31:16:33 | key | PrototypePollutionUtility/tests.js:16:27:16:34 | dst[key] | +| PrototypePollutionUtility/tests.js:16:37:16:39 | src | PrototypePollutionUtility/tests.js:16:37:16:44 | src[key] | +| PrototypePollutionUtility/tests.js:16:37:16:39 | src | PrototypePollutionUtility/tests.js:16:37:16:44 | src[key] | +| PrototypePollutionUtility/tests.js:16:37:16:44 | src[key] | PrototypePollutionUtility/tests.js:13:29:13:31 | src | +| PrototypePollutionUtility/tests.js:16:37:16:44 | src[key] | PrototypePollutionUtility/tests.js:13:29:13:31 | src | +| PrototypePollutionUtility/tests.js:16:37:16:44 | src[key] | PrototypePollutionUtility/tests.js:13:29:13:31 | src | +| PrototypePollutionUtility/tests.js:16:37:16:44 | src[key] | PrototypePollutionUtility/tests.js:13:29:13:31 | src | +| PrototypePollutionUtility/tests.js:16:37:16:44 | src[key] | PrototypePollutionUtility/tests.js:13:29:13:31 | src | +| PrototypePollutionUtility/tests.js:16:37:16:44 | src[key] | PrototypePollutionUtility/tests.js:13:29:13:31 | src | +| PrototypePollutionUtility/tests.js:16:41:16:43 | key | PrototypePollutionUtility/tests.js:16:37:16:44 | src[key] | +| PrototypePollutionUtility/tests.js:16:41:16:43 | key | PrototypePollutionUtility/tests.js:16:37:16:44 | src[key] | +| PrototypePollutionUtility/tests.js:18:24:18:26 | src | PrototypePollutionUtility/tests.js:18:24:18:31 | src[key] | +| PrototypePollutionUtility/tests.js:18:24:18:26 | src | PrototypePollutionUtility/tests.js:18:24:18:31 | src[key] | +| PrototypePollutionUtility/tests.js:18:24:18:26 | src | PrototypePollutionUtility/tests.js:18:24:18:31 | src[key] | +| PrototypePollutionUtility/tests.js:18:24:18:26 | src | PrototypePollutionUtility/tests.js:18:24:18:31 | src[key] | +| PrototypePollutionUtility/tests.js:18:24:18:31 | src[key] | PrototypePollutionUtility/tests.js:18:24:18:31 | src[key] | +| PrototypePollutionUtility/tests.js:18:28:18:30 | key | PrototypePollutionUtility/tests.js:18:24:18:31 | src[key] | +| PrototypePollutionUtility/tests.js:18:28:18:30 | key | PrototypePollutionUtility/tests.js:18:24:18:31 | src[key] | +| PrototypePollutionUtility/tests.js:18:28:18:30 | key | PrototypePollutionUtility/tests.js:18:24:18:31 | src[key] | +| PrototypePollutionUtility/tests.js:18:28:18:30 | key | PrototypePollutionUtility/tests.js:18:24:18:31 | src[key] | +| PrototypePollutionUtility/tests.js:23:19:23:21 | dst | PrototypePollutionUtility/tests.js:26:25:26:27 | dst | +| PrototypePollutionUtility/tests.js:23:19:23:21 | dst | PrototypePollutionUtility/tests.js:26:25:26:27 | dst | +| PrototypePollutionUtility/tests.js:25:18:25:20 | key | PrototypePollutionUtility/tests.js:26:37:26:39 | key | +| PrototypePollutionUtility/tests.js:25:18:25:20 | key | PrototypePollutionUtility/tests.js:26:37:26:39 | key | +| PrototypePollutionUtility/tests.js:25:18:25:20 | key | PrototypePollutionUtility/tests.js:26:37:26:39 | key | +| PrototypePollutionUtility/tests.js:25:18:25:20 | key | PrototypePollutionUtility/tests.js:26:37:26:39 | key | +| PrototypePollutionUtility/tests.js:25:18:25:20 | key | PrototypePollutionUtility/tests.js:26:43:26:45 | key | +| PrototypePollutionUtility/tests.js:25:18:25:20 | key | PrototypePollutionUtility/tests.js:26:43:26:45 | key | +| PrototypePollutionUtility/tests.js:25:18:25:20 | key | PrototypePollutionUtility/tests.js:26:43:26:45 | key | +| PrototypePollutionUtility/tests.js:25:18:25:20 | key | PrototypePollutionUtility/tests.js:26:43:26:45 | key | +| PrototypePollutionUtility/tests.js:26:25:26:27 | dst | PrototypePollutionUtility/tests.js:31:22:31:24 | dst | +| PrototypePollutionUtility/tests.js:26:25:26:27 | dst | PrototypePollutionUtility/tests.js:31:22:31:24 | dst | +| PrototypePollutionUtility/tests.js:26:30:26:40 | source[key] | PrototypePollutionUtility/tests.js:31:27:31:31 | value | +| PrototypePollutionUtility/tests.js:26:30:26:40 | source[key] | PrototypePollutionUtility/tests.js:31:27:31:31 | value | +| PrototypePollutionUtility/tests.js:26:30:26:40 | source[key] | PrototypePollutionUtility/tests.js:31:27:31:31 | value | +| PrototypePollutionUtility/tests.js:26:30:26:40 | source[key] | PrototypePollutionUtility/tests.js:31:27:31:31 | value | +| PrototypePollutionUtility/tests.js:26:37:26:39 | key | PrototypePollutionUtility/tests.js:26:30:26:40 | source[key] | +| PrototypePollutionUtility/tests.js:26:37:26:39 | key | PrototypePollutionUtility/tests.js:26:30:26:40 | source[key] | +| PrototypePollutionUtility/tests.js:26:43:26:45 | key | PrototypePollutionUtility/tests.js:31:34:31:36 | key | +| PrototypePollutionUtility/tests.js:26:43:26:45 | key | PrototypePollutionUtility/tests.js:31:34:31:36 | key | +| PrototypePollutionUtility/tests.js:31:22:31:24 | dst | PrototypePollutionUtility/tests.js:32:20:32:22 | dst | +| PrototypePollutionUtility/tests.js:31:22:31:24 | dst | PrototypePollutionUtility/tests.js:32:20:32:22 | dst | +| PrototypePollutionUtility/tests.js:31:22:31:24 | dst | PrototypePollutionUtility/tests.js:36:9:36:11 | dst | +| PrototypePollutionUtility/tests.js:31:22:31:24 | dst | PrototypePollutionUtility/tests.js:36:9:36:11 | dst | +| PrototypePollutionUtility/tests.js:31:22:31:24 | dst | PrototypePollutionUtility/tests.js:36:9:36:11 | dst | +| PrototypePollutionUtility/tests.js:31:22:31:24 | dst | PrototypePollutionUtility/tests.js:36:9:36:11 | dst | +| PrototypePollutionUtility/tests.js:31:27:31:31 | value | PrototypePollutionUtility/tests.js:36:20:36:24 | value | +| PrototypePollutionUtility/tests.js:31:27:31:31 | value | PrototypePollutionUtility/tests.js:36:20:36:24 | value | +| PrototypePollutionUtility/tests.js:31:27:31:31 | value | PrototypePollutionUtility/tests.js:36:20:36:24 | value | +| PrototypePollutionUtility/tests.js:31:27:31:31 | value | PrototypePollutionUtility/tests.js:36:20:36:24 | value | +| PrototypePollutionUtility/tests.js:31:34:31:36 | key | PrototypePollutionUtility/tests.js:32:24:32:26 | key | +| PrototypePollutionUtility/tests.js:31:34:31:36 | key | PrototypePollutionUtility/tests.js:32:24:32:26 | key | +| PrototypePollutionUtility/tests.js:31:34:31:36 | key | PrototypePollutionUtility/tests.js:36:13:36:15 | key | +| PrototypePollutionUtility/tests.js:31:34:31:36 | key | PrototypePollutionUtility/tests.js:36:13:36:15 | key | +| PrototypePollutionUtility/tests.js:31:34:31:36 | key | PrototypePollutionUtility/tests.js:36:13:36:15 | key | +| PrototypePollutionUtility/tests.js:31:34:31:36 | key | PrototypePollutionUtility/tests.js:36:13:36:15 | key | +| PrototypePollutionUtility/tests.js:32:9:32:27 | dstValue | PrototypePollutionUtility/tests.js:34:18:34:25 | dstValue | +| PrototypePollutionUtility/tests.js:32:9:32:27 | dstValue | PrototypePollutionUtility/tests.js:34:18:34:25 | dstValue | +| PrototypePollutionUtility/tests.js:32:20:32:22 | dst | PrototypePollutionUtility/tests.js:32:20:32:27 | dst[key] | +| PrototypePollutionUtility/tests.js:32:20:32:22 | dst | PrototypePollutionUtility/tests.js:32:20:32:27 | dst[key] | +| PrototypePollutionUtility/tests.js:32:20:32:27 | dst[key] | PrototypePollutionUtility/tests.js:32:9:32:27 | dstValue | +| PrototypePollutionUtility/tests.js:32:20:32:27 | dst[key] | PrototypePollutionUtility/tests.js:32:9:32:27 | dstValue | +| PrototypePollutionUtility/tests.js:32:24:32:26 | key | PrototypePollutionUtility/tests.js:32:20:32:27 | dst[key] | +| PrototypePollutionUtility/tests.js:32:24:32:26 | key | PrototypePollutionUtility/tests.js:32:20:32:27 | dst[key] | +| PrototypePollutionUtility/tests.js:34:18:34:25 | dstValue | PrototypePollutionUtility/tests.js:23:19:23:21 | dst | +| PrototypePollutionUtility/tests.js:34:18:34:25 | dstValue | PrototypePollutionUtility/tests.js:23:19:23:21 | dst | +| PrototypePollutionUtility/tests.js:40:27:40:29 | dst | PrototypePollutionUtility/tests.js:44:30:44:32 | dst | +| PrototypePollutionUtility/tests.js:40:27:40:29 | dst | PrototypePollutionUtility/tests.js:46:13:46:15 | dst | +| PrototypePollutionUtility/tests.js:40:27:40:29 | dst | PrototypePollutionUtility/tests.js:46:13:46:15 | dst | +| PrototypePollutionUtility/tests.js:40:32:40:34 | src | PrototypePollutionUtility/tests.js:44:40:44:42 | src | +| PrototypePollutionUtility/tests.js:40:32:40:34 | src | PrototypePollutionUtility/tests.js:44:40:44:42 | src | +| PrototypePollutionUtility/tests.js:40:32:40:34 | src | PrototypePollutionUtility/tests.js:46:24:46:26 | src | +| PrototypePollutionUtility/tests.js:40:32:40:34 | src | PrototypePollutionUtility/tests.js:46:24:46:26 | src | +| PrototypePollutionUtility/tests.js:41:14:41:16 | key | PrototypePollutionUtility/tests.js:44:34:44:36 | key | +| PrototypePollutionUtility/tests.js:41:14:41:16 | key | PrototypePollutionUtility/tests.js:44:34:44:36 | key | +| PrototypePollutionUtility/tests.js:41:14:41:16 | key | PrototypePollutionUtility/tests.js:44:44:44:46 | key | +| PrototypePollutionUtility/tests.js:41:14:41:16 | key | PrototypePollutionUtility/tests.js:44:44:44:46 | key | +| PrototypePollutionUtility/tests.js:41:14:41:16 | key | PrototypePollutionUtility/tests.js:46:17:46:19 | key | +| PrototypePollutionUtility/tests.js:41:14:41:16 | key | PrototypePollutionUtility/tests.js:46:17:46:19 | key | +| PrototypePollutionUtility/tests.js:41:14:41:16 | key | PrototypePollutionUtility/tests.js:46:17:46:19 | key | +| PrototypePollutionUtility/tests.js:41:14:41:16 | key | PrototypePollutionUtility/tests.js:46:17:46:19 | key | +| PrototypePollutionUtility/tests.js:41:14:41:16 | key | PrototypePollutionUtility/tests.js:46:28:46:30 | key | +| PrototypePollutionUtility/tests.js:41:14:41:16 | key | PrototypePollutionUtility/tests.js:46:28:46:30 | key | +| PrototypePollutionUtility/tests.js:44:30:44:32 | dst | PrototypePollutionUtility/tests.js:44:30:44:37 | dst[key] | +| PrototypePollutionUtility/tests.js:44:30:44:37 | dst[key] | PrototypePollutionUtility/tests.js:40:27:40:29 | dst | +| PrototypePollutionUtility/tests.js:44:30:44:37 | dst[key] | PrototypePollutionUtility/tests.js:40:27:40:29 | dst | +| PrototypePollutionUtility/tests.js:44:34:44:36 | key | PrototypePollutionUtility/tests.js:44:30:44:37 | dst[key] | +| PrototypePollutionUtility/tests.js:44:40:44:42 | src | PrototypePollutionUtility/tests.js:44:40:44:47 | src[key] | +| PrototypePollutionUtility/tests.js:44:40:44:42 | src | PrototypePollutionUtility/tests.js:44:40:44:47 | src[key] | +| PrototypePollutionUtility/tests.js:44:40:44:47 | src[key] | PrototypePollutionUtility/tests.js:40:32:40:34 | src | +| PrototypePollutionUtility/tests.js:44:40:44:47 | src[key] | PrototypePollutionUtility/tests.js:40:32:40:34 | src | +| PrototypePollutionUtility/tests.js:44:40:44:47 | src[key] | PrototypePollutionUtility/tests.js:40:32:40:34 | src | +| PrototypePollutionUtility/tests.js:44:40:44:47 | src[key] | PrototypePollutionUtility/tests.js:40:32:40:34 | src | +| PrototypePollutionUtility/tests.js:44:40:44:47 | src[key] | PrototypePollutionUtility/tests.js:40:32:40:34 | src | +| PrototypePollutionUtility/tests.js:44:40:44:47 | src[key] | PrototypePollutionUtility/tests.js:40:32:40:34 | src | +| PrototypePollutionUtility/tests.js:44:44:44:46 | key | PrototypePollutionUtility/tests.js:44:40:44:47 | src[key] | +| PrototypePollutionUtility/tests.js:46:24:46:26 | src | PrototypePollutionUtility/tests.js:46:24:46:31 | src[key] | +| PrototypePollutionUtility/tests.js:46:24:46:26 | src | PrototypePollutionUtility/tests.js:46:24:46:31 | src[key] | +| PrototypePollutionUtility/tests.js:46:24:46:26 | src | PrototypePollutionUtility/tests.js:46:24:46:31 | src[key] | +| PrototypePollutionUtility/tests.js:46:24:46:26 | src | PrototypePollutionUtility/tests.js:46:24:46:31 | src[key] | +| PrototypePollutionUtility/tests.js:46:24:46:31 | src[key] | PrototypePollutionUtility/tests.js:46:24:46:31 | src[key] | +| PrototypePollutionUtility/tests.js:46:28:46:30 | key | PrototypePollutionUtility/tests.js:46:24:46:31 | src[key] | +| PrototypePollutionUtility/tests.js:46:28:46:30 | key | PrototypePollutionUtility/tests.js:46:24:46:31 | src[key] | +| PrototypePollutionUtility/tests.js:51:26:51:28 | dst | PrototypePollutionUtility/tests.js:55:29:55:31 | dst | +| PrototypePollutionUtility/tests.js:51:26:51:28 | dst | PrototypePollutionUtility/tests.js:57:13:57:15 | dst | +| PrototypePollutionUtility/tests.js:51:26:51:28 | dst | PrototypePollutionUtility/tests.js:57:13:57:15 | dst | +| PrototypePollutionUtility/tests.js:51:31:51:33 | src | PrototypePollutionUtility/tests.js:55:39:55:41 | src | +| PrototypePollutionUtility/tests.js:51:31:51:33 | src | PrototypePollutionUtility/tests.js:55:39:55:41 | src | +| PrototypePollutionUtility/tests.js:51:31:51:33 | src | PrototypePollutionUtility/tests.js:57:24:57:26 | src | +| PrototypePollutionUtility/tests.js:51:31:51:33 | src | PrototypePollutionUtility/tests.js:57:24:57:26 | src | +| PrototypePollutionUtility/tests.js:52:14:52:16 | key | PrototypePollutionUtility/tests.js:55:33:55:35 | key | +| PrototypePollutionUtility/tests.js:52:14:52:16 | key | PrototypePollutionUtility/tests.js:55:33:55:35 | key | +| PrototypePollutionUtility/tests.js:52:14:52:16 | key | PrototypePollutionUtility/tests.js:55:43:55:45 | key | +| PrototypePollutionUtility/tests.js:52:14:52:16 | key | PrototypePollutionUtility/tests.js:55:43:55:45 | key | +| PrototypePollutionUtility/tests.js:52:14:52:16 | key | PrototypePollutionUtility/tests.js:57:17:57:19 | key | +| PrototypePollutionUtility/tests.js:52:14:52:16 | key | PrototypePollutionUtility/tests.js:57:17:57:19 | key | +| PrototypePollutionUtility/tests.js:52:14:52:16 | key | PrototypePollutionUtility/tests.js:57:17:57:19 | key | +| PrototypePollutionUtility/tests.js:52:14:52:16 | key | PrototypePollutionUtility/tests.js:57:17:57:19 | key | +| PrototypePollutionUtility/tests.js:52:14:52:16 | key | PrototypePollutionUtility/tests.js:57:28:57:30 | key | +| PrototypePollutionUtility/tests.js:52:14:52:16 | key | PrototypePollutionUtility/tests.js:57:28:57:30 | key | +| PrototypePollutionUtility/tests.js:55:29:55:31 | dst | PrototypePollutionUtility/tests.js:55:29:55:36 | dst[key] | +| PrototypePollutionUtility/tests.js:55:29:55:36 | dst[key] | PrototypePollutionUtility/tests.js:51:26:51:28 | dst | +| PrototypePollutionUtility/tests.js:55:29:55:36 | dst[key] | PrototypePollutionUtility/tests.js:51:26:51:28 | dst | +| PrototypePollutionUtility/tests.js:55:33:55:35 | key | PrototypePollutionUtility/tests.js:55:29:55:36 | dst[key] | +| PrototypePollutionUtility/tests.js:55:39:55:41 | src | PrototypePollutionUtility/tests.js:55:39:55:46 | src[key] | +| PrototypePollutionUtility/tests.js:55:39:55:41 | src | PrototypePollutionUtility/tests.js:55:39:55:46 | src[key] | +| PrototypePollutionUtility/tests.js:55:39:55:46 | src[key] | PrototypePollutionUtility/tests.js:51:31:51:33 | src | +| PrototypePollutionUtility/tests.js:55:39:55:46 | src[key] | PrototypePollutionUtility/tests.js:51:31:51:33 | src | +| PrototypePollutionUtility/tests.js:55:39:55:46 | src[key] | PrototypePollutionUtility/tests.js:51:31:51:33 | src | +| PrototypePollutionUtility/tests.js:55:39:55:46 | src[key] | PrototypePollutionUtility/tests.js:51:31:51:33 | src | +| PrototypePollutionUtility/tests.js:55:39:55:46 | src[key] | PrototypePollutionUtility/tests.js:51:31:51:33 | src | +| PrototypePollutionUtility/tests.js:55:39:55:46 | src[key] | PrototypePollutionUtility/tests.js:51:31:51:33 | src | +| PrototypePollutionUtility/tests.js:55:43:55:45 | key | PrototypePollutionUtility/tests.js:55:39:55:46 | src[key] | +| PrototypePollutionUtility/tests.js:57:24:57:26 | src | PrototypePollutionUtility/tests.js:57:24:57:31 | src[key] | +| PrototypePollutionUtility/tests.js:57:24:57:26 | src | PrototypePollutionUtility/tests.js:57:24:57:31 | src[key] | +| PrototypePollutionUtility/tests.js:57:24:57:26 | src | PrototypePollutionUtility/tests.js:57:24:57:31 | src[key] | +| PrototypePollutionUtility/tests.js:57:24:57:26 | src | PrototypePollutionUtility/tests.js:57:24:57:31 | src[key] | +| PrototypePollutionUtility/tests.js:57:24:57:31 | src[key] | PrototypePollutionUtility/tests.js:57:24:57:31 | src[key] | +| PrototypePollutionUtility/tests.js:57:28:57:30 | key | PrototypePollutionUtility/tests.js:57:24:57:31 | src[key] | +| PrototypePollutionUtility/tests.js:57:28:57:30 | key | PrototypePollutionUtility/tests.js:57:24:57:31 | src[key] | +| PrototypePollutionUtility/tests.js:62:33:62:35 | src | PrototypePollutionUtility/tests.js:66:41:66:43 | src | +| PrototypePollutionUtility/tests.js:62:33:62:35 | src | PrototypePollutionUtility/tests.js:66:41:66:43 | src | +| PrototypePollutionUtility/tests.js:62:33:62:35 | src | PrototypePollutionUtility/tests.js:68:24:68:26 | src | +| PrototypePollutionUtility/tests.js:62:33:62:35 | src | PrototypePollutionUtility/tests.js:68:24:68:26 | src | +| PrototypePollutionUtility/tests.js:66:41:66:43 | src | PrototypePollutionUtility/tests.js:66:41:66:48 | src[key] | +| PrototypePollutionUtility/tests.js:66:41:66:43 | src | PrototypePollutionUtility/tests.js:66:41:66:48 | src[key] | +| PrototypePollutionUtility/tests.js:66:41:66:48 | src[key] | PrototypePollutionUtility/tests.js:62:33:62:35 | src | +| PrototypePollutionUtility/tests.js:66:41:66:48 | src[key] | PrototypePollutionUtility/tests.js:62:33:62:35 | src | +| PrototypePollutionUtility/tests.js:66:41:66:48 | src[key] | PrototypePollutionUtility/tests.js:62:33:62:35 | src | +| PrototypePollutionUtility/tests.js:66:41:66:48 | src[key] | PrototypePollutionUtility/tests.js:62:33:62:35 | src | +| PrototypePollutionUtility/tests.js:66:41:66:48 | src[key] | PrototypePollutionUtility/tests.js:62:33:62:35 | src | +| PrototypePollutionUtility/tests.js:66:41:66:48 | src[key] | PrototypePollutionUtility/tests.js:62:33:62:35 | src | +| PrototypePollutionUtility/tests.js:68:24:68:26 | src | PrototypePollutionUtility/tests.js:68:24:68:31 | src[key] | +| PrototypePollutionUtility/tests.js:68:24:68:26 | src | PrototypePollutionUtility/tests.js:68:24:68:31 | src[key] | +| PrototypePollutionUtility/tests.js:68:24:68:26 | src | PrototypePollutionUtility/tests.js:68:24:68:31 | src[key] | +| PrototypePollutionUtility/tests.js:68:24:68:26 | src | PrototypePollutionUtility/tests.js:68:24:68:31 | src[key] | +| PrototypePollutionUtility/tests.js:68:24:68:31 | src[key] | PrototypePollutionUtility/tests.js:68:24:68:31 | src[key] | +| PrototypePollutionUtility/tests.js:77:27:77:29 | src | PrototypePollutionUtility/tests.js:81:39:81:41 | src | +| PrototypePollutionUtility/tests.js:77:27:77:29 | src | PrototypePollutionUtility/tests.js:81:39:81:41 | src | +| PrototypePollutionUtility/tests.js:77:27:77:29 | src | PrototypePollutionUtility/tests.js:83:28:83:30 | src | +| PrototypePollutionUtility/tests.js:77:27:77:29 | src | PrototypePollutionUtility/tests.js:83:28:83:30 | src | +| PrototypePollutionUtility/tests.js:81:39:81:41 | src | PrototypePollutionUtility/tests.js:81:39:81:46 | src[key] | +| PrototypePollutionUtility/tests.js:81:39:81:41 | src | PrototypePollutionUtility/tests.js:81:39:81:46 | src[key] | +| PrototypePollutionUtility/tests.js:81:39:81:46 | src[key] | PrototypePollutionUtility/tests.js:77:27:77:29 | src | +| PrototypePollutionUtility/tests.js:81:39:81:46 | src[key] | PrototypePollutionUtility/tests.js:77:27:77:29 | src | +| PrototypePollutionUtility/tests.js:81:39:81:46 | src[key] | PrototypePollutionUtility/tests.js:77:27:77:29 | src | +| PrototypePollutionUtility/tests.js:81:39:81:46 | src[key] | PrototypePollutionUtility/tests.js:77:27:77:29 | src | +| PrototypePollutionUtility/tests.js:81:39:81:46 | src[key] | PrototypePollutionUtility/tests.js:77:27:77:29 | src | +| PrototypePollutionUtility/tests.js:81:39:81:46 | src[key] | PrototypePollutionUtility/tests.js:77:27:77:29 | src | +| PrototypePollutionUtility/tests.js:83:28:83:30 | src | PrototypePollutionUtility/tests.js:83:28:83:35 | src[key] | +| PrototypePollutionUtility/tests.js:83:28:83:30 | src | PrototypePollutionUtility/tests.js:83:28:83:35 | src[key] | +| PrototypePollutionUtility/tests.js:83:28:83:30 | src | PrototypePollutionUtility/tests.js:83:28:83:35 | src[key] | +| PrototypePollutionUtility/tests.js:83:28:83:30 | src | PrototypePollutionUtility/tests.js:83:28:83:35 | src[key] | +| PrototypePollutionUtility/tests.js:83:28:83:35 | src[key] | PrototypePollutionUtility/tests.js:83:28:83:35 | src[key] | +| PrototypePollutionUtility/tests.js:89:34:89:36 | src | PrototypePollutionUtility/tests.js:94:42:94:44 | src | +| PrototypePollutionUtility/tests.js:89:34:89:36 | src | PrototypePollutionUtility/tests.js:94:42:94:44 | src | +| PrototypePollutionUtility/tests.js:89:34:89:36 | src | PrototypePollutionUtility/tests.js:96:24:96:26 | src | +| PrototypePollutionUtility/tests.js:89:34:89:36 | src | PrototypePollutionUtility/tests.js:96:24:96:26 | src | +| PrototypePollutionUtility/tests.js:90:14:90:16 | key | PrototypePollutionUtility/tests.js:96:17:96:19 | key | +| PrototypePollutionUtility/tests.js:90:14:90:16 | key | PrototypePollutionUtility/tests.js:96:17:96:19 | key | +| PrototypePollutionUtility/tests.js:90:14:90:16 | key | PrototypePollutionUtility/tests.js:96:17:96:19 | key | +| PrototypePollutionUtility/tests.js:90:14:90:16 | key | PrototypePollutionUtility/tests.js:96:17:96:19 | key | +| PrototypePollutionUtility/tests.js:90:14:90:16 | key | PrototypePollutionUtility/tests.js:96:17:96:19 | key | +| PrototypePollutionUtility/tests.js:90:14:90:16 | key | PrototypePollutionUtility/tests.js:96:17:96:19 | key | +| PrototypePollutionUtility/tests.js:90:14:90:16 | key | PrototypePollutionUtility/tests.js:96:17:96:19 | key | +| PrototypePollutionUtility/tests.js:90:14:90:16 | key | PrototypePollutionUtility/tests.js:96:28:96:30 | key | +| PrototypePollutionUtility/tests.js:90:14:90:16 | key | PrototypePollutionUtility/tests.js:96:28:96:30 | key | +| PrototypePollutionUtility/tests.js:90:14:90:16 | key | PrototypePollutionUtility/tests.js:96:28:96:30 | key | +| PrototypePollutionUtility/tests.js:90:14:90:16 | key | PrototypePollutionUtility/tests.js:96:28:96:30 | key | +| PrototypePollutionUtility/tests.js:94:42:94:44 | src | PrototypePollutionUtility/tests.js:94:42:94:49 | src[key] | +| PrototypePollutionUtility/tests.js:94:42:94:44 | src | PrototypePollutionUtility/tests.js:94:42:94:49 | src[key] | +| PrototypePollutionUtility/tests.js:94:42:94:49 | src[key] | PrototypePollutionUtility/tests.js:89:34:89:36 | src | +| PrototypePollutionUtility/tests.js:94:42:94:49 | src[key] | PrototypePollutionUtility/tests.js:89:34:89:36 | src | +| PrototypePollutionUtility/tests.js:94:42:94:49 | src[key] | PrototypePollutionUtility/tests.js:89:34:89:36 | src | +| PrototypePollutionUtility/tests.js:94:42:94:49 | src[key] | PrototypePollutionUtility/tests.js:89:34:89:36 | src | +| PrototypePollutionUtility/tests.js:94:42:94:49 | src[key] | PrototypePollutionUtility/tests.js:89:34:89:36 | src | +| PrototypePollutionUtility/tests.js:94:42:94:49 | src[key] | PrototypePollutionUtility/tests.js:89:34:89:36 | src | +| PrototypePollutionUtility/tests.js:96:24:96:26 | src | PrototypePollutionUtility/tests.js:96:24:96:31 | src[key] | +| PrototypePollutionUtility/tests.js:96:24:96:26 | src | PrototypePollutionUtility/tests.js:96:24:96:31 | src[key] | +| PrototypePollutionUtility/tests.js:96:24:96:26 | src | PrototypePollutionUtility/tests.js:96:24:96:31 | src[key] | +| PrototypePollutionUtility/tests.js:96:24:96:26 | src | PrototypePollutionUtility/tests.js:96:24:96:31 | src[key] | +| PrototypePollutionUtility/tests.js:96:24:96:31 | src[key] | PrototypePollutionUtility/tests.js:96:24:96:31 | src[key] | +| PrototypePollutionUtility/tests.js:96:28:96:30 | key | PrototypePollutionUtility/tests.js:96:24:96:31 | src[key] | +| PrototypePollutionUtility/tests.js:96:28:96:30 | key | PrototypePollutionUtility/tests.js:96:24:96:31 | src[key] | +| PrototypePollutionUtility/tests.js:96:28:96:30 | key | PrototypePollutionUtility/tests.js:96:24:96:31 | src[key] | +| PrototypePollutionUtility/tests.js:96:28:96:30 | key | PrototypePollutionUtility/tests.js:96:24:96:31 | src[key] | +| PrototypePollutionUtility/tests.js:101:32:101:34 | dst | PrototypePollutionUtility/tests.js:107:35:107:37 | dst | +| PrototypePollutionUtility/tests.js:101:32:101:34 | dst | PrototypePollutionUtility/tests.js:107:35:107:37 | dst | +| PrototypePollutionUtility/tests.js:101:32:101:34 | dst | PrototypePollutionUtility/tests.js:109:13:109:15 | dst | +| PrototypePollutionUtility/tests.js:101:32:101:34 | dst | PrototypePollutionUtility/tests.js:109:13:109:15 | dst | +| PrototypePollutionUtility/tests.js:101:32:101:34 | dst | PrototypePollutionUtility/tests.js:109:13:109:15 | dst | +| PrototypePollutionUtility/tests.js:101:32:101:34 | dst | PrototypePollutionUtility/tests.js:109:13:109:15 | dst | +| PrototypePollutionUtility/tests.js:101:37:101:39 | src | PrototypePollutionUtility/tests.js:107:45:107:47 | src | +| PrototypePollutionUtility/tests.js:101:37:101:39 | src | PrototypePollutionUtility/tests.js:107:45:107:47 | src | +| PrototypePollutionUtility/tests.js:101:37:101:39 | src | PrototypePollutionUtility/tests.js:109:24:109:26 | src | +| PrototypePollutionUtility/tests.js:101:37:101:39 | src | PrototypePollutionUtility/tests.js:109:24:109:26 | src | +| PrototypePollutionUtility/tests.js:102:14:102:16 | key | PrototypePollutionUtility/tests.js:107:39:107:41 | key | +| PrototypePollutionUtility/tests.js:102:14:102:16 | key | PrototypePollutionUtility/tests.js:107:39:107:41 | key | +| PrototypePollutionUtility/tests.js:102:14:102:16 | key | PrototypePollutionUtility/tests.js:107:39:107:41 | key | +| PrototypePollutionUtility/tests.js:102:14:102:16 | key | PrototypePollutionUtility/tests.js:107:39:107:41 | key | +| PrototypePollutionUtility/tests.js:102:14:102:16 | key | PrototypePollutionUtility/tests.js:107:49:107:51 | key | +| PrototypePollutionUtility/tests.js:102:14:102:16 | key | PrototypePollutionUtility/tests.js:107:49:107:51 | key | +| PrototypePollutionUtility/tests.js:102:14:102:16 | key | PrototypePollutionUtility/tests.js:107:49:107:51 | key | +| PrototypePollutionUtility/tests.js:102:14:102:16 | key | PrototypePollutionUtility/tests.js:107:49:107:51 | key | +| PrototypePollutionUtility/tests.js:102:14:102:16 | key | PrototypePollutionUtility/tests.js:109:17:109:19 | key | +| PrototypePollutionUtility/tests.js:102:14:102:16 | key | PrototypePollutionUtility/tests.js:109:17:109:19 | key | +| PrototypePollutionUtility/tests.js:102:14:102:16 | key | PrototypePollutionUtility/tests.js:109:17:109:19 | key | +| PrototypePollutionUtility/tests.js:102:14:102:16 | key | PrototypePollutionUtility/tests.js:109:17:109:19 | key | +| PrototypePollutionUtility/tests.js:102:14:102:16 | key | PrototypePollutionUtility/tests.js:109:17:109:19 | key | +| PrototypePollutionUtility/tests.js:102:14:102:16 | key | PrototypePollutionUtility/tests.js:109:17:109:19 | key | +| PrototypePollutionUtility/tests.js:102:14:102:16 | key | PrototypePollutionUtility/tests.js:109:17:109:19 | key | +| PrototypePollutionUtility/tests.js:102:14:102:16 | key | PrototypePollutionUtility/tests.js:109:28:109:30 | key | +| PrototypePollutionUtility/tests.js:102:14:102:16 | key | PrototypePollutionUtility/tests.js:109:28:109:30 | key | +| PrototypePollutionUtility/tests.js:102:14:102:16 | key | PrototypePollutionUtility/tests.js:109:28:109:30 | key | +| PrototypePollutionUtility/tests.js:102:14:102:16 | key | PrototypePollutionUtility/tests.js:109:28:109:30 | key | +| PrototypePollutionUtility/tests.js:107:35:107:37 | dst | PrototypePollutionUtility/tests.js:107:35:107:42 | dst[key] | +| PrototypePollutionUtility/tests.js:107:35:107:37 | dst | PrototypePollutionUtility/tests.js:107:35:107:42 | dst[key] | +| PrototypePollutionUtility/tests.js:107:35:107:42 | dst[key] | PrototypePollutionUtility/tests.js:101:32:101:34 | dst | +| PrototypePollutionUtility/tests.js:107:35:107:42 | dst[key] | PrototypePollutionUtility/tests.js:101:32:101:34 | dst | +| PrototypePollutionUtility/tests.js:107:35:107:42 | dst[key] | PrototypePollutionUtility/tests.js:101:32:101:34 | dst | +| PrototypePollutionUtility/tests.js:107:35:107:42 | dst[key] | PrototypePollutionUtility/tests.js:101:32:101:34 | dst | +| PrototypePollutionUtility/tests.js:107:39:107:41 | key | PrototypePollutionUtility/tests.js:107:35:107:42 | dst[key] | +| PrototypePollutionUtility/tests.js:107:39:107:41 | key | PrototypePollutionUtility/tests.js:107:35:107:42 | dst[key] | +| PrototypePollutionUtility/tests.js:107:45:107:47 | src | PrototypePollutionUtility/tests.js:107:45:107:52 | src[key] | +| PrototypePollutionUtility/tests.js:107:45:107:47 | src | PrototypePollutionUtility/tests.js:107:45:107:52 | src[key] | +| PrototypePollutionUtility/tests.js:107:45:107:52 | src[key] | PrototypePollutionUtility/tests.js:101:37:101:39 | src | +| PrototypePollutionUtility/tests.js:107:45:107:52 | src[key] | PrototypePollutionUtility/tests.js:101:37:101:39 | src | +| PrototypePollutionUtility/tests.js:107:45:107:52 | src[key] | PrototypePollutionUtility/tests.js:101:37:101:39 | src | +| PrototypePollutionUtility/tests.js:107:45:107:52 | src[key] | PrototypePollutionUtility/tests.js:101:37:101:39 | src | +| PrototypePollutionUtility/tests.js:107:45:107:52 | src[key] | PrototypePollutionUtility/tests.js:101:37:101:39 | src | +| PrototypePollutionUtility/tests.js:107:45:107:52 | src[key] | PrototypePollutionUtility/tests.js:101:37:101:39 | src | +| PrototypePollutionUtility/tests.js:107:49:107:51 | key | PrototypePollutionUtility/tests.js:107:45:107:52 | src[key] | +| PrototypePollutionUtility/tests.js:107:49:107:51 | key | PrototypePollutionUtility/tests.js:107:45:107:52 | src[key] | +| PrototypePollutionUtility/tests.js:109:24:109:26 | src | PrototypePollutionUtility/tests.js:109:24:109:31 | src[key] | +| PrototypePollutionUtility/tests.js:109:24:109:26 | src | PrototypePollutionUtility/tests.js:109:24:109:31 | src[key] | +| PrototypePollutionUtility/tests.js:109:24:109:26 | src | PrototypePollutionUtility/tests.js:109:24:109:31 | src[key] | +| PrototypePollutionUtility/tests.js:109:24:109:26 | src | PrototypePollutionUtility/tests.js:109:24:109:31 | src[key] | +| PrototypePollutionUtility/tests.js:109:24:109:31 | src[key] | PrototypePollutionUtility/tests.js:109:24:109:31 | src[key] | +| PrototypePollutionUtility/tests.js:109:28:109:30 | key | PrototypePollutionUtility/tests.js:109:24:109:31 | src[key] | +| PrototypePollutionUtility/tests.js:109:28:109:30 | key | PrototypePollutionUtility/tests.js:109:24:109:31 | src[key] | +| PrototypePollutionUtility/tests.js:109:28:109:30 | key | PrototypePollutionUtility/tests.js:109:24:109:31 | src[key] | +| PrototypePollutionUtility/tests.js:109:28:109:30 | key | PrototypePollutionUtility/tests.js:109:24:109:31 | src[key] | +| PrototypePollutionUtility/tests.js:116:41:116:43 | src | PrototypePollutionUtility/tests.js:119:49:119:51 | src | +| PrototypePollutionUtility/tests.js:116:41:116:43 | src | PrototypePollutionUtility/tests.js:119:49:119:51 | src | +| PrototypePollutionUtility/tests.js:116:41:116:43 | src | PrototypePollutionUtility/tests.js:121:24:121:26 | src | +| PrototypePollutionUtility/tests.js:116:41:116:43 | src | PrototypePollutionUtility/tests.js:121:24:121:26 | src | +| PrototypePollutionUtility/tests.js:117:14:117:16 | key | PrototypePollutionUtility/tests.js:121:17:121:19 | key | +| PrototypePollutionUtility/tests.js:117:14:117:16 | key | PrototypePollutionUtility/tests.js:121:17:121:19 | key | +| PrototypePollutionUtility/tests.js:117:14:117:16 | key | PrototypePollutionUtility/tests.js:121:17:121:19 | key | +| PrototypePollutionUtility/tests.js:117:14:117:16 | key | PrototypePollutionUtility/tests.js:121:17:121:19 | key | +| PrototypePollutionUtility/tests.js:117:14:117:16 | key | PrototypePollutionUtility/tests.js:121:17:121:19 | key | +| PrototypePollutionUtility/tests.js:117:14:117:16 | key | PrototypePollutionUtility/tests.js:121:17:121:19 | key | +| PrototypePollutionUtility/tests.js:117:14:117:16 | key | PrototypePollutionUtility/tests.js:121:17:121:19 | key | +| PrototypePollutionUtility/tests.js:117:14:117:16 | key | PrototypePollutionUtility/tests.js:121:28:121:30 | key | +| PrototypePollutionUtility/tests.js:117:14:117:16 | key | PrototypePollutionUtility/tests.js:121:28:121:30 | key | +| PrototypePollutionUtility/tests.js:117:14:117:16 | key | PrototypePollutionUtility/tests.js:121:28:121:30 | key | +| PrototypePollutionUtility/tests.js:117:14:117:16 | key | PrototypePollutionUtility/tests.js:121:28:121:30 | key | +| PrototypePollutionUtility/tests.js:119:49:119:51 | src | PrototypePollutionUtility/tests.js:119:49:119:56 | src[key] | +| PrototypePollutionUtility/tests.js:119:49:119:51 | src | PrototypePollutionUtility/tests.js:119:49:119:56 | src[key] | +| PrototypePollutionUtility/tests.js:119:49:119:56 | src[key] | PrototypePollutionUtility/tests.js:116:41:116:43 | src | +| PrototypePollutionUtility/tests.js:119:49:119:56 | src[key] | PrototypePollutionUtility/tests.js:116:41:116:43 | src | +| PrototypePollutionUtility/tests.js:119:49:119:56 | src[key] | PrototypePollutionUtility/tests.js:116:41:116:43 | src | +| PrototypePollutionUtility/tests.js:119:49:119:56 | src[key] | PrototypePollutionUtility/tests.js:116:41:116:43 | src | +| PrototypePollutionUtility/tests.js:119:49:119:56 | src[key] | PrototypePollutionUtility/tests.js:116:41:116:43 | src | +| PrototypePollutionUtility/tests.js:119:49:119:56 | src[key] | PrototypePollutionUtility/tests.js:116:41:116:43 | src | +| PrototypePollutionUtility/tests.js:121:24:121:26 | src | PrototypePollutionUtility/tests.js:121:24:121:31 | src[key] | +| PrototypePollutionUtility/tests.js:121:24:121:26 | src | PrototypePollutionUtility/tests.js:121:24:121:31 | src[key] | +| PrototypePollutionUtility/tests.js:121:24:121:26 | src | PrototypePollutionUtility/tests.js:121:24:121:31 | src[key] | +| PrototypePollutionUtility/tests.js:121:24:121:26 | src | PrototypePollutionUtility/tests.js:121:24:121:31 | src[key] | +| PrototypePollutionUtility/tests.js:121:24:121:31 | src[key] | PrototypePollutionUtility/tests.js:121:24:121:31 | src[key] | +| PrototypePollutionUtility/tests.js:121:28:121:30 | key | PrototypePollutionUtility/tests.js:121:24:121:31 | src[key] | +| PrototypePollutionUtility/tests.js:121:28:121:30 | key | PrototypePollutionUtility/tests.js:121:24:121:31 | src[key] | +| PrototypePollutionUtility/tests.js:121:28:121:30 | key | PrototypePollutionUtility/tests.js:121:24:121:31 | src[key] | +| PrototypePollutionUtility/tests.js:121:28:121:30 | key | PrototypePollutionUtility/tests.js:121:24:121:31 | src[key] | +| PrototypePollutionUtility/tests.js:127:14:127:16 | key | PrototypePollutionUtility/tests.js:128:13:128:15 | key | +| PrototypePollutionUtility/tests.js:127:14:127:16 | key | PrototypePollutionUtility/tests.js:128:13:128:15 | key | +| PrototypePollutionUtility/tests.js:127:14:127:16 | key | PrototypePollutionUtility/tests.js:128:13:128:15 | key | +| PrototypePollutionUtility/tests.js:127:14:127:16 | key | PrototypePollutionUtility/tests.js:128:13:128:15 | key | +| PrototypePollutionUtility/tests.js:127:14:127:16 | key | PrototypePollutionUtility/tests.js:128:13:128:15 | key | +| PrototypePollutionUtility/tests.js:127:14:127:16 | key | PrototypePollutionUtility/tests.js:128:13:128:15 | key | +| PrototypePollutionUtility/tests.js:127:14:127:16 | key | PrototypePollutionUtility/tests.js:128:13:128:15 | key | +| PrototypePollutionUtility/tests.js:127:14:127:16 | key | PrototypePollutionUtility/tests.js:128:24:128:26 | key | +| PrototypePollutionUtility/tests.js:127:14:127:16 | key | PrototypePollutionUtility/tests.js:128:24:128:26 | key | +| PrototypePollutionUtility/tests.js:127:14:127:16 | key | PrototypePollutionUtility/tests.js:128:24:128:26 | key | +| PrototypePollutionUtility/tests.js:127:14:127:16 | key | PrototypePollutionUtility/tests.js:128:24:128:26 | key | +| PrototypePollutionUtility/tests.js:128:20:128:27 | src[key] | PrototypePollutionUtility/tests.js:128:20:128:27 | src[key] | +| PrototypePollutionUtility/tests.js:128:24:128:26 | key | PrototypePollutionUtility/tests.js:128:20:128:27 | src[key] | +| PrototypePollutionUtility/tests.js:128:24:128:26 | key | PrototypePollutionUtility/tests.js:128:20:128:27 | src[key] | +| PrototypePollutionUtility/tests.js:128:24:128:26 | key | PrototypePollutionUtility/tests.js:128:20:128:27 | src[key] | +| PrototypePollutionUtility/tests.js:128:24:128:26 | key | PrototypePollutionUtility/tests.js:128:20:128:27 | src[key] | +| PrototypePollutionUtility/tests.js:140:16:140:18 | src | PrototypePollutionUtility/tests.js:144:29:144:31 | src | +| PrototypePollutionUtility/tests.js:143:14:143:16 | key | PrototypePollutionUtility/tests.js:144:16:144:18 | key | +| PrototypePollutionUtility/tests.js:143:14:143:16 | key | PrototypePollutionUtility/tests.js:144:16:144:18 | key | +| PrototypePollutionUtility/tests.js:143:14:143:16 | key | PrototypePollutionUtility/tests.js:144:16:144:18 | key | +| PrototypePollutionUtility/tests.js:143:14:143:16 | key | PrototypePollutionUtility/tests.js:144:16:144:18 | key | +| PrototypePollutionUtility/tests.js:143:14:143:16 | key | PrototypePollutionUtility/tests.js:144:16:144:18 | key | +| PrototypePollutionUtility/tests.js:143:14:143:16 | key | PrototypePollutionUtility/tests.js:144:16:144:18 | key | +| PrototypePollutionUtility/tests.js:143:14:143:16 | key | PrototypePollutionUtility/tests.js:144:16:144:18 | key | +| PrototypePollutionUtility/tests.js:143:14:143:16 | key | PrototypePollutionUtility/tests.js:144:33:144:35 | key | +| PrototypePollutionUtility/tests.js:143:14:143:16 | key | PrototypePollutionUtility/tests.js:144:33:144:35 | key | +| PrototypePollutionUtility/tests.js:143:14:143:16 | key | PrototypePollutionUtility/tests.js:144:33:144:35 | key | +| PrototypePollutionUtility/tests.js:143:14:143:16 | key | PrototypePollutionUtility/tests.js:144:33:144:35 | key | +| PrototypePollutionUtility/tests.js:144:29:144:31 | src | PrototypePollutionUtility/tests.js:144:29:144:36 | src[key] | +| PrototypePollutionUtility/tests.js:144:29:144:36 | src[key] | PrototypePollutionUtility/tests.js:140:16:140:18 | src | +| PrototypePollutionUtility/tests.js:144:29:144:36 | src[key] | PrototypePollutionUtility/tests.js:140:16:140:18 | src | +| PrototypePollutionUtility/tests.js:144:29:144:36 | src[key] | PrototypePollutionUtility/tests.js:140:16:140:18 | src | +| PrototypePollutionUtility/tests.js:144:29:144:36 | src[key] | PrototypePollutionUtility/tests.js:144:23:144:37 | clone(src[key]) | +| PrototypePollutionUtility/tests.js:144:29:144:36 | src[key] | PrototypePollutionUtility/tests.js:144:23:144:37 | clone(src[key]) | +| PrototypePollutionUtility/tests.js:144:29:144:36 | src[key] | PrototypePollutionUtility/tests.js:144:23:144:37 | clone(src[key]) | +| PrototypePollutionUtility/tests.js:144:29:144:36 | src[key] | PrototypePollutionUtility/tests.js:144:23:144:37 | clone(src[key]) | +| PrototypePollutionUtility/tests.js:144:29:144:36 | src[key] | PrototypePollutionUtility/tests.js:144:23:144:37 | clone(src[key]) | +| PrototypePollutionUtility/tests.js:144:29:144:36 | src[key] | PrototypePollutionUtility/tests.js:144:23:144:37 | clone(src[key]) | +| PrototypePollutionUtility/tests.js:144:29:144:36 | src[key] | PrototypePollutionUtility/tests.js:144:23:144:37 | clone(src[key]) | +| PrototypePollutionUtility/tests.js:144:29:144:36 | src[key] | PrototypePollutionUtility/tests.js:144:23:144:37 | clone(src[key]) | +| PrototypePollutionUtility/tests.js:144:29:144:36 | src[key] | PrototypePollutionUtility/tests.js:144:23:144:37 | clone(src[key]) | +| PrototypePollutionUtility/tests.js:144:33:144:35 | key | PrototypePollutionUtility/tests.js:144:29:144:36 | src[key] | +| PrototypePollutionUtility/tests.js:144:33:144:35 | key | PrototypePollutionUtility/tests.js:144:29:144:36 | src[key] | +| PrototypePollutionUtility/tests.js:149:31:149:33 | dst | PrototypePollutionUtility/tests.js:152:22:152:24 | dst | +| PrototypePollutionUtility/tests.js:149:31:149:33 | dst | PrototypePollutionUtility/tests.js:152:22:152:24 | dst | +| PrototypePollutionUtility/tests.js:149:31:149:33 | dst | PrototypePollutionUtility/tests.js:152:22:152:24 | dst | +| PrototypePollutionUtility/tests.js:149:31:149:33 | dst | PrototypePollutionUtility/tests.js:152:22:152:24 | dst | +| PrototypePollutionUtility/tests.js:149:31:149:33 | dst | PrototypePollutionUtility/tests.js:154:13:154:15 | dst | +| PrototypePollutionUtility/tests.js:149:31:149:33 | dst | PrototypePollutionUtility/tests.js:154:13:154:15 | dst | +| PrototypePollutionUtility/tests.js:149:31:149:33 | dst | PrototypePollutionUtility/tests.js:154:13:154:15 | dst | +| PrototypePollutionUtility/tests.js:149:31:149:33 | dst | PrototypePollutionUtility/tests.js:154:13:154:15 | dst | +| PrototypePollutionUtility/tests.js:149:31:149:33 | dst | PrototypePollutionUtility/tests.js:154:13:154:15 | dst | +| PrototypePollutionUtility/tests.js:149:31:149:33 | dst | PrototypePollutionUtility/tests.js:154:13:154:15 | dst | +| PrototypePollutionUtility/tests.js:149:31:149:33 | dst | PrototypePollutionUtility/tests.js:154:13:154:15 | dst | +| PrototypePollutionUtility/tests.js:149:31:149:33 | dst | PrototypePollutionUtility/tests.js:154:13:154:15 | dst | +| PrototypePollutionUtility/tests.js:149:36:149:38 | src | PrototypePollutionUtility/tests.js:152:27:152:29 | src | +| PrototypePollutionUtility/tests.js:149:36:149:38 | src | PrototypePollutionUtility/tests.js:152:27:152:29 | src | +| PrototypePollutionUtility/tests.js:149:36:149:38 | src | PrototypePollutionUtility/tests.js:152:27:152:29 | src | +| PrototypePollutionUtility/tests.js:149:36:149:38 | src | PrototypePollutionUtility/tests.js:152:27:152:29 | src | +| PrototypePollutionUtility/tests.js:149:36:149:38 | src | PrototypePollutionUtility/tests.js:154:24:154:26 | src | +| PrototypePollutionUtility/tests.js:149:36:149:38 | src | PrototypePollutionUtility/tests.js:154:24:154:26 | src | +| PrototypePollutionUtility/tests.js:149:36:149:38 | src | PrototypePollutionUtility/tests.js:154:24:154:26 | src | +| PrototypePollutionUtility/tests.js:149:36:149:38 | src | PrototypePollutionUtility/tests.js:154:24:154:26 | src | +| PrototypePollutionUtility/tests.js:150:14:150:16 | key | PrototypePollutionUtility/tests.js:152:32:152:34 | key | +| PrototypePollutionUtility/tests.js:150:14:150:16 | key | PrototypePollutionUtility/tests.js:152:32:152:34 | key | +| PrototypePollutionUtility/tests.js:150:14:150:16 | key | PrototypePollutionUtility/tests.js:152:32:152:34 | key | +| PrototypePollutionUtility/tests.js:150:14:150:16 | key | PrototypePollutionUtility/tests.js:152:32:152:34 | key | +| PrototypePollutionUtility/tests.js:150:14:150:16 | key | PrototypePollutionUtility/tests.js:154:17:154:19 | key | +| PrototypePollutionUtility/tests.js:150:14:150:16 | key | PrototypePollutionUtility/tests.js:154:17:154:19 | key | +| PrototypePollutionUtility/tests.js:150:14:150:16 | key | PrototypePollutionUtility/tests.js:154:17:154:19 | key | +| PrototypePollutionUtility/tests.js:150:14:150:16 | key | PrototypePollutionUtility/tests.js:154:17:154:19 | key | +| PrototypePollutionUtility/tests.js:150:14:150:16 | key | PrototypePollutionUtility/tests.js:154:17:154:19 | key | +| PrototypePollutionUtility/tests.js:150:14:150:16 | key | PrototypePollutionUtility/tests.js:154:17:154:19 | key | +| PrototypePollutionUtility/tests.js:150:14:150:16 | key | PrototypePollutionUtility/tests.js:154:17:154:19 | key | +| PrototypePollutionUtility/tests.js:150:14:150:16 | key | PrototypePollutionUtility/tests.js:154:28:154:30 | key | +| PrototypePollutionUtility/tests.js:150:14:150:16 | key | PrototypePollutionUtility/tests.js:154:28:154:30 | key | +| PrototypePollutionUtility/tests.js:150:14:150:16 | key | PrototypePollutionUtility/tests.js:154:28:154:30 | key | +| PrototypePollutionUtility/tests.js:150:14:150:16 | key | PrototypePollutionUtility/tests.js:154:28:154:30 | key | +| PrototypePollutionUtility/tests.js:152:22:152:24 | dst | PrototypePollutionUtility/tests.js:160:37:160:39 | dst | +| PrototypePollutionUtility/tests.js:152:22:152:24 | dst | PrototypePollutionUtility/tests.js:160:37:160:39 | dst | +| PrototypePollutionUtility/tests.js:152:22:152:24 | dst | PrototypePollutionUtility/tests.js:160:37:160:39 | dst | +| PrototypePollutionUtility/tests.js:152:22:152:24 | dst | PrototypePollutionUtility/tests.js:160:37:160:39 | dst | +| PrototypePollutionUtility/tests.js:152:27:152:29 | src | PrototypePollutionUtility/tests.js:160:42:160:44 | src | +| PrototypePollutionUtility/tests.js:152:27:152:29 | src | PrototypePollutionUtility/tests.js:160:42:160:44 | src | +| PrototypePollutionUtility/tests.js:152:27:152:29 | src | PrototypePollutionUtility/tests.js:160:42:160:44 | src | +| PrototypePollutionUtility/tests.js:152:27:152:29 | src | PrototypePollutionUtility/tests.js:160:42:160:44 | src | +| PrototypePollutionUtility/tests.js:152:32:152:34 | key | PrototypePollutionUtility/tests.js:160:47:160:49 | key | +| PrototypePollutionUtility/tests.js:152:32:152:34 | key | PrototypePollutionUtility/tests.js:160:47:160:49 | key | +| PrototypePollutionUtility/tests.js:152:32:152:34 | key | PrototypePollutionUtility/tests.js:160:47:160:49 | key | +| PrototypePollutionUtility/tests.js:152:32:152:34 | key | PrototypePollutionUtility/tests.js:160:47:160:49 | key | +| PrototypePollutionUtility/tests.js:154:24:154:26 | src | PrototypePollutionUtility/tests.js:154:24:154:31 | src[key] | +| PrototypePollutionUtility/tests.js:154:24:154:26 | src | PrototypePollutionUtility/tests.js:154:24:154:31 | src[key] | +| PrototypePollutionUtility/tests.js:154:24:154:26 | src | PrototypePollutionUtility/tests.js:154:24:154:31 | src[key] | +| PrototypePollutionUtility/tests.js:154:24:154:26 | src | PrototypePollutionUtility/tests.js:154:24:154:31 | src[key] | +| PrototypePollutionUtility/tests.js:154:24:154:26 | src | PrototypePollutionUtility/tests.js:154:24:154:31 | src[key] | +| PrototypePollutionUtility/tests.js:154:24:154:26 | src | PrototypePollutionUtility/tests.js:154:24:154:31 | src[key] | +| PrototypePollutionUtility/tests.js:154:24:154:26 | src | PrototypePollutionUtility/tests.js:154:24:154:31 | src[key] | +| PrototypePollutionUtility/tests.js:154:24:154:26 | src | PrototypePollutionUtility/tests.js:154:24:154:31 | src[key] | +| PrototypePollutionUtility/tests.js:154:24:154:31 | src[key] | PrototypePollutionUtility/tests.js:154:24:154:31 | src[key] | +| PrototypePollutionUtility/tests.js:154:28:154:30 | key | PrototypePollutionUtility/tests.js:154:24:154:31 | src[key] | +| PrototypePollutionUtility/tests.js:154:28:154:30 | key | PrototypePollutionUtility/tests.js:154:24:154:31 | src[key] | +| PrototypePollutionUtility/tests.js:154:28:154:30 | key | PrototypePollutionUtility/tests.js:154:24:154:31 | src[key] | +| PrototypePollutionUtility/tests.js:154:28:154:30 | key | PrototypePollutionUtility/tests.js:154:24:154:31 | src[key] | +| PrototypePollutionUtility/tests.js:159:36:159:38 | dst | PrototypePollutionUtility/tests.js:160:26:160:28 | dst | +| PrototypePollutionUtility/tests.js:159:36:159:38 | dst | PrototypePollutionUtility/tests.js:160:26:160:28 | dst | +| PrototypePollutionUtility/tests.js:159:36:159:38 | dst | PrototypePollutionUtility/tests.js:160:26:160:28 | dst | +| PrototypePollutionUtility/tests.js:159:36:159:38 | dst | PrototypePollutionUtility/tests.js:160:26:160:28 | dst | +| PrototypePollutionUtility/tests.js:159:41:159:43 | src | PrototypePollutionUtility/tests.js:160:31:160:33 | src | +| PrototypePollutionUtility/tests.js:159:41:159:43 | src | PrototypePollutionUtility/tests.js:160:31:160:33 | src | +| PrototypePollutionUtility/tests.js:159:41:159:43 | src | PrototypePollutionUtility/tests.js:160:31:160:33 | src | +| PrototypePollutionUtility/tests.js:159:41:159:43 | src | PrototypePollutionUtility/tests.js:160:31:160:33 | src | +| PrototypePollutionUtility/tests.js:160:26:160:28 | dst | PrototypePollutionUtility/tests.js:149:31:149:33 | dst | +| PrototypePollutionUtility/tests.js:160:26:160:28 | dst | PrototypePollutionUtility/tests.js:149:31:149:33 | dst | +| PrototypePollutionUtility/tests.js:160:26:160:28 | dst | PrototypePollutionUtility/tests.js:149:31:149:33 | dst | +| PrototypePollutionUtility/tests.js:160:26:160:28 | dst | PrototypePollutionUtility/tests.js:149:31:149:33 | dst | +| PrototypePollutionUtility/tests.js:160:26:160:28 | dst | PrototypePollutionUtility/tests.js:160:37:160:39 | dst | +| PrototypePollutionUtility/tests.js:160:26:160:28 | dst | PrototypePollutionUtility/tests.js:160:37:160:39 | dst | +| PrototypePollutionUtility/tests.js:160:26:160:28 | dst | PrototypePollutionUtility/tests.js:160:37:160:39 | dst | +| PrototypePollutionUtility/tests.js:160:26:160:28 | dst | PrototypePollutionUtility/tests.js:160:37:160:39 | dst | +| PrototypePollutionUtility/tests.js:160:31:160:33 | src | PrototypePollutionUtility/tests.js:149:36:149:38 | src | +| PrototypePollutionUtility/tests.js:160:31:160:33 | src | PrototypePollutionUtility/tests.js:149:36:149:38 | src | +| PrototypePollutionUtility/tests.js:160:31:160:33 | src | PrototypePollutionUtility/tests.js:149:36:149:38 | src | +| PrototypePollutionUtility/tests.js:160:31:160:33 | src | PrototypePollutionUtility/tests.js:149:36:149:38 | src | +| PrototypePollutionUtility/tests.js:160:31:160:33 | src | PrototypePollutionUtility/tests.js:160:42:160:44 | src | +| PrototypePollutionUtility/tests.js:160:31:160:33 | src | PrototypePollutionUtility/tests.js:160:42:160:44 | src | +| PrototypePollutionUtility/tests.js:160:31:160:33 | src | PrototypePollutionUtility/tests.js:160:42:160:44 | src | +| PrototypePollutionUtility/tests.js:160:31:160:33 | src | PrototypePollutionUtility/tests.js:160:42:160:44 | src | +| PrototypePollutionUtility/tests.js:160:37:160:39 | dst | PrototypePollutionUtility/tests.js:161:35:161:37 | dst | +| PrototypePollutionUtility/tests.js:160:37:160:39 | dst | PrototypePollutionUtility/tests.js:161:35:161:37 | dst | +| PrototypePollutionUtility/tests.js:160:37:160:39 | dst | PrototypePollutionUtility/tests.js:161:35:161:37 | dst | +| PrototypePollutionUtility/tests.js:160:37:160:39 | dst | PrototypePollutionUtility/tests.js:161:35:161:37 | dst | +| PrototypePollutionUtility/tests.js:160:42:160:44 | src | PrototypePollutionUtility/tests.js:161:45:161:47 | src | +| PrototypePollutionUtility/tests.js:160:42:160:44 | src | PrototypePollutionUtility/tests.js:161:45:161:47 | src | +| PrototypePollutionUtility/tests.js:160:42:160:44 | src | PrototypePollutionUtility/tests.js:161:45:161:47 | src | +| PrototypePollutionUtility/tests.js:160:42:160:44 | src | PrototypePollutionUtility/tests.js:161:45:161:47 | src | +| PrototypePollutionUtility/tests.js:160:47:160:49 | key | PrototypePollutionUtility/tests.js:161:39:161:41 | key | +| PrototypePollutionUtility/tests.js:160:47:160:49 | key | PrototypePollutionUtility/tests.js:161:39:161:41 | key | +| PrototypePollutionUtility/tests.js:160:47:160:49 | key | PrototypePollutionUtility/tests.js:161:39:161:41 | key | +| PrototypePollutionUtility/tests.js:160:47:160:49 | key | PrototypePollutionUtility/tests.js:161:39:161:41 | key | +| PrototypePollutionUtility/tests.js:160:47:160:49 | key | PrototypePollutionUtility/tests.js:161:49:161:51 | key | +| PrototypePollutionUtility/tests.js:160:47:160:49 | key | PrototypePollutionUtility/tests.js:161:49:161:51 | key | +| PrototypePollutionUtility/tests.js:160:47:160:49 | key | PrototypePollutionUtility/tests.js:161:49:161:51 | key | +| PrototypePollutionUtility/tests.js:160:47:160:49 | key | PrototypePollutionUtility/tests.js:161:49:161:51 | key | +| PrototypePollutionUtility/tests.js:161:35:161:37 | dst | PrototypePollutionUtility/tests.js:161:35:161:42 | dst[key] | +| PrototypePollutionUtility/tests.js:161:35:161:37 | dst | PrototypePollutionUtility/tests.js:161:35:161:42 | dst[key] | +| PrototypePollutionUtility/tests.js:161:35:161:37 | dst | PrototypePollutionUtility/tests.js:161:35:161:42 | dst[key] | +| PrototypePollutionUtility/tests.js:161:35:161:37 | dst | PrototypePollutionUtility/tests.js:161:35:161:42 | dst[key] | +| PrototypePollutionUtility/tests.js:161:35:161:42 | dst[key] | PrototypePollutionUtility/tests.js:159:36:159:38 | dst | +| PrototypePollutionUtility/tests.js:161:35:161:42 | dst[key] | PrototypePollutionUtility/tests.js:159:36:159:38 | dst | +| PrototypePollutionUtility/tests.js:161:35:161:42 | dst[key] | PrototypePollutionUtility/tests.js:159:36:159:38 | dst | +| PrototypePollutionUtility/tests.js:161:35:161:42 | dst[key] | PrototypePollutionUtility/tests.js:159:36:159:38 | dst | +| PrototypePollutionUtility/tests.js:161:39:161:41 | key | PrototypePollutionUtility/tests.js:161:35:161:42 | dst[key] | +| PrototypePollutionUtility/tests.js:161:39:161:41 | key | PrototypePollutionUtility/tests.js:161:35:161:42 | dst[key] | +| PrototypePollutionUtility/tests.js:161:39:161:41 | key | PrototypePollutionUtility/tests.js:161:35:161:42 | dst[key] | +| PrototypePollutionUtility/tests.js:161:39:161:41 | key | PrototypePollutionUtility/tests.js:161:35:161:42 | dst[key] | +| PrototypePollutionUtility/tests.js:161:45:161:47 | src | PrototypePollutionUtility/tests.js:161:45:161:52 | src[key] | +| PrototypePollutionUtility/tests.js:161:45:161:47 | src | PrototypePollutionUtility/tests.js:161:45:161:52 | src[key] | +| PrototypePollutionUtility/tests.js:161:45:161:47 | src | PrototypePollutionUtility/tests.js:161:45:161:52 | src[key] | +| PrototypePollutionUtility/tests.js:161:45:161:47 | src | PrototypePollutionUtility/tests.js:161:45:161:52 | src[key] | +| PrototypePollutionUtility/tests.js:161:45:161:52 | src[key] | PrototypePollutionUtility/tests.js:159:41:159:43 | src | +| PrototypePollutionUtility/tests.js:161:45:161:52 | src[key] | PrototypePollutionUtility/tests.js:159:41:159:43 | src | +| PrototypePollutionUtility/tests.js:161:45:161:52 | src[key] | PrototypePollutionUtility/tests.js:159:41:159:43 | src | +| PrototypePollutionUtility/tests.js:161:45:161:52 | src[key] | PrototypePollutionUtility/tests.js:159:41:159:43 | src | +| PrototypePollutionUtility/tests.js:161:49:161:51 | key | PrototypePollutionUtility/tests.js:161:45:161:52 | src[key] | +| PrototypePollutionUtility/tests.js:161:49:161:51 | key | PrototypePollutionUtility/tests.js:161:45:161:52 | src[key] | +| PrototypePollutionUtility/tests.js:161:49:161:51 | key | PrototypePollutionUtility/tests.js:161:45:161:52 | src[key] | +| PrototypePollutionUtility/tests.js:161:49:161:51 | key | PrototypePollutionUtility/tests.js:161:45:161:52 | src[key] | +| PrototypePollutionUtility/tests.js:165:37:165:39 | src | PrototypePollutionUtility/tests.js:169:45:169:47 | src | +| PrototypePollutionUtility/tests.js:165:37:165:39 | src | PrototypePollutionUtility/tests.js:169:45:169:47 | src | +| PrototypePollutionUtility/tests.js:165:37:165:39 | src | PrototypePollutionUtility/tests.js:171:24:171:26 | src | +| PrototypePollutionUtility/tests.js:165:37:165:39 | src | PrototypePollutionUtility/tests.js:171:24:171:26 | src | +| PrototypePollutionUtility/tests.js:166:14:166:16 | key | PrototypePollutionUtility/tests.js:169:49:169:51 | key | +| PrototypePollutionUtility/tests.js:166:14:166:16 | key | PrototypePollutionUtility/tests.js:169:49:169:51 | key | +| PrototypePollutionUtility/tests.js:166:14:166:16 | key | PrototypePollutionUtility/tests.js:169:49:169:51 | key | +| PrototypePollutionUtility/tests.js:166:14:166:16 | key | PrototypePollutionUtility/tests.js:169:49:169:51 | key | +| PrototypePollutionUtility/tests.js:166:14:166:16 | key | PrototypePollutionUtility/tests.js:171:17:171:19 | key | +| PrototypePollutionUtility/tests.js:166:14:166:16 | key | PrototypePollutionUtility/tests.js:171:17:171:19 | key | +| PrototypePollutionUtility/tests.js:166:14:166:16 | key | PrototypePollutionUtility/tests.js:171:17:171:19 | key | +| PrototypePollutionUtility/tests.js:166:14:166:16 | key | PrototypePollutionUtility/tests.js:171:17:171:19 | key | +| PrototypePollutionUtility/tests.js:166:14:166:16 | key | PrototypePollutionUtility/tests.js:171:17:171:19 | key | +| PrototypePollutionUtility/tests.js:166:14:166:16 | key | PrototypePollutionUtility/tests.js:171:17:171:19 | key | +| PrototypePollutionUtility/tests.js:166:14:166:16 | key | PrototypePollutionUtility/tests.js:171:17:171:19 | key | +| PrototypePollutionUtility/tests.js:166:14:166:16 | key | PrototypePollutionUtility/tests.js:171:28:171:30 | key | +| PrototypePollutionUtility/tests.js:166:14:166:16 | key | PrototypePollutionUtility/tests.js:171:28:171:30 | key | +| PrototypePollutionUtility/tests.js:166:14:166:16 | key | PrototypePollutionUtility/tests.js:171:28:171:30 | key | +| PrototypePollutionUtility/tests.js:166:14:166:16 | key | PrototypePollutionUtility/tests.js:171:28:171:30 | key | +| PrototypePollutionUtility/tests.js:169:45:169:47 | src | PrototypePollutionUtility/tests.js:169:45:169:52 | src[key] | +| PrototypePollutionUtility/tests.js:169:45:169:47 | src | PrototypePollutionUtility/tests.js:169:45:169:52 | src[key] | +| PrototypePollutionUtility/tests.js:169:45:169:52 | src[key] | PrototypePollutionUtility/tests.js:165:37:165:39 | src | +| PrototypePollutionUtility/tests.js:169:45:169:52 | src[key] | PrototypePollutionUtility/tests.js:165:37:165:39 | src | +| PrototypePollutionUtility/tests.js:169:45:169:52 | src[key] | PrototypePollutionUtility/tests.js:165:37:165:39 | src | +| PrototypePollutionUtility/tests.js:169:45:169:52 | src[key] | PrototypePollutionUtility/tests.js:165:37:165:39 | src | +| PrototypePollutionUtility/tests.js:169:45:169:52 | src[key] | PrototypePollutionUtility/tests.js:165:37:165:39 | src | +| PrototypePollutionUtility/tests.js:169:45:169:52 | src[key] | PrototypePollutionUtility/tests.js:165:37:165:39 | src | +| PrototypePollutionUtility/tests.js:169:49:169:51 | key | PrototypePollutionUtility/tests.js:169:45:169:52 | src[key] | +| PrototypePollutionUtility/tests.js:169:49:169:51 | key | PrototypePollutionUtility/tests.js:169:45:169:52 | src[key] | +| PrototypePollutionUtility/tests.js:171:24:171:26 | src | PrototypePollutionUtility/tests.js:171:24:171:31 | src[key] | +| PrototypePollutionUtility/tests.js:171:24:171:26 | src | PrototypePollutionUtility/tests.js:171:24:171:31 | src[key] | +| PrototypePollutionUtility/tests.js:171:24:171:26 | src | PrototypePollutionUtility/tests.js:171:24:171:31 | src[key] | +| PrototypePollutionUtility/tests.js:171:24:171:26 | src | PrototypePollutionUtility/tests.js:171:24:171:31 | src[key] | +| PrototypePollutionUtility/tests.js:171:24:171:31 | src[key] | PrototypePollutionUtility/tests.js:171:24:171:31 | src[key] | +| PrototypePollutionUtility/tests.js:171:28:171:30 | key | PrototypePollutionUtility/tests.js:171:24:171:31 | src[key] | +| PrototypePollutionUtility/tests.js:171:28:171:30 | key | PrototypePollutionUtility/tests.js:171:24:171:31 | src[key] | +| PrototypePollutionUtility/tests.js:171:28:171:30 | key | PrototypePollutionUtility/tests.js:171:24:171:31 | src[key] | +| PrototypePollutionUtility/tests.js:171:28:171:30 | key | PrototypePollutionUtility/tests.js:171:24:171:31 | src[key] | +| PrototypePollutionUtility/tests.js:178:33:178:35 | src | PrototypePollutionUtility/tests.js:182:41:182:43 | src | +| PrototypePollutionUtility/tests.js:178:33:178:35 | src | PrototypePollutionUtility/tests.js:182:41:182:43 | src | +| PrototypePollutionUtility/tests.js:178:33:178:35 | src | PrototypePollutionUtility/tests.js:184:24:184:26 | src | +| PrototypePollutionUtility/tests.js:178:33:178:35 | src | PrototypePollutionUtility/tests.js:184:24:184:26 | src | +| PrototypePollutionUtility/tests.js:182:41:182:43 | src | PrototypePollutionUtility/tests.js:182:41:182:48 | src[key] | +| PrototypePollutionUtility/tests.js:182:41:182:43 | src | PrototypePollutionUtility/tests.js:182:41:182:48 | src[key] | +| PrototypePollutionUtility/tests.js:182:41:182:48 | src[key] | PrototypePollutionUtility/tests.js:178:33:178:35 | src | +| PrototypePollutionUtility/tests.js:182:41:182:48 | src[key] | PrototypePollutionUtility/tests.js:178:33:178:35 | src | +| PrototypePollutionUtility/tests.js:182:41:182:48 | src[key] | PrototypePollutionUtility/tests.js:178:33:178:35 | src | +| PrototypePollutionUtility/tests.js:182:41:182:48 | src[key] | PrototypePollutionUtility/tests.js:178:33:178:35 | src | +| PrototypePollutionUtility/tests.js:182:41:182:48 | src[key] | PrototypePollutionUtility/tests.js:178:33:178:35 | src | +| PrototypePollutionUtility/tests.js:182:41:182:48 | src[key] | PrototypePollutionUtility/tests.js:178:33:178:35 | src | +| PrototypePollutionUtility/tests.js:184:24:184:26 | src | PrototypePollutionUtility/tests.js:184:24:184:31 | src[key] | +| PrototypePollutionUtility/tests.js:184:24:184:26 | src | PrototypePollutionUtility/tests.js:184:24:184:31 | src[key] | +| PrototypePollutionUtility/tests.js:184:24:184:26 | src | PrototypePollutionUtility/tests.js:184:24:184:31 | src[key] | +| PrototypePollutionUtility/tests.js:184:24:184:26 | src | PrototypePollutionUtility/tests.js:184:24:184:31 | src[key] | +| PrototypePollutionUtility/tests.js:184:24:184:31 | src[key] | PrototypePollutionUtility/tests.js:184:24:184:31 | src[key] | +| PrototypePollutionUtility/tests.js:189:32:189:34 | dst | PrototypePollutionUtility/tests.js:194:35:194:37 | dst | +| PrototypePollutionUtility/tests.js:189:32:189:34 | dst | PrototypePollutionUtility/tests.js:194:35:194:37 | dst | +| PrototypePollutionUtility/tests.js:189:32:189:34 | dst | PrototypePollutionUtility/tests.js:196:13:196:15 | dst | +| PrototypePollutionUtility/tests.js:189:32:189:34 | dst | PrototypePollutionUtility/tests.js:196:13:196:15 | dst | +| PrototypePollutionUtility/tests.js:189:32:189:34 | dst | PrototypePollutionUtility/tests.js:196:13:196:15 | dst | +| PrototypePollutionUtility/tests.js:189:32:189:34 | dst | PrototypePollutionUtility/tests.js:196:13:196:15 | dst | +| PrototypePollutionUtility/tests.js:189:37:189:39 | src | PrototypePollutionUtility/tests.js:194:45:194:47 | src | +| PrototypePollutionUtility/tests.js:189:37:189:39 | src | PrototypePollutionUtility/tests.js:194:45:194:47 | src | +| PrototypePollutionUtility/tests.js:189:37:189:39 | src | PrototypePollutionUtility/tests.js:196:24:196:26 | src | +| PrototypePollutionUtility/tests.js:189:37:189:39 | src | PrototypePollutionUtility/tests.js:196:24:196:26 | src | +| PrototypePollutionUtility/tests.js:192:13:192:25 | key | PrototypePollutionUtility/tests.js:194:39:194:41 | key | +| PrototypePollutionUtility/tests.js:192:13:192:25 | key | PrototypePollutionUtility/tests.js:194:39:194:41 | key | +| PrototypePollutionUtility/tests.js:192:13:192:25 | key | PrototypePollutionUtility/tests.js:194:49:194:51 | key | +| PrototypePollutionUtility/tests.js:192:13:192:25 | key | PrototypePollutionUtility/tests.js:194:49:194:51 | key | +| PrototypePollutionUtility/tests.js:192:13:192:25 | key | PrototypePollutionUtility/tests.js:196:17:196:19 | key | +| PrototypePollutionUtility/tests.js:192:13:192:25 | key | PrototypePollutionUtility/tests.js:196:17:196:19 | key | +| PrototypePollutionUtility/tests.js:192:13:192:25 | key | PrototypePollutionUtility/tests.js:196:17:196:19 | key | +| PrototypePollutionUtility/tests.js:192:13:192:25 | key | PrototypePollutionUtility/tests.js:196:17:196:19 | key | +| PrototypePollutionUtility/tests.js:192:13:192:25 | key | PrototypePollutionUtility/tests.js:196:28:196:30 | key | +| PrototypePollutionUtility/tests.js:192:13:192:25 | key | PrototypePollutionUtility/tests.js:196:28:196:30 | key | +| PrototypePollutionUtility/tests.js:192:19:192:25 | keys[i] | PrototypePollutionUtility/tests.js:192:13:192:25 | key | +| PrototypePollutionUtility/tests.js:192:19:192:25 | keys[i] | PrototypePollutionUtility/tests.js:192:13:192:25 | key | +| PrototypePollutionUtility/tests.js:192:19:192:25 | keys[i] | PrototypePollutionUtility/tests.js:192:13:192:25 | key | +| PrototypePollutionUtility/tests.js:192:19:192:25 | keys[i] | PrototypePollutionUtility/tests.js:192:13:192:25 | key | +| PrototypePollutionUtility/tests.js:194:35:194:37 | dst | PrototypePollutionUtility/tests.js:194:35:194:42 | dst[key] | +| PrototypePollutionUtility/tests.js:194:35:194:37 | dst | PrototypePollutionUtility/tests.js:194:35:194:42 | dst[key] | +| PrototypePollutionUtility/tests.js:194:35:194:42 | dst[key] | PrototypePollutionUtility/tests.js:189:32:189:34 | dst | +| PrototypePollutionUtility/tests.js:194:35:194:42 | dst[key] | PrototypePollutionUtility/tests.js:189:32:189:34 | dst | +| PrototypePollutionUtility/tests.js:194:35:194:42 | dst[key] | PrototypePollutionUtility/tests.js:189:32:189:34 | dst | +| PrototypePollutionUtility/tests.js:194:35:194:42 | dst[key] | PrototypePollutionUtility/tests.js:189:32:189:34 | dst | +| PrototypePollutionUtility/tests.js:194:39:194:41 | key | PrototypePollutionUtility/tests.js:194:35:194:42 | dst[key] | +| PrototypePollutionUtility/tests.js:194:39:194:41 | key | PrototypePollutionUtility/tests.js:194:35:194:42 | dst[key] | +| PrototypePollutionUtility/tests.js:194:45:194:47 | src | PrototypePollutionUtility/tests.js:194:45:194:52 | src[key] | +| PrototypePollutionUtility/tests.js:194:45:194:47 | src | PrototypePollutionUtility/tests.js:194:45:194:52 | src[key] | +| PrototypePollutionUtility/tests.js:194:45:194:52 | src[key] | PrototypePollutionUtility/tests.js:189:37:189:39 | src | +| PrototypePollutionUtility/tests.js:194:45:194:52 | src[key] | PrototypePollutionUtility/tests.js:189:37:189:39 | src | +| PrototypePollutionUtility/tests.js:194:45:194:52 | src[key] | PrototypePollutionUtility/tests.js:189:37:189:39 | src | +| PrototypePollutionUtility/tests.js:194:45:194:52 | src[key] | PrototypePollutionUtility/tests.js:189:37:189:39 | src | +| PrototypePollutionUtility/tests.js:194:45:194:52 | src[key] | PrototypePollutionUtility/tests.js:189:37:189:39 | src | +| PrototypePollutionUtility/tests.js:194:45:194:52 | src[key] | PrototypePollutionUtility/tests.js:189:37:189:39 | src | +| PrototypePollutionUtility/tests.js:194:49:194:51 | key | PrototypePollutionUtility/tests.js:194:45:194:52 | src[key] | +| PrototypePollutionUtility/tests.js:194:49:194:51 | key | PrototypePollutionUtility/tests.js:194:45:194:52 | src[key] | +| PrototypePollutionUtility/tests.js:196:24:196:26 | src | PrototypePollutionUtility/tests.js:196:24:196:31 | src[key] | +| PrototypePollutionUtility/tests.js:196:24:196:26 | src | PrototypePollutionUtility/tests.js:196:24:196:31 | src[key] | +| PrototypePollutionUtility/tests.js:196:24:196:26 | src | PrototypePollutionUtility/tests.js:196:24:196:31 | src[key] | +| PrototypePollutionUtility/tests.js:196:24:196:26 | src | PrototypePollutionUtility/tests.js:196:24:196:31 | src[key] | +| PrototypePollutionUtility/tests.js:196:24:196:31 | src[key] | PrototypePollutionUtility/tests.js:196:24:196:31 | src[key] | +| PrototypePollutionUtility/tests.js:196:28:196:30 | key | PrototypePollutionUtility/tests.js:196:24:196:31 | src[key] | +| PrototypePollutionUtility/tests.js:196:28:196:30 | key | PrototypePollutionUtility/tests.js:196:24:196:31 | src[key] | +| PrototypePollutionUtility/tests.js:196:28:196:30 | key | PrototypePollutionUtility/tests.js:196:24:196:31 | src[key] | +| PrototypePollutionUtility/tests.js:196:28:196:30 | key | PrototypePollutionUtility/tests.js:196:24:196:31 | src[key] | +| PrototypePollutionUtility/tests.js:201:39:201:41 | dst | PrototypePollutionUtility/tests.js:206:42:206:44 | dst | +| PrototypePollutionUtility/tests.js:201:39:201:41 | dst | PrototypePollutionUtility/tests.js:206:42:206:44 | dst | +| PrototypePollutionUtility/tests.js:201:39:201:41 | dst | PrototypePollutionUtility/tests.js:208:13:208:15 | dst | +| PrototypePollutionUtility/tests.js:201:39:201:41 | dst | PrototypePollutionUtility/tests.js:208:13:208:15 | dst | +| PrototypePollutionUtility/tests.js:201:39:201:41 | dst | PrototypePollutionUtility/tests.js:208:13:208:15 | dst | +| PrototypePollutionUtility/tests.js:201:39:201:41 | dst | PrototypePollutionUtility/tests.js:208:13:208:15 | dst | +| PrototypePollutionUtility/tests.js:201:44:201:46 | src | PrototypePollutionUtility/tests.js:206:56:206:58 | src | +| PrototypePollutionUtility/tests.js:201:44:201:46 | src | PrototypePollutionUtility/tests.js:206:56:206:58 | src | +| PrototypePollutionUtility/tests.js:201:44:201:46 | src | PrototypePollutionUtility/tests.js:208:28:208:30 | src | +| PrototypePollutionUtility/tests.js:201:44:201:46 | src | PrototypePollutionUtility/tests.js:208:28:208:30 | src | +| PrototypePollutionUtility/tests.js:206:42:206:44 | dst | PrototypePollutionUtility/tests.js:206:42:206:53 | dst[keys[i]] | +| PrototypePollutionUtility/tests.js:206:42:206:44 | dst | PrototypePollutionUtility/tests.js:206:42:206:53 | dst[keys[i]] | +| PrototypePollutionUtility/tests.js:206:42:206:53 | dst[keys[i]] | PrototypePollutionUtility/tests.js:201:39:201:41 | dst | +| PrototypePollutionUtility/tests.js:206:42:206:53 | dst[keys[i]] | PrototypePollutionUtility/tests.js:201:39:201:41 | dst | +| PrototypePollutionUtility/tests.js:206:42:206:53 | dst[keys[i]] | PrototypePollutionUtility/tests.js:201:39:201:41 | dst | +| PrototypePollutionUtility/tests.js:206:42:206:53 | dst[keys[i]] | PrototypePollutionUtility/tests.js:201:39:201:41 | dst | +| PrototypePollutionUtility/tests.js:206:46:206:52 | keys[i] | PrototypePollutionUtility/tests.js:206:42:206:53 | dst[keys[i]] | +| PrototypePollutionUtility/tests.js:206:46:206:52 | keys[i] | PrototypePollutionUtility/tests.js:206:42:206:53 | dst[keys[i]] | +| PrototypePollutionUtility/tests.js:206:46:206:52 | keys[i] | PrototypePollutionUtility/tests.js:206:42:206:53 | dst[keys[i]] | +| PrototypePollutionUtility/tests.js:206:46:206:52 | keys[i] | PrototypePollutionUtility/tests.js:206:42:206:53 | dst[keys[i]] | +| PrototypePollutionUtility/tests.js:206:56:206:58 | src | PrototypePollutionUtility/tests.js:206:56:206:67 | src[keys[i]] | +| PrototypePollutionUtility/tests.js:206:56:206:58 | src | PrototypePollutionUtility/tests.js:206:56:206:67 | src[keys[i]] | +| PrototypePollutionUtility/tests.js:206:56:206:67 | src[keys[i]] | PrototypePollutionUtility/tests.js:201:44:201:46 | src | +| PrototypePollutionUtility/tests.js:206:56:206:67 | src[keys[i]] | PrototypePollutionUtility/tests.js:201:44:201:46 | src | +| PrototypePollutionUtility/tests.js:206:56:206:67 | src[keys[i]] | PrototypePollutionUtility/tests.js:201:44:201:46 | src | +| PrototypePollutionUtility/tests.js:206:56:206:67 | src[keys[i]] | PrototypePollutionUtility/tests.js:201:44:201:46 | src | +| PrototypePollutionUtility/tests.js:206:56:206:67 | src[keys[i]] | PrototypePollutionUtility/tests.js:201:44:201:46 | src | +| PrototypePollutionUtility/tests.js:206:56:206:67 | src[keys[i]] | PrototypePollutionUtility/tests.js:201:44:201:46 | src | +| PrototypePollutionUtility/tests.js:206:60:206:66 | keys[i] | PrototypePollutionUtility/tests.js:206:56:206:67 | src[keys[i]] | +| PrototypePollutionUtility/tests.js:206:60:206:66 | keys[i] | PrototypePollutionUtility/tests.js:206:56:206:67 | src[keys[i]] | +| PrototypePollutionUtility/tests.js:206:60:206:66 | keys[i] | PrototypePollutionUtility/tests.js:206:56:206:67 | src[keys[i]] | +| PrototypePollutionUtility/tests.js:206:60:206:66 | keys[i] | PrototypePollutionUtility/tests.js:206:56:206:67 | src[keys[i]] | +| PrototypePollutionUtility/tests.js:208:17:208:23 | keys[i] | PrototypePollutionUtility/tests.js:208:17:208:23 | keys[i] | +| PrototypePollutionUtility/tests.js:208:28:208:30 | src | PrototypePollutionUtility/tests.js:208:28:208:39 | src[keys[i]] | +| PrototypePollutionUtility/tests.js:208:28:208:30 | src | PrototypePollutionUtility/tests.js:208:28:208:39 | src[keys[i]] | +| PrototypePollutionUtility/tests.js:208:28:208:30 | src | PrototypePollutionUtility/tests.js:208:28:208:39 | src[keys[i]] | +| PrototypePollutionUtility/tests.js:208:28:208:30 | src | PrototypePollutionUtility/tests.js:208:28:208:39 | src[keys[i]] | +| PrototypePollutionUtility/tests.js:208:28:208:39 | src[keys[i]] | PrototypePollutionUtility/tests.js:208:28:208:39 | src[keys[i]] | +| PrototypePollutionUtility/tests.js:208:32:208:38 | keys[i] | PrototypePollutionUtility/tests.js:208:28:208:39 | src[keys[i]] | +| PrototypePollutionUtility/tests.js:208:32:208:38 | keys[i] | PrototypePollutionUtility/tests.js:208:28:208:39 | src[keys[i]] | +| PrototypePollutionUtility/tests.js:208:32:208:38 | keys[i] | PrototypePollutionUtility/tests.js:208:28:208:39 | src[keys[i]] | +| PrototypePollutionUtility/tests.js:208:32:208:38 | keys[i] | PrototypePollutionUtility/tests.js:208:28:208:39 | src[keys[i]] | +| PrototypePollutionUtility/tests.js:208:32:208:38 | keys[i] | PrototypePollutionUtility/tests.js:208:28:208:39 | src[keys[i]] | +| PrototypePollutionUtility/tests.js:208:32:208:38 | keys[i] | PrototypePollutionUtility/tests.js:208:28:208:39 | src[keys[i]] | +| PrototypePollutionUtility/tests.js:208:32:208:38 | keys[i] | PrototypePollutionUtility/tests.js:208:28:208:39 | src[keys[i]] | +#select +| PrototypePollutionUtility/tests.js:8:13:8:15 | dst | PrototypePollutionUtility/tests.js:4:14:4:16 | key | PrototypePollutionUtility/tests.js:8:13:8:15 | dst | Properties are copied from $@ to $@ without guarding against prototype pollution. | PrototypePollutionUtility/tests.js:4:21:4:23 | src | src | PrototypePollutionUtility/tests.js:8:13:8:15 | dst | dst | +| PrototypePollutionUtility/tests.js:18:13:18:15 | dst | PrototypePollutionUtility/tests.js:14:30:14:32 | key | PrototypePollutionUtility/tests.js:18:13:18:15 | dst | Properties are copied from $@ to $@ without guarding against prototype pollution. | PrototypePollutionUtility/tests.js:14:17:14:19 | src | src | PrototypePollutionUtility/tests.js:18:13:18:15 | dst | dst | +| PrototypePollutionUtility/tests.js:36:9:36:11 | dst | PrototypePollutionUtility/tests.js:25:18:25:20 | key | PrototypePollutionUtility/tests.js:36:9:36:11 | dst | Properties are copied from $@ to $@ without guarding against prototype pollution. | PrototypePollutionUtility/tests.js:25:25:25:30 | source | source | PrototypePollutionUtility/tests.js:36:9:36:11 | dst | dst | +| PrototypePollutionUtility/tests.js:46:13:46:15 | dst | PrototypePollutionUtility/tests.js:41:14:41:16 | key | PrototypePollutionUtility/tests.js:46:13:46:15 | dst | Properties are copied from $@ to $@ without guarding against prototype pollution. | PrototypePollutionUtility/tests.js:41:21:41:23 | src | src | PrototypePollutionUtility/tests.js:46:13:46:15 | dst | dst | +| PrototypePollutionUtility/tests.js:57:13:57:15 | dst | PrototypePollutionUtility/tests.js:52:14:52:16 | key | PrototypePollutionUtility/tests.js:57:13:57:15 | dst | Properties are copied from $@ to $@ without guarding against prototype pollution. | PrototypePollutionUtility/tests.js:52:21:52:23 | src | src | PrototypePollutionUtility/tests.js:57:13:57:15 | dst | dst | +| PrototypePollutionUtility/tests.js:109:13:109:15 | dst | PrototypePollutionUtility/tests.js:102:14:102:16 | key | PrototypePollutionUtility/tests.js:109:13:109:15 | dst | Properties are copied from $@ to $@ without guarding against prototype pollution. | PrototypePollutionUtility/tests.js:102:21:102:23 | src | src | PrototypePollutionUtility/tests.js:109:13:109:15 | dst | dst | +| PrototypePollutionUtility/tests.js:154:13:154:15 | dst | PrototypePollutionUtility/tests.js:150:14:150:16 | key | PrototypePollutionUtility/tests.js:154:13:154:15 | dst | Properties are copied from $@ to $@ without guarding against prototype pollution. | PrototypePollutionUtility/tests.js:150:21:150:23 | src | src | PrototypePollutionUtility/tests.js:154:13:154:15 | dst | dst | +| PrototypePollutionUtility/tests.js:196:13:196:15 | dst | PrototypePollutionUtility/tests.js:192:19:192:25 | keys[i] | PrototypePollutionUtility/tests.js:196:13:196:15 | dst | Properties are copied from $@ to $@ without guarding against prototype pollution. | PrototypePollutionUtility/tests.js:190:28:190:30 | src | src | PrototypePollutionUtility/tests.js:196:13:196:15 | dst | dst | diff --git a/javascript/ql/test/query-tests/Security/CWE-400/PrototypePollutionUtility.qlref b/javascript/ql/test/query-tests/Security/CWE-400/PrototypePollutionUtility.qlref new file mode 100644 index 00000000000..d8265b5566a --- /dev/null +++ b/javascript/ql/test/query-tests/Security/CWE-400/PrototypePollutionUtility.qlref @@ -0,0 +1 @@ +Security/CWE-400/PrototypePollutionUtility.ql \ No newline at end of file diff --git a/javascript/ql/test/query-tests/Security/CWE-400/PrototypePollutionUtility/tests.js b/javascript/ql/test/query-tests/Security/CWE-400/PrototypePollutionUtility/tests.js new file mode 100644 index 00000000000..1540b9429af --- /dev/null +++ b/javascript/ql/test/query-tests/Security/CWE-400/PrototypePollutionUtility/tests.js @@ -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 + } + } +} From c889420dd3d7b73c84add27c9e9804145367f24f Mon Sep 17 00:00:00 2001 From: Asger F Date: Fri, 8 Nov 2019 10:56:30 +0000 Subject: [PATCH 03/17] JS: Add qhelp samples to test suite --- .../PrototypePollutionUtility.expected | 188 ++++++++++++++++++ .../examples/PrototypePollutionUtility.js | 10 + .../PrototypePollutionUtility_fixed.js | 10 + .../PrototypePollutionUtility_fixed2.js | 11 + 4 files changed, 219 insertions(+) create mode 100644 javascript/ql/test/query-tests/Security/CWE-400/examples/PrototypePollutionUtility.js create mode 100644 javascript/ql/test/query-tests/Security/CWE-400/examples/PrototypePollutionUtility_fixed.js create mode 100644 javascript/ql/test/query-tests/Security/CWE-400/examples/PrototypePollutionUtility_fixed2.js diff --git a/javascript/ql/test/query-tests/Security/CWE-400/PrototypePollutionUtility.expected b/javascript/ql/test/query-tests/Security/CWE-400/PrototypePollutionUtility.expected index 1c911a35bbe..45d6657b911 100644 --- a/javascript/ql/test/query-tests/Security/CWE-400/PrototypePollutionUtility.expected +++ b/javascript/ql/test/query-tests/Security/CWE-400/PrototypePollutionUtility.expected @@ -554,6 +554,88 @@ nodes | PrototypePollutionUtility/tests.js:208:32:208:38 | keys[i] | | PrototypePollutionUtility/tests.js:208:32:208:38 | keys[i] | | PrototypePollutionUtility/tests.js:208:32:208:38 | keys[i] | +| examples/PrototypePollutionUtility.js:1:16:1:18 | dst | +| examples/PrototypePollutionUtility.js:1:16:1:18 | dst | +| examples/PrototypePollutionUtility.js:1:21:1:23 | src | +| examples/PrototypePollutionUtility.js:1:21:1:23 | src | +| examples/PrototypePollutionUtility.js:2:14:2:16 | key | +| examples/PrototypePollutionUtility.js:2:14:2:16 | key | +| examples/PrototypePollutionUtility.js:2:14:2:16 | key | +| examples/PrototypePollutionUtility.js:5:19:5:21 | dst | +| examples/PrototypePollutionUtility.js:5:19:5:21 | dst | +| examples/PrototypePollutionUtility.js:5:19:5:26 | dst[key] | +| examples/PrototypePollutionUtility.js:5:19:5:26 | dst[key] | +| examples/PrototypePollutionUtility.js:5:19:5:26 | dst[key] | +| examples/PrototypePollutionUtility.js:5:19:5:26 | dst[key] | +| examples/PrototypePollutionUtility.js:5:23:5:25 | key | +| examples/PrototypePollutionUtility.js:5:23:5:25 | key | +| examples/PrototypePollutionUtility.js:5:29:5:31 | src | +| examples/PrototypePollutionUtility.js:5:29:5:31 | src | +| examples/PrototypePollutionUtility.js:5:29:5:36 | src[key] | +| examples/PrototypePollutionUtility.js:5:29:5:36 | src[key] | +| examples/PrototypePollutionUtility.js:5:29:5:36 | src[key] | +| examples/PrototypePollutionUtility.js:5:29:5:36 | src[key] | +| examples/PrototypePollutionUtility.js:5:29:5:36 | src[key] | +| examples/PrototypePollutionUtility.js:5:33:5:35 | key | +| examples/PrototypePollutionUtility.js:5:33:5:35 | key | +| examples/PrototypePollutionUtility.js:7:13:7:15 | dst | +| examples/PrototypePollutionUtility.js:7:13:7:15 | dst | +| examples/PrototypePollutionUtility.js:7:13:7:15 | dst | +| examples/PrototypePollutionUtility.js:7:17:7:19 | key | +| examples/PrototypePollutionUtility.js:7:17:7:19 | key | +| examples/PrototypePollutionUtility.js:7:17:7:19 | key | +| examples/PrototypePollutionUtility.js:7:24:7:26 | src | +| examples/PrototypePollutionUtility.js:7:24:7:26 | src | +| examples/PrototypePollutionUtility.js:7:24:7:31 | src[key] | +| examples/PrototypePollutionUtility.js:7:24:7:31 | src[key] | +| examples/PrototypePollutionUtility.js:7:24:7:31 | src[key] | +| examples/PrototypePollutionUtility.js:7:24:7:31 | src[key] | +| examples/PrototypePollutionUtility.js:7:24:7:31 | src[key] | +| examples/PrototypePollutionUtility.js:7:24:7:31 | src[key] | +| examples/PrototypePollutionUtility.js:7:28:7:30 | key | +| examples/PrototypePollutionUtility.js:7:28:7:30 | key | +| examples/PrototypePollutionUtility_fixed2.js:1:21:1:23 | src | +| examples/PrototypePollutionUtility_fixed2.js:1:21:1:23 | src | +| examples/PrototypePollutionUtility_fixed2.js:6:29:6:31 | src | +| examples/PrototypePollutionUtility_fixed2.js:6:29:6:31 | src | +| examples/PrototypePollutionUtility_fixed2.js:6:29:6:36 | src[key] | +| examples/PrototypePollutionUtility_fixed2.js:6:29:6:36 | src[key] | +| examples/PrototypePollutionUtility_fixed2.js:6:29:6:36 | src[key] | +| examples/PrototypePollutionUtility_fixed2.js:6:29:6:36 | src[key] | +| examples/PrototypePollutionUtility_fixed2.js:6:29:6:36 | src[key] | +| examples/PrototypePollutionUtility_fixed2.js:8:24:8:26 | src | +| examples/PrototypePollutionUtility_fixed2.js:8:24:8:26 | src | +| examples/PrototypePollutionUtility_fixed2.js:8:24:8:31 | src[key] | +| examples/PrototypePollutionUtility_fixed2.js:8:24:8:31 | src[key] | +| examples/PrototypePollutionUtility_fixed2.js:8:24:8:31 | src[key] | +| examples/PrototypePollutionUtility_fixed2.js:8:24:8:31 | src[key] | +| examples/PrototypePollutionUtility_fixed2.js:8:24:8:31 | src[key] | +| examples/PrototypePollutionUtility_fixed2.js:8:24:8:31 | src[key] | +| examples/PrototypePollutionUtility_fixed.js:1:21:1:23 | src | +| examples/PrototypePollutionUtility_fixed.js:1:21:1:23 | src | +| examples/PrototypePollutionUtility_fixed.js:2:14:2:16 | key | +| examples/PrototypePollutionUtility_fixed.js:2:14:2:16 | key | +| examples/PrototypePollutionUtility_fixed.js:2:14:2:16 | key | +| examples/PrototypePollutionUtility_fixed.js:5:29:5:31 | src | +| examples/PrototypePollutionUtility_fixed.js:5:29:5:31 | src | +| examples/PrototypePollutionUtility_fixed.js:5:29:5:36 | src[key] | +| examples/PrototypePollutionUtility_fixed.js:5:29:5:36 | src[key] | +| examples/PrototypePollutionUtility_fixed.js:5:29:5:36 | src[key] | +| examples/PrototypePollutionUtility_fixed.js:5:29:5:36 | src[key] | +| examples/PrototypePollutionUtility_fixed.js:5:29:5:36 | src[key] | +| examples/PrototypePollutionUtility_fixed.js:7:17:7:19 | key | +| examples/PrototypePollutionUtility_fixed.js:7:17:7:19 | key | +| examples/PrototypePollutionUtility_fixed.js:7:17:7:19 | key | +| examples/PrototypePollutionUtility_fixed.js:7:24:7:26 | src | +| examples/PrototypePollutionUtility_fixed.js:7:24:7:26 | src | +| examples/PrototypePollutionUtility_fixed.js:7:24:7:31 | src[key] | +| examples/PrototypePollutionUtility_fixed.js:7:24:7:31 | src[key] | +| examples/PrototypePollutionUtility_fixed.js:7:24:7:31 | src[key] | +| examples/PrototypePollutionUtility_fixed.js:7:24:7:31 | src[key] | +| examples/PrototypePollutionUtility_fixed.js:7:24:7:31 | src[key] | +| examples/PrototypePollutionUtility_fixed.js:7:24:7:31 | src[key] | +| examples/PrototypePollutionUtility_fixed.js:7:28:7:30 | key | +| examples/PrototypePollutionUtility_fixed.js:7:28:7:30 | key | edges | PrototypePollutionUtility/tests.js:3:25:3:27 | dst | PrototypePollutionUtility/tests.js:6:28:6:30 | dst | | PrototypePollutionUtility/tests.js:3:25:3:27 | dst | PrototypePollutionUtility/tests.js:6:28:6:30 | dst | @@ -1259,6 +1341,111 @@ edges | PrototypePollutionUtility/tests.js:208:32:208:38 | keys[i] | PrototypePollutionUtility/tests.js:208:28:208:39 | src[keys[i]] | | PrototypePollutionUtility/tests.js:208:32:208:38 | keys[i] | PrototypePollutionUtility/tests.js:208:28:208:39 | src[keys[i]] | | PrototypePollutionUtility/tests.js:208:32:208:38 | keys[i] | PrototypePollutionUtility/tests.js:208:28:208:39 | src[keys[i]] | +| examples/PrototypePollutionUtility.js:1:16:1:18 | dst | examples/PrototypePollutionUtility.js:5:19:5:21 | dst | +| examples/PrototypePollutionUtility.js:1:16:1:18 | dst | examples/PrototypePollutionUtility.js:5:19:5:21 | dst | +| examples/PrototypePollutionUtility.js:1:16:1:18 | dst | examples/PrototypePollutionUtility.js:7:13:7:15 | dst | +| examples/PrototypePollutionUtility.js:1:16:1:18 | dst | examples/PrototypePollutionUtility.js:7:13:7:15 | dst | +| examples/PrototypePollutionUtility.js:1:16:1:18 | dst | examples/PrototypePollutionUtility.js:7:13:7:15 | dst | +| examples/PrototypePollutionUtility.js:1:16:1:18 | dst | examples/PrototypePollutionUtility.js:7:13:7:15 | dst | +| examples/PrototypePollutionUtility.js:1:21:1:23 | src | examples/PrototypePollutionUtility.js:5:29:5:31 | src | +| examples/PrototypePollutionUtility.js:1:21:1:23 | src | examples/PrototypePollutionUtility.js:5:29:5:31 | src | +| examples/PrototypePollutionUtility.js:1:21:1:23 | src | examples/PrototypePollutionUtility.js:7:24:7:26 | src | +| examples/PrototypePollutionUtility.js:1:21:1:23 | src | examples/PrototypePollutionUtility.js:7:24:7:26 | src | +| examples/PrototypePollutionUtility.js:2:14:2:16 | key | examples/PrototypePollutionUtility.js:5:23:5:25 | key | +| examples/PrototypePollutionUtility.js:2:14:2:16 | key | examples/PrototypePollutionUtility.js:5:23:5:25 | key | +| examples/PrototypePollutionUtility.js:2:14:2:16 | key | examples/PrototypePollutionUtility.js:5:23:5:25 | key | +| examples/PrototypePollutionUtility.js:2:14:2:16 | key | examples/PrototypePollutionUtility.js:5:23:5:25 | key | +| examples/PrototypePollutionUtility.js:2:14:2:16 | key | examples/PrototypePollutionUtility.js:5:33:5:35 | key | +| examples/PrototypePollutionUtility.js:2:14:2:16 | key | examples/PrototypePollutionUtility.js:5:33:5:35 | key | +| examples/PrototypePollutionUtility.js:2:14:2:16 | key | examples/PrototypePollutionUtility.js:5:33:5:35 | key | +| examples/PrototypePollutionUtility.js:2:14:2:16 | key | examples/PrototypePollutionUtility.js:5:33:5:35 | key | +| examples/PrototypePollutionUtility.js:2:14:2:16 | key | examples/PrototypePollutionUtility.js:7:17:7:19 | key | +| examples/PrototypePollutionUtility.js:2:14:2:16 | key | examples/PrototypePollutionUtility.js:7:17:7:19 | key | +| examples/PrototypePollutionUtility.js:2:14:2:16 | key | examples/PrototypePollutionUtility.js:7:17:7:19 | key | +| examples/PrototypePollutionUtility.js:2:14:2:16 | key | examples/PrototypePollutionUtility.js:7:17:7:19 | key | +| examples/PrototypePollutionUtility.js:2:14:2:16 | key | examples/PrototypePollutionUtility.js:7:17:7:19 | key | +| examples/PrototypePollutionUtility.js:2:14:2:16 | key | examples/PrototypePollutionUtility.js:7:17:7:19 | key | +| examples/PrototypePollutionUtility.js:2:14:2:16 | key | examples/PrototypePollutionUtility.js:7:17:7:19 | key | +| examples/PrototypePollutionUtility.js:2:14:2:16 | key | examples/PrototypePollutionUtility.js:7:28:7:30 | key | +| examples/PrototypePollutionUtility.js:2:14:2:16 | key | examples/PrototypePollutionUtility.js:7:28:7:30 | key | +| examples/PrototypePollutionUtility.js:2:14:2:16 | key | examples/PrototypePollutionUtility.js:7:28:7:30 | key | +| examples/PrototypePollutionUtility.js:2:14:2:16 | key | examples/PrototypePollutionUtility.js:7:28:7:30 | key | +| examples/PrototypePollutionUtility.js:5:19:5:21 | dst | examples/PrototypePollutionUtility.js:5:19:5:26 | dst[key] | +| examples/PrototypePollutionUtility.js:5:19:5:21 | dst | examples/PrototypePollutionUtility.js:5:19:5:26 | dst[key] | +| examples/PrototypePollutionUtility.js:5:19:5:26 | dst[key] | examples/PrototypePollutionUtility.js:1:16:1:18 | dst | +| examples/PrototypePollutionUtility.js:5:19:5:26 | dst[key] | examples/PrototypePollutionUtility.js:1:16:1:18 | dst | +| examples/PrototypePollutionUtility.js:5:19:5:26 | dst[key] | examples/PrototypePollutionUtility.js:1:16:1:18 | dst | +| examples/PrototypePollutionUtility.js:5:19:5:26 | dst[key] | examples/PrototypePollutionUtility.js:1:16:1:18 | dst | +| examples/PrototypePollutionUtility.js:5:23:5:25 | key | examples/PrototypePollutionUtility.js:5:19:5:26 | dst[key] | +| examples/PrototypePollutionUtility.js:5:23:5:25 | key | examples/PrototypePollutionUtility.js:5:19:5:26 | dst[key] | +| examples/PrototypePollutionUtility.js:5:29:5:31 | src | examples/PrototypePollutionUtility.js:5:29:5:36 | src[key] | +| examples/PrototypePollutionUtility.js:5:29:5:31 | src | examples/PrototypePollutionUtility.js:5:29:5:36 | src[key] | +| examples/PrototypePollutionUtility.js:5:29:5:36 | src[key] | examples/PrototypePollutionUtility.js:1:21:1:23 | src | +| examples/PrototypePollutionUtility.js:5:29:5:36 | src[key] | examples/PrototypePollutionUtility.js:1:21:1:23 | src | +| examples/PrototypePollutionUtility.js:5:29:5:36 | src[key] | examples/PrototypePollutionUtility.js:1:21:1:23 | src | +| examples/PrototypePollutionUtility.js:5:29:5:36 | src[key] | examples/PrototypePollutionUtility.js:1:21:1:23 | src | +| examples/PrototypePollutionUtility.js:5:29:5:36 | src[key] | examples/PrototypePollutionUtility.js:1:21:1:23 | src | +| examples/PrototypePollutionUtility.js:5:29:5:36 | src[key] | examples/PrototypePollutionUtility.js:1:21:1:23 | src | +| examples/PrototypePollutionUtility.js:5:33:5:35 | key | examples/PrototypePollutionUtility.js:5:29:5:36 | src[key] | +| examples/PrototypePollutionUtility.js:5:33:5:35 | key | examples/PrototypePollutionUtility.js:5:29:5:36 | src[key] | +| examples/PrototypePollutionUtility.js:7:24:7:26 | src | examples/PrototypePollutionUtility.js:7:24:7:31 | src[key] | +| examples/PrototypePollutionUtility.js:7:24:7:26 | src | examples/PrototypePollutionUtility.js:7:24:7:31 | src[key] | +| examples/PrototypePollutionUtility.js:7:24:7:26 | src | examples/PrototypePollutionUtility.js:7:24:7:31 | src[key] | +| examples/PrototypePollutionUtility.js:7:24:7:26 | src | examples/PrototypePollutionUtility.js:7:24:7:31 | src[key] | +| examples/PrototypePollutionUtility.js:7:24:7:31 | src[key] | examples/PrototypePollutionUtility.js:7:24:7:31 | src[key] | +| examples/PrototypePollutionUtility.js:7:28:7:30 | key | examples/PrototypePollutionUtility.js:7:24:7:31 | src[key] | +| examples/PrototypePollutionUtility.js:7:28:7:30 | key | examples/PrototypePollutionUtility.js:7:24:7:31 | src[key] | +| examples/PrototypePollutionUtility.js:7:28:7:30 | key | examples/PrototypePollutionUtility.js:7:24:7:31 | src[key] | +| examples/PrototypePollutionUtility.js:7:28:7:30 | key | examples/PrototypePollutionUtility.js:7:24:7:31 | src[key] | +| examples/PrototypePollutionUtility_fixed2.js:1:21:1:23 | src | examples/PrototypePollutionUtility_fixed2.js:6:29:6:31 | src | +| examples/PrototypePollutionUtility_fixed2.js:1:21:1:23 | src | examples/PrototypePollutionUtility_fixed2.js:6:29:6:31 | src | +| examples/PrototypePollutionUtility_fixed2.js:1:21:1:23 | src | examples/PrototypePollutionUtility_fixed2.js:8:24:8:26 | src | +| examples/PrototypePollutionUtility_fixed2.js:1:21:1:23 | src | examples/PrototypePollutionUtility_fixed2.js:8:24:8:26 | src | +| examples/PrototypePollutionUtility_fixed2.js:6:29:6:31 | src | examples/PrototypePollutionUtility_fixed2.js:6:29:6:36 | src[key] | +| examples/PrototypePollutionUtility_fixed2.js:6:29:6:31 | src | examples/PrototypePollutionUtility_fixed2.js:6:29:6:36 | src[key] | +| examples/PrototypePollutionUtility_fixed2.js:6:29:6:36 | src[key] | examples/PrototypePollutionUtility_fixed2.js:1:21:1:23 | src | +| examples/PrototypePollutionUtility_fixed2.js:6:29:6:36 | src[key] | examples/PrototypePollutionUtility_fixed2.js:1:21:1:23 | src | +| examples/PrototypePollutionUtility_fixed2.js:6:29:6:36 | src[key] | examples/PrototypePollutionUtility_fixed2.js:1:21:1:23 | src | +| examples/PrototypePollutionUtility_fixed2.js:6:29:6:36 | src[key] | examples/PrototypePollutionUtility_fixed2.js:1:21:1:23 | src | +| examples/PrototypePollutionUtility_fixed2.js:6:29:6:36 | src[key] | examples/PrototypePollutionUtility_fixed2.js:1:21:1:23 | src | +| examples/PrototypePollutionUtility_fixed2.js:6:29:6:36 | src[key] | examples/PrototypePollutionUtility_fixed2.js:1:21:1:23 | src | +| examples/PrototypePollutionUtility_fixed2.js:8:24:8:26 | src | examples/PrototypePollutionUtility_fixed2.js:8:24:8:31 | src[key] | +| examples/PrototypePollutionUtility_fixed2.js:8:24:8:26 | src | examples/PrototypePollutionUtility_fixed2.js:8:24:8:31 | src[key] | +| examples/PrototypePollutionUtility_fixed2.js:8:24:8:26 | src | examples/PrototypePollutionUtility_fixed2.js:8:24:8:31 | src[key] | +| examples/PrototypePollutionUtility_fixed2.js:8:24:8:26 | src | examples/PrototypePollutionUtility_fixed2.js:8:24:8:31 | src[key] | +| examples/PrototypePollutionUtility_fixed2.js:8:24:8:31 | src[key] | examples/PrototypePollutionUtility_fixed2.js:8:24:8:31 | src[key] | +| examples/PrototypePollutionUtility_fixed.js:1:21:1:23 | src | examples/PrototypePollutionUtility_fixed.js:5:29:5:31 | src | +| examples/PrototypePollutionUtility_fixed.js:1:21:1:23 | src | examples/PrototypePollutionUtility_fixed.js:5:29:5:31 | src | +| examples/PrototypePollutionUtility_fixed.js:1:21:1:23 | src | examples/PrototypePollutionUtility_fixed.js:7:24:7:26 | src | +| examples/PrototypePollutionUtility_fixed.js:1:21:1:23 | src | examples/PrototypePollutionUtility_fixed.js:7:24:7:26 | src | +| examples/PrototypePollutionUtility_fixed.js:2:14:2:16 | key | examples/PrototypePollutionUtility_fixed.js:7:17:7:19 | key | +| examples/PrototypePollutionUtility_fixed.js:2:14:2:16 | key | examples/PrototypePollutionUtility_fixed.js:7:17:7:19 | key | +| examples/PrototypePollutionUtility_fixed.js:2:14:2:16 | key | examples/PrototypePollutionUtility_fixed.js:7:17:7:19 | key | +| examples/PrototypePollutionUtility_fixed.js:2:14:2:16 | key | examples/PrototypePollutionUtility_fixed.js:7:17:7:19 | key | +| examples/PrototypePollutionUtility_fixed.js:2:14:2:16 | key | examples/PrototypePollutionUtility_fixed.js:7:17:7:19 | key | +| examples/PrototypePollutionUtility_fixed.js:2:14:2:16 | key | examples/PrototypePollutionUtility_fixed.js:7:17:7:19 | key | +| examples/PrototypePollutionUtility_fixed.js:2:14:2:16 | key | examples/PrototypePollutionUtility_fixed.js:7:17:7:19 | key | +| examples/PrototypePollutionUtility_fixed.js:2:14:2:16 | key | examples/PrototypePollutionUtility_fixed.js:7:28:7:30 | key | +| examples/PrototypePollutionUtility_fixed.js:2:14:2:16 | key | examples/PrototypePollutionUtility_fixed.js:7:28:7:30 | key | +| examples/PrototypePollutionUtility_fixed.js:2:14:2:16 | key | examples/PrototypePollutionUtility_fixed.js:7:28:7:30 | key | +| examples/PrototypePollutionUtility_fixed.js:2:14:2:16 | key | examples/PrototypePollutionUtility_fixed.js:7:28:7:30 | key | +| examples/PrototypePollutionUtility_fixed.js:5:29:5:31 | src | examples/PrototypePollutionUtility_fixed.js:5:29:5:36 | src[key] | +| examples/PrototypePollutionUtility_fixed.js:5:29:5:31 | src | examples/PrototypePollutionUtility_fixed.js:5:29:5:36 | src[key] | +| examples/PrototypePollutionUtility_fixed.js:5:29:5:36 | src[key] | examples/PrototypePollutionUtility_fixed.js:1:21:1:23 | src | +| examples/PrototypePollutionUtility_fixed.js:5:29:5:36 | src[key] | examples/PrototypePollutionUtility_fixed.js:1:21:1:23 | src | +| examples/PrototypePollutionUtility_fixed.js:5:29:5:36 | src[key] | examples/PrototypePollutionUtility_fixed.js:1:21:1:23 | src | +| examples/PrototypePollutionUtility_fixed.js:5:29:5:36 | src[key] | examples/PrototypePollutionUtility_fixed.js:1:21:1:23 | src | +| examples/PrototypePollutionUtility_fixed.js:5:29:5:36 | src[key] | examples/PrototypePollutionUtility_fixed.js:1:21:1:23 | src | +| examples/PrototypePollutionUtility_fixed.js:5:29:5:36 | src[key] | examples/PrototypePollutionUtility_fixed.js:1:21:1:23 | src | +| examples/PrototypePollutionUtility_fixed.js:7:24:7:26 | src | examples/PrototypePollutionUtility_fixed.js:7:24:7:31 | src[key] | +| examples/PrototypePollutionUtility_fixed.js:7:24:7:26 | src | examples/PrototypePollutionUtility_fixed.js:7:24:7:31 | src[key] | +| examples/PrototypePollutionUtility_fixed.js:7:24:7:26 | src | examples/PrototypePollutionUtility_fixed.js:7:24:7:31 | src[key] | +| examples/PrototypePollutionUtility_fixed.js:7:24:7:26 | src | examples/PrototypePollutionUtility_fixed.js:7:24:7:31 | src[key] | +| examples/PrototypePollutionUtility_fixed.js:7:24:7:31 | src[key] | examples/PrototypePollutionUtility_fixed.js:7:24:7:31 | src[key] | +| examples/PrototypePollutionUtility_fixed.js:7:28:7:30 | key | examples/PrototypePollutionUtility_fixed.js:7:24:7:31 | src[key] | +| examples/PrototypePollutionUtility_fixed.js:7:28:7:30 | key | examples/PrototypePollutionUtility_fixed.js:7:24:7:31 | src[key] | +| examples/PrototypePollutionUtility_fixed.js:7:28:7:30 | key | examples/PrototypePollutionUtility_fixed.js:7:24:7:31 | src[key] | +| examples/PrototypePollutionUtility_fixed.js:7:28:7:30 | key | examples/PrototypePollutionUtility_fixed.js:7:24:7:31 | src[key] | #select | PrototypePollutionUtility/tests.js:8:13:8:15 | dst | PrototypePollutionUtility/tests.js:4:14:4:16 | key | PrototypePollutionUtility/tests.js:8:13:8:15 | dst | Properties are copied from $@ to $@ without guarding against prototype pollution. | PrototypePollutionUtility/tests.js:4:21:4:23 | src | src | PrototypePollutionUtility/tests.js:8:13:8:15 | dst | dst | | PrototypePollutionUtility/tests.js:18:13:18:15 | dst | PrototypePollutionUtility/tests.js:14:30:14:32 | key | PrototypePollutionUtility/tests.js:18:13:18:15 | dst | Properties are copied from $@ to $@ without guarding against prototype pollution. | PrototypePollutionUtility/tests.js:14:17:14:19 | src | src | PrototypePollutionUtility/tests.js:18:13:18:15 | dst | dst | @@ -1268,3 +1455,4 @@ edges | PrototypePollutionUtility/tests.js:109:13:109:15 | dst | PrototypePollutionUtility/tests.js:102:14:102:16 | key | PrototypePollutionUtility/tests.js:109:13:109:15 | dst | Properties are copied from $@ to $@ without guarding against prototype pollution. | PrototypePollutionUtility/tests.js:102:21:102:23 | src | src | PrototypePollutionUtility/tests.js:109:13:109:15 | dst | dst | | PrototypePollutionUtility/tests.js:154:13:154:15 | dst | PrototypePollutionUtility/tests.js:150:14:150:16 | key | PrototypePollutionUtility/tests.js:154:13:154:15 | dst | Properties are copied from $@ to $@ without guarding against prototype pollution. | PrototypePollutionUtility/tests.js:150:21:150:23 | src | src | PrototypePollutionUtility/tests.js:154:13:154:15 | dst | dst | | PrototypePollutionUtility/tests.js:196:13:196:15 | dst | PrototypePollutionUtility/tests.js:192:19:192:25 | keys[i] | PrototypePollutionUtility/tests.js:196:13:196:15 | dst | Properties are copied from $@ to $@ without guarding against prototype pollution. | PrototypePollutionUtility/tests.js:190:28:190:30 | src | src | PrototypePollutionUtility/tests.js:196:13:196:15 | dst | dst | +| examples/PrototypePollutionUtility.js:7:13:7:15 | dst | examples/PrototypePollutionUtility.js:2:14:2:16 | key | examples/PrototypePollutionUtility.js:7:13:7:15 | dst | Properties are copied from $@ to $@ without guarding against prototype pollution. | examples/PrototypePollutionUtility.js:2:21:2:23 | src | src | examples/PrototypePollutionUtility.js:7:13:7:15 | dst | dst | diff --git a/javascript/ql/test/query-tests/Security/CWE-400/examples/PrototypePollutionUtility.js b/javascript/ql/test/query-tests/Security/CWE-400/examples/PrototypePollutionUtility.js new file mode 100644 index 00000000000..1953ba57f00 --- /dev/null +++ b/javascript/ql/test/query-tests/Security/CWE-400/examples/PrototypePollutionUtility.js @@ -0,0 +1,10 @@ +function merge(dst, src) { + for (let key in src) { + if (!src.hasOwnProperty(key)) continue; + if (isObject(dst[key])) { + merge(dst[key], src[key]); + } else { + dst[key] = src[key]; + } + } +} diff --git a/javascript/ql/test/query-tests/Security/CWE-400/examples/PrototypePollutionUtility_fixed.js b/javascript/ql/test/query-tests/Security/CWE-400/examples/PrototypePollutionUtility_fixed.js new file mode 100644 index 00000000000..d1b762fb43c --- /dev/null +++ b/javascript/ql/test/query-tests/Security/CWE-400/examples/PrototypePollutionUtility_fixed.js @@ -0,0 +1,10 @@ +function merge(dst, src) { + for (let key in src) { + if (!src.hasOwnProperty(key)) continue; + if (dst.hasOwnProperty(key) && isObject(dst[key])) { + merge(dst[key], src[key]); + } else { + dst[key] = src[key]; + } + } +} diff --git a/javascript/ql/test/query-tests/Security/CWE-400/examples/PrototypePollutionUtility_fixed2.js b/javascript/ql/test/query-tests/Security/CWE-400/examples/PrototypePollutionUtility_fixed2.js new file mode 100644 index 00000000000..a4e108a4bd0 --- /dev/null +++ b/javascript/ql/test/query-tests/Security/CWE-400/examples/PrototypePollutionUtility_fixed2.js @@ -0,0 +1,11 @@ +function merge(dst, src) { + for (let key in src) { + if (!src.hasOwnProperty(key)) continue; + if (key === "__proto__" || key === "constructor") continue; + if (isObject(dst[key])) { + merge(dst[key], src[key]); + } else { + dst[key] = src[key]; + } + } +} From bc7871078abf4374f6c110121a1a938962a8619c Mon Sep 17 00:00:00 2001 From: Asger F Date: Fri, 8 Nov 2019 12:29:31 +0000 Subject: [PATCH 04/17] JS: Fix FPs from Object.create(null) --- .../CWE-400/PrototypePollutionUtility.ql | 71 ++++++- .../PrototypePollutionUtility.expected | 175 ++++++++++++++++++ .../PrototypePollutionUtility/tests.js | 31 ++++ 3 files changed, 272 insertions(+), 5 deletions(-) diff --git a/javascript/ql/src/Security/CWE-400/PrototypePollutionUtility.ql b/javascript/ql/src/Security/CWE-400/PrototypePollutionUtility.ql index 8fb9ae89af4..df871c0b0cb 100644 --- a/javascript/ql/src/Security/CWE-400/PrototypePollutionUtility.ql +++ b/javascript/ql/src/Security/CWE-400/PrototypePollutionUtility.ql @@ -349,17 +349,78 @@ string deriveExprName(DataFlow::Node node) { result = "this object" } +/** + * Holds if the dynamic property write `base[prop] = rhs` can pollute the prototype + * of `base` due to flow from `enum`. + * + * In most cases this will result in an alert, the exception being the case where + * `base` does not have a prototype at all. + */ +predicate isPrototypePollutingAssignment(Node base, Node prop, Node rhs, EnumeratedPropName enum) { + dynamicPropWrite(base, prop, rhs) and + exists(PropNameTracking cfg | + cfg.hasFlow(enum, base) and + cfg.hasFlow(enum, prop) and + cfg.hasFlow(enum, rhs) and + cfg.hasFlow(enum.getASourceProp(), rhs) + ) +} + +/** Gets a data flow node leading to the base of a prototype-polluting assignment. */ +private DataFlow::SourceNode getANodeLeadingToBase(DataFlow::TypeBackTracker t, Node base) { + t.start() and + isPrototypePollutingAssignment(base, _, _, _) and + result = base.getALocalSource() + or + exists(DataFlow::TypeBackTracker t2 | + result = getANodeLeadingToBase(t2, base).backtrack(t2, t) + ) +} + +/** + * Gets a data flow node leading to the base of dynamic property read leading to a + * prototype-polluting assignment. + * + * For example, this is the `dst` in `dst[key1][key2] = ...`. + * This dynamic read is where the reference to a built-in prototype object is obtained, + * and we need this to ensure that this object actually has a prototype. + */ +private DataFlow::SourceNode getANodeLeadingToBaseBase(DataFlow::TypeBackTracker t, Node base) { + exists(DynamicPropRead read | + read = getANodeLeadingToBase(t, base) and + result = read.getBase().getALocalSource() + ) + or + exists(DataFlow::TypeBackTracker t2 | + result = getANodeLeadingToBaseBase(t2, base).backtrack(t2, t) + ) +} + +DataFlow::SourceNode getANodeLeadingToBaseBase(Node base) { + result = getANodeLeadingToBaseBase(DataFlow::TypeBackTracker::end(), base) +} + +/** A call to `Object.create(null)`. */ +class ObjectCreateNullCall extends CallNode { + ObjectCreateNullCall() { + this = globalVarRef("Object").getAMemberCall("create") and + getArgument(0).asExpr() instanceof NullLiteral + } +} + from PropNameTracking cfg, DataFlow::PathNode source, DataFlow::PathNode sink, EnumeratedPropName enum, - Node base, Node prop, Node rhs + Node base where cfg.hasFlowPath(source, sink) and - dynamicPropWrite(base, prop, rhs) and + isPrototypePollutingAssignment(base, _, _, enum) and sink.getNode() = base and source.getNode() = enum and - cfg.hasFlow(enum, prop) and - cfg.hasFlow(enum, rhs) and - cfg.hasFlow(enum.getASourceProp(), rhs) + ( + getANodeLeadingToBaseBase(base) instanceof ObjectLiteralNode + or + not getANodeLeadingToBaseBase(base) instanceof ObjectCreateNullCall + ) select base, source, sink, "Properties are copied from $@ to $@ without guarding against prototype pollution.", enum.getSourceObject(), deriveExprName(enum.getSourceObject()), base, deriveExprName(base) diff --git a/javascript/ql/test/query-tests/Security/CWE-400/PrototypePollutionUtility.expected b/javascript/ql/test/query-tests/Security/CWE-400/PrototypePollutionUtility.expected index 45d6657b911..90a245ac8ba 100644 --- a/javascript/ql/test/query-tests/Security/CWE-400/PrototypePollutionUtility.expected +++ b/javascript/ql/test/query-tests/Security/CWE-400/PrototypePollutionUtility.expected @@ -554,6 +554,80 @@ nodes | PrototypePollutionUtility/tests.js:208:32:208:38 | keys[i] | | PrototypePollutionUtility/tests.js:208:32:208:38 | keys[i] | | PrototypePollutionUtility/tests.js:208:32:208:38 | keys[i] | +| PrototypePollutionUtility/tests.js:213:23:213:26 | key1 | +| PrototypePollutionUtility/tests.js:213:23:213:26 | key1 | +| PrototypePollutionUtility/tests.js:213:29:213:32 | key2 | +| PrototypePollutionUtility/tests.js:213:29:213:32 | key2 | +| PrototypePollutionUtility/tests.js:213:35:213:39 | value | +| PrototypePollutionUtility/tests.js:213:35:213:39 | value | +| PrototypePollutionUtility/tests.js:215:13:215:16 | key1 | +| PrototypePollutionUtility/tests.js:215:13:215:16 | key1 | +| PrototypePollutionUtility/tests.js:215:13:215:16 | key1 | +| PrototypePollutionUtility/tests.js:217:5:217:13 | map[key1] | +| PrototypePollutionUtility/tests.js:217:5:217:13 | map[key1] | +| PrototypePollutionUtility/tests.js:217:5:217:13 | map[key1] | +| PrototypePollutionUtility/tests.js:217:9:217:12 | key1 | +| PrototypePollutionUtility/tests.js:217:9:217:12 | key1 | +| PrototypePollutionUtility/tests.js:217:15:217:18 | key2 | +| PrototypePollutionUtility/tests.js:217:15:217:18 | key2 | +| PrototypePollutionUtility/tests.js:217:15:217:18 | key2 | +| PrototypePollutionUtility/tests.js:217:23:217:27 | value | +| PrototypePollutionUtility/tests.js:217:23:217:27 | value | +| PrototypePollutionUtility/tests.js:217:23:217:27 | value | +| PrototypePollutionUtility/tests.js:223:14:223:16 | key | +| PrototypePollutionUtility/tests.js:223:14:223:16 | key | +| PrototypePollutionUtility/tests.js:223:14:223:16 | key | +| PrototypePollutionUtility/tests.js:224:23:224:25 | key | +| PrototypePollutionUtility/tests.js:224:23:224:25 | key | +| PrototypePollutionUtility/tests.js:224:33:224:41 | data[key] | +| PrototypePollutionUtility/tests.js:224:33:224:41 | data[key] | +| PrototypePollutionUtility/tests.js:224:33:224:41 | data[key] | +| PrototypePollutionUtility/tests.js:224:38:224:40 | key | +| PrototypePollutionUtility/tests.js:224:38:224:40 | key | +| PrototypePollutionUtility/tests.js:225:28:225:30 | key | +| PrototypePollutionUtility/tests.js:225:28:225:30 | key | +| PrototypePollutionUtility/tests.js:225:33:225:41 | data[key] | +| PrototypePollutionUtility/tests.js:225:33:225:41 | data[key] | +| PrototypePollutionUtility/tests.js:225:33:225:41 | data[key] | +| PrototypePollutionUtility/tests.js:225:38:225:40 | key | +| PrototypePollutionUtility/tests.js:225:38:225:40 | key | +| PrototypePollutionUtility/tests.js:229:26:229:29 | key1 | +| PrototypePollutionUtility/tests.js:229:26:229:29 | key1 | +| PrototypePollutionUtility/tests.js:229:32:229:35 | key2 | +| PrototypePollutionUtility/tests.js:229:32:229:35 | key2 | +| PrototypePollutionUtility/tests.js:229:38:229:42 | value | +| PrototypePollutionUtility/tests.js:229:38:229:42 | value | +| PrototypePollutionUtility/tests.js:231:13:231:16 | key1 | +| PrototypePollutionUtility/tests.js:231:13:231:16 | key1 | +| PrototypePollutionUtility/tests.js:231:13:231:16 | key1 | +| PrototypePollutionUtility/tests.js:233:5:233:13 | map[key1] | +| PrototypePollutionUtility/tests.js:233:5:233:13 | map[key1] | +| PrototypePollutionUtility/tests.js:233:5:233:13 | map[key1] | +| PrototypePollutionUtility/tests.js:233:9:233:12 | key1 | +| PrototypePollutionUtility/tests.js:233:9:233:12 | key1 | +| PrototypePollutionUtility/tests.js:233:15:233:18 | key2 | +| PrototypePollutionUtility/tests.js:233:15:233:18 | key2 | +| PrototypePollutionUtility/tests.js:233:15:233:18 | key2 | +| PrototypePollutionUtility/tests.js:233:23:233:27 | value | +| PrototypePollutionUtility/tests.js:233:23:233:27 | value | +| PrototypePollutionUtility/tests.js:233:23:233:27 | value | +| PrototypePollutionUtility/tests.js:238:14:238:16 | key | +| PrototypePollutionUtility/tests.js:238:14:238:16 | key | +| PrototypePollutionUtility/tests.js:238:14:238:16 | key | +| PrototypePollutionUtility/tests.js:239:24:239:26 | key | +| PrototypePollutionUtility/tests.js:239:24:239:26 | key | +| PrototypePollutionUtility/tests.js:239:34:239:42 | data[key] | +| PrototypePollutionUtility/tests.js:239:34:239:42 | data[key] | +| PrototypePollutionUtility/tests.js:239:34:239:42 | data[key] | +| PrototypePollutionUtility/tests.js:239:39:239:41 | key | +| PrototypePollutionUtility/tests.js:239:39:239:41 | key | +| PrototypePollutionUtility/tests.js:240:31:240:33 | key | +| PrototypePollutionUtility/tests.js:240:31:240:33 | key | +| PrototypePollutionUtility/tests.js:240:36:240:44 | data[key] | +| PrototypePollutionUtility/tests.js:240:36:240:44 | data[key] | +| PrototypePollutionUtility/tests.js:240:36:240:44 | data[key] | +| PrototypePollutionUtility/tests.js:240:41:240:43 | key | +| PrototypePollutionUtility/tests.js:240:41:240:43 | key | | examples/PrototypePollutionUtility.js:1:16:1:18 | dst | | examples/PrototypePollutionUtility.js:1:16:1:18 | dst | | examples/PrototypePollutionUtility.js:1:21:1:23 | src | @@ -1341,6 +1415,106 @@ edges | PrototypePollutionUtility/tests.js:208:32:208:38 | keys[i] | PrototypePollutionUtility/tests.js:208:28:208:39 | src[keys[i]] | | PrototypePollutionUtility/tests.js:208:32:208:38 | keys[i] | PrototypePollutionUtility/tests.js:208:28:208:39 | src[keys[i]] | | PrototypePollutionUtility/tests.js:208:32:208:38 | keys[i] | PrototypePollutionUtility/tests.js:208:28:208:39 | src[keys[i]] | +| PrototypePollutionUtility/tests.js:213:23:213:26 | key1 | PrototypePollutionUtility/tests.js:215:13:215:16 | key1 | +| PrototypePollutionUtility/tests.js:213:23:213:26 | key1 | PrototypePollutionUtility/tests.js:215:13:215:16 | key1 | +| PrototypePollutionUtility/tests.js:213:23:213:26 | key1 | PrototypePollutionUtility/tests.js:215:13:215:16 | key1 | +| PrototypePollutionUtility/tests.js:213:23:213:26 | key1 | PrototypePollutionUtility/tests.js:215:13:215:16 | key1 | +| PrototypePollutionUtility/tests.js:213:23:213:26 | key1 | PrototypePollutionUtility/tests.js:217:9:217:12 | key1 | +| PrototypePollutionUtility/tests.js:213:23:213:26 | key1 | PrototypePollutionUtility/tests.js:217:9:217:12 | key1 | +| PrototypePollutionUtility/tests.js:213:29:213:32 | key2 | PrototypePollutionUtility/tests.js:217:15:217:18 | key2 | +| PrototypePollutionUtility/tests.js:213:29:213:32 | key2 | PrototypePollutionUtility/tests.js:217:15:217:18 | key2 | +| PrototypePollutionUtility/tests.js:213:29:213:32 | key2 | PrototypePollutionUtility/tests.js:217:15:217:18 | key2 | +| PrototypePollutionUtility/tests.js:213:29:213:32 | key2 | PrototypePollutionUtility/tests.js:217:15:217:18 | key2 | +| PrototypePollutionUtility/tests.js:213:35:213:39 | value | PrototypePollutionUtility/tests.js:217:23:217:27 | value | +| PrototypePollutionUtility/tests.js:213:35:213:39 | value | PrototypePollutionUtility/tests.js:217:23:217:27 | value | +| PrototypePollutionUtility/tests.js:213:35:213:39 | value | PrototypePollutionUtility/tests.js:217:23:217:27 | value | +| PrototypePollutionUtility/tests.js:213:35:213:39 | value | PrototypePollutionUtility/tests.js:217:23:217:27 | value | +| PrototypePollutionUtility/tests.js:217:9:217:12 | key1 | PrototypePollutionUtility/tests.js:217:5:217:13 | map[key1] | +| PrototypePollutionUtility/tests.js:217:9:217:12 | key1 | PrototypePollutionUtility/tests.js:217:5:217:13 | map[key1] | +| PrototypePollutionUtility/tests.js:217:9:217:12 | key1 | PrototypePollutionUtility/tests.js:217:5:217:13 | map[key1] | +| PrototypePollutionUtility/tests.js:217:9:217:12 | key1 | PrototypePollutionUtility/tests.js:217:5:217:13 | map[key1] | +| PrototypePollutionUtility/tests.js:223:14:223:16 | key | PrototypePollutionUtility/tests.js:224:23:224:25 | key | +| PrototypePollutionUtility/tests.js:223:14:223:16 | key | PrototypePollutionUtility/tests.js:224:23:224:25 | key | +| PrototypePollutionUtility/tests.js:223:14:223:16 | key | PrototypePollutionUtility/tests.js:224:23:224:25 | key | +| PrototypePollutionUtility/tests.js:223:14:223:16 | key | PrototypePollutionUtility/tests.js:224:23:224:25 | key | +| PrototypePollutionUtility/tests.js:223:14:223:16 | key | PrototypePollutionUtility/tests.js:224:38:224:40 | key | +| PrototypePollutionUtility/tests.js:223:14:223:16 | key | PrototypePollutionUtility/tests.js:224:38:224:40 | key | +| PrototypePollutionUtility/tests.js:223:14:223:16 | key | PrototypePollutionUtility/tests.js:224:38:224:40 | key | +| PrototypePollutionUtility/tests.js:223:14:223:16 | key | PrototypePollutionUtility/tests.js:224:38:224:40 | key | +| PrototypePollutionUtility/tests.js:223:14:223:16 | key | PrototypePollutionUtility/tests.js:225:28:225:30 | key | +| PrototypePollutionUtility/tests.js:223:14:223:16 | key | PrototypePollutionUtility/tests.js:225:28:225:30 | key | +| PrototypePollutionUtility/tests.js:223:14:223:16 | key | PrototypePollutionUtility/tests.js:225:28:225:30 | key | +| PrototypePollutionUtility/tests.js:223:14:223:16 | key | PrototypePollutionUtility/tests.js:225:28:225:30 | key | +| PrototypePollutionUtility/tests.js:223:14:223:16 | key | PrototypePollutionUtility/tests.js:225:38:225:40 | key | +| PrototypePollutionUtility/tests.js:223:14:223:16 | key | PrototypePollutionUtility/tests.js:225:38:225:40 | key | +| PrototypePollutionUtility/tests.js:223:14:223:16 | key | PrototypePollutionUtility/tests.js:225:38:225:40 | key | +| PrototypePollutionUtility/tests.js:223:14:223:16 | key | PrototypePollutionUtility/tests.js:225:38:225:40 | key | +| PrototypePollutionUtility/tests.js:224:23:224:25 | key | PrototypePollutionUtility/tests.js:213:23:213:26 | key1 | +| PrototypePollutionUtility/tests.js:224:23:224:25 | key | PrototypePollutionUtility/tests.js:213:23:213:26 | key1 | +| PrototypePollutionUtility/tests.js:224:33:224:41 | data[key] | PrototypePollutionUtility/tests.js:213:35:213:39 | value | +| PrototypePollutionUtility/tests.js:224:33:224:41 | data[key] | PrototypePollutionUtility/tests.js:213:35:213:39 | value | +| PrototypePollutionUtility/tests.js:224:33:224:41 | data[key] | PrototypePollutionUtility/tests.js:213:35:213:39 | value | +| PrototypePollutionUtility/tests.js:224:33:224:41 | data[key] | PrototypePollutionUtility/tests.js:213:35:213:39 | value | +| PrototypePollutionUtility/tests.js:224:38:224:40 | key | PrototypePollutionUtility/tests.js:224:33:224:41 | data[key] | +| PrototypePollutionUtility/tests.js:224:38:224:40 | key | PrototypePollutionUtility/tests.js:224:33:224:41 | data[key] | +| PrototypePollutionUtility/tests.js:225:28:225:30 | key | PrototypePollutionUtility/tests.js:213:29:213:32 | key2 | +| PrototypePollutionUtility/tests.js:225:28:225:30 | key | PrototypePollutionUtility/tests.js:213:29:213:32 | key2 | +| PrototypePollutionUtility/tests.js:225:33:225:41 | data[key] | PrototypePollutionUtility/tests.js:213:35:213:39 | value | +| PrototypePollutionUtility/tests.js:225:33:225:41 | data[key] | PrototypePollutionUtility/tests.js:213:35:213:39 | value | +| PrototypePollutionUtility/tests.js:225:33:225:41 | data[key] | PrototypePollutionUtility/tests.js:213:35:213:39 | value | +| PrototypePollutionUtility/tests.js:225:33:225:41 | data[key] | PrototypePollutionUtility/tests.js:213:35:213:39 | value | +| PrototypePollutionUtility/tests.js:225:38:225:40 | key | PrototypePollutionUtility/tests.js:225:33:225:41 | data[key] | +| PrototypePollutionUtility/tests.js:225:38:225:40 | key | PrototypePollutionUtility/tests.js:225:33:225:41 | data[key] | +| PrototypePollutionUtility/tests.js:229:26:229:29 | key1 | PrototypePollutionUtility/tests.js:231:13:231:16 | key1 | +| PrototypePollutionUtility/tests.js:229:26:229:29 | key1 | PrototypePollutionUtility/tests.js:231:13:231:16 | key1 | +| PrototypePollutionUtility/tests.js:229:26:229:29 | key1 | PrototypePollutionUtility/tests.js:231:13:231:16 | key1 | +| PrototypePollutionUtility/tests.js:229:26:229:29 | key1 | PrototypePollutionUtility/tests.js:231:13:231:16 | key1 | +| PrototypePollutionUtility/tests.js:229:26:229:29 | key1 | PrototypePollutionUtility/tests.js:233:9:233:12 | key1 | +| PrototypePollutionUtility/tests.js:229:26:229:29 | key1 | PrototypePollutionUtility/tests.js:233:9:233:12 | key1 | +| PrototypePollutionUtility/tests.js:229:32:229:35 | key2 | PrototypePollutionUtility/tests.js:233:15:233:18 | key2 | +| PrototypePollutionUtility/tests.js:229:32:229:35 | key2 | PrototypePollutionUtility/tests.js:233:15:233:18 | key2 | +| PrototypePollutionUtility/tests.js:229:32:229:35 | key2 | PrototypePollutionUtility/tests.js:233:15:233:18 | key2 | +| PrototypePollutionUtility/tests.js:229:32:229:35 | key2 | PrototypePollutionUtility/tests.js:233:15:233:18 | key2 | +| PrototypePollutionUtility/tests.js:229:38:229:42 | value | PrototypePollutionUtility/tests.js:233:23:233:27 | value | +| PrototypePollutionUtility/tests.js:229:38:229:42 | value | PrototypePollutionUtility/tests.js:233:23:233:27 | value | +| PrototypePollutionUtility/tests.js:229:38:229:42 | value | PrototypePollutionUtility/tests.js:233:23:233:27 | value | +| PrototypePollutionUtility/tests.js:229:38:229:42 | value | PrototypePollutionUtility/tests.js:233:23:233:27 | value | +| PrototypePollutionUtility/tests.js:233:9:233:12 | key1 | PrototypePollutionUtility/tests.js:233:5:233:13 | map[key1] | +| PrototypePollutionUtility/tests.js:233:9:233:12 | key1 | PrototypePollutionUtility/tests.js:233:5:233:13 | map[key1] | +| PrototypePollutionUtility/tests.js:233:9:233:12 | key1 | PrototypePollutionUtility/tests.js:233:5:233:13 | map[key1] | +| PrototypePollutionUtility/tests.js:233:9:233:12 | key1 | PrototypePollutionUtility/tests.js:233:5:233:13 | map[key1] | +| PrototypePollutionUtility/tests.js:238:14:238:16 | key | PrototypePollutionUtility/tests.js:239:24:239:26 | key | +| PrototypePollutionUtility/tests.js:238:14:238:16 | key | PrototypePollutionUtility/tests.js:239:24:239:26 | key | +| PrototypePollutionUtility/tests.js:238:14:238:16 | key | PrototypePollutionUtility/tests.js:239:24:239:26 | key | +| PrototypePollutionUtility/tests.js:238:14:238:16 | key | PrototypePollutionUtility/tests.js:239:24:239:26 | key | +| PrototypePollutionUtility/tests.js:238:14:238:16 | key | PrototypePollutionUtility/tests.js:239:39:239:41 | key | +| PrototypePollutionUtility/tests.js:238:14:238:16 | key | PrototypePollutionUtility/tests.js:239:39:239:41 | key | +| PrototypePollutionUtility/tests.js:238:14:238:16 | key | PrototypePollutionUtility/tests.js:239:39:239:41 | key | +| PrototypePollutionUtility/tests.js:238:14:238:16 | key | PrototypePollutionUtility/tests.js:239:39:239:41 | key | +| PrototypePollutionUtility/tests.js:238:14:238:16 | key | PrototypePollutionUtility/tests.js:240:31:240:33 | key | +| PrototypePollutionUtility/tests.js:238:14:238:16 | key | PrototypePollutionUtility/tests.js:240:31:240:33 | key | +| PrototypePollutionUtility/tests.js:238:14:238:16 | key | PrototypePollutionUtility/tests.js:240:31:240:33 | key | +| PrototypePollutionUtility/tests.js:238:14:238:16 | key | PrototypePollutionUtility/tests.js:240:31:240:33 | key | +| PrototypePollutionUtility/tests.js:238:14:238:16 | key | PrototypePollutionUtility/tests.js:240:41:240:43 | key | +| PrototypePollutionUtility/tests.js:238:14:238:16 | key | PrototypePollutionUtility/tests.js:240:41:240:43 | key | +| PrototypePollutionUtility/tests.js:238:14:238:16 | key | PrototypePollutionUtility/tests.js:240:41:240:43 | key | +| PrototypePollutionUtility/tests.js:238:14:238:16 | key | PrototypePollutionUtility/tests.js:240:41:240:43 | key | +| PrototypePollutionUtility/tests.js:239:24:239:26 | key | PrototypePollutionUtility/tests.js:229:26:229:29 | key1 | +| PrototypePollutionUtility/tests.js:239:24:239:26 | key | PrototypePollutionUtility/tests.js:229:26:229:29 | key1 | +| PrototypePollutionUtility/tests.js:239:34:239:42 | data[key] | PrototypePollutionUtility/tests.js:229:38:229:42 | value | +| PrototypePollutionUtility/tests.js:239:34:239:42 | data[key] | PrototypePollutionUtility/tests.js:229:38:229:42 | value | +| PrototypePollutionUtility/tests.js:239:34:239:42 | data[key] | PrototypePollutionUtility/tests.js:229:38:229:42 | value | +| PrototypePollutionUtility/tests.js:239:34:239:42 | data[key] | PrototypePollutionUtility/tests.js:229:38:229:42 | value | +| PrototypePollutionUtility/tests.js:239:39:239:41 | key | PrototypePollutionUtility/tests.js:239:34:239:42 | data[key] | +| PrototypePollutionUtility/tests.js:239:39:239:41 | key | PrototypePollutionUtility/tests.js:239:34:239:42 | data[key] | +| PrototypePollutionUtility/tests.js:240:31:240:33 | key | PrototypePollutionUtility/tests.js:229:32:229:35 | key2 | +| PrototypePollutionUtility/tests.js:240:31:240:33 | key | PrototypePollutionUtility/tests.js:229:32:229:35 | key2 | +| PrototypePollutionUtility/tests.js:240:36:240:44 | data[key] | PrototypePollutionUtility/tests.js:229:38:229:42 | value | +| PrototypePollutionUtility/tests.js:240:36:240:44 | data[key] | PrototypePollutionUtility/tests.js:229:38:229:42 | value | +| PrototypePollutionUtility/tests.js:240:36:240:44 | data[key] | PrototypePollutionUtility/tests.js:229:38:229:42 | value | +| PrototypePollutionUtility/tests.js:240:36:240:44 | data[key] | PrototypePollutionUtility/tests.js:229:38:229:42 | value | +| PrototypePollutionUtility/tests.js:240:41:240:43 | key | PrototypePollutionUtility/tests.js:240:36:240:44 | data[key] | +| PrototypePollutionUtility/tests.js:240:41:240:43 | key | PrototypePollutionUtility/tests.js:240:36:240:44 | data[key] | | examples/PrototypePollutionUtility.js:1:16:1:18 | dst | examples/PrototypePollutionUtility.js:5:19:5:21 | dst | | examples/PrototypePollutionUtility.js:1:16:1:18 | dst | examples/PrototypePollutionUtility.js:5:19:5:21 | dst | | examples/PrototypePollutionUtility.js:1:16:1:18 | dst | examples/PrototypePollutionUtility.js:7:13:7:15 | dst | @@ -1455,4 +1629,5 @@ edges | PrototypePollutionUtility/tests.js:109:13:109:15 | dst | PrototypePollutionUtility/tests.js:102:14:102:16 | key | PrototypePollutionUtility/tests.js:109:13:109:15 | dst | Properties are copied from $@ to $@ without guarding against prototype pollution. | PrototypePollutionUtility/tests.js:102:21:102:23 | src | src | PrototypePollutionUtility/tests.js:109:13:109:15 | dst | dst | | PrototypePollutionUtility/tests.js:154:13:154:15 | dst | PrototypePollutionUtility/tests.js:150:14:150:16 | key | PrototypePollutionUtility/tests.js:154:13:154:15 | dst | Properties are copied from $@ to $@ without guarding against prototype pollution. | PrototypePollutionUtility/tests.js:150:21:150:23 | src | src | PrototypePollutionUtility/tests.js:154:13:154:15 | dst | dst | | PrototypePollutionUtility/tests.js:196:13:196:15 | dst | PrototypePollutionUtility/tests.js:192:19:192:25 | keys[i] | PrototypePollutionUtility/tests.js:196:13:196:15 | dst | Properties are copied from $@ to $@ without guarding against prototype pollution. | PrototypePollutionUtility/tests.js:190:28:190:30 | src | src | PrototypePollutionUtility/tests.js:196:13:196:15 | dst | dst | +| PrototypePollutionUtility/tests.js:233:5:233:13 | map[key1] | PrototypePollutionUtility/tests.js:238:14:238:16 | key | PrototypePollutionUtility/tests.js:233:5:233:13 | map[key1] | Properties are copied from $@ to $@ without guarding against prototype pollution. | PrototypePollutionUtility/tests.js:238:21:238:24 | data | data | PrototypePollutionUtility/tests.js:233:5:233:13 | map[key1] | this object | | examples/PrototypePollutionUtility.js:7:13:7:15 | dst | examples/PrototypePollutionUtility.js:2:14:2:16 | key | examples/PrototypePollutionUtility.js:7:13:7:15 | dst | Properties are copied from $@ to $@ without guarding against prototype pollution. | examples/PrototypePollutionUtility.js:2:21:2:23 | src | src | examples/PrototypePollutionUtility.js:7:13:7:15 | dst | dst | diff --git a/javascript/ql/test/query-tests/Security/CWE-400/PrototypePollutionUtility/tests.js b/javascript/ql/test/query-tests/Security/CWE-400/PrototypePollutionUtility/tests.js index 1540b9429af..33ff9e6f855 100644 --- a/javascript/ql/test/query-tests/Security/CWE-400/PrototypePollutionUtility/tests.js +++ b/javascript/ql/test/query-tests/Security/CWE-400/PrototypePollutionUtility/tests.js @@ -209,3 +209,34 @@ function copyUsingPlainForLoopNoAlias(dst, src) { } } } + +function deepSet(map, key1, key2, value) { + if (!map[key1]) { + map[key1] = Object.create(null); + } + map[key1][key2] = value; // OK +} + +function deepSetCaller(data) { + let map1 = Object.create(null); + let map2 = Object.create(null); + for (let key in data) { + deepSet(map1, key, 'x', data[key]); + deepSet(map2, 'x', key, data[key]); + } +} + +function deepSetBad(map, key1, key2, value) { + if (!map[key1]) { + map[key1] = Object.create(null); + } + map[key1][key2] = value; // NOT OK - object literal can flow here +} + +function deepSetCallerBad(data) { + let map1 = Object.create(null); + for (let key in data) { + deepSetBad({}, key, 'x', data[key]); // oops + deepSetBad(map1, 'x', key, data[key]); + } +} From 96bf9db20055f2260b1870c1136b1bcf7587ec6c Mon Sep 17 00:00:00 2001 From: Asger F Date: Tue, 12 Nov 2019 15:00:19 +0000 Subject: [PATCH 05/17] JS: Add another test and more barriers --- .../CWE-400/PrototypePollutionUtility.ql | 23 +++++ .../PrototypePollutionUtility.expected | 88 ++++++++++++------- .../PrototypePollutionUtility/tests.js | 19 ++++ 3 files changed, 98 insertions(+), 32 deletions(-) diff --git a/javascript/ql/src/Security/CWE-400/PrototypePollutionUtility.ql b/javascript/ql/src/Security/CWE-400/PrototypePollutionUtility.ql index df871c0b0cb..452f25ba1a5 100644 --- a/javascript/ql/src/Security/CWE-400/PrototypePollutionUtility.ql +++ b/javascript/ql/src/Security/CWE-400/PrototypePollutionUtility.ql @@ -214,6 +214,17 @@ class PropNameTracking extends DataFlow::Configuration { ) } + override predicate isBarrier(DataFlow::Node node) { + super.isBarrier(node) + or + exists(ConditionGuardNode guard, SsaRefinementNode refinement | + node = DataFlow::ssaDefinitionNode(refinement) and + refinement.getGuard() = guard and + guard.getTest() instanceof VarAccess and + guard.getOutcome() = false + ) + } + override predicate isBarrierGuard(DataFlow::BarrierGuardNode node) { node instanceof EqualityGuard or node instanceof HasOwnPropertyGuard or @@ -307,6 +318,18 @@ class TypeofGuard extends DataFlow::LabeledBarrierGuardNode, DataFlow::ValueNode typeofStr = "function" and label = "__proto__" ) + or + e = typeof.getOperand() and + outcome = astNode.getPolarity().booleanNot() and + ( + // If something is not an object, sanitize object, as both must end + // in non-function prototype object. + typeofStr = "object" and + label instanceof UnsafePropLabel + or + typeofStr = "function" and + label = "constructor" + ) } } diff --git a/javascript/ql/test/query-tests/Security/CWE-400/PrototypePollutionUtility.expected b/javascript/ql/test/query-tests/Security/CWE-400/PrototypePollutionUtility.expected index 90a245ac8ba..b869a4c9158 100644 --- a/javascript/ql/test/query-tests/Security/CWE-400/PrototypePollutionUtility.expected +++ b/javascript/ql/test/query-tests/Security/CWE-400/PrototypePollutionUtility.expected @@ -314,24 +314,12 @@ nodes | PrototypePollutionUtility/tests.js:128:20:128:27 | src[key] | | PrototypePollutionUtility/tests.js:128:24:128:26 | key | | PrototypePollutionUtility/tests.js:128:24:128:26 | key | -| PrototypePollutionUtility/tests.js:140:16:140:18 | src | | PrototypePollutionUtility/tests.js:143:14:143:16 | key | | PrototypePollutionUtility/tests.js:143:14:143:16 | key | | PrototypePollutionUtility/tests.js:143:14:143:16 | key | | PrototypePollutionUtility/tests.js:144:16:144:18 | key | | PrototypePollutionUtility/tests.js:144:16:144:18 | key | | PrototypePollutionUtility/tests.js:144:16:144:18 | key | -| PrototypePollutionUtility/tests.js:144:23:144:37 | clone(src[key]) | -| PrototypePollutionUtility/tests.js:144:23:144:37 | clone(src[key]) | -| PrototypePollutionUtility/tests.js:144:23:144:37 | clone(src[key]) | -| PrototypePollutionUtility/tests.js:144:23:144:37 | clone(src[key]) | -| PrototypePollutionUtility/tests.js:144:29:144:31 | src | -| PrototypePollutionUtility/tests.js:144:29:144:36 | src[key] | -| PrototypePollutionUtility/tests.js:144:29:144:36 | src[key] | -| PrototypePollutionUtility/tests.js:144:29:144:36 | src[key] | -| PrototypePollutionUtility/tests.js:144:29:144:36 | src[key] | -| PrototypePollutionUtility/tests.js:144:33:144:35 | key | -| PrototypePollutionUtility/tests.js:144:33:144:35 | key | | PrototypePollutionUtility/tests.js:149:31:149:33 | dst | | PrototypePollutionUtility/tests.js:149:31:149:33 | dst | | PrototypePollutionUtility/tests.js:149:31:149:33 | dst | @@ -628,6 +616,28 @@ nodes | PrototypePollutionUtility/tests.js:240:36:240:44 | data[key] | | PrototypePollutionUtility/tests.js:240:41:240:43 | key | | PrototypePollutionUtility/tests.js:240:41:240:43 | key | +| PrototypePollutionUtility/tests.js:252:29:252:31 | src | +| PrototypePollutionUtility/tests.js:252:29:252:31 | src | +| PrototypePollutionUtility/tests.js:255:14:255:16 | key | +| PrototypePollutionUtility/tests.js:255:14:255:16 | key | +| PrototypePollutionUtility/tests.js:255:14:255:16 | key | +| PrototypePollutionUtility/tests.js:257:20:257:22 | key | +| PrototypePollutionUtility/tests.js:257:20:257:22 | key | +| PrototypePollutionUtility/tests.js:257:20:257:22 | key | +| PrototypePollutionUtility/tests.js:257:27:257:59 | mergeWi ... c[key]) | +| PrototypePollutionUtility/tests.js:257:27:257:59 | mergeWi ... c[key]) | +| PrototypePollutionUtility/tests.js:257:27:257:59 | mergeWi ... c[key]) | +| PrototypePollutionUtility/tests.js:257:27:257:59 | mergeWi ... c[key]) | +| PrototypePollutionUtility/tests.js:257:27:257:59 | mergeWi ... c[key]) | +| PrototypePollutionUtility/tests.js:257:51:257:53 | src | +| PrototypePollutionUtility/tests.js:257:51:257:53 | src | +| PrototypePollutionUtility/tests.js:257:51:257:58 | src[key] | +| PrototypePollutionUtility/tests.js:257:51:257:58 | src[key] | +| PrototypePollutionUtility/tests.js:257:51:257:58 | src[key] | +| PrototypePollutionUtility/tests.js:257:51:257:58 | src[key] | +| PrototypePollutionUtility/tests.js:257:51:257:58 | src[key] | +| PrototypePollutionUtility/tests.js:257:55:257:57 | key | +| PrototypePollutionUtility/tests.js:257:55:257:57 | key | | examples/PrototypePollutionUtility.js:1:16:1:18 | dst | | examples/PrototypePollutionUtility.js:1:16:1:18 | dst | | examples/PrototypePollutionUtility.js:1:21:1:23 | src | @@ -1113,7 +1123,6 @@ edges | PrototypePollutionUtility/tests.js:128:24:128:26 | key | PrototypePollutionUtility/tests.js:128:20:128:27 | src[key] | | PrototypePollutionUtility/tests.js:128:24:128:26 | key | PrototypePollutionUtility/tests.js:128:20:128:27 | src[key] | | PrototypePollutionUtility/tests.js:128:24:128:26 | key | PrototypePollutionUtility/tests.js:128:20:128:27 | src[key] | -| PrototypePollutionUtility/tests.js:140:16:140:18 | src | PrototypePollutionUtility/tests.js:144:29:144:31 | src | | PrototypePollutionUtility/tests.js:143:14:143:16 | key | PrototypePollutionUtility/tests.js:144:16:144:18 | key | | PrototypePollutionUtility/tests.js:143:14:143:16 | key | PrototypePollutionUtility/tests.js:144:16:144:18 | key | | PrototypePollutionUtility/tests.js:143:14:143:16 | key | PrototypePollutionUtility/tests.js:144:16:144:18 | key | @@ -1121,25 +1130,6 @@ edges | PrototypePollutionUtility/tests.js:143:14:143:16 | key | PrototypePollutionUtility/tests.js:144:16:144:18 | key | | PrototypePollutionUtility/tests.js:143:14:143:16 | key | PrototypePollutionUtility/tests.js:144:16:144:18 | key | | PrototypePollutionUtility/tests.js:143:14:143:16 | key | PrototypePollutionUtility/tests.js:144:16:144:18 | key | -| PrototypePollutionUtility/tests.js:143:14:143:16 | key | PrototypePollutionUtility/tests.js:144:33:144:35 | key | -| PrototypePollutionUtility/tests.js:143:14:143:16 | key | PrototypePollutionUtility/tests.js:144:33:144:35 | key | -| PrototypePollutionUtility/tests.js:143:14:143:16 | key | PrototypePollutionUtility/tests.js:144:33:144:35 | key | -| PrototypePollutionUtility/tests.js:143:14:143:16 | key | PrototypePollutionUtility/tests.js:144:33:144:35 | key | -| PrototypePollutionUtility/tests.js:144:29:144:31 | src | PrototypePollutionUtility/tests.js:144:29:144:36 | src[key] | -| PrototypePollutionUtility/tests.js:144:29:144:36 | src[key] | PrototypePollutionUtility/tests.js:140:16:140:18 | src | -| PrototypePollutionUtility/tests.js:144:29:144:36 | src[key] | PrototypePollutionUtility/tests.js:140:16:140:18 | src | -| PrototypePollutionUtility/tests.js:144:29:144:36 | src[key] | PrototypePollutionUtility/tests.js:140:16:140:18 | src | -| PrototypePollutionUtility/tests.js:144:29:144:36 | src[key] | PrototypePollutionUtility/tests.js:144:23:144:37 | clone(src[key]) | -| PrototypePollutionUtility/tests.js:144:29:144:36 | src[key] | PrototypePollutionUtility/tests.js:144:23:144:37 | clone(src[key]) | -| PrototypePollutionUtility/tests.js:144:29:144:36 | src[key] | PrototypePollutionUtility/tests.js:144:23:144:37 | clone(src[key]) | -| PrototypePollutionUtility/tests.js:144:29:144:36 | src[key] | PrototypePollutionUtility/tests.js:144:23:144:37 | clone(src[key]) | -| PrototypePollutionUtility/tests.js:144:29:144:36 | src[key] | PrototypePollutionUtility/tests.js:144:23:144:37 | clone(src[key]) | -| PrototypePollutionUtility/tests.js:144:29:144:36 | src[key] | PrototypePollutionUtility/tests.js:144:23:144:37 | clone(src[key]) | -| PrototypePollutionUtility/tests.js:144:29:144:36 | src[key] | PrototypePollutionUtility/tests.js:144:23:144:37 | clone(src[key]) | -| PrototypePollutionUtility/tests.js:144:29:144:36 | src[key] | PrototypePollutionUtility/tests.js:144:23:144:37 | clone(src[key]) | -| PrototypePollutionUtility/tests.js:144:29:144:36 | src[key] | PrototypePollutionUtility/tests.js:144:23:144:37 | clone(src[key]) | -| PrototypePollutionUtility/tests.js:144:33:144:35 | key | PrototypePollutionUtility/tests.js:144:29:144:36 | src[key] | -| PrototypePollutionUtility/tests.js:144:33:144:35 | key | PrototypePollutionUtility/tests.js:144:29:144:36 | src[key] | | PrototypePollutionUtility/tests.js:149:31:149:33 | dst | PrototypePollutionUtility/tests.js:152:22:152:24 | dst | | PrototypePollutionUtility/tests.js:149:31:149:33 | dst | PrototypePollutionUtility/tests.js:152:22:152:24 | dst | | PrototypePollutionUtility/tests.js:149:31:149:33 | dst | PrototypePollutionUtility/tests.js:152:22:152:24 | dst | @@ -1515,6 +1505,40 @@ edges | PrototypePollutionUtility/tests.js:240:36:240:44 | data[key] | PrototypePollutionUtility/tests.js:229:38:229:42 | value | | PrototypePollutionUtility/tests.js:240:41:240:43 | key | PrototypePollutionUtility/tests.js:240:36:240:44 | data[key] | | PrototypePollutionUtility/tests.js:240:41:240:43 | key | PrototypePollutionUtility/tests.js:240:36:240:44 | data[key] | +| PrototypePollutionUtility/tests.js:252:29:252:31 | src | PrototypePollutionUtility/tests.js:257:51:257:53 | src | +| PrototypePollutionUtility/tests.js:252:29:252:31 | src | PrototypePollutionUtility/tests.js:257:51:257:53 | src | +| PrototypePollutionUtility/tests.js:255:14:255:16 | key | PrototypePollutionUtility/tests.js:257:20:257:22 | key | +| PrototypePollutionUtility/tests.js:255:14:255:16 | key | PrototypePollutionUtility/tests.js:257:20:257:22 | key | +| PrototypePollutionUtility/tests.js:255:14:255:16 | key | PrototypePollutionUtility/tests.js:257:20:257:22 | key | +| PrototypePollutionUtility/tests.js:255:14:255:16 | key | PrototypePollutionUtility/tests.js:257:20:257:22 | key | +| PrototypePollutionUtility/tests.js:255:14:255:16 | key | PrototypePollutionUtility/tests.js:257:20:257:22 | key | +| PrototypePollutionUtility/tests.js:255:14:255:16 | key | PrototypePollutionUtility/tests.js:257:20:257:22 | key | +| PrototypePollutionUtility/tests.js:255:14:255:16 | key | PrototypePollutionUtility/tests.js:257:20:257:22 | key | +| PrototypePollutionUtility/tests.js:255:14:255:16 | key | PrototypePollutionUtility/tests.js:257:55:257:57 | key | +| PrototypePollutionUtility/tests.js:255:14:255:16 | key | PrototypePollutionUtility/tests.js:257:55:257:57 | key | +| PrototypePollutionUtility/tests.js:255:14:255:16 | key | PrototypePollutionUtility/tests.js:257:55:257:57 | key | +| PrototypePollutionUtility/tests.js:255:14:255:16 | key | PrototypePollutionUtility/tests.js:257:55:257:57 | key | +| PrototypePollutionUtility/tests.js:257:51:257:53 | src | PrototypePollutionUtility/tests.js:257:51:257:58 | src[key] | +| PrototypePollutionUtility/tests.js:257:51:257:53 | src | PrototypePollutionUtility/tests.js:257:51:257:58 | src[key] | +| PrototypePollutionUtility/tests.js:257:51:257:58 | src[key] | PrototypePollutionUtility/tests.js:252:29:252:31 | src | +| PrototypePollutionUtility/tests.js:257:51:257:58 | src[key] | PrototypePollutionUtility/tests.js:252:29:252:31 | src | +| PrototypePollutionUtility/tests.js:257:51:257:58 | src[key] | PrototypePollutionUtility/tests.js:252:29:252:31 | src | +| PrototypePollutionUtility/tests.js:257:51:257:58 | src[key] | PrototypePollutionUtility/tests.js:252:29:252:31 | src | +| PrototypePollutionUtility/tests.js:257:51:257:58 | src[key] | PrototypePollutionUtility/tests.js:252:29:252:31 | src | +| PrototypePollutionUtility/tests.js:257:51:257:58 | src[key] | PrototypePollutionUtility/tests.js:252:29:252:31 | src | +| PrototypePollutionUtility/tests.js:257:51:257:58 | src[key] | PrototypePollutionUtility/tests.js:257:27:257:59 | mergeWi ... c[key]) | +| PrototypePollutionUtility/tests.js:257:51:257:58 | src[key] | PrototypePollutionUtility/tests.js:257:27:257:59 | mergeWi ... c[key]) | +| PrototypePollutionUtility/tests.js:257:51:257:58 | src[key] | PrototypePollutionUtility/tests.js:257:27:257:59 | mergeWi ... c[key]) | +| PrototypePollutionUtility/tests.js:257:51:257:58 | src[key] | PrototypePollutionUtility/tests.js:257:27:257:59 | mergeWi ... c[key]) | +| PrototypePollutionUtility/tests.js:257:51:257:58 | src[key] | PrototypePollutionUtility/tests.js:257:27:257:59 | mergeWi ... c[key]) | +| PrototypePollutionUtility/tests.js:257:51:257:58 | src[key] | PrototypePollutionUtility/tests.js:257:27:257:59 | mergeWi ... c[key]) | +| PrototypePollutionUtility/tests.js:257:51:257:58 | src[key] | PrototypePollutionUtility/tests.js:257:27:257:59 | mergeWi ... c[key]) | +| PrototypePollutionUtility/tests.js:257:51:257:58 | src[key] | PrototypePollutionUtility/tests.js:257:27:257:59 | mergeWi ... c[key]) | +| PrototypePollutionUtility/tests.js:257:51:257:58 | src[key] | PrototypePollutionUtility/tests.js:257:27:257:59 | mergeWi ... c[key]) | +| PrototypePollutionUtility/tests.js:257:51:257:58 | src[key] | PrototypePollutionUtility/tests.js:257:27:257:59 | mergeWi ... c[key]) | +| PrototypePollutionUtility/tests.js:257:51:257:58 | src[key] | PrototypePollutionUtility/tests.js:257:27:257:59 | mergeWi ... c[key]) | +| PrototypePollutionUtility/tests.js:257:55:257:57 | key | PrototypePollutionUtility/tests.js:257:51:257:58 | src[key] | +| PrototypePollutionUtility/tests.js:257:55:257:57 | key | PrototypePollutionUtility/tests.js:257:51:257:58 | src[key] | | examples/PrototypePollutionUtility.js:1:16:1:18 | dst | examples/PrototypePollutionUtility.js:5:19:5:21 | dst | | examples/PrototypePollutionUtility.js:1:16:1:18 | dst | examples/PrototypePollutionUtility.js:5:19:5:21 | dst | | examples/PrototypePollutionUtility.js:1:16:1:18 | dst | examples/PrototypePollutionUtility.js:7:13:7:15 | dst | diff --git a/javascript/ql/test/query-tests/Security/CWE-400/PrototypePollutionUtility/tests.js b/javascript/ql/test/query-tests/Security/CWE-400/PrototypePollutionUtility/tests.js index 33ff9e6f855..96a2f1bf135 100644 --- a/javascript/ql/test/query-tests/Security/CWE-400/PrototypePollutionUtility/tests.js +++ b/javascript/ql/test/query-tests/Security/CWE-400/PrototypePollutionUtility/tests.js @@ -240,3 +240,22 @@ function deepSetCallerBad(data) { deepSetBad(map1, 'x', key, data[key]); } } + +function maybeCopy(x) { + if (x && typeof x === 'object') { + return {...x}; + } else { + return x; + } +} + +function mergeWithCopy(dst, src) { + if (dst == null) return src; + let result = maybeCopy(dst); + for (let key in src) { + if (src.hasOwnProperty(key)) { + result[key] = mergeWithCopy(dst[key], src[key]); // OK + } + } + return result; +} From ac2f0a8e114d0261816abe75a22fa28ccc50dbdf Mon Sep 17 00:00:00 2001 From: Asger F Date: Fri, 15 Nov 2019 10:08:33 +0000 Subject: [PATCH 06/17] JS: Do not require flow from key -> rhs --- .../ql/src/Security/CWE-400/PrototypePollutionUtility.ql | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/javascript/ql/src/Security/CWE-400/PrototypePollutionUtility.ql b/javascript/ql/src/Security/CWE-400/PrototypePollutionUtility.ql index 452f25ba1a5..c2a2a1a2373 100644 --- a/javascript/ql/src/Security/CWE-400/PrototypePollutionUtility.ql +++ b/javascript/ql/src/Security/CWE-400/PrototypePollutionUtility.ql @@ -161,12 +161,12 @@ class UnsafePropLabel extends FlowLabel { * } * ``` * - * This configuration is used to find four separate data flow paths originating + * This configuration is used to find three separate data flow paths originating * from a property enumeration, all leading to the same dynamic property write. * - * In particular, the base, property name, and rhs of the property write should all + * In particular, the base and property name of the property write should all * depend on the enumerated property name (`key`) and the right-hand side should - * additionally depend on the source object (`src`), while allowing steps of form + * depend on the source property (`src[key]`), while allowing steps of form * `x -> x[p]` and `p -> x[p]`. * * Note that in the above example, the flow from `key` to the base of the write (`dst`) @@ -384,7 +384,6 @@ predicate isPrototypePollutingAssignment(Node base, Node prop, Node rhs, Enumera exists(PropNameTracking cfg | cfg.hasFlow(enum, base) and cfg.hasFlow(enum, prop) and - cfg.hasFlow(enum, rhs) and cfg.hasFlow(enum.getASourceProp(), rhs) ) } From 8af233307a6a71e13ea34a4bb2b917b375bc056b Mon Sep 17 00:00:00 2001 From: Asger F Date: Fri, 15 Nov 2019 10:10:32 +0000 Subject: [PATCH 07/17] JS: Support enumeration through Object.entries --- .../CWE-400/PrototypePollutionUtility.ql | 67 ++++++++++++++----- .../PrototypePollutionUtility.expected | 62 +++++++++++++++++ .../PrototypePollutionUtility/tests.js | 12 ++++ 3 files changed, 123 insertions(+), 18 deletions(-) diff --git a/javascript/ql/src/Security/CWE-400/PrototypePollutionUtility.ql b/javascript/ql/src/Security/CWE-400/PrototypePollutionUtility.ql index c2a2a1a2373..4eb3bdcafb8 100644 --- a/javascript/ql/src/Security/CWE-400/PrototypePollutionUtility.ql +++ b/javascript/ql/src/Security/CWE-400/PrototypePollutionUtility.ql @@ -39,29 +39,13 @@ SourceNode getAnEnumeratedArrayElement(SourceNode array) { * A data flow node that refers to the name of a property obtained by enumerating * the properties of some object. */ -class EnumeratedPropName extends DataFlow::Node { - DataFlow::Node object; - - EnumeratedPropName() { - exists(ForInStmt stmt | - this = DataFlow::lvalueNode(stmt.getLValue()) and - object = stmt.getIterationDomain().flow() - ) - or - exists(CallNode call, string name | - call = globalVarRef("Object").getAMemberCall(name) and - (name = "keys" or name = "getOwnPropertyNames") and - object = call.getArgument(0) and - this = getAnEnumeratedArrayElement(call) - ) - } - +abstract class EnumeratedPropName extends DataFlow::Node { /** * Gets the object whose properties are being enumerated. * * For example, gets `src` in `for (var key in src)`. */ - Node getSourceObject() { result = object } + abstract DataFlow::Node getSourceObject(); /** * Gets a local reference of the source object. @@ -86,6 +70,53 @@ class EnumeratedPropName extends DataFlow::Node { } } +/** + * Property enumeration through `for-in` for `Object.keys` or `Object.getOwnPropertyName`. + */ +class ForInEnumeratedPropName extends EnumeratedPropName { + DataFlow::Node object; + + ForInEnumeratedPropName() { + exists(ForInStmt stmt | + this = DataFlow::lvalueNode(stmt.getLValue()) and + object = stmt.getIterationDomain().flow() + ) + or + exists(CallNode call, string name | + call = globalVarRef("Object").getAMemberCall(name) and + (name = "keys" or name = "getOwnPropertyNames") and + object = call.getArgument(0) and + this = getAnEnumeratedArrayElement(call) + ) + } + + override Node getSourceObject() { result = object } +} + +/** + * Property enumeration through `Object.entries`. + */ +class EntriesEnumeratedPropName extends EnumeratedPropName { + CallNode entries; + SourceNode entry; + + EntriesEnumeratedPropName() { + entries = globalVarRef("Object").getAMemberCall("entries") and + entry = getAnEnumeratedArrayElement(entries) and + this = entry.getAPropertyRead("0") + } + + override DataFlow::Node getSourceObject() { + result = entries.getArgument(0) + } + + override PropRead getASourceProp() { + result = super.getASourceProp() + or + result = entry.getAPropertyRead("1") + } +} + /** * Holds if the properties of `node` are enumerated locally. */ diff --git a/javascript/ql/test/query-tests/Security/CWE-400/PrototypePollutionUtility.expected b/javascript/ql/test/query-tests/Security/CWE-400/PrototypePollutionUtility.expected index b869a4c9158..d335d856011 100644 --- a/javascript/ql/test/query-tests/Security/CWE-400/PrototypePollutionUtility.expected +++ b/javascript/ql/test/query-tests/Security/CWE-400/PrototypePollutionUtility.expected @@ -638,6 +638,35 @@ nodes | PrototypePollutionUtility/tests.js:257:51:257:58 | src[key] | | PrototypePollutionUtility/tests.js:257:55:257:57 | key | | PrototypePollutionUtility/tests.js:257:55:257:57 | key | +| PrototypePollutionUtility/tests.js:263:27:263:29 | dst | +| PrototypePollutionUtility/tests.js:263:27:263:29 | dst | +| PrototypePollutionUtility/tests.js:265:13:265:26 | key | +| PrototypePollutionUtility/tests.js:265:13:265:26 | key | +| PrototypePollutionUtility/tests.js:265:19:265:26 | entry[0] | +| PrototypePollutionUtility/tests.js:265:19:265:26 | entry[0] | +| PrototypePollutionUtility/tests.js:265:19:265:26 | entry[0] | +| PrototypePollutionUtility/tests.js:266:13:266:28 | value | +| PrototypePollutionUtility/tests.js:266:13:266:28 | value | +| PrototypePollutionUtility/tests.js:266:21:266:28 | entry[1] | +| PrototypePollutionUtility/tests.js:266:21:266:28 | entry[1] | +| PrototypePollutionUtility/tests.js:266:21:266:28 | entry[1] | +| PrototypePollutionUtility/tests.js:268:30:268:32 | dst | +| PrototypePollutionUtility/tests.js:268:30:268:32 | dst | +| PrototypePollutionUtility/tests.js:268:30:268:37 | dst[key] | +| PrototypePollutionUtility/tests.js:268:30:268:37 | dst[key] | +| PrototypePollutionUtility/tests.js:268:30:268:37 | dst[key] | +| PrototypePollutionUtility/tests.js:268:30:268:37 | dst[key] | +| PrototypePollutionUtility/tests.js:268:34:268:36 | key | +| PrototypePollutionUtility/tests.js:268:34:268:36 | key | +| PrototypePollutionUtility/tests.js:270:13:270:15 | dst | +| PrototypePollutionUtility/tests.js:270:13:270:15 | dst | +| PrototypePollutionUtility/tests.js:270:13:270:15 | dst | +| PrototypePollutionUtility/tests.js:270:17:270:19 | key | +| PrototypePollutionUtility/tests.js:270:17:270:19 | key | +| PrototypePollutionUtility/tests.js:270:17:270:19 | key | +| PrototypePollutionUtility/tests.js:270:24:270:28 | value | +| PrototypePollutionUtility/tests.js:270:24:270:28 | value | +| PrototypePollutionUtility/tests.js:270:24:270:28 | value | | examples/PrototypePollutionUtility.js:1:16:1:18 | dst | | examples/PrototypePollutionUtility.js:1:16:1:18 | dst | | examples/PrototypePollutionUtility.js:1:21:1:23 | src | @@ -1539,6 +1568,38 @@ edges | PrototypePollutionUtility/tests.js:257:51:257:58 | src[key] | PrototypePollutionUtility/tests.js:257:27:257:59 | mergeWi ... c[key]) | | PrototypePollutionUtility/tests.js:257:55:257:57 | key | PrototypePollutionUtility/tests.js:257:51:257:58 | src[key] | | PrototypePollutionUtility/tests.js:257:55:257:57 | key | PrototypePollutionUtility/tests.js:257:51:257:58 | src[key] | +| PrototypePollutionUtility/tests.js:263:27:263:29 | dst | PrototypePollutionUtility/tests.js:268:30:268:32 | dst | +| PrototypePollutionUtility/tests.js:263:27:263:29 | dst | PrototypePollutionUtility/tests.js:268:30:268:32 | dst | +| PrototypePollutionUtility/tests.js:263:27:263:29 | dst | PrototypePollutionUtility/tests.js:270:13:270:15 | dst | +| PrototypePollutionUtility/tests.js:263:27:263:29 | dst | PrototypePollutionUtility/tests.js:270:13:270:15 | dst | +| PrototypePollutionUtility/tests.js:263:27:263:29 | dst | PrototypePollutionUtility/tests.js:270:13:270:15 | dst | +| PrototypePollutionUtility/tests.js:263:27:263:29 | dst | PrototypePollutionUtility/tests.js:270:13:270:15 | dst | +| PrototypePollutionUtility/tests.js:265:13:265:26 | key | PrototypePollutionUtility/tests.js:268:34:268:36 | key | +| PrototypePollutionUtility/tests.js:265:13:265:26 | key | PrototypePollutionUtility/tests.js:268:34:268:36 | key | +| PrototypePollutionUtility/tests.js:265:13:265:26 | key | PrototypePollutionUtility/tests.js:270:17:270:19 | key | +| PrototypePollutionUtility/tests.js:265:13:265:26 | key | PrototypePollutionUtility/tests.js:270:17:270:19 | key | +| PrototypePollutionUtility/tests.js:265:13:265:26 | key | PrototypePollutionUtility/tests.js:270:17:270:19 | key | +| PrototypePollutionUtility/tests.js:265:13:265:26 | key | PrototypePollutionUtility/tests.js:270:17:270:19 | key | +| PrototypePollutionUtility/tests.js:265:19:265:26 | entry[0] | PrototypePollutionUtility/tests.js:265:13:265:26 | key | +| PrototypePollutionUtility/tests.js:265:19:265:26 | entry[0] | PrototypePollutionUtility/tests.js:265:13:265:26 | key | +| PrototypePollutionUtility/tests.js:265:19:265:26 | entry[0] | PrototypePollutionUtility/tests.js:265:13:265:26 | key | +| PrototypePollutionUtility/tests.js:265:19:265:26 | entry[0] | PrototypePollutionUtility/tests.js:265:13:265:26 | key | +| PrototypePollutionUtility/tests.js:266:13:266:28 | value | PrototypePollutionUtility/tests.js:270:24:270:28 | value | +| PrototypePollutionUtility/tests.js:266:13:266:28 | value | PrototypePollutionUtility/tests.js:270:24:270:28 | value | +| PrototypePollutionUtility/tests.js:266:13:266:28 | value | PrototypePollutionUtility/tests.js:270:24:270:28 | value | +| PrototypePollutionUtility/tests.js:266:13:266:28 | value | PrototypePollutionUtility/tests.js:270:24:270:28 | value | +| PrototypePollutionUtility/tests.js:266:21:266:28 | entry[1] | PrototypePollutionUtility/tests.js:266:13:266:28 | value | +| PrototypePollutionUtility/tests.js:266:21:266:28 | entry[1] | PrototypePollutionUtility/tests.js:266:13:266:28 | value | +| PrototypePollutionUtility/tests.js:266:21:266:28 | entry[1] | PrototypePollutionUtility/tests.js:266:13:266:28 | value | +| PrototypePollutionUtility/tests.js:266:21:266:28 | entry[1] | PrototypePollutionUtility/tests.js:266:13:266:28 | value | +| PrototypePollutionUtility/tests.js:268:30:268:32 | dst | PrototypePollutionUtility/tests.js:268:30:268:37 | dst[key] | +| PrototypePollutionUtility/tests.js:268:30:268:32 | dst | PrototypePollutionUtility/tests.js:268:30:268:37 | dst[key] | +| PrototypePollutionUtility/tests.js:268:30:268:37 | dst[key] | PrototypePollutionUtility/tests.js:263:27:263:29 | dst | +| PrototypePollutionUtility/tests.js:268:30:268:37 | dst[key] | PrototypePollutionUtility/tests.js:263:27:263:29 | dst | +| PrototypePollutionUtility/tests.js:268:30:268:37 | dst[key] | PrototypePollutionUtility/tests.js:263:27:263:29 | dst | +| PrototypePollutionUtility/tests.js:268:30:268:37 | dst[key] | PrototypePollutionUtility/tests.js:263:27:263:29 | dst | +| PrototypePollutionUtility/tests.js:268:34:268:36 | key | PrototypePollutionUtility/tests.js:268:30:268:37 | dst[key] | +| PrototypePollutionUtility/tests.js:268:34:268:36 | key | PrototypePollutionUtility/tests.js:268:30:268:37 | dst[key] | | examples/PrototypePollutionUtility.js:1:16:1:18 | dst | examples/PrototypePollutionUtility.js:5:19:5:21 | dst | | examples/PrototypePollutionUtility.js:1:16:1:18 | dst | examples/PrototypePollutionUtility.js:5:19:5:21 | dst | | examples/PrototypePollutionUtility.js:1:16:1:18 | dst | examples/PrototypePollutionUtility.js:7:13:7:15 | dst | @@ -1654,4 +1715,5 @@ edges | PrototypePollutionUtility/tests.js:154:13:154:15 | dst | PrototypePollutionUtility/tests.js:150:14:150:16 | key | PrototypePollutionUtility/tests.js:154:13:154:15 | dst | Properties are copied from $@ to $@ without guarding against prototype pollution. | PrototypePollutionUtility/tests.js:150:21:150:23 | src | src | PrototypePollutionUtility/tests.js:154:13:154:15 | dst | dst | | PrototypePollutionUtility/tests.js:196:13:196:15 | dst | PrototypePollutionUtility/tests.js:192:19:192:25 | keys[i] | PrototypePollutionUtility/tests.js:196:13:196:15 | dst | Properties are copied from $@ to $@ without guarding against prototype pollution. | PrototypePollutionUtility/tests.js:190:28:190:30 | src | src | PrototypePollutionUtility/tests.js:196:13:196:15 | dst | dst | | PrototypePollutionUtility/tests.js:233:5:233:13 | map[key1] | PrototypePollutionUtility/tests.js:238:14:238:16 | key | PrototypePollutionUtility/tests.js:233:5:233:13 | map[key1] | Properties are copied from $@ to $@ without guarding against prototype pollution. | PrototypePollutionUtility/tests.js:238:21:238:24 | data | data | PrototypePollutionUtility/tests.js:233:5:233:13 | map[key1] | this object | +| PrototypePollutionUtility/tests.js:270:13:270:15 | dst | PrototypePollutionUtility/tests.js:265:19:265:26 | entry[0] | PrototypePollutionUtility/tests.js:270:13:270:15 | dst | Properties are copied from $@ to $@ without guarding against prototype pollution. | PrototypePollutionUtility/tests.js:264:20:264:22 | src | src | PrototypePollutionUtility/tests.js:270:13:270:15 | dst | dst | | examples/PrototypePollutionUtility.js:7:13:7:15 | dst | examples/PrototypePollutionUtility.js:2:14:2:16 | key | examples/PrototypePollutionUtility.js:7:13:7:15 | dst | Properties are copied from $@ to $@ without guarding against prototype pollution. | examples/PrototypePollutionUtility.js:2:21:2:23 | src | src | examples/PrototypePollutionUtility.js:7:13:7:15 | dst | dst | diff --git a/javascript/ql/test/query-tests/Security/CWE-400/PrototypePollutionUtility/tests.js b/javascript/ql/test/query-tests/Security/CWE-400/PrototypePollutionUtility/tests.js index 96a2f1bf135..18f619612fa 100644 --- a/javascript/ql/test/query-tests/Security/CWE-400/PrototypePollutionUtility/tests.js +++ b/javascript/ql/test/query-tests/Security/CWE-400/PrototypePollutionUtility/tests.js @@ -259,3 +259,15 @@ function mergeWithCopy(dst, src) { } return result; } + +function copyUsingEntries(dst, src) { + Object.entries(src).forEach(entry => { + let key = entry[0]; + let value = entry[1]; + if (dst[key]) { + copyUsingEntries(dst[key], value); + } else { + dst[key] = value; // NOT OK + } + }); +} From f7543aec95b05459aa85446c2bee0aa4e6834478 Mon Sep 17 00:00:00 2001 From: Asger F Date: Thu, 21 Nov 2019 12:03:22 +0000 Subject: [PATCH 08/17] JS: Support Reflect.ownKeys --- .../CWE-400/PrototypePollutionUtility.ql | 12 ++- .../PrototypePollutionUtility.expected | 97 +++++++++++++++++++ .../PrototypePollutionUtility/tests.js | 10 ++ 3 files changed, 115 insertions(+), 4 deletions(-) diff --git a/javascript/ql/src/Security/CWE-400/PrototypePollutionUtility.ql b/javascript/ql/src/Security/CWE-400/PrototypePollutionUtility.ql index 4eb3bdcafb8..a4505601caa 100644 --- a/javascript/ql/src/Security/CWE-400/PrototypePollutionUtility.ql +++ b/javascript/ql/src/Security/CWE-400/PrototypePollutionUtility.ql @@ -71,7 +71,7 @@ abstract class EnumeratedPropName extends DataFlow::Node { } /** - * Property enumeration through `for-in` for `Object.keys` or `Object.getOwnPropertyName`. + * Property enumeration through `for-in` for `Object.keys` or similar. */ class ForInEnumeratedPropName extends EnumeratedPropName { DataFlow::Node object; @@ -82,9 +82,13 @@ class ForInEnumeratedPropName extends EnumeratedPropName { object = stmt.getIterationDomain().flow() ) or - exists(CallNode call, string name | - call = globalVarRef("Object").getAMemberCall(name) and - (name = "keys" or name = "getOwnPropertyNames") and + exists(CallNode call | + call = globalVarRef("Object").getAMemberCall("keys") + or + call = globalVarRef("Object").getAMemberCall("getOwnPropertyNames") + or + call = globalVarRef("Reflect").getAMemberCall("ownKeys") + | object = call.getArgument(0) and this = getAnEnumeratedArrayElement(call) ) diff --git a/javascript/ql/test/query-tests/Security/CWE-400/PrototypePollutionUtility.expected b/javascript/ql/test/query-tests/Security/CWE-400/PrototypePollutionUtility.expected index d335d856011..0b12cd1b86e 100644 --- a/javascript/ql/test/query-tests/Security/CWE-400/PrototypePollutionUtility.expected +++ b/javascript/ql/test/query-tests/Security/CWE-400/PrototypePollutionUtility.expected @@ -667,6 +667,46 @@ nodes | PrototypePollutionUtility/tests.js:270:24:270:28 | value | | PrototypePollutionUtility/tests.js:270:24:270:28 | value | | PrototypePollutionUtility/tests.js:270:24:270:28 | value | +| PrototypePollutionUtility/tests.js:275:27:275:29 | dst | +| PrototypePollutionUtility/tests.js:275:27:275:29 | dst | +| PrototypePollutionUtility/tests.js:275:32:275:34 | src | +| PrototypePollutionUtility/tests.js:275:32:275:34 | src | +| PrototypePollutionUtility/tests.js:276:34:276:36 | key | +| PrototypePollutionUtility/tests.js:276:34:276:36 | key | +| PrototypePollutionUtility/tests.js:276:34:276:36 | key | +| PrototypePollutionUtility/tests.js:278:30:278:32 | dst | +| PrototypePollutionUtility/tests.js:278:30:278:32 | dst | +| PrototypePollutionUtility/tests.js:278:30:278:37 | dst[key] | +| PrototypePollutionUtility/tests.js:278:30:278:37 | dst[key] | +| PrototypePollutionUtility/tests.js:278:30:278:37 | dst[key] | +| PrototypePollutionUtility/tests.js:278:30:278:37 | dst[key] | +| PrototypePollutionUtility/tests.js:278:34:278:36 | key | +| PrototypePollutionUtility/tests.js:278:34:278:36 | key | +| PrototypePollutionUtility/tests.js:278:40:278:42 | src | +| PrototypePollutionUtility/tests.js:278:40:278:42 | src | +| PrototypePollutionUtility/tests.js:278:40:278:47 | src[key] | +| PrototypePollutionUtility/tests.js:278:40:278:47 | src[key] | +| PrototypePollutionUtility/tests.js:278:40:278:47 | src[key] | +| PrototypePollutionUtility/tests.js:278:40:278:47 | src[key] | +| PrototypePollutionUtility/tests.js:278:40:278:47 | src[key] | +| PrototypePollutionUtility/tests.js:278:44:278:46 | key | +| PrototypePollutionUtility/tests.js:278:44:278:46 | key | +| PrototypePollutionUtility/tests.js:280:13:280:15 | dst | +| PrototypePollutionUtility/tests.js:280:13:280:15 | dst | +| PrototypePollutionUtility/tests.js:280:13:280:15 | dst | +| PrototypePollutionUtility/tests.js:280:17:280:19 | key | +| PrototypePollutionUtility/tests.js:280:17:280:19 | key | +| PrototypePollutionUtility/tests.js:280:17:280:19 | key | +| PrototypePollutionUtility/tests.js:280:24:280:26 | src | +| PrototypePollutionUtility/tests.js:280:24:280:26 | src | +| PrototypePollutionUtility/tests.js:280:24:280:31 | src[key] | +| PrototypePollutionUtility/tests.js:280:24:280:31 | src[key] | +| PrototypePollutionUtility/tests.js:280:24:280:31 | src[key] | +| PrototypePollutionUtility/tests.js:280:24:280:31 | src[key] | +| PrototypePollutionUtility/tests.js:280:24:280:31 | src[key] | +| PrototypePollutionUtility/tests.js:280:24:280:31 | src[key] | +| PrototypePollutionUtility/tests.js:280:28:280:30 | key | +| PrototypePollutionUtility/tests.js:280:28:280:30 | key | | examples/PrototypePollutionUtility.js:1:16:1:18 | dst | | examples/PrototypePollutionUtility.js:1:16:1:18 | dst | | examples/PrototypePollutionUtility.js:1:21:1:23 | src | @@ -1600,6 +1640,62 @@ edges | PrototypePollutionUtility/tests.js:268:30:268:37 | dst[key] | PrototypePollutionUtility/tests.js:263:27:263:29 | dst | | PrototypePollutionUtility/tests.js:268:34:268:36 | key | PrototypePollutionUtility/tests.js:268:30:268:37 | dst[key] | | PrototypePollutionUtility/tests.js:268:34:268:36 | key | PrototypePollutionUtility/tests.js:268:30:268:37 | dst[key] | +| PrototypePollutionUtility/tests.js:275:27:275:29 | dst | PrototypePollutionUtility/tests.js:278:30:278:32 | dst | +| PrototypePollutionUtility/tests.js:275:27:275:29 | dst | PrototypePollutionUtility/tests.js:278:30:278:32 | dst | +| PrototypePollutionUtility/tests.js:275:27:275:29 | dst | PrototypePollutionUtility/tests.js:280:13:280:15 | dst | +| PrototypePollutionUtility/tests.js:275:27:275:29 | dst | PrototypePollutionUtility/tests.js:280:13:280:15 | dst | +| PrototypePollutionUtility/tests.js:275:27:275:29 | dst | PrototypePollutionUtility/tests.js:280:13:280:15 | dst | +| PrototypePollutionUtility/tests.js:275:27:275:29 | dst | PrototypePollutionUtility/tests.js:280:13:280:15 | dst | +| PrototypePollutionUtility/tests.js:275:32:275:34 | src | PrototypePollutionUtility/tests.js:278:40:278:42 | src | +| PrototypePollutionUtility/tests.js:275:32:275:34 | src | PrototypePollutionUtility/tests.js:278:40:278:42 | src | +| PrototypePollutionUtility/tests.js:275:32:275:34 | src | PrototypePollutionUtility/tests.js:280:24:280:26 | src | +| PrototypePollutionUtility/tests.js:275:32:275:34 | src | PrototypePollutionUtility/tests.js:280:24:280:26 | src | +| PrototypePollutionUtility/tests.js:276:34:276:36 | key | PrototypePollutionUtility/tests.js:278:34:278:36 | key | +| PrototypePollutionUtility/tests.js:276:34:276:36 | key | PrototypePollutionUtility/tests.js:278:34:278:36 | key | +| PrototypePollutionUtility/tests.js:276:34:276:36 | key | PrototypePollutionUtility/tests.js:278:34:278:36 | key | +| PrototypePollutionUtility/tests.js:276:34:276:36 | key | PrototypePollutionUtility/tests.js:278:34:278:36 | key | +| PrototypePollutionUtility/tests.js:276:34:276:36 | key | PrototypePollutionUtility/tests.js:278:44:278:46 | key | +| PrototypePollutionUtility/tests.js:276:34:276:36 | key | PrototypePollutionUtility/tests.js:278:44:278:46 | key | +| PrototypePollutionUtility/tests.js:276:34:276:36 | key | PrototypePollutionUtility/tests.js:278:44:278:46 | key | +| PrototypePollutionUtility/tests.js:276:34:276:36 | key | PrototypePollutionUtility/tests.js:278:44:278:46 | key | +| PrototypePollutionUtility/tests.js:276:34:276:36 | key | PrototypePollutionUtility/tests.js:280:17:280:19 | key | +| PrototypePollutionUtility/tests.js:276:34:276:36 | key | PrototypePollutionUtility/tests.js:280:17:280:19 | key | +| PrototypePollutionUtility/tests.js:276:34:276:36 | key | PrototypePollutionUtility/tests.js:280:17:280:19 | key | +| PrototypePollutionUtility/tests.js:276:34:276:36 | key | PrototypePollutionUtility/tests.js:280:17:280:19 | key | +| PrototypePollutionUtility/tests.js:276:34:276:36 | key | PrototypePollutionUtility/tests.js:280:17:280:19 | key | +| PrototypePollutionUtility/tests.js:276:34:276:36 | key | PrototypePollutionUtility/tests.js:280:17:280:19 | key | +| PrototypePollutionUtility/tests.js:276:34:276:36 | key | PrototypePollutionUtility/tests.js:280:17:280:19 | key | +| PrototypePollutionUtility/tests.js:276:34:276:36 | key | PrototypePollutionUtility/tests.js:280:28:280:30 | key | +| PrototypePollutionUtility/tests.js:276:34:276:36 | key | PrototypePollutionUtility/tests.js:280:28:280:30 | key | +| PrototypePollutionUtility/tests.js:276:34:276:36 | key | PrototypePollutionUtility/tests.js:280:28:280:30 | key | +| PrototypePollutionUtility/tests.js:276:34:276:36 | key | PrototypePollutionUtility/tests.js:280:28:280:30 | key | +| PrototypePollutionUtility/tests.js:278:30:278:32 | dst | PrototypePollutionUtility/tests.js:278:30:278:37 | dst[key] | +| PrototypePollutionUtility/tests.js:278:30:278:32 | dst | PrototypePollutionUtility/tests.js:278:30:278:37 | dst[key] | +| PrototypePollutionUtility/tests.js:278:30:278:37 | dst[key] | PrototypePollutionUtility/tests.js:275:27:275:29 | dst | +| PrototypePollutionUtility/tests.js:278:30:278:37 | dst[key] | PrototypePollutionUtility/tests.js:275:27:275:29 | dst | +| PrototypePollutionUtility/tests.js:278:30:278:37 | dst[key] | PrototypePollutionUtility/tests.js:275:27:275:29 | dst | +| PrototypePollutionUtility/tests.js:278:30:278:37 | dst[key] | PrototypePollutionUtility/tests.js:275:27:275:29 | dst | +| PrototypePollutionUtility/tests.js:278:34:278:36 | key | PrototypePollutionUtility/tests.js:278:30:278:37 | dst[key] | +| PrototypePollutionUtility/tests.js:278:34:278:36 | key | PrototypePollutionUtility/tests.js:278:30:278:37 | dst[key] | +| PrototypePollutionUtility/tests.js:278:40:278:42 | src | PrototypePollutionUtility/tests.js:278:40:278:47 | src[key] | +| PrototypePollutionUtility/tests.js:278:40:278:42 | src | PrototypePollutionUtility/tests.js:278:40:278:47 | src[key] | +| PrototypePollutionUtility/tests.js:278:40:278:47 | src[key] | PrototypePollutionUtility/tests.js:275:32:275:34 | src | +| PrototypePollutionUtility/tests.js:278:40:278:47 | src[key] | PrototypePollutionUtility/tests.js:275:32:275:34 | src | +| PrototypePollutionUtility/tests.js:278:40:278:47 | src[key] | PrototypePollutionUtility/tests.js:275:32:275:34 | src | +| PrototypePollutionUtility/tests.js:278:40:278:47 | src[key] | PrototypePollutionUtility/tests.js:275:32:275:34 | src | +| PrototypePollutionUtility/tests.js:278:40:278:47 | src[key] | PrototypePollutionUtility/tests.js:275:32:275:34 | src | +| PrototypePollutionUtility/tests.js:278:40:278:47 | src[key] | PrototypePollutionUtility/tests.js:275:32:275:34 | src | +| PrototypePollutionUtility/tests.js:278:44:278:46 | key | PrototypePollutionUtility/tests.js:278:40:278:47 | src[key] | +| PrototypePollutionUtility/tests.js:278:44:278:46 | key | PrototypePollutionUtility/tests.js:278:40:278:47 | src[key] | +| PrototypePollutionUtility/tests.js:280:24:280:26 | src | PrototypePollutionUtility/tests.js:280:24:280:31 | src[key] | +| PrototypePollutionUtility/tests.js:280:24:280:26 | src | PrototypePollutionUtility/tests.js:280:24:280:31 | src[key] | +| PrototypePollutionUtility/tests.js:280:24:280:26 | src | PrototypePollutionUtility/tests.js:280:24:280:31 | src[key] | +| PrototypePollutionUtility/tests.js:280:24:280:26 | src | PrototypePollutionUtility/tests.js:280:24:280:31 | src[key] | +| PrototypePollutionUtility/tests.js:280:24:280:31 | src[key] | PrototypePollutionUtility/tests.js:280:24:280:31 | src[key] | +| PrototypePollutionUtility/tests.js:280:28:280:30 | key | PrototypePollutionUtility/tests.js:280:24:280:31 | src[key] | +| PrototypePollutionUtility/tests.js:280:28:280:30 | key | PrototypePollutionUtility/tests.js:280:24:280:31 | src[key] | +| PrototypePollutionUtility/tests.js:280:28:280:30 | key | PrototypePollutionUtility/tests.js:280:24:280:31 | src[key] | +| PrototypePollutionUtility/tests.js:280:28:280:30 | key | PrototypePollutionUtility/tests.js:280:24:280:31 | src[key] | | examples/PrototypePollutionUtility.js:1:16:1:18 | dst | examples/PrototypePollutionUtility.js:5:19:5:21 | dst | | examples/PrototypePollutionUtility.js:1:16:1:18 | dst | examples/PrototypePollutionUtility.js:5:19:5:21 | dst | | examples/PrototypePollutionUtility.js:1:16:1:18 | dst | examples/PrototypePollutionUtility.js:7:13:7:15 | dst | @@ -1716,4 +1812,5 @@ edges | PrototypePollutionUtility/tests.js:196:13:196:15 | dst | PrototypePollutionUtility/tests.js:192:19:192:25 | keys[i] | PrototypePollutionUtility/tests.js:196:13:196:15 | dst | Properties are copied from $@ to $@ without guarding against prototype pollution. | PrototypePollutionUtility/tests.js:190:28:190:30 | src | src | PrototypePollutionUtility/tests.js:196:13:196:15 | dst | dst | | PrototypePollutionUtility/tests.js:233:5:233:13 | map[key1] | PrototypePollutionUtility/tests.js:238:14:238:16 | key | PrototypePollutionUtility/tests.js:233:5:233:13 | map[key1] | Properties are copied from $@ to $@ without guarding against prototype pollution. | PrototypePollutionUtility/tests.js:238:21:238:24 | data | data | PrototypePollutionUtility/tests.js:233:5:233:13 | map[key1] | this object | | PrototypePollutionUtility/tests.js:270:13:270:15 | dst | PrototypePollutionUtility/tests.js:265:19:265:26 | entry[0] | PrototypePollutionUtility/tests.js:270:13:270:15 | dst | Properties are copied from $@ to $@ without guarding against prototype pollution. | PrototypePollutionUtility/tests.js:264:20:264:22 | src | src | PrototypePollutionUtility/tests.js:270:13:270:15 | dst | dst | +| PrototypePollutionUtility/tests.js:280:13:280:15 | dst | PrototypePollutionUtility/tests.js:276:34:276:36 | key | PrototypePollutionUtility/tests.js:280:13:280:15 | dst | Properties are copied from $@ to $@ without guarding against prototype pollution. | PrototypePollutionUtility/tests.js:276:21:276:23 | src | src | PrototypePollutionUtility/tests.js:280:13:280:15 | dst | dst | | examples/PrototypePollutionUtility.js:7:13:7:15 | dst | examples/PrototypePollutionUtility.js:2:14:2:16 | key | examples/PrototypePollutionUtility.js:7:13:7:15 | dst | Properties are copied from $@ to $@ without guarding against prototype pollution. | examples/PrototypePollutionUtility.js:2:21:2:23 | src | src | examples/PrototypePollutionUtility.js:7:13:7:15 | dst | dst | diff --git a/javascript/ql/test/query-tests/Security/CWE-400/PrototypePollutionUtility/tests.js b/javascript/ql/test/query-tests/Security/CWE-400/PrototypePollutionUtility/tests.js index 18f619612fa..de765fde1b1 100644 --- a/javascript/ql/test/query-tests/Security/CWE-400/PrototypePollutionUtility/tests.js +++ b/javascript/ql/test/query-tests/Security/CWE-400/PrototypePollutionUtility/tests.js @@ -271,3 +271,13 @@ function copyUsingEntries(dst, src) { } }); } + +function copyUsingReflect(dst, src) { + Reflect.ownKeys(src).forEach(key => { + if (dst[key]) { + copyUsingReflect(dst[key], src[key]); + } else { + dst[key] = src[key]; // NOT OK + } + }); +} \ No newline at end of file From 738123d3f50fd4a416b5c0a8a9f2bf67d3bd1f00 Mon Sep 17 00:00:00 2001 From: Asger F Date: Fri, 22 Nov 2019 09:36:50 +0000 Subject: [PATCH 09/17] JS: More sanitizers --- .../CWE-400/PrototypePollutionUtility.ql | 47 ++++++++++++++++--- 1 file changed, 41 insertions(+), 6 deletions(-) diff --git a/javascript/ql/src/Security/CWE-400/PrototypePollutionUtility.ql b/javascript/ql/src/Security/CWE-400/PrototypePollutionUtility.ql index a4505601caa..d8f7f8b1760 100644 --- a/javascript/ql/src/Security/CWE-400/PrototypePollutionUtility.ql +++ b/javascript/ql/src/Security/CWE-400/PrototypePollutionUtility.ql @@ -261,22 +261,24 @@ class PropNameTracking extends DataFlow::Configuration { } override predicate isBarrierGuard(DataFlow::BarrierGuardNode node) { - node instanceof EqualityGuard or + node instanceof BlacklistEqualityGuard or + node instanceof WhitelistEqualityGuard or node instanceof HasOwnPropertyGuard or node instanceof InstanceOfGuard or node instanceof TypeofGuard or - node instanceof ArrayInclusionGuard + node instanceof BlacklistInclusionGuard or + node instanceof WhitelistInclusionGuard } } /** * Sanitizer guard of form `x === "__proto__"` or `x === "constructor"`. */ -class EqualityGuard extends DataFlow::LabeledBarrierGuardNode, ValueNode { +class BlacklistEqualityGuard extends DataFlow::LabeledBarrierGuardNode, ValueNode { override EqualityTest astNode; string propName; - EqualityGuard() { + BlacklistEqualityGuard() { astNode.getAnOperand().getStringValue() = propName and propName = unsafePropName() } @@ -288,6 +290,24 @@ class EqualityGuard extends DataFlow::LabeledBarrierGuardNode, ValueNode { } } +/** + * An equality test with something other than `__proto__` or `constructor`. + */ +class WhitelistEqualityGuard extends DataFlow::LabeledBarrierGuardNode, ValueNode { + override EqualityTest astNode; + + WhitelistEqualityGuard() { + not astNode.getAnOperand().getStringValue() = unsafePropName() and + astNode.getAnOperand() instanceof Literal + } + + override predicate blocks(boolean outcome, Expr e, FlowLabel label) { + e = astNode.getAnOperand() and + outcome = astNode.getPolarity() and + label instanceof UnsafePropLabel + } +} + /** * Sanitizer guard for calls to `Object.prototype.hasOwnProperty`. * @@ -371,10 +391,10 @@ class TypeofGuard extends DataFlow::LabeledBarrierGuardNode, DataFlow::ValueNode /** * A check of form `["__proto__"].includes(x)` or similar. */ -class ArrayInclusionGuard extends DataFlow::LabeledBarrierGuardNode, InclusionTest { +class BlacklistInclusionGuard extends DataFlow::LabeledBarrierGuardNode, InclusionTest { UnsafePropLabel label; - ArrayInclusionGuard() { + BlacklistInclusionGuard() { exists(DataFlow::ArrayCreationNode array | array.getAnElement().getStringValue() = label and array.flowsTo(getContainerNode()) @@ -388,6 +408,21 @@ class ArrayInclusionGuard extends DataFlow::LabeledBarrierGuardNode, InclusionTe } } +/** + * A check of form `xs.includes(x)` or similar, which sanitizes `x` in the true case. + */ +class WhitelistInclusionGuard extends DataFlow::LabeledBarrierGuardNode { + WhitelistInclusionGuard() { + this instanceof TaintTracking::PositiveIndexOfSanitizer or + this instanceof TaintTracking::InclusionSanitizer + } + + override predicate blocks(boolean outcome, Expr e, DataFlow::FlowLabel lbl) { + this.(TaintTracking::AdditionalSanitizerGuardNode).sanitizes(outcome, e) and + lbl instanceof UnsafePropLabel + } +} + /** * Gets a meaningful name for `node` if possible. */ From bd9405ab84654329151176a2cad838fcbce3f53d Mon Sep 17 00:00:00 2001 From: Asger F Date: Tue, 26 Nov 2019 09:28:55 +0000 Subject: [PATCH 10/17] JS: Guard against more FPs --- .../CWE-400/PrototypePollutionUtility.ql | 22 +++++ .../PrototypePollutionUtility.expected | 86 +++++++++++++++++++ .../PrototypePollutionUtility/tests.js | 18 +++- 3 files changed, 125 insertions(+), 1 deletion(-) diff --git a/javascript/ql/src/Security/CWE-400/PrototypePollutionUtility.ql b/javascript/ql/src/Security/CWE-400/PrototypePollutionUtility.ql index d8f7f8b1760..09c2a7bd0b5 100644 --- a/javascript/ql/src/Security/CWE-400/PrototypePollutionUtility.ql +++ b/javascript/ql/src/Security/CWE-400/PrototypePollutionUtility.ql @@ -144,6 +144,26 @@ class DynamicPropRead extends DataFlow::SourceNode, DataFlow::ValueNode { /** Gets the base of the dynamic read. */ DataFlow::Node getBase() { result = astNode.getBase().flow() } + + /** + * Holds if the value of this read was assigned to earlier in the same basic block. + * + * For example, this is true for `dst[x]` on line 2 below: + * ```js + * dst[x] = {}; + * dst[x][y] = src[y]; + * ``` + */ + predicate hasDominatingAssignment() { + exists(DataFlow::PropWrite write, BasicBlock bb, int i, int j, SsaVariable ssaVar | + write = getBase().getALocalSource().getAPropertyWrite() and + bb.getNode(i) = write.getWriteNode() and + bb.getNode(j) = astNode and + i < j and + write.getPropertyNameExpr() = ssaVar.getAUse() and + astNode.getIndex() = ssaVar.getAUse() + ) + } } /** @@ -238,11 +258,13 @@ class PropNameTracking extends DataFlow::Configuration { // Step through `p -> x[p]` exists(PropRead read | pred = read.getPropertyNameExpr().flow() and + not read.(DynamicPropRead).hasDominatingAssignment() and succ = read ) or // Step through `x -> x[p]` exists(DynamicPropRead read | + not read.hasDominatingAssignment() and pred = read.getBase() and succ = read ) diff --git a/javascript/ql/test/query-tests/Security/CWE-400/PrototypePollutionUtility.expected b/javascript/ql/test/query-tests/Security/CWE-400/PrototypePollutionUtility.expected index 0b12cd1b86e..3b5f3a06e30 100644 --- a/javascript/ql/test/query-tests/Security/CWE-400/PrototypePollutionUtility.expected +++ b/javascript/ql/test/query-tests/Security/CWE-400/PrototypePollutionUtility.expected @@ -707,6 +707,42 @@ nodes | PrototypePollutionUtility/tests.js:280:24:280:31 | src[key] | | PrototypePollutionUtility/tests.js:280:28:280:30 | key | | PrototypePollutionUtility/tests.js:280:28:280:30 | key | +| PrototypePollutionUtility/tests.js:285:28:285:30 | src | +| PrototypePollutionUtility/tests.js:285:28:285:30 | src | +| PrototypePollutionUtility/tests.js:285:33:285:36 | path | +| PrototypePollutionUtility/tests.js:285:33:285:36 | path | +| PrototypePollutionUtility/tests.js:286:14:286:16 | key | +| PrototypePollutionUtility/tests.js:286:14:286:16 | key | +| PrototypePollutionUtility/tests.js:286:14:286:16 | key | +| PrototypePollutionUtility/tests.js:289:40:289:42 | src | +| PrototypePollutionUtility/tests.js:289:40:289:42 | src | +| PrototypePollutionUtility/tests.js:289:40:289:47 | src[key] | +| PrototypePollutionUtility/tests.js:289:40:289:47 | src[key] | +| PrototypePollutionUtility/tests.js:289:40:289:47 | src[key] | +| PrototypePollutionUtility/tests.js:289:40:289:47 | src[key] | +| PrototypePollutionUtility/tests.js:289:40:289:47 | src[key] | +| PrototypePollutionUtility/tests.js:289:44:289:46 | key | +| PrototypePollutionUtility/tests.js:289:44:289:46 | key | +| PrototypePollutionUtility/tests.js:289:50:289:78 | path ? ... y : key | +| PrototypePollutionUtility/tests.js:289:50:289:78 | path ? ... y : key | +| PrototypePollutionUtility/tests.js:289:76:289:78 | key | +| PrototypePollutionUtility/tests.js:289:76:289:78 | key | +| PrototypePollutionUtility/tests.js:292:24:292:27 | path | +| PrototypePollutionUtility/tests.js:292:24:292:27 | path | +| PrototypePollutionUtility/tests.js:292:24:292:27 | path | +| PrototypePollutionUtility/tests.js:293:30:293:32 | key | +| PrototypePollutionUtility/tests.js:293:30:293:32 | key | +| PrototypePollutionUtility/tests.js:293:30:293:32 | key | +| PrototypePollutionUtility/tests.js:293:37:293:39 | src | +| PrototypePollutionUtility/tests.js:293:37:293:39 | src | +| PrototypePollutionUtility/tests.js:293:37:293:44 | src[key] | +| PrototypePollutionUtility/tests.js:293:37:293:44 | src[key] | +| PrototypePollutionUtility/tests.js:293:37:293:44 | src[key] | +| PrototypePollutionUtility/tests.js:293:37:293:44 | src[key] | +| PrototypePollutionUtility/tests.js:293:37:293:44 | src[key] | +| PrototypePollutionUtility/tests.js:293:37:293:44 | src[key] | +| PrototypePollutionUtility/tests.js:293:41:293:43 | key | +| PrototypePollutionUtility/tests.js:293:41:293:43 | key | | examples/PrototypePollutionUtility.js:1:16:1:18 | dst | | examples/PrototypePollutionUtility.js:1:16:1:18 | dst | | examples/PrototypePollutionUtility.js:1:21:1:23 | src | @@ -1696,6 +1732,56 @@ edges | PrototypePollutionUtility/tests.js:280:28:280:30 | key | PrototypePollutionUtility/tests.js:280:24:280:31 | src[key] | | PrototypePollutionUtility/tests.js:280:28:280:30 | key | PrototypePollutionUtility/tests.js:280:24:280:31 | src[key] | | PrototypePollutionUtility/tests.js:280:28:280:30 | key | PrototypePollutionUtility/tests.js:280:24:280:31 | src[key] | +| PrototypePollutionUtility/tests.js:285:28:285:30 | src | PrototypePollutionUtility/tests.js:289:40:289:42 | src | +| PrototypePollutionUtility/tests.js:285:28:285:30 | src | PrototypePollutionUtility/tests.js:289:40:289:42 | src | +| PrototypePollutionUtility/tests.js:285:28:285:30 | src | PrototypePollutionUtility/tests.js:293:37:293:39 | src | +| PrototypePollutionUtility/tests.js:285:28:285:30 | src | PrototypePollutionUtility/tests.js:293:37:293:39 | src | +| PrototypePollutionUtility/tests.js:285:33:285:36 | path | PrototypePollutionUtility/tests.js:292:24:292:27 | path | +| PrototypePollutionUtility/tests.js:285:33:285:36 | path | PrototypePollutionUtility/tests.js:292:24:292:27 | path | +| PrototypePollutionUtility/tests.js:285:33:285:36 | path | PrototypePollutionUtility/tests.js:292:24:292:27 | path | +| PrototypePollutionUtility/tests.js:285:33:285:36 | path | PrototypePollutionUtility/tests.js:292:24:292:27 | path | +| PrototypePollutionUtility/tests.js:286:14:286:16 | key | PrototypePollutionUtility/tests.js:289:44:289:46 | key | +| PrototypePollutionUtility/tests.js:286:14:286:16 | key | PrototypePollutionUtility/tests.js:289:44:289:46 | key | +| PrototypePollutionUtility/tests.js:286:14:286:16 | key | PrototypePollutionUtility/tests.js:289:44:289:46 | key | +| PrototypePollutionUtility/tests.js:286:14:286:16 | key | PrototypePollutionUtility/tests.js:289:44:289:46 | key | +| PrototypePollutionUtility/tests.js:286:14:286:16 | key | PrototypePollutionUtility/tests.js:289:76:289:78 | key | +| PrototypePollutionUtility/tests.js:286:14:286:16 | key | PrototypePollutionUtility/tests.js:289:76:289:78 | key | +| PrototypePollutionUtility/tests.js:286:14:286:16 | key | PrototypePollutionUtility/tests.js:289:76:289:78 | key | +| PrototypePollutionUtility/tests.js:286:14:286:16 | key | PrototypePollutionUtility/tests.js:289:76:289:78 | key | +| PrototypePollutionUtility/tests.js:286:14:286:16 | key | PrototypePollutionUtility/tests.js:293:30:293:32 | key | +| PrototypePollutionUtility/tests.js:286:14:286:16 | key | PrototypePollutionUtility/tests.js:293:30:293:32 | key | +| PrototypePollutionUtility/tests.js:286:14:286:16 | key | PrototypePollutionUtility/tests.js:293:30:293:32 | key | +| PrototypePollutionUtility/tests.js:286:14:286:16 | key | PrototypePollutionUtility/tests.js:293:30:293:32 | key | +| PrototypePollutionUtility/tests.js:286:14:286:16 | key | PrototypePollutionUtility/tests.js:293:30:293:32 | key | +| PrototypePollutionUtility/tests.js:286:14:286:16 | key | PrototypePollutionUtility/tests.js:293:30:293:32 | key | +| PrototypePollutionUtility/tests.js:286:14:286:16 | key | PrototypePollutionUtility/tests.js:293:30:293:32 | key | +| PrototypePollutionUtility/tests.js:286:14:286:16 | key | PrototypePollutionUtility/tests.js:293:41:293:43 | key | +| PrototypePollutionUtility/tests.js:286:14:286:16 | key | PrototypePollutionUtility/tests.js:293:41:293:43 | key | +| PrototypePollutionUtility/tests.js:286:14:286:16 | key | PrototypePollutionUtility/tests.js:293:41:293:43 | key | +| PrototypePollutionUtility/tests.js:286:14:286:16 | key | PrototypePollutionUtility/tests.js:293:41:293:43 | key | +| PrototypePollutionUtility/tests.js:289:40:289:42 | src | PrototypePollutionUtility/tests.js:289:40:289:47 | src[key] | +| PrototypePollutionUtility/tests.js:289:40:289:42 | src | PrototypePollutionUtility/tests.js:289:40:289:47 | src[key] | +| PrototypePollutionUtility/tests.js:289:40:289:47 | src[key] | PrototypePollutionUtility/tests.js:285:28:285:30 | src | +| PrototypePollutionUtility/tests.js:289:40:289:47 | src[key] | PrototypePollutionUtility/tests.js:285:28:285:30 | src | +| PrototypePollutionUtility/tests.js:289:40:289:47 | src[key] | PrototypePollutionUtility/tests.js:285:28:285:30 | src | +| PrototypePollutionUtility/tests.js:289:40:289:47 | src[key] | PrototypePollutionUtility/tests.js:285:28:285:30 | src | +| PrototypePollutionUtility/tests.js:289:40:289:47 | src[key] | PrototypePollutionUtility/tests.js:285:28:285:30 | src | +| PrototypePollutionUtility/tests.js:289:40:289:47 | src[key] | PrototypePollutionUtility/tests.js:285:28:285:30 | src | +| PrototypePollutionUtility/tests.js:289:44:289:46 | key | PrototypePollutionUtility/tests.js:289:40:289:47 | src[key] | +| PrototypePollutionUtility/tests.js:289:44:289:46 | key | PrototypePollutionUtility/tests.js:289:40:289:47 | src[key] | +| PrototypePollutionUtility/tests.js:289:50:289:78 | path ? ... y : key | PrototypePollutionUtility/tests.js:285:33:285:36 | path | +| PrototypePollutionUtility/tests.js:289:50:289:78 | path ? ... y : key | PrototypePollutionUtility/tests.js:285:33:285:36 | path | +| PrototypePollutionUtility/tests.js:289:76:289:78 | key | PrototypePollutionUtility/tests.js:289:50:289:78 | path ? ... y : key | +| PrototypePollutionUtility/tests.js:289:76:289:78 | key | PrototypePollutionUtility/tests.js:289:50:289:78 | path ? ... y : key | +| PrototypePollutionUtility/tests.js:293:37:293:39 | src | PrototypePollutionUtility/tests.js:293:37:293:44 | src[key] | +| PrototypePollutionUtility/tests.js:293:37:293:39 | src | PrototypePollutionUtility/tests.js:293:37:293:44 | src[key] | +| PrototypePollutionUtility/tests.js:293:37:293:39 | src | PrototypePollutionUtility/tests.js:293:37:293:44 | src[key] | +| PrototypePollutionUtility/tests.js:293:37:293:39 | src | PrototypePollutionUtility/tests.js:293:37:293:44 | src[key] | +| PrototypePollutionUtility/tests.js:293:37:293:44 | src[key] | PrototypePollutionUtility/tests.js:293:37:293:44 | src[key] | +| PrototypePollutionUtility/tests.js:293:41:293:43 | key | PrototypePollutionUtility/tests.js:293:37:293:44 | src[key] | +| PrototypePollutionUtility/tests.js:293:41:293:43 | key | PrototypePollutionUtility/tests.js:293:37:293:44 | src[key] | +| PrototypePollutionUtility/tests.js:293:41:293:43 | key | PrototypePollutionUtility/tests.js:293:37:293:44 | src[key] | +| PrototypePollutionUtility/tests.js:293:41:293:43 | key | PrototypePollutionUtility/tests.js:293:37:293:44 | src[key] | | examples/PrototypePollutionUtility.js:1:16:1:18 | dst | examples/PrototypePollutionUtility.js:5:19:5:21 | dst | | examples/PrototypePollutionUtility.js:1:16:1:18 | dst | examples/PrototypePollutionUtility.js:5:19:5:21 | dst | | examples/PrototypePollutionUtility.js:1:16:1:18 | dst | examples/PrototypePollutionUtility.js:7:13:7:15 | dst | diff --git a/javascript/ql/test/query-tests/Security/CWE-400/PrototypePollutionUtility/tests.js b/javascript/ql/test/query-tests/Security/CWE-400/PrototypePollutionUtility/tests.js index de765fde1b1..58a65cf6cc9 100644 --- a/javascript/ql/test/query-tests/Security/CWE-400/PrototypePollutionUtility/tests.js +++ b/javascript/ql/test/query-tests/Security/CWE-400/PrototypePollutionUtility/tests.js @@ -280,4 +280,20 @@ function copyUsingReflect(dst, src) { dst[key] = src[key]; // NOT OK } }); -} \ No newline at end of file +} + +function copyWithPath(dst, src, path) { + for (let key in src) { + if (src.hasOwnProperty(key)) { + if (dst[key]) { + copyWithPath(dst[key], src[key], path ? path + '.' + key : key); + } else { + let target = {}; + target[path] = {}; + target[path][key] = src[key]; // OK + doSomething(target); + } + } + } + return dst; +} From a447645c1046fb34fed901a0a75399a77f490ab7 Mon Sep 17 00:00:00 2001 From: Asger F Date: Tue, 26 Nov 2019 13:27:01 +0000 Subject: [PATCH 11/17] JS: Add test with typeof on value --- .../PrototypePollutionUtility.expected | 85 +++++++++++++++++++ .../PrototypePollutionUtility/tests.js | 13 +++ 2 files changed, 98 insertions(+) diff --git a/javascript/ql/test/query-tests/Security/CWE-400/PrototypePollutionUtility.expected b/javascript/ql/test/query-tests/Security/CWE-400/PrototypePollutionUtility.expected index 3b5f3a06e30..457ce94a300 100644 --- a/javascript/ql/test/query-tests/Security/CWE-400/PrototypePollutionUtility.expected +++ b/javascript/ql/test/query-tests/Security/CWE-400/PrototypePollutionUtility.expected @@ -743,6 +743,42 @@ nodes | PrototypePollutionUtility/tests.js:293:37:293:44 | src[key] | | PrototypePollutionUtility/tests.js:293:41:293:43 | key | | PrototypePollutionUtility/tests.js:293:41:293:43 | key | +| PrototypePollutionUtility/tests.js:301:27:301:29 | dst | +| PrototypePollutionUtility/tests.js:301:27:301:29 | dst | +| PrototypePollutionUtility/tests.js:301:32:301:34 | src | +| PrototypePollutionUtility/tests.js:302:14:302:16 | key | +| PrototypePollutionUtility/tests.js:302:14:302:16 | key | +| PrototypePollutionUtility/tests.js:302:14:302:16 | key | +| PrototypePollutionUtility/tests.js:304:17:304:32 | value | +| PrototypePollutionUtility/tests.js:304:17:304:32 | value | +| PrototypePollutionUtility/tests.js:304:17:304:32 | value | +| PrototypePollutionUtility/tests.js:304:25:304:27 | src | +| PrototypePollutionUtility/tests.js:304:25:304:32 | src[key] | +| PrototypePollutionUtility/tests.js:304:25:304:32 | src[key] | +| PrototypePollutionUtility/tests.js:304:25:304:32 | src[key] | +| PrototypePollutionUtility/tests.js:304:25:304:32 | src[key] | +| PrototypePollutionUtility/tests.js:304:29:304:31 | key | +| PrototypePollutionUtility/tests.js:304:29:304:31 | key | +| PrototypePollutionUtility/tests.js:306:34:306:36 | dst | +| PrototypePollutionUtility/tests.js:306:34:306:36 | dst | +| PrototypePollutionUtility/tests.js:306:34:306:41 | dst[key] | +| PrototypePollutionUtility/tests.js:306:34:306:41 | dst[key] | +| PrototypePollutionUtility/tests.js:306:34:306:41 | dst[key] | +| PrototypePollutionUtility/tests.js:306:34:306:41 | dst[key] | +| PrototypePollutionUtility/tests.js:306:38:306:40 | key | +| PrototypePollutionUtility/tests.js:306:38:306:40 | key | +| PrototypePollutionUtility/tests.js:306:44:306:48 | value | +| PrototypePollutionUtility/tests.js:306:44:306:48 | value | +| PrototypePollutionUtility/tests.js:308:17:308:19 | dst | +| PrototypePollutionUtility/tests.js:308:17:308:19 | dst | +| PrototypePollutionUtility/tests.js:308:17:308:19 | dst | +| PrototypePollutionUtility/tests.js:308:21:308:23 | key | +| PrototypePollutionUtility/tests.js:308:21:308:23 | key | +| PrototypePollutionUtility/tests.js:308:21:308:23 | key | +| PrototypePollutionUtility/tests.js:308:28:308:32 | value | +| PrototypePollutionUtility/tests.js:308:28:308:32 | value | +| PrototypePollutionUtility/tests.js:308:28:308:32 | value | +| PrototypePollutionUtility/tests.js:308:28:308:32 | value | | examples/PrototypePollutionUtility.js:1:16:1:18 | dst | | examples/PrototypePollutionUtility.js:1:16:1:18 | dst | | examples/PrototypePollutionUtility.js:1:21:1:23 | src | @@ -1782,6 +1818,54 @@ edges | PrototypePollutionUtility/tests.js:293:41:293:43 | key | PrototypePollutionUtility/tests.js:293:37:293:44 | src[key] | | PrototypePollutionUtility/tests.js:293:41:293:43 | key | PrototypePollutionUtility/tests.js:293:37:293:44 | src[key] | | PrototypePollutionUtility/tests.js:293:41:293:43 | key | PrototypePollutionUtility/tests.js:293:37:293:44 | src[key] | +| PrototypePollutionUtility/tests.js:301:27:301:29 | dst | PrototypePollutionUtility/tests.js:306:34:306:36 | dst | +| PrototypePollutionUtility/tests.js:301:27:301:29 | dst | PrototypePollutionUtility/tests.js:306:34:306:36 | dst | +| PrototypePollutionUtility/tests.js:301:27:301:29 | dst | PrototypePollutionUtility/tests.js:308:17:308:19 | dst | +| PrototypePollutionUtility/tests.js:301:27:301:29 | dst | PrototypePollutionUtility/tests.js:308:17:308:19 | dst | +| PrototypePollutionUtility/tests.js:301:27:301:29 | dst | PrototypePollutionUtility/tests.js:308:17:308:19 | dst | +| PrototypePollutionUtility/tests.js:301:27:301:29 | dst | PrototypePollutionUtility/tests.js:308:17:308:19 | dst | +| PrototypePollutionUtility/tests.js:301:32:301:34 | src | PrototypePollutionUtility/tests.js:304:25:304:27 | src | +| PrototypePollutionUtility/tests.js:302:14:302:16 | key | PrototypePollutionUtility/tests.js:304:29:304:31 | key | +| PrototypePollutionUtility/tests.js:302:14:302:16 | key | PrototypePollutionUtility/tests.js:304:29:304:31 | key | +| PrototypePollutionUtility/tests.js:302:14:302:16 | key | PrototypePollutionUtility/tests.js:304:29:304:31 | key | +| PrototypePollutionUtility/tests.js:302:14:302:16 | key | PrototypePollutionUtility/tests.js:304:29:304:31 | key | +| PrototypePollutionUtility/tests.js:302:14:302:16 | key | PrototypePollutionUtility/tests.js:306:38:306:40 | key | +| PrototypePollutionUtility/tests.js:302:14:302:16 | key | PrototypePollutionUtility/tests.js:306:38:306:40 | key | +| PrototypePollutionUtility/tests.js:302:14:302:16 | key | PrototypePollutionUtility/tests.js:306:38:306:40 | key | +| PrototypePollutionUtility/tests.js:302:14:302:16 | key | PrototypePollutionUtility/tests.js:306:38:306:40 | key | +| PrototypePollutionUtility/tests.js:302:14:302:16 | key | PrototypePollutionUtility/tests.js:308:21:308:23 | key | +| PrototypePollutionUtility/tests.js:302:14:302:16 | key | PrototypePollutionUtility/tests.js:308:21:308:23 | key | +| PrototypePollutionUtility/tests.js:302:14:302:16 | key | PrototypePollutionUtility/tests.js:308:21:308:23 | key | +| PrototypePollutionUtility/tests.js:302:14:302:16 | key | PrototypePollutionUtility/tests.js:308:21:308:23 | key | +| PrototypePollutionUtility/tests.js:302:14:302:16 | key | PrototypePollutionUtility/tests.js:308:21:308:23 | key | +| PrototypePollutionUtility/tests.js:302:14:302:16 | key | PrototypePollutionUtility/tests.js:308:21:308:23 | key | +| PrototypePollutionUtility/tests.js:302:14:302:16 | key | PrototypePollutionUtility/tests.js:308:21:308:23 | key | +| PrototypePollutionUtility/tests.js:304:17:304:32 | value | PrototypePollutionUtility/tests.js:306:44:306:48 | value | +| PrototypePollutionUtility/tests.js:304:17:304:32 | value | PrototypePollutionUtility/tests.js:306:44:306:48 | value | +| PrototypePollutionUtility/tests.js:304:17:304:32 | value | PrototypePollutionUtility/tests.js:308:28:308:32 | value | +| PrototypePollutionUtility/tests.js:304:17:304:32 | value | PrototypePollutionUtility/tests.js:308:28:308:32 | value | +| PrototypePollutionUtility/tests.js:304:17:304:32 | value | PrototypePollutionUtility/tests.js:308:28:308:32 | value | +| PrototypePollutionUtility/tests.js:304:17:304:32 | value | PrototypePollutionUtility/tests.js:308:28:308:32 | value | +| PrototypePollutionUtility/tests.js:304:17:304:32 | value | PrototypePollutionUtility/tests.js:308:28:308:32 | value | +| PrototypePollutionUtility/tests.js:304:17:304:32 | value | PrototypePollutionUtility/tests.js:308:28:308:32 | value | +| PrototypePollutionUtility/tests.js:304:25:304:27 | src | PrototypePollutionUtility/tests.js:304:25:304:32 | src[key] | +| PrototypePollutionUtility/tests.js:304:25:304:32 | src[key] | PrototypePollutionUtility/tests.js:304:17:304:32 | value | +| PrototypePollutionUtility/tests.js:304:25:304:32 | src[key] | PrototypePollutionUtility/tests.js:304:17:304:32 | value | +| PrototypePollutionUtility/tests.js:304:25:304:32 | src[key] | PrototypePollutionUtility/tests.js:304:17:304:32 | value | +| PrototypePollutionUtility/tests.js:304:25:304:32 | src[key] | PrototypePollutionUtility/tests.js:304:17:304:32 | value | +| PrototypePollutionUtility/tests.js:304:25:304:32 | src[key] | PrototypePollutionUtility/tests.js:304:17:304:32 | value | +| PrototypePollutionUtility/tests.js:304:29:304:31 | key | PrototypePollutionUtility/tests.js:304:25:304:32 | src[key] | +| PrototypePollutionUtility/tests.js:304:29:304:31 | key | PrototypePollutionUtility/tests.js:304:25:304:32 | src[key] | +| PrototypePollutionUtility/tests.js:306:34:306:36 | dst | PrototypePollutionUtility/tests.js:306:34:306:41 | dst[key] | +| PrototypePollutionUtility/tests.js:306:34:306:36 | dst | PrototypePollutionUtility/tests.js:306:34:306:41 | dst[key] | +| PrototypePollutionUtility/tests.js:306:34:306:41 | dst[key] | PrototypePollutionUtility/tests.js:301:27:301:29 | dst | +| PrototypePollutionUtility/tests.js:306:34:306:41 | dst[key] | PrototypePollutionUtility/tests.js:301:27:301:29 | dst | +| PrototypePollutionUtility/tests.js:306:34:306:41 | dst[key] | PrototypePollutionUtility/tests.js:301:27:301:29 | dst | +| PrototypePollutionUtility/tests.js:306:34:306:41 | dst[key] | PrototypePollutionUtility/tests.js:301:27:301:29 | dst | +| PrototypePollutionUtility/tests.js:306:38:306:40 | key | PrototypePollutionUtility/tests.js:306:34:306:41 | dst[key] | +| PrototypePollutionUtility/tests.js:306:38:306:40 | key | PrototypePollutionUtility/tests.js:306:34:306:41 | dst[key] | +| PrototypePollutionUtility/tests.js:306:44:306:48 | value | PrototypePollutionUtility/tests.js:301:32:301:34 | src | +| PrototypePollutionUtility/tests.js:306:44:306:48 | value | PrototypePollutionUtility/tests.js:301:32:301:34 | src | | examples/PrototypePollutionUtility.js:1:16:1:18 | dst | examples/PrototypePollutionUtility.js:5:19:5:21 | dst | | examples/PrototypePollutionUtility.js:1:16:1:18 | dst | examples/PrototypePollutionUtility.js:5:19:5:21 | dst | | examples/PrototypePollutionUtility.js:1:16:1:18 | dst | examples/PrototypePollutionUtility.js:7:13:7:15 | dst | @@ -1899,4 +1983,5 @@ edges | PrototypePollutionUtility/tests.js:233:5:233:13 | map[key1] | PrototypePollutionUtility/tests.js:238:14:238:16 | key | PrototypePollutionUtility/tests.js:233:5:233:13 | map[key1] | Properties are copied from $@ to $@ without guarding against prototype pollution. | PrototypePollutionUtility/tests.js:238:21:238:24 | data | data | PrototypePollutionUtility/tests.js:233:5:233:13 | map[key1] | this object | | PrototypePollutionUtility/tests.js:270:13:270:15 | dst | PrototypePollutionUtility/tests.js:265:19:265:26 | entry[0] | PrototypePollutionUtility/tests.js:270:13:270:15 | dst | Properties are copied from $@ to $@ without guarding against prototype pollution. | PrototypePollutionUtility/tests.js:264:20:264:22 | src | src | PrototypePollutionUtility/tests.js:270:13:270:15 | dst | dst | | PrototypePollutionUtility/tests.js:280:13:280:15 | dst | PrototypePollutionUtility/tests.js:276:34:276:36 | key | PrototypePollutionUtility/tests.js:280:13:280:15 | dst | Properties are copied from $@ to $@ without guarding against prototype pollution. | PrototypePollutionUtility/tests.js:276:21:276:23 | src | src | PrototypePollutionUtility/tests.js:280:13:280:15 | dst | dst | +| PrototypePollutionUtility/tests.js:308:17:308:19 | dst | PrototypePollutionUtility/tests.js:302:14:302:16 | key | PrototypePollutionUtility/tests.js:308:17:308:19 | dst | Properties are copied from $@ to $@ without guarding against prototype pollution. | PrototypePollutionUtility/tests.js:302:21:302:23 | src | src | PrototypePollutionUtility/tests.js:308:17:308:19 | dst | dst | | examples/PrototypePollutionUtility.js:7:13:7:15 | dst | examples/PrototypePollutionUtility.js:2:14:2:16 | key | examples/PrototypePollutionUtility.js:7:13:7:15 | dst | Properties are copied from $@ to $@ without guarding against prototype pollution. | examples/PrototypePollutionUtility.js:2:21:2:23 | src | src | examples/PrototypePollutionUtility.js:7:13:7:15 | dst | dst | diff --git a/javascript/ql/test/query-tests/Security/CWE-400/PrototypePollutionUtility/tests.js b/javascript/ql/test/query-tests/Security/CWE-400/PrototypePollutionUtility/tests.js index 58a65cf6cc9..2a74a9d9624 100644 --- a/javascript/ql/test/query-tests/Security/CWE-400/PrototypePollutionUtility/tests.js +++ b/javascript/ql/test/query-tests/Security/CWE-400/PrototypePollutionUtility/tests.js @@ -297,3 +297,16 @@ function copyWithPath(dst, src, path) { } return dst; } + +function typeofObjectTest(dst, src) { + for (let key in src) { + if (src.hasOwnProperty(key)) { + let value = src[key]; + if (dst[key] && typeof value === 'object') { + typeofObjectTest(dst[key], value); + } else { + dst[key] = value; // NOT OK + } + } + } +} From 7ac30e22897c07ca1739e046a315ee55ba3cb959 Mon Sep 17 00:00:00 2001 From: Asger Feldthaus Date: Fri, 10 Jan 2020 11:29:41 +0000 Subject: [PATCH 12/17] JS: Add test for rephinement nodes --- .../PrototypePollutionUtility.expected | 85 +++++++++++++++++++ .../PrototypePollutionUtility/tests.js | 14 +++ 2 files changed, 99 insertions(+) diff --git a/javascript/ql/test/query-tests/Security/CWE-400/PrototypePollutionUtility.expected b/javascript/ql/test/query-tests/Security/CWE-400/PrototypePollutionUtility.expected index 457ce94a300..1708058bb98 100644 --- a/javascript/ql/test/query-tests/Security/CWE-400/PrototypePollutionUtility.expected +++ b/javascript/ql/test/query-tests/Security/CWE-400/PrototypePollutionUtility.expected @@ -779,6 +779,42 @@ nodes | PrototypePollutionUtility/tests.js:308:28:308:32 | value | | PrototypePollutionUtility/tests.js:308:28:308:32 | value | | PrototypePollutionUtility/tests.js:308:28:308:32 | value | +| PrototypePollutionUtility/tests.js:314:31:314:33 | dst | +| PrototypePollutionUtility/tests.js:314:31:314:33 | dst | +| PrototypePollutionUtility/tests.js:314:36:314:38 | src | +| PrototypePollutionUtility/tests.js:315:14:315:16 | key | +| PrototypePollutionUtility/tests.js:315:14:315:16 | key | +| PrototypePollutionUtility/tests.js:315:14:315:16 | key | +| PrototypePollutionUtility/tests.js:318:17:318:32 | value | +| PrototypePollutionUtility/tests.js:318:17:318:32 | value | +| PrototypePollutionUtility/tests.js:318:17:318:32 | value | +| PrototypePollutionUtility/tests.js:318:25:318:27 | src | +| PrototypePollutionUtility/tests.js:318:25:318:32 | src[key] | +| PrototypePollutionUtility/tests.js:318:25:318:32 | src[key] | +| PrototypePollutionUtility/tests.js:318:25:318:32 | src[key] | +| PrototypePollutionUtility/tests.js:318:25:318:32 | src[key] | +| PrototypePollutionUtility/tests.js:318:29:318:31 | key | +| PrototypePollutionUtility/tests.js:318:29:318:31 | key | +| PrototypePollutionUtility/tests.js:320:38:320:40 | dst | +| PrototypePollutionUtility/tests.js:320:38:320:40 | dst | +| PrototypePollutionUtility/tests.js:320:38:320:45 | dst[key] | +| PrototypePollutionUtility/tests.js:320:38:320:45 | dst[key] | +| PrototypePollutionUtility/tests.js:320:38:320:45 | dst[key] | +| PrototypePollutionUtility/tests.js:320:38:320:45 | dst[key] | +| PrototypePollutionUtility/tests.js:320:42:320:44 | key | +| PrototypePollutionUtility/tests.js:320:42:320:44 | key | +| PrototypePollutionUtility/tests.js:320:48:320:52 | value | +| PrototypePollutionUtility/tests.js:320:48:320:52 | value | +| PrototypePollutionUtility/tests.js:322:17:322:19 | dst | +| PrototypePollutionUtility/tests.js:322:17:322:19 | dst | +| PrototypePollutionUtility/tests.js:322:17:322:19 | dst | +| PrototypePollutionUtility/tests.js:322:21:322:23 | key | +| PrototypePollutionUtility/tests.js:322:21:322:23 | key | +| PrototypePollutionUtility/tests.js:322:21:322:23 | key | +| PrototypePollutionUtility/tests.js:322:28:322:32 | value | +| PrototypePollutionUtility/tests.js:322:28:322:32 | value | +| PrototypePollutionUtility/tests.js:322:28:322:32 | value | +| PrototypePollutionUtility/tests.js:322:28:322:32 | value | | examples/PrototypePollutionUtility.js:1:16:1:18 | dst | | examples/PrototypePollutionUtility.js:1:16:1:18 | dst | | examples/PrototypePollutionUtility.js:1:21:1:23 | src | @@ -1866,6 +1902,54 @@ edges | PrototypePollutionUtility/tests.js:306:38:306:40 | key | PrototypePollutionUtility/tests.js:306:34:306:41 | dst[key] | | PrototypePollutionUtility/tests.js:306:44:306:48 | value | PrototypePollutionUtility/tests.js:301:32:301:34 | src | | PrototypePollutionUtility/tests.js:306:44:306:48 | value | PrototypePollutionUtility/tests.js:301:32:301:34 | src | +| PrototypePollutionUtility/tests.js:314:31:314:33 | dst | PrototypePollutionUtility/tests.js:320:38:320:40 | dst | +| PrototypePollutionUtility/tests.js:314:31:314:33 | dst | PrototypePollutionUtility/tests.js:320:38:320:40 | dst | +| PrototypePollutionUtility/tests.js:314:31:314:33 | dst | PrototypePollutionUtility/tests.js:322:17:322:19 | dst | +| PrototypePollutionUtility/tests.js:314:31:314:33 | dst | PrototypePollutionUtility/tests.js:322:17:322:19 | dst | +| PrototypePollutionUtility/tests.js:314:31:314:33 | dst | PrototypePollutionUtility/tests.js:322:17:322:19 | dst | +| PrototypePollutionUtility/tests.js:314:31:314:33 | dst | PrototypePollutionUtility/tests.js:322:17:322:19 | dst | +| PrototypePollutionUtility/tests.js:314:36:314:38 | src | PrototypePollutionUtility/tests.js:318:25:318:27 | src | +| PrototypePollutionUtility/tests.js:315:14:315:16 | key | PrototypePollutionUtility/tests.js:318:29:318:31 | key | +| PrototypePollutionUtility/tests.js:315:14:315:16 | key | PrototypePollutionUtility/tests.js:318:29:318:31 | key | +| PrototypePollutionUtility/tests.js:315:14:315:16 | key | PrototypePollutionUtility/tests.js:318:29:318:31 | key | +| PrototypePollutionUtility/tests.js:315:14:315:16 | key | PrototypePollutionUtility/tests.js:318:29:318:31 | key | +| PrototypePollutionUtility/tests.js:315:14:315:16 | key | PrototypePollutionUtility/tests.js:320:42:320:44 | key | +| PrototypePollutionUtility/tests.js:315:14:315:16 | key | PrototypePollutionUtility/tests.js:320:42:320:44 | key | +| PrototypePollutionUtility/tests.js:315:14:315:16 | key | PrototypePollutionUtility/tests.js:320:42:320:44 | key | +| PrototypePollutionUtility/tests.js:315:14:315:16 | key | PrototypePollutionUtility/tests.js:320:42:320:44 | key | +| PrototypePollutionUtility/tests.js:315:14:315:16 | key | PrototypePollutionUtility/tests.js:322:21:322:23 | key | +| PrototypePollutionUtility/tests.js:315:14:315:16 | key | PrototypePollutionUtility/tests.js:322:21:322:23 | key | +| PrototypePollutionUtility/tests.js:315:14:315:16 | key | PrototypePollutionUtility/tests.js:322:21:322:23 | key | +| PrototypePollutionUtility/tests.js:315:14:315:16 | key | PrototypePollutionUtility/tests.js:322:21:322:23 | key | +| PrototypePollutionUtility/tests.js:315:14:315:16 | key | PrototypePollutionUtility/tests.js:322:21:322:23 | key | +| PrototypePollutionUtility/tests.js:315:14:315:16 | key | PrototypePollutionUtility/tests.js:322:21:322:23 | key | +| PrototypePollutionUtility/tests.js:315:14:315:16 | key | PrototypePollutionUtility/tests.js:322:21:322:23 | key | +| PrototypePollutionUtility/tests.js:318:17:318:32 | value | PrototypePollutionUtility/tests.js:320:48:320:52 | value | +| PrototypePollutionUtility/tests.js:318:17:318:32 | value | PrototypePollutionUtility/tests.js:320:48:320:52 | value | +| PrototypePollutionUtility/tests.js:318:17:318:32 | value | PrototypePollutionUtility/tests.js:322:28:322:32 | value | +| PrototypePollutionUtility/tests.js:318:17:318:32 | value | PrototypePollutionUtility/tests.js:322:28:322:32 | value | +| PrototypePollutionUtility/tests.js:318:17:318:32 | value | PrototypePollutionUtility/tests.js:322:28:322:32 | value | +| PrototypePollutionUtility/tests.js:318:17:318:32 | value | PrototypePollutionUtility/tests.js:322:28:322:32 | value | +| PrototypePollutionUtility/tests.js:318:17:318:32 | value | PrototypePollutionUtility/tests.js:322:28:322:32 | value | +| PrototypePollutionUtility/tests.js:318:17:318:32 | value | PrototypePollutionUtility/tests.js:322:28:322:32 | value | +| PrototypePollutionUtility/tests.js:318:25:318:27 | src | PrototypePollutionUtility/tests.js:318:25:318:32 | src[key] | +| PrototypePollutionUtility/tests.js:318:25:318:32 | src[key] | PrototypePollutionUtility/tests.js:318:17:318:32 | value | +| PrototypePollutionUtility/tests.js:318:25:318:32 | src[key] | PrototypePollutionUtility/tests.js:318:17:318:32 | value | +| PrototypePollutionUtility/tests.js:318:25:318:32 | src[key] | PrototypePollutionUtility/tests.js:318:17:318:32 | value | +| PrototypePollutionUtility/tests.js:318:25:318:32 | src[key] | PrototypePollutionUtility/tests.js:318:17:318:32 | value | +| PrototypePollutionUtility/tests.js:318:25:318:32 | src[key] | PrototypePollutionUtility/tests.js:318:17:318:32 | value | +| PrototypePollutionUtility/tests.js:318:29:318:31 | key | PrototypePollutionUtility/tests.js:318:25:318:32 | src[key] | +| PrototypePollutionUtility/tests.js:318:29:318:31 | key | PrototypePollutionUtility/tests.js:318:25:318:32 | src[key] | +| PrototypePollutionUtility/tests.js:320:38:320:40 | dst | PrototypePollutionUtility/tests.js:320:38:320:45 | dst[key] | +| PrototypePollutionUtility/tests.js:320:38:320:40 | dst | PrototypePollutionUtility/tests.js:320:38:320:45 | dst[key] | +| PrototypePollutionUtility/tests.js:320:38:320:45 | dst[key] | PrototypePollutionUtility/tests.js:314:31:314:33 | dst | +| PrototypePollutionUtility/tests.js:320:38:320:45 | dst[key] | PrototypePollutionUtility/tests.js:314:31:314:33 | dst | +| PrototypePollutionUtility/tests.js:320:38:320:45 | dst[key] | PrototypePollutionUtility/tests.js:314:31:314:33 | dst | +| PrototypePollutionUtility/tests.js:320:38:320:45 | dst[key] | PrototypePollutionUtility/tests.js:314:31:314:33 | dst | +| PrototypePollutionUtility/tests.js:320:42:320:44 | key | PrototypePollutionUtility/tests.js:320:38:320:45 | dst[key] | +| PrototypePollutionUtility/tests.js:320:42:320:44 | key | PrototypePollutionUtility/tests.js:320:38:320:45 | dst[key] | +| PrototypePollutionUtility/tests.js:320:48:320:52 | value | PrototypePollutionUtility/tests.js:314:36:314:38 | src | +| PrototypePollutionUtility/tests.js:320:48:320:52 | value | PrototypePollutionUtility/tests.js:314:36:314:38 | src | | examples/PrototypePollutionUtility.js:1:16:1:18 | dst | examples/PrototypePollutionUtility.js:5:19:5:21 | dst | | examples/PrototypePollutionUtility.js:1:16:1:18 | dst | examples/PrototypePollutionUtility.js:5:19:5:21 | dst | | examples/PrototypePollutionUtility.js:1:16:1:18 | dst | examples/PrototypePollutionUtility.js:7:13:7:15 | dst | @@ -1984,4 +2068,5 @@ edges | PrototypePollutionUtility/tests.js:270:13:270:15 | dst | PrototypePollutionUtility/tests.js:265:19:265:26 | entry[0] | PrototypePollutionUtility/tests.js:270:13:270:15 | dst | Properties are copied from $@ to $@ without guarding against prototype pollution. | PrototypePollutionUtility/tests.js:264:20:264:22 | src | src | PrototypePollutionUtility/tests.js:270:13:270:15 | dst | dst | | PrototypePollutionUtility/tests.js:280:13:280:15 | dst | PrototypePollutionUtility/tests.js:276:34:276:36 | key | PrototypePollutionUtility/tests.js:280:13:280:15 | dst | Properties are copied from $@ to $@ without guarding against prototype pollution. | PrototypePollutionUtility/tests.js:276:21:276:23 | src | src | PrototypePollutionUtility/tests.js:280:13:280:15 | dst | dst | | PrototypePollutionUtility/tests.js:308:17:308:19 | dst | PrototypePollutionUtility/tests.js:302:14:302:16 | key | PrototypePollutionUtility/tests.js:308:17:308:19 | dst | Properties are copied from $@ to $@ without guarding against prototype pollution. | PrototypePollutionUtility/tests.js:302:21:302:23 | src | src | PrototypePollutionUtility/tests.js:308:17:308:19 | dst | dst | +| PrototypePollutionUtility/tests.js:322:17:322:19 | dst | PrototypePollutionUtility/tests.js:315:14:315:16 | key | PrototypePollutionUtility/tests.js:322:17:322:19 | dst | Properties are copied from $@ to $@ without guarding against prototype pollution. | PrototypePollutionUtility/tests.js:315:21:315:23 | src | src | PrototypePollutionUtility/tests.js:322:17:322:19 | dst | dst | | examples/PrototypePollutionUtility.js:7:13:7:15 | dst | examples/PrototypePollutionUtility.js:2:14:2:16 | key | examples/PrototypePollutionUtility.js:7:13:7:15 | dst | Properties are copied from $@ to $@ without guarding against prototype pollution. | examples/PrototypePollutionUtility.js:2:21:2:23 | src | src | examples/PrototypePollutionUtility.js:7:13:7:15 | dst | dst | diff --git a/javascript/ql/test/query-tests/Security/CWE-400/PrototypePollutionUtility/tests.js b/javascript/ql/test/query-tests/Security/CWE-400/PrototypePollutionUtility/tests.js index 2a74a9d9624..9c479c122d5 100644 --- a/javascript/ql/test/query-tests/Security/CWE-400/PrototypePollutionUtility/tests.js +++ b/javascript/ql/test/query-tests/Security/CWE-400/PrototypePollutionUtility/tests.js @@ -310,3 +310,17 @@ function typeofObjectTest(dst, src) { } } } + +function mergeRephinementNode(dst, src) { + for (let key in src) { + if (src.hasOwnProperty(key)) { + if (key === key && key === key) continue; // Create a phi-node of refinement nodes + let value = src[key]; + if (dst[key] && typeof value === 'object') { + mergeRephinementNode(dst[key], value); + } else { + dst[key] = value; // NOT OK + } + } + } +} From 9bd3c4a11c2d3407a2cb178c1eed26cf1dc20e1e Mon Sep 17 00:00:00 2001 From: Asger F Date: Tue, 26 Nov 2019 15:14:19 +0000 Subject: [PATCH 13/17] JS: Add sanitizer for "in" exprs --- .../CWE-400/PrototypePollutionUtility.ql | 20 +++++++++++ .../PrototypePollutionUtility.expected | 34 +++++++++++++++++++ .../PrototypePollutionUtility/tests.js | 16 +++++++++ 3 files changed, 70 insertions(+) diff --git a/javascript/ql/src/Security/CWE-400/PrototypePollutionUtility.ql b/javascript/ql/src/Security/CWE-400/PrototypePollutionUtility.ql index 09c2a7bd0b5..54827708447 100644 --- a/javascript/ql/src/Security/CWE-400/PrototypePollutionUtility.ql +++ b/javascript/ql/src/Security/CWE-400/PrototypePollutionUtility.ql @@ -286,6 +286,7 @@ class PropNameTracking extends DataFlow::Configuration { node instanceof BlacklistEqualityGuard or node instanceof WhitelistEqualityGuard or node instanceof HasOwnPropertyGuard or + node instanceof InExprGuard or node instanceof InstanceOfGuard or node instanceof TypeofGuard or node instanceof BlacklistInclusionGuard or @@ -353,6 +354,25 @@ class HasOwnPropertyGuard extends DataFlow::BarrierGuardNode, CallNode { } } +/** + * Sanitizer guard for `key in dst`. + * + * Since `"__proto__" in obj` and `"constructor" in obj` is true for most objects, + * this is seen as a sanitizer for `key` in the false outcome. + */ +class InExprGuard extends DataFlow::BarrierGuardNode, DataFlow::ValueNode { + override InExpr astNode; + + InExprGuard() { + // Exclude tests of form `key in src` for the same reason as in HasOwnPropertyGuard + not arePropertiesEnumerated(astNode.getRightOperand().flow().getALocalSource()) + } + + override predicate blocks(boolean outcome, Expr e) { + e = astNode.getLeftOperand() and outcome = false + } +} + /** * Sanitizer guard for `instanceof` expressions. * diff --git a/javascript/ql/test/query-tests/Security/CWE-400/PrototypePollutionUtility.expected b/javascript/ql/test/query-tests/Security/CWE-400/PrototypePollutionUtility.expected index 1708058bb98..1f22243aa01 100644 --- a/javascript/ql/test/query-tests/Security/CWE-400/PrototypePollutionUtility.expected +++ b/javascript/ql/test/query-tests/Security/CWE-400/PrototypePollutionUtility.expected @@ -815,6 +815,23 @@ nodes | PrototypePollutionUtility/tests.js:322:28:322:32 | value | | PrototypePollutionUtility/tests.js:322:28:322:32 | value | | PrototypePollutionUtility/tests.js:322:28:322:32 | value | +| PrototypePollutionUtility/tests.js:328:30:328:32 | src | +| PrototypePollutionUtility/tests.js:328:30:328:32 | src | +| PrototypePollutionUtility/tests.js:336:42:336:44 | src | +| PrototypePollutionUtility/tests.js:336:42:336:44 | src | +| PrototypePollutionUtility/tests.js:336:42:336:49 | src[key] | +| PrototypePollutionUtility/tests.js:336:42:336:49 | src[key] | +| PrototypePollutionUtility/tests.js:336:42:336:49 | src[key] | +| PrototypePollutionUtility/tests.js:336:42:336:49 | src[key] | +| PrototypePollutionUtility/tests.js:336:42:336:49 | src[key] | +| PrototypePollutionUtility/tests.js:338:28:338:30 | src | +| PrototypePollutionUtility/tests.js:338:28:338:30 | src | +| PrototypePollutionUtility/tests.js:338:28:338:35 | src[key] | +| PrototypePollutionUtility/tests.js:338:28:338:35 | src[key] | +| PrototypePollutionUtility/tests.js:338:28:338:35 | src[key] | +| PrototypePollutionUtility/tests.js:338:28:338:35 | src[key] | +| PrototypePollutionUtility/tests.js:338:28:338:35 | src[key] | +| PrototypePollutionUtility/tests.js:338:28:338:35 | src[key] | | examples/PrototypePollutionUtility.js:1:16:1:18 | dst | | examples/PrototypePollutionUtility.js:1:16:1:18 | dst | | examples/PrototypePollutionUtility.js:1:21:1:23 | src | @@ -1950,6 +1967,23 @@ edges | PrototypePollutionUtility/tests.js:320:42:320:44 | key | PrototypePollutionUtility/tests.js:320:38:320:45 | dst[key] | | PrototypePollutionUtility/tests.js:320:48:320:52 | value | PrototypePollutionUtility/tests.js:314:36:314:38 | src | | PrototypePollutionUtility/tests.js:320:48:320:52 | value | PrototypePollutionUtility/tests.js:314:36:314:38 | src | +| PrototypePollutionUtility/tests.js:328:30:328:32 | src | PrototypePollutionUtility/tests.js:336:42:336:44 | src | +| PrototypePollutionUtility/tests.js:328:30:328:32 | src | PrototypePollutionUtility/tests.js:336:42:336:44 | src | +| PrototypePollutionUtility/tests.js:328:30:328:32 | src | PrototypePollutionUtility/tests.js:338:28:338:30 | src | +| PrototypePollutionUtility/tests.js:328:30:328:32 | src | PrototypePollutionUtility/tests.js:338:28:338:30 | src | +| PrototypePollutionUtility/tests.js:336:42:336:44 | src | PrototypePollutionUtility/tests.js:336:42:336:49 | src[key] | +| PrototypePollutionUtility/tests.js:336:42:336:44 | src | PrototypePollutionUtility/tests.js:336:42:336:49 | src[key] | +| PrototypePollutionUtility/tests.js:336:42:336:49 | src[key] | PrototypePollutionUtility/tests.js:328:30:328:32 | src | +| PrototypePollutionUtility/tests.js:336:42:336:49 | src[key] | PrototypePollutionUtility/tests.js:328:30:328:32 | src | +| PrototypePollutionUtility/tests.js:336:42:336:49 | src[key] | PrototypePollutionUtility/tests.js:328:30:328:32 | src | +| PrototypePollutionUtility/tests.js:336:42:336:49 | src[key] | PrototypePollutionUtility/tests.js:328:30:328:32 | src | +| PrototypePollutionUtility/tests.js:336:42:336:49 | src[key] | PrototypePollutionUtility/tests.js:328:30:328:32 | src | +| PrototypePollutionUtility/tests.js:336:42:336:49 | src[key] | PrototypePollutionUtility/tests.js:328:30:328:32 | src | +| PrototypePollutionUtility/tests.js:338:28:338:30 | src | PrototypePollutionUtility/tests.js:338:28:338:35 | src[key] | +| PrototypePollutionUtility/tests.js:338:28:338:30 | src | PrototypePollutionUtility/tests.js:338:28:338:35 | src[key] | +| PrototypePollutionUtility/tests.js:338:28:338:30 | src | PrototypePollutionUtility/tests.js:338:28:338:35 | src[key] | +| PrototypePollutionUtility/tests.js:338:28:338:30 | src | PrototypePollutionUtility/tests.js:338:28:338:35 | src[key] | +| PrototypePollutionUtility/tests.js:338:28:338:35 | src[key] | PrototypePollutionUtility/tests.js:338:28:338:35 | src[key] | | examples/PrototypePollutionUtility.js:1:16:1:18 | dst | examples/PrototypePollutionUtility.js:5:19:5:21 | dst | | examples/PrototypePollutionUtility.js:1:16:1:18 | dst | examples/PrototypePollutionUtility.js:5:19:5:21 | dst | | examples/PrototypePollutionUtility.js:1:16:1:18 | dst | examples/PrototypePollutionUtility.js:7:13:7:15 | dst | diff --git a/javascript/ql/test/query-tests/Security/CWE-400/PrototypePollutionUtility/tests.js b/javascript/ql/test/query-tests/Security/CWE-400/PrototypePollutionUtility/tests.js index 9c479c122d5..23d0b1b7a4c 100644 --- a/javascript/ql/test/query-tests/Security/CWE-400/PrototypePollutionUtility/tests.js +++ b/javascript/ql/test/query-tests/Security/CWE-400/PrototypePollutionUtility/tests.js @@ -324,3 +324,19 @@ function mergeRephinementNode(dst, src) { } } } + +function mergeSelective(dst, src) { + for (let key in src) { + if (src.hasOwnProperty(key)) { + // Only 'prefs' is merged recursively + if (key in dst && key !== 'prefs') { + continue; + } + if (dst[key]) { + mergeSelective(dst[key], src[key]); + } else { + dst[key] = src[key]; // OK + } + } + } +} From 2c05ee8ab88b7e43d0a06edb3650d40e66991b6b Mon Sep 17 00:00:00 2001 From: Asger F Date: Tue, 26 Nov 2019 15:34:38 +0000 Subject: [PATCH 14/17] JS: Add regression test --- .../PrototypePollutionUtility.expected | 33 +++++++++++++++++++ .../PrototypePollutionUtility/tests.js | 20 +++++++++++ 2 files changed, 53 insertions(+) diff --git a/javascript/ql/test/query-tests/Security/CWE-400/PrototypePollutionUtility.expected b/javascript/ql/test/query-tests/Security/CWE-400/PrototypePollutionUtility.expected index 1f22243aa01..fe8fb9351d0 100644 --- a/javascript/ql/test/query-tests/Security/CWE-400/PrototypePollutionUtility.expected +++ b/javascript/ql/test/query-tests/Security/CWE-400/PrototypePollutionUtility.expected @@ -832,6 +832,22 @@ nodes | PrototypePollutionUtility/tests.js:338:28:338:35 | src[key] | | PrototypePollutionUtility/tests.js:338:28:338:35 | src[key] | | PrototypePollutionUtility/tests.js:338:28:338:35 | src[key] | +| PrototypePollutionUtility/tests.js:348:40:348:45 | source | +| PrototypePollutionUtility/tests.js:350:37:350:39 | key | +| PrototypePollutionUtility/tests.js:350:37:350:39 | key | +| PrototypePollutionUtility/tests.js:355:66:355:71 | source | +| PrototypePollutionUtility/tests.js:355:66:355:76 | source[key] | +| PrototypePollutionUtility/tests.js:355:66:355:76 | source[key] | +| PrototypePollutionUtility/tests.js:355:66:355:76 | source[key] | +| PrototypePollutionUtility/tests.js:357:24:357:26 | key | +| PrototypePollutionUtility/tests.js:357:24:357:26 | key | +| PrototypePollutionUtility/tests.js:357:31:357:36 | source | +| PrototypePollutionUtility/tests.js:357:31:357:41 | source[key] | +| PrototypePollutionUtility/tests.js:357:31:357:41 | source[key] | +| PrototypePollutionUtility/tests.js:357:31:357:41 | source[key] | +| PrototypePollutionUtility/tests.js:357:31:357:41 | source[key] | +| PrototypePollutionUtility/tests.js:357:31:357:41 | source[key] | +| PrototypePollutionUtility/tests.js:357:38:357:40 | key | | examples/PrototypePollutionUtility.js:1:16:1:18 | dst | | examples/PrototypePollutionUtility.js:1:16:1:18 | dst | | examples/PrototypePollutionUtility.js:1:21:1:23 | src | @@ -1984,6 +2000,23 @@ edges | PrototypePollutionUtility/tests.js:338:28:338:30 | src | PrototypePollutionUtility/tests.js:338:28:338:35 | src[key] | | PrototypePollutionUtility/tests.js:338:28:338:30 | src | PrototypePollutionUtility/tests.js:338:28:338:35 | src[key] | | PrototypePollutionUtility/tests.js:338:28:338:35 | src[key] | PrototypePollutionUtility/tests.js:338:28:338:35 | src[key] | +| PrototypePollutionUtility/tests.js:348:40:348:45 | source | PrototypePollutionUtility/tests.js:355:66:355:71 | source | +| PrototypePollutionUtility/tests.js:348:40:348:45 | source | PrototypePollutionUtility/tests.js:357:31:357:36 | source | +| PrototypePollutionUtility/tests.js:350:37:350:39 | key | PrototypePollutionUtility/tests.js:357:24:357:26 | key | +| PrototypePollutionUtility/tests.js:350:37:350:39 | key | PrototypePollutionUtility/tests.js:357:24:357:26 | key | +| PrototypePollutionUtility/tests.js:350:37:350:39 | key | PrototypePollutionUtility/tests.js:357:24:357:26 | key | +| PrototypePollutionUtility/tests.js:350:37:350:39 | key | PrototypePollutionUtility/tests.js:357:24:357:26 | key | +| PrototypePollutionUtility/tests.js:350:37:350:39 | key | PrototypePollutionUtility/tests.js:357:38:357:40 | key | +| PrototypePollutionUtility/tests.js:350:37:350:39 | key | PrototypePollutionUtility/tests.js:357:38:357:40 | key | +| PrototypePollutionUtility/tests.js:355:66:355:71 | source | PrototypePollutionUtility/tests.js:355:66:355:76 | source[key] | +| PrototypePollutionUtility/tests.js:355:66:355:76 | source[key] | PrototypePollutionUtility/tests.js:348:40:348:45 | source | +| PrototypePollutionUtility/tests.js:355:66:355:76 | source[key] | PrototypePollutionUtility/tests.js:348:40:348:45 | source | +| PrototypePollutionUtility/tests.js:355:66:355:76 | source[key] | PrototypePollutionUtility/tests.js:348:40:348:45 | source | +| PrototypePollutionUtility/tests.js:357:31:357:36 | source | PrototypePollutionUtility/tests.js:357:31:357:41 | source[key] | +| PrototypePollutionUtility/tests.js:357:31:357:36 | source | PrototypePollutionUtility/tests.js:357:31:357:41 | source[key] | +| PrototypePollutionUtility/tests.js:357:31:357:41 | source[key] | PrototypePollutionUtility/tests.js:357:31:357:41 | source[key] | +| PrototypePollutionUtility/tests.js:357:38:357:40 | key | PrototypePollutionUtility/tests.js:357:31:357:41 | source[key] | +| PrototypePollutionUtility/tests.js:357:38:357:40 | key | PrototypePollutionUtility/tests.js:357:31:357:41 | source[key] | | examples/PrototypePollutionUtility.js:1:16:1:18 | dst | examples/PrototypePollutionUtility.js:5:19:5:21 | dst | | examples/PrototypePollutionUtility.js:1:16:1:18 | dst | examples/PrototypePollutionUtility.js:5:19:5:21 | dst | | examples/PrototypePollutionUtility.js:1:16:1:18 | dst | examples/PrototypePollutionUtility.js:7:13:7:15 | dst | diff --git a/javascript/ql/test/query-tests/Security/CWE-400/PrototypePollutionUtility/tests.js b/javascript/ql/test/query-tests/Security/CWE-400/PrototypePollutionUtility/tests.js index 23d0b1b7a4c..57f080770d9 100644 --- a/javascript/ql/test/query-tests/Security/CWE-400/PrototypePollutionUtility/tests.js +++ b/javascript/ql/test/query-tests/Security/CWE-400/PrototypePollutionUtility/tests.js @@ -340,3 +340,23 @@ function mergeSelective(dst, src) { } } } + +function isNonArrayObject(item) { + return item && typeof item === 'object' && !Array.isArray(item); +} + +function mergePlainObjectsOnly(target, source) { + if (isNonArrayObject(target) && isNonArrayObject(source)) { + Object.keys(source).forEach(key => { + if (key === '__proto__') { + return; + } + if (isNonArrayObject(source[key]) && key in target) { + target[key] = mergePlainObjectsOnly(target[key], source[key], options); + } else { + target[key] = source[key]; // OK + } + }); + } + return target; +} From d76859b7df0a0bb19b0813dfb15ef9312e359e8c Mon Sep 17 00:00:00 2001 From: Asger Feldthaus Date: Tue, 14 Jan 2020 10:30:28 +0000 Subject: [PATCH 15/17] JS: Address review comments --- .../CWE-400/PrototypePollutionUtility.qhelp | 4 ++-- .../CWE-400/PrototypePollutionUtility.ql | 8 +++++++- .../semmle/javascript/GlobalAccessPaths.qll | 18 ++++++++++++++++++ 3 files changed, 27 insertions(+), 3 deletions(-) diff --git a/javascript/ql/src/Security/CWE-400/PrototypePollutionUtility.qhelp b/javascript/ql/src/Security/CWE-400/PrototypePollutionUtility.qhelp index 387d438922b..b6a91350ccb 100644 --- a/javascript/ql/src/Security/CWE-400/PrototypePollutionUtility.qhelp +++ b/javascript/ql/src/Security/CWE-400/PrototypePollutionUtility.qhelp @@ -41,8 +41,8 @@

    - However, if src is the object {"__proto__": {"xxx": true}}, - it will inject the property xxx: true in in Object.prototype. + However, if src is the object {"__proto__": {"isAdmin": true}}, + it will inject the property isAdmin: true in in Object.prototype.

    diff --git a/javascript/ql/src/Security/CWE-400/PrototypePollutionUtility.ql b/javascript/ql/src/Security/CWE-400/PrototypePollutionUtility.ql index 54827708447..2c2d816b4eb 100644 --- a/javascript/ql/src/Security/CWE-400/PrototypePollutionUtility.ql +++ b/javascript/ql/src/Security/CWE-400/PrototypePollutionUtility.ql @@ -226,7 +226,13 @@ class UnsafePropLabel extends FlowLabel { * * Note that in the above example, the flow from `key` to the base of the write (`dst`) * requires stepping through the recursive call. - * Such a path would be absent for a shallow copying operation. + * Such a path would be absent for a shallow copying operation, where the `dst` object + * isn't derived from a property of the source object. + * + * This configuration can't enforce that all three paths must end at the same + * dynamic property write, so we treat the paths independently here and check + * for coinciding paths afterwards. This means this configuration can't be used as + * a standalone configuration like in most path queries. */ class PropNameTracking extends DataFlow::Configuration { PropNameTracking() { this = "PropNameTracking" } diff --git a/javascript/ql/src/semmle/javascript/GlobalAccessPaths.qll b/javascript/ql/src/semmle/javascript/GlobalAccessPaths.qll index 77defbed7d1..35755fb6c8b 100644 --- a/javascript/ql/src/semmle/javascript/GlobalAccessPaths.qll +++ b/javascript/ql/src/semmle/javascript/GlobalAccessPaths.qll @@ -35,6 +35,24 @@ module GlobalAccessPath { } } +/** + * Provides predicates for associating access paths with data flow nodes. + * + * For example, `AccessPath.getAReferenceTo(x)` can be used to obtain the global access path + * that `x` refers to, as in the following sample: + * ``` + * function f() { + * let v = foo.bar; // reference to 'foo.bar' + * v.baz; // reference to 'foo.bar.baz' + * } + * + * (function(ns) { + * ns.x; // reference to 'NS.x' + * })(NS = NS || {}); + * ``` + * + * A pseudo-property named `[number]` is sometimes used to represent array indices within an access path. + */ module AccessPath { /** * A source node that can be the root of an access path. From 2245882441d37dc95d70cbf5a893715b7f3e7e8c Mon Sep 17 00:00:00 2001 From: Asger Feldthaus Date: Tue, 14 Jan 2020 10:49:48 +0000 Subject: [PATCH 16/17] JS: Add change note and fix cwe tags --- change-notes/1.24/analysis-javascript.md | 1 + .../ql/src/Security/CWE-400/PrototypePollutionUtility.ql | 4 ++-- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/change-notes/1.24/analysis-javascript.md b/change-notes/1.24/analysis-javascript.md index 7f908a2471d..9dbe956dcba 100644 --- a/change-notes/1.24/analysis-javascript.md +++ b/change-notes/1.24/analysis-javascript.md @@ -21,6 +21,7 @@ | Cross-site scripting through exception (`js/xss-through-exception`) | security, external/cwe/cwe-079, external/cwe/cwe-116 | Highlights potential XSS vulnerabilities where an exception is written to the DOM. Results are not shown on LGTM by default. | | Regular expression always matches (`js/regex/always-matches`) | correctness, regular-expressions | Highlights regular expression checks that trivially succeed by matching an empty substring. Results are shown on LGTM by default. | | Missing await (`js/missing-await`) | correctness | Highlights expressions that operate directly on a promise object in a nonsensical way, instead of awaiting its result. Results are shown on LGTM by default. | +| Prototype pollution in utility function (`js/prototype-pollution-utility`) | security, external/cwe/cwe-400, external/cwe/cwe-471 | Highlights recursive copying operations that are susceptible to prototype pollution. Results are shown on LGTM by default. | ## Changes to existing queries diff --git a/javascript/ql/src/Security/CWE-400/PrototypePollutionUtility.ql b/javascript/ql/src/Security/CWE-400/PrototypePollutionUtility.ql index 2c2d816b4eb..9e1e38662fc 100644 --- a/javascript/ql/src/Security/CWE-400/PrototypePollutionUtility.ql +++ b/javascript/ql/src/Security/CWE-400/PrototypePollutionUtility.ql @@ -7,8 +7,8 @@ * @precision high * @id js/prototype-pollution-utility * @tags security - * external/cwe/cwe-079 - * external/cwe/cwe-116 + * external/cwe/cwe-400 + * external/cwe/cwe-471 */ import javascript From 7a1d068f1ce6183682b6cc1e48afc7a4150c1e35 Mon Sep 17 00:00:00 2001 From: Asger F Date: Thu, 16 Jan 2020 09:47:18 +0000 Subject: [PATCH 17/17] Update javascript/ql/src/Security/CWE-400/PrototypePollutionUtility.qhelp Co-Authored-By: mc <42146119+mchammer01@users.noreply.github.com> --- .../ql/src/Security/CWE-400/PrototypePollutionUtility.qhelp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/javascript/ql/src/Security/CWE-400/PrototypePollutionUtility.qhelp b/javascript/ql/src/Security/CWE-400/PrototypePollutionUtility.qhelp index b6a91350ccb..49a77a7445d 100644 --- a/javascript/ql/src/Security/CWE-400/PrototypePollutionUtility.qhelp +++ b/javascript/ql/src/Security/CWE-400/PrototypePollutionUtility.qhelp @@ -42,7 +42,7 @@

    However, if src is the object {"__proto__": {"isAdmin": true}}, - it will inject the property isAdmin: true in in Object.prototype. + it will inject the property isAdmin: true in Object.prototype.