From f1f45927b121fb858c5bfc3c8078c1915ae9731b Mon Sep 17 00:00:00 2001 From: Asger F Date: Wed, 4 Oct 2023 21:36:31 +0200 Subject: [PATCH] JS: Port PrototypePollutingAssignment --- ...otypePollutingAssignmentCustomizations.qll | 32 +- .../PrototypePollutingAssignmentQuery.qll | 138 ++++-- .../CWE-915/PrototypePollutingAssignment.ql | 9 +- .../Consistency.expected | 1 + .../Consistency.ql | 11 +- .../PrototypePollutingAssignment.expected | 402 ++++++------------ 6 files changed, 286 insertions(+), 307 deletions(-) diff --git a/javascript/ql/lib/semmle/javascript/security/dataflow/PrototypePollutingAssignmentCustomizations.qll b/javascript/ql/lib/semmle/javascript/security/dataflow/PrototypePollutingAssignmentCustomizations.qll index 656c7bb3849..4b0b954066a 100644 --- a/javascript/ql/lib/semmle/javascript/security/dataflow/PrototypePollutingAssignmentCustomizations.qll +++ b/javascript/ql/lib/semmle/javascript/security/dataflow/PrototypePollutingAssignmentCustomizations.qll @@ -38,6 +38,30 @@ module PrototypePollutingAssignment { */ abstract class Sanitizer extends DataFlow::Node { } + /** + * A barrier guard for prototype-polluting assignments. + */ + abstract class BarrierGuard extends DataFlow::Node { + /** + * Holds if this node acts as a barrier for data flow, blocking further flow from `e` if `this` evaluates to `outcome`. + */ + predicate blocksExpr(boolean outcome, Expr e) { none() } + + /** + * Holds if this node acts as a barrier for `label`, blocking further flow from `e` if `this` evaluates to `outcome`. + */ + predicate blocksExpr(boolean outcome, Expr e, DataFlow::FlowLabel label) { none() } + } + + /** A subclass of `BarrierGuard` that is used for backward compatibility with the old data flow library. */ + abstract class BarrierGuardLegacy extends BarrierGuard, TaintTracking::SanitizerGuardNode { + override predicate sanitizes(boolean outcome, Expr e) { this.blocksExpr(outcome, e) } + + override predicate sanitizes(boolean outcome, Expr e, DataFlow::FlowLabel label) { + this.blocksExpr(outcome, e, label) + } + } + /** A flow label representing the `Object.prototype` value. */ abstract class ObjectPrototype extends DataFlow::FlowLabel { ObjectPrototype() { this = "Object.prototype" } @@ -46,7 +70,9 @@ module PrototypePollutingAssignment { /** The base of an assignment or extend call, as a sink for `Object.prototype` references. */ private class DefaultSink extends Sink { DefaultSink() { - this = any(DataFlow::PropWrite write).getBase() + // Avoid using PropWrite here as we only want assignments that can mutate a pre-existing object, + // so not object literals or array literals. + this = any(AssignExpr assign).getTarget().(PropAccess).getBase().flow() or this = any(ExtendCall c).getDestinationOperand() or @@ -67,7 +93,9 @@ module PrototypePollutingAssignment { * A parameter of an exported function, seen as a source prototype-polluting assignment. */ class ExternalInputSource extends Source { - ExternalInputSource() { this = Exports::getALibraryInputParameter() } + ExternalInputSource() { + this = Exports::getALibraryInputParameter() and not this instanceof RemoteFlowSource + } override string describe() { result = "library input" } } diff --git a/javascript/ql/lib/semmle/javascript/security/dataflow/PrototypePollutingAssignmentQuery.qll b/javascript/ql/lib/semmle/javascript/security/dataflow/PrototypePollutingAssignmentQuery.qll index 0ba2f26b24c..ca61ebf284d 100644 --- a/javascript/ql/lib/semmle/javascript/security/dataflow/PrototypePollutingAssignmentQuery.qll +++ b/javascript/ql/lib/semmle/javascript/security/dataflow/PrototypePollutingAssignmentQuery.qll @@ -19,16 +19,18 @@ private class ConcreteObjectPrototype extends ObjectPrototype { } /** A taint-tracking configuration for reasoning about prototype-polluting assignments. */ -class Configuration extends TaintTracking::Configuration { - Configuration() { this = "PrototypePollutingAssignment" } +module PrototypePollutingAssignmentConfig implements DataFlow::StateConfigSig { + class FlowState = DataFlow::FlowLabel; - override predicate isSource(DataFlow::Node node) { node instanceof Source } + predicate isSource(DataFlow::Node node, DataFlow::FlowLabel label) { + node instanceof Source and label.isTaint() + } - override predicate isSink(DataFlow::Node node, DataFlow::FlowLabel lbl) { + predicate isSink(DataFlow::Node node, DataFlow::FlowLabel lbl) { node.(Sink).getAFlowLabel() = lbl } - override predicate isSanitizer(DataFlow::Node node) { + predicate isBarrier(DataFlow::Node node) { node instanceof Sanitizer or // Concatenating with a string will in practice prevent the string `__proto__` from arising. @@ -53,17 +55,24 @@ class Configuration extends TaintTracking::Configuration { not replace.getRawReplacement().getStringValue() = "" ) ) + or + node = DataFlow::MakeBarrierGuard::getABarrierNode() } - override predicate isSanitizerOut(DataFlow::Node node, DataFlow::FlowLabel lbl) { + predicate isBarrierOut(DataFlow::Node node, DataFlow::FlowLabel lbl) { // Suppress the value-preserving step src -> dst in `extend(dst, src)`. This is modeled as a value-preserving // step because it preserves all properties, but the destination is not actually Object.prototype. node = any(ExtendCall call).getASourceOperand() and lbl instanceof ObjectPrototype } - override predicate isAdditionalFlowStep( - DataFlow::Node pred, DataFlow::Node succ, DataFlow::FlowLabel inlbl, DataFlow::FlowLabel outlbl + predicate isBarrierIn(DataFlow::Node node, DataFlow::FlowLabel lbl) { + // FIXME: This should only be an in-barrier for the corresponding flow state, but flow-state specific in-barriers are not supported right now. + isSource(node, lbl) + } + + predicate isAdditionalFlowStep( + DataFlow::Node pred, DataFlow::FlowLabel inlbl, DataFlow::Node succ, DataFlow::FlowLabel outlbl ) { // Step from x -> obj[x] while switching to the ObjectPrototype label // (If `x` can have the value `__proto__` then the result can be Object.prototype) @@ -91,7 +100,80 @@ class Configuration extends TaintTracking::Configuration { outlbl instanceof ObjectPrototype ) or - DataFlow::localFieldStep(pred, succ) and inlbl = outlbl + // TODO: local field step becomes a jump step, resulting in FPs (closure-lib) + // TODO: localFieldStep is too expensive with dataflow2 + // DataFlow::localFieldStep(pred, succ) + none() + or + inlbl.isTaint() and + TaintTracking::defaultTaintStep(pred, succ) and + inlbl = outlbl + } + + DataFlow::FlowFeature getAFeature() { result instanceof DataFlow::FeatureHasSourceCallContext } + + predicate isBarrier(DataFlow::Node node, DataFlow::FlowLabel lbl) { + lbl.isTaint() and + TaintTracking::defaultSanitizer(node) + or + // Don't propagate into the receiver, as the method lookups will generally fail on Object.prototype. + node instanceof DataFlow::ThisNode and + lbl instanceof ObjectPrototype + or + node = DataFlow::MakeLabeledBarrierGuard::getABarrierNode(lbl) + } +} + +/** Taint-tracking for reasoning about prototype-polluting assignments. */ +module PrototypePollutingAssignmentFlow = + DataFlow::GlobalWithState; + +/** + * Holds if the given `source, sink` pair should not be reported, as we don't have enough + * confidence in the alert given that source is a library input. + */ +bindingset[source, sink] +predicate isIgnoredLibraryFlow(ExternalInputSource source, Sink sink) { + exists(source) and + // filter away paths that start with library inputs and end with a write to a fixed property. + exists(DataFlow::PropWrite write | sink = write.getBase() | + // fixed property name + exists(write.getPropertyName()) + or + // non-string property name (likely number) + exists(Expr prop | prop = write.getPropertyNameExpr() | + not prop.analyze().getAType() = TTString() + ) + ) +} + +/** + * DEPRECATED. Use the `PrototypePollutingAssignmentFlow` module instead. + */ +deprecated class Configuration extends TaintTracking::Configuration { + Configuration() { this = "PrototypePollutingAssignment" } + + override predicate isSource(DataFlow::Node node) { node instanceof Source } + + override predicate isSink(DataFlow::Node node, DataFlow::FlowLabel lbl) { + node.(Sink).getAFlowLabel() = lbl + } + + override predicate isSanitizer(DataFlow::Node node) { + PrototypePollutingAssignmentConfig::isBarrier(node) + } + + override predicate isSanitizerOut(DataFlow::Node node, DataFlow::FlowLabel lbl) { + // Suppress the value-preserving step src -> dst in `extend(dst, src)`. This is modeled as a value-preserving + // step because it preserves all properties, but the destination is not actually Object.prototype. + node = any(ExtendCall call).getASourceOperand() and + lbl instanceof ObjectPrototype + } + + override predicate isAdditionalFlowStep( + DataFlow::Node pred, DataFlow::Node succ, DataFlow::FlowLabel inlbl, DataFlow::FlowLabel outlbl + ) { + PrototypePollutingAssignmentConfig::isAdditionalFlowStep(pred, inlbl, succ, outlbl) } override predicate hasFlowPath(DataFlow::SourcePathNode source, DataFlow::SinkPathNode sink) { @@ -174,9 +256,7 @@ private predicate isPropertyPresentOnObjectPrototype(string prop) { } /** A check of form `e.prop` where `prop` is not present on `Object.prototype`. */ -private class PropertyPresenceCheck extends TaintTracking::LabeledSanitizerGuardNode, - DataFlow::ValueNode -{ +private class PropertyPresenceCheck extends BarrierGuardLegacy, DataFlow::ValueNode { override PropAccess astNode; PropertyPresenceCheck() { @@ -184,7 +264,7 @@ private class PropertyPresenceCheck extends TaintTracking::LabeledSanitizerGuard not isPropertyPresentOnObjectPrototype(astNode.getPropertyName()) } - override predicate sanitizes(boolean outcome, Expr e, DataFlow::FlowLabel label) { + override predicate blocksExpr(boolean outcome, Expr e, DataFlow::FlowLabel label) { e = astNode.getBase() and outcome = true and label instanceof ObjectPrototype @@ -192,14 +272,14 @@ private class PropertyPresenceCheck extends TaintTracking::LabeledSanitizerGuard } /** A check of form `"prop" in e` where `prop` is not present on `Object.prototype`. */ -private class InExprCheck extends TaintTracking::LabeledSanitizerGuardNode, DataFlow::ValueNode { +private class InExprCheck extends BarrierGuardLegacy, DataFlow::ValueNode { override InExpr astNode; InExprCheck() { not isPropertyPresentOnObjectPrototype(astNode.getLeftOperand().getStringValue()) } - override predicate sanitizes(boolean outcome, Expr e, DataFlow::FlowLabel label) { + override predicate blocksExpr(boolean outcome, Expr e, DataFlow::FlowLabel label) { e = astNode.getRightOperand() and outcome = true and label instanceof ObjectPrototype @@ -207,10 +287,10 @@ private class InExprCheck extends TaintTracking::LabeledSanitizerGuardNode, Data } /** A check of form `e instanceof X`, which is always false for `Object.prototype`. */ -private class InstanceofCheck extends TaintTracking::LabeledSanitizerGuardNode, DataFlow::ValueNode { +private class InstanceofCheck extends BarrierGuardLegacy, DataFlow::ValueNode { override InstanceofExpr astNode; - override predicate sanitizes(boolean outcome, Expr e, DataFlow::FlowLabel label) { + override predicate blocksExpr(boolean outcome, Expr e, DataFlow::FlowLabel label) { e = astNode.getLeftOperand() and outcome = true and label instanceof ObjectPrototype @@ -218,7 +298,7 @@ private class InstanceofCheck extends TaintTracking::LabeledSanitizerGuardNode, } /** A check of form `typeof e === "string"`. */ -private class TypeofCheck extends TaintTracking::LabeledSanitizerGuardNode, DataFlow::ValueNode { +private class TypeofCheck extends BarrierGuardLegacy, DataFlow::ValueNode { override EqualityTest astNode; Expr operand; boolean polarity; @@ -231,7 +311,7 @@ private class TypeofCheck extends TaintTracking::LabeledSanitizerGuardNode, Data ) } - override predicate sanitizes(boolean outcome, Expr e, DataFlow::FlowLabel label) { + override predicate blocksExpr(boolean outcome, Expr e, DataFlow::FlowLabel label) { polarity = outcome and e = operand and label instanceof ObjectPrototype @@ -239,20 +319,20 @@ private class TypeofCheck extends TaintTracking::LabeledSanitizerGuardNode, Data } /** A guard that checks whether `x` is a number. */ -class NumberGuard extends TaintTracking::SanitizerGuardNode instanceof DataFlow::CallNode { +class NumberGuard extends BarrierGuardLegacy instanceof DataFlow::CallNode { Expr x; boolean polarity; NumberGuard() { TaintTracking::isNumberGuard(this, x, polarity) } - override predicate sanitizes(boolean outcome, Expr e) { e = x and outcome = polarity } + override predicate blocksExpr(boolean outcome, Expr e) { e = x and outcome = polarity } } /** A call to `Array.isArray`, which is false for `Object.prototype`. */ -private class IsArrayCheck extends TaintTracking::LabeledSanitizerGuardNode, DataFlow::CallNode { +private class IsArrayCheck extends BarrierGuardLegacy, DataFlow::CallNode { IsArrayCheck() { this = DataFlow::globalVarRef("Array").getAMemberCall("isArray") } - override predicate sanitizes(boolean outcome, Expr e, DataFlow::FlowLabel label) { + override predicate blocksExpr(boolean outcome, Expr e, DataFlow::FlowLabel label) { e = this.getArgument(0).asExpr() and outcome = true and label instanceof ObjectPrototype @@ -262,12 +342,12 @@ private class IsArrayCheck extends TaintTracking::LabeledSanitizerGuardNode, Dat /** * Sanitizer guard of form `x !== "__proto__"`. */ -private class EqualityCheck extends TaintTracking::SanitizerGuardNode, DataFlow::ValueNode { +private class EqualityCheck extends BarrierGuardLegacy, DataFlow::ValueNode { override EqualityTest astNode; EqualityCheck() { astNode.getAnOperand().getStringValue() = "__proto__" } - override predicate sanitizes(boolean outcome, Expr e) { + override predicate blocksExpr(boolean outcome, Expr e) { e = astNode.getAnOperand() and outcome = astNode.getPolarity().booleanNot() } @@ -276,10 +356,10 @@ private class EqualityCheck extends TaintTracking::SanitizerGuardNode, DataFlow: /** * Sanitizer guard of the form `x.includes("__proto__")`. */ -private class IncludesCheck extends TaintTracking::LabeledSanitizerGuardNode, InclusionTest { +private class IncludesCheck extends BarrierGuardLegacy, InclusionTest { IncludesCheck() { this.getContainedNode().mayHaveStringValue("__proto__") } - override predicate sanitizes(boolean outcome, Expr e) { + override predicate blocksExpr(boolean outcome, Expr e) { e = this.getContainerNode().asExpr() and outcome = this.getPolarity().booleanNot() } @@ -288,7 +368,7 @@ private class IncludesCheck extends TaintTracking::LabeledSanitizerGuardNode, In /** * A sanitizer guard that checks tests whether `x` is included in a list like `["__proto__"].includes(x)`. */ -private class DenyListInclusionGuard extends TaintTracking::SanitizerGuardNode, InclusionTest { +private class DenyListInclusionGuard extends BarrierGuardLegacy, InclusionTest { DenyListInclusionGuard() { this.getContainerNode() .getALocalSource() @@ -297,7 +377,7 @@ private class DenyListInclusionGuard extends TaintTracking::SanitizerGuardNode, .mayHaveStringValue("__proto__") } - override predicate sanitizes(boolean outcome, Expr e) { + override predicate blocksExpr(boolean outcome, Expr e) { e = this.getContainedNode().asExpr() and outcome = super.getPolarity().booleanNot() } diff --git a/javascript/ql/src/Security/CWE-915/PrototypePollutingAssignment.ql b/javascript/ql/src/Security/CWE-915/PrototypePollutingAssignment.ql index 2b916426169..b5f86910e9d 100644 --- a/javascript/ql/src/Security/CWE-915/PrototypePollutingAssignment.ql +++ b/javascript/ql/src/Security/CWE-915/PrototypePollutingAssignment.ql @@ -19,10 +19,13 @@ import javascript import semmle.javascript.security.dataflow.PrototypePollutingAssignmentQuery -import DataFlow::PathGraph +import PrototypePollutingAssignmentFlow::PathGraph -from Configuration cfg, DataFlow::PathNode source, DataFlow::PathNode sink -where cfg.hasFlowPath(source, sink) +from + PrototypePollutingAssignmentFlow::PathNode source, PrototypePollutingAssignmentFlow::PathNode sink +where + PrototypePollutingAssignmentFlow::flowPath(source, sink) and + not isIgnoredLibraryFlow(source.getNode(), sink.getNode()) select sink, source, sink, "This assignment may alter Object.prototype if a malicious '__proto__' string is injected from $@.", source.getNode(), source.getNode().(Source).describe() diff --git a/javascript/ql/test/query-tests/Security/CWE-915/PrototypePollutingAssignment/Consistency.expected b/javascript/ql/test/query-tests/Security/CWE-915/PrototypePollutingAssignment/Consistency.expected index e69de29bb2d..8d013c40b5f 100644 --- a/javascript/ql/test/query-tests/Security/CWE-915/PrototypePollutingAssignment/Consistency.expected +++ b/javascript/ql/test/query-tests/Security/CWE-915/PrototypePollutingAssignment/Consistency.expected @@ -0,0 +1 @@ +| query-tests/Security/CWE-915/PrototypePollutingAssignment/lib.js:70 | expected an alert, but found none | NOT OK | Config | diff --git a/javascript/ql/test/query-tests/Security/CWE-915/PrototypePollutingAssignment/Consistency.ql b/javascript/ql/test/query-tests/Security/CWE-915/PrototypePollutingAssignment/Consistency.ql index 7a440ac58bb..636d6e3bbda 100644 --- a/javascript/ql/test/query-tests/Security/CWE-915/PrototypePollutingAssignment/Consistency.ql +++ b/javascript/ql/test/query-tests/Security/CWE-915/PrototypePollutingAssignment/Consistency.ql @@ -2,6 +2,15 @@ import javascript import testUtilities.ConsistencyChecking import semmle.javascript.security.dataflow.PrototypePollutingAssignmentQuery -class Config extends ConsistencyConfiguration, Configuration { +class Config extends ConsistencyConfiguration { + Config() { this = "Config" } + override File getAFile() { any() } + + override DataFlow::Node getAnAlert() { + exists(DataFlow::Node source | + PrototypePollutingAssignmentFlow::flow(source, result) and + not isIgnoredLibraryFlow(source, result) + ) + } } diff --git a/javascript/ql/test/query-tests/Security/CWE-915/PrototypePollutingAssignment/PrototypePollutingAssignment.expected b/javascript/ql/test/query-tests/Security/CWE-915/PrototypePollutingAssignment/PrototypePollutingAssignment.expected index 891aeff4221..e3e20255490 100644 --- a/javascript/ql/test/query-tests/Security/CWE-915/PrototypePollutingAssignment/PrototypePollutingAssignment.expected +++ b/javascript/ql/test/query-tests/Security/CWE-915/PrototypePollutingAssignment/PrototypePollutingAssignment.expected @@ -1,371 +1,230 @@ -nodes -| lib.js:1:38:1:40 | obj | -| lib.js:1:43:1:46 | path | -| lib.js:1:43:1:46 | path | -| lib.js:1:43:1:46 | path | -| lib.js:2:7:2:27 | currentPath | -| lib.js:2:7:2:27 | currentPath | -| lib.js:2:21:2:24 | path | -| lib.js:2:21:2:24 | path | -| lib.js:2:21:2:27 | path[0] | -| lib.js:2:21:2:27 | path[0] | -| lib.js:6:7:6:9 | obj | -| lib.js:6:7:6:9 | obj | -| lib.js:11:17:11:32 | obj[currentPath] | -| lib.js:11:17:11:32 | obj[currentPath] | -| lib.js:11:21:11:31 | currentPath | -| lib.js:11:21:11:31 | currentPath | -| lib.js:11:35:11:38 | path | -| lib.js:11:35:11:38 | path | -| lib.js:11:35:11:47 | path.slice(1) | -| lib.js:11:35:11:47 | path.slice(1) | -| lib.js:14:38:14:41 | path | -| lib.js:14:38:14:41 | path | -| lib.js:15:3:15:14 | obj[path[0]] | -| lib.js:15:3:15:14 | obj[path[0]] | -| lib.js:15:7:15:10 | path | -| lib.js:15:7:15:13 | path[0] | -| lib.js:20:7:20:25 | path | -| lib.js:20:14:20:22 | arguments | -| lib.js:20:14:20:22 | arguments | -| lib.js:20:14:20:25 | arguments[1] | -| lib.js:22:3:22:14 | obj[path[0]] | -| lib.js:22:3:22:14 | obj[path[0]] | -| lib.js:22:7:22:10 | path | -| lib.js:22:7:22:13 | path[0] | -| lib.js:25:44:25:47 | path | -| lib.js:25:44:25:47 | path | -| lib.js:26:10:26:21 | obj[path[0]] | -| lib.js:26:10:26:21 | obj[path[0]] | -| lib.js:26:14:26:17 | path | -| lib.js:26:14:26:20 | path[0] | -| lib.js:30:9:30:52 | args | -| lib.js:30:16:30:52 | Array.p ... uments) | -| lib.js:30:43:30:51 | arguments | -| lib.js:30:43:30:51 | arguments | -| lib.js:32:7:32:20 | path | -| lib.js:32:14:32:17 | args | -| lib.js:32:14:32:20 | args[1] | -| lib.js:34:3:34:14 | obj[path[0]] | -| lib.js:34:3:34:14 | obj[path[0]] | -| lib.js:34:7:34:10 | path | -| lib.js:34:7:34:13 | path[0] | -| lib.js:38:9:38:36 | args | -| lib.js:38:16:38:36 | Array.f ... uments) | -| lib.js:38:27:38:35 | arguments | -| lib.js:38:27:38:35 | arguments | -| lib.js:40:7:40:20 | path | -| lib.js:40:14:40:17 | args | -| lib.js:40:14:40:20 | args[1] | -| lib.js:42:3:42:14 | obj[path[0]] | -| lib.js:42:3:42:14 | obj[path[0]] | -| lib.js:42:7:42:10 | path | -| lib.js:42:7:42:13 | path[0] | -| lib.js:45:13:45:13 | s | -| lib.js:45:13:45:13 | s | -| lib.js:46:10:46:10 | s | -| lib.js:52:9:52:22 | path | -| lib.js:52:16:52:22 | id("x") | -| lib.js:55:11:55:22 | obj[path[0]] | -| lib.js:55:11:55:22 | obj[path[0]] | -| lib.js:55:15:55:18 | path | -| lib.js:55:15:55:21 | path[0] | -| lib.js:59:18:59:18 | s | -| lib.js:59:18:59:18 | s | -| lib.js:61:17:61:17 | s | -| lib.js:68:11:68:26 | path | -| lib.js:68:18:68:26 | this.path | -| lib.js:70:13:70:24 | obj[path[0]] | -| lib.js:70:13:70:24 | obj[path[0]] | -| lib.js:70:17:70:20 | path | -| lib.js:70:17:70:23 | path[0] | -| lib.js:83:7:83:25 | path | -| lib.js:83:14:83:22 | arguments | -| lib.js:83:14:83:22 | arguments | -| lib.js:83:14:83:25 | arguments[1] | -| lib.js:86:7:86:26 | proto | -| lib.js:86:15:86:26 | obj[path[0]] | -| lib.js:86:19:86:22 | path | -| lib.js:86:19:86:25 | path[0] | -| lib.js:87:10:87:14 | proto | -| lib.js:87:10:87:14 | proto | -| lib.js:90:43:90:46 | path | -| lib.js:90:43:90:46 | path | -| lib.js:91:7:91:28 | maybeProto | -| lib.js:91:20:91:28 | obj[path] | -| lib.js:91:24:91:27 | path | -| lib.js:92:3:92:12 | maybeProto | -| lib.js:92:3:92:12 | maybeProto | -| lib.js:95:3:95:12 | maybeProto | -| lib.js:95:3:95:12 | maybeProto | -| lib.js:104:7:104:24 | one | -| lib.js:104:13:104:21 | arguments | -| lib.js:104:13:104:21 | arguments | -| lib.js:104:13:104:24 | arguments[1] | -| lib.js:108:3:108:10 | obj[one] | -| lib.js:108:3:108:10 | obj[one] | -| lib.js:108:7:108:9 | one | -| lib.js:118:29:118:32 | path | -| lib.js:118:29:118:32 | path | -| lib.js:119:13:119:24 | obj[path[0]] | -| lib.js:119:13:119:24 | obj[path[0]] | -| lib.js:119:17:119:20 | path | -| lib.js:119:17:119:23 | path[0] | -| lib.js:127:14:127:17 | path | -| lib.js:127:14:127:17 | path | -| lib.js:128:9:128:20 | obj[path[0]] | -| lib.js:128:9:128:20 | obj[path[0]] | -| lib.js:128:13:128:16 | path | -| lib.js:128:13:128:19 | path[0] | -| otherlib/src/otherlibimpl.js:1:37:1:40 | path | -| otherlib/src/otherlibimpl.js:1:37:1:40 | path | -| otherlib/src/otherlibimpl.js:2:3:2:14 | obj[path[0]] | -| otherlib/src/otherlibimpl.js:2:3:2:14 | obj[path[0]] | -| otherlib/src/otherlibimpl.js:2:7:2:10 | path | -| otherlib/src/otherlibimpl.js:2:7:2:13 | path[0] | -| sublib/other.js:5:28:5:31 | path | -| sublib/other.js:5:28:5:31 | path | -| sublib/other.js:6:7:6:18 | obj[path[0]] | -| sublib/other.js:6:7:6:18 | obj[path[0]] | -| sublib/other.js:6:11:6:14 | path | -| sublib/other.js:6:11:6:17 | path[0] | -| sublib/sub.js:1:37:1:40 | path | -| sublib/sub.js:1:37:1:40 | path | -| sublib/sub.js:2:3:2:14 | obj[path[0]] | -| sublib/sub.js:2:3:2:14 | obj[path[0]] | -| sublib/sub.js:2:7:2:10 | path | -| sublib/sub.js:2:7:2:13 | path[0] | -| tst.js:5:9:5:38 | taint | -| tst.js:5:17:5:38 | String( ... y.data) | -| tst.js:5:24:5:37 | req.query.data | -| tst.js:5:24:5:37 | req.query.data | -| tst.js:8:5:8:17 | object[taint] | -| tst.js:8:5:8:17 | object[taint] | -| tst.js:8:12:8:16 | taint | -| tst.js:9:5:9:17 | object[taint] | -| tst.js:9:5:9:17 | object[taint] | -| tst.js:9:12:9:16 | taint | -| tst.js:12:18:12:30 | object[taint] | -| tst.js:12:25:12:29 | taint | -| tst.js:14:5:14:32 | unsafeG ... taint) | -| tst.js:14:5:14:32 | unsafeG ... taint) | -| tst.js:14:27:14:31 | taint | -| tst.js:33:23:33:25 | obj | -| tst.js:34:5:34:7 | obj | -| tst.js:34:5:34:7 | obj | -| tst.js:39:9:39:11 | obj | -| tst.js:39:9:39:11 | obj | -| tst.js:45:9:45:11 | obj | -| tst.js:45:9:45:11 | obj | -| tst.js:48:9:48:11 | obj | -| tst.js:48:9:48:11 | obj | -| tst.js:77:9:77:38 | taint | -| tst.js:77:17:77:38 | String( ... y.data) | -| tst.js:77:24:77:37 | req.query.data | -| tst.js:77:24:77:37 | req.query.data | -| tst.js:80:5:80:17 | object[taint] | -| tst.js:80:5:80:17 | object[taint] | -| tst.js:80:12:80:16 | taint | -| tst.js:82:5:82:22 | object["" + taint] | -| tst.js:82:5:82:22 | object["" + taint] | -| tst.js:82:12:82:21 | "" + taint | -| tst.js:82:17:82:21 | taint | -| tst.js:87:9:87:21 | object[taint] | -| tst.js:87:9:87:21 | object[taint] | -| tst.js:87:16:87:20 | taint | -| tst.js:94:5:94:37 | obj[req ... ', '')] | -| tst.js:94:5:94:37 | obj[req ... ', '')] | -| tst.js:94:9:94:19 | req.query.x | -| tst.js:94:9:94:19 | req.query.x | -| tst.js:94:9:94:36 | req.que ... _', '') | -| tst.js:97:5:97:46 | obj[req ... g, '')] | -| tst.js:97:5:97:46 | obj[req ... g, '')] | -| tst.js:97:9:97:19 | req.query.x | -| tst.js:97:9:97:19 | req.query.x | -| tst.js:97:9:97:45 | req.que ... /g, '') | -| tst.js:102:9:102:38 | taint | -| tst.js:102:17:102:38 | String( ... y.data) | -| tst.js:102:24:102:37 | req.query.data | -| tst.js:102:24:102:37 | req.query.data | -| tst.js:105:5:105:17 | object[taint] | -| tst.js:105:5:105:17 | object[taint] | -| tst.js:105:12:105:16 | taint | edges | lib.js:1:38:1:40 | obj | lib.js:6:7:6:9 | obj | -| lib.js:1:38:1:40 | obj | lib.js:6:7:6:9 | obj | | lib.js:1:43:1:46 | path | lib.js:2:21:2:24 | path | -| lib.js:1:43:1:46 | path | lib.js:2:21:2:24 | path | -| lib.js:1:43:1:46 | path | lib.js:2:21:2:24 | path | -| lib.js:1:43:1:46 | path | lib.js:11:35:11:38 | path | -| lib.js:1:43:1:46 | path | lib.js:11:35:11:38 | path | -| lib.js:1:43:1:46 | path | lib.js:11:35:11:38 | path | -| lib.js:2:7:2:27 | currentPath | lib.js:11:21:11:31 | currentPath | | lib.js:2:7:2:27 | currentPath | lib.js:11:21:11:31 | currentPath | | lib.js:2:21:2:24 | path | lib.js:2:21:2:27 | path[0] | -| lib.js:2:21:2:24 | path | lib.js:2:21:2:27 | path[0] | -| lib.js:2:21:2:27 | path[0] | lib.js:2:7:2:27 | currentPath | | lib.js:2:21:2:27 | path[0] | lib.js:2:7:2:27 | currentPath | | lib.js:11:17:11:32 | obj[currentPath] | lib.js:1:38:1:40 | obj | -| lib.js:11:17:11:32 | obj[currentPath] | lib.js:1:38:1:40 | obj | | lib.js:11:21:11:31 | currentPath | lib.js:11:17:11:32 | obj[currentPath] | -| lib.js:11:21:11:31 | currentPath | lib.js:11:17:11:32 | obj[currentPath] | -| lib.js:11:35:11:38 | path | lib.js:11:35:11:47 | path.slice(1) | -| lib.js:11:35:11:38 | path | lib.js:11:35:11:47 | path.slice(1) | -| lib.js:11:35:11:47 | path.slice(1) | lib.js:1:43:1:46 | path | -| lib.js:11:35:11:47 | path.slice(1) | lib.js:1:43:1:46 | path | -| lib.js:14:38:14:41 | path | lib.js:15:7:15:10 | path | | lib.js:14:38:14:41 | path | lib.js:15:7:15:10 | path | | lib.js:15:7:15:10 | path | lib.js:15:7:15:13 | path[0] | | lib.js:15:7:15:13 | path[0] | lib.js:15:3:15:14 | obj[path[0]] | -| lib.js:15:7:15:13 | path[0] | lib.js:15:3:15:14 | obj[path[0]] | | lib.js:20:7:20:25 | path | lib.js:22:7:22:10 | path | | lib.js:20:14:20:22 | arguments | lib.js:20:14:20:25 | arguments[1] | -| lib.js:20:14:20:22 | arguments | lib.js:20:14:20:25 | arguments[1] | | lib.js:20:14:20:25 | arguments[1] | lib.js:20:7:20:25 | path | | lib.js:22:7:22:10 | path | lib.js:22:7:22:13 | path[0] | | lib.js:22:7:22:13 | path[0] | lib.js:22:3:22:14 | obj[path[0]] | -| lib.js:22:7:22:13 | path[0] | lib.js:22:3:22:14 | obj[path[0]] | -| lib.js:25:44:25:47 | path | lib.js:26:14:26:17 | path | | lib.js:25:44:25:47 | path | lib.js:26:14:26:17 | path | | lib.js:26:14:26:17 | path | lib.js:26:14:26:20 | path[0] | | lib.js:26:14:26:20 | path[0] | lib.js:26:10:26:21 | obj[path[0]] | -| lib.js:26:14:26:20 | path[0] | lib.js:26:10:26:21 | obj[path[0]] | | lib.js:30:9:30:52 | args | lib.js:32:14:32:17 | args | | lib.js:30:16:30:52 | Array.p ... uments) | lib.js:30:9:30:52 | args | -| lib.js:30:43:30:51 | arguments | lib.js:30:16:30:52 | Array.p ... uments) | -| lib.js:30:43:30:51 | arguments | lib.js:30:16:30:52 | Array.p ... uments) | +| lib.js:30:16:30:52 | reflective call | lib.js:30:16:30:52 | Array.p ... uments) | +| lib.js:30:43:30:51 | arguments | lib.js:30:16:30:52 | reflective call | | lib.js:32:7:32:20 | path | lib.js:34:7:34:10 | path | | lib.js:32:14:32:17 | args | lib.js:32:14:32:20 | args[1] | | lib.js:32:14:32:20 | args[1] | lib.js:32:7:32:20 | path | | lib.js:34:7:34:10 | path | lib.js:34:7:34:13 | path[0] | | lib.js:34:7:34:13 | path[0] | lib.js:34:3:34:14 | obj[path[0]] | -| lib.js:34:7:34:13 | path[0] | lib.js:34:3:34:14 | obj[path[0]] | | lib.js:38:9:38:36 | args | lib.js:40:14:40:17 | args | | lib.js:38:16:38:36 | Array.f ... uments) | lib.js:38:9:38:36 | args | | lib.js:38:27:38:35 | arguments | lib.js:38:16:38:36 | Array.f ... uments) | -| lib.js:38:27:38:35 | arguments | lib.js:38:16:38:36 | Array.f ... uments) | | lib.js:40:7:40:20 | path | lib.js:42:7:42:10 | path | | lib.js:40:14:40:17 | args | lib.js:40:14:40:20 | args[1] | | lib.js:40:14:40:20 | args[1] | lib.js:40:7:40:20 | path | | lib.js:42:7:42:10 | path | lib.js:42:7:42:13 | path[0] | | lib.js:42:7:42:13 | path[0] | lib.js:42:3:42:14 | obj[path[0]] | -| lib.js:42:7:42:13 | path[0] | lib.js:42:3:42:14 | obj[path[0]] | -| lib.js:45:13:45:13 | s | lib.js:46:10:46:10 | s | -| lib.js:45:13:45:13 | s | lib.js:46:10:46:10 | s | -| lib.js:46:10:46:10 | s | lib.js:52:16:52:22 | id("x") | -| lib.js:52:9:52:22 | path | lib.js:55:15:55:18 | path | -| lib.js:52:16:52:22 | id("x") | lib.js:52:9:52:22 | path | -| lib.js:55:15:55:18 | path | lib.js:55:15:55:21 | path[0] | -| lib.js:55:15:55:21 | path[0] | lib.js:55:11:55:22 | obj[path[0]] | -| lib.js:55:15:55:21 | path[0] | lib.js:55:11:55:22 | obj[path[0]] | -| lib.js:59:18:59:18 | s | lib.js:61:17:61:17 | s | -| lib.js:59:18:59:18 | s | lib.js:61:17:61:17 | s | -| lib.js:61:17:61:17 | s | lib.js:68:11:68:26 | path | -| lib.js:61:17:61:17 | s | lib.js:68:18:68:26 | this.path | -| lib.js:61:17:61:17 | s | lib.js:70:17:70:20 | path | -| lib.js:68:11:68:26 | path | lib.js:70:17:70:20 | path | -| lib.js:68:18:68:26 | this.path | lib.js:68:11:68:26 | path | -| lib.js:70:17:70:20 | path | lib.js:70:17:70:23 | path[0] | -| lib.js:70:17:70:23 | path[0] | lib.js:70:13:70:24 | obj[path[0]] | -| lib.js:70:17:70:23 | path[0] | lib.js:70:13:70:24 | obj[path[0]] | | lib.js:83:7:83:25 | path | lib.js:86:19:86:22 | path | | lib.js:83:14:83:22 | arguments | lib.js:83:14:83:25 | arguments[1] | -| lib.js:83:14:83:22 | arguments | lib.js:83:14:83:25 | arguments[1] | | lib.js:83:14:83:25 | arguments[1] | lib.js:83:7:83:25 | path | | lib.js:86:7:86:26 | proto | lib.js:87:10:87:14 | proto | -| lib.js:86:7:86:26 | proto | lib.js:87:10:87:14 | proto | | lib.js:86:15:86:26 | obj[path[0]] | lib.js:86:7:86:26 | proto | | lib.js:86:19:86:22 | path | lib.js:86:19:86:25 | path[0] | | lib.js:86:19:86:25 | path[0] | lib.js:86:15:86:26 | obj[path[0]] | | lib.js:90:43:90:46 | path | lib.js:91:24:91:27 | path | -| lib.js:90:43:90:46 | path | lib.js:91:24:91:27 | path | | lib.js:91:7:91:28 | maybeProto | lib.js:92:3:92:12 | maybeProto | -| lib.js:91:7:91:28 | maybeProto | lib.js:92:3:92:12 | maybeProto | -| lib.js:91:7:91:28 | maybeProto | lib.js:95:3:95:12 | maybeProto | | lib.js:91:7:91:28 | maybeProto | lib.js:95:3:95:12 | maybeProto | | lib.js:91:20:91:28 | obj[path] | lib.js:91:7:91:28 | maybeProto | | lib.js:91:24:91:27 | path | lib.js:91:20:91:28 | obj[path] | | lib.js:104:7:104:24 | one | lib.js:108:7:108:9 | one | | lib.js:104:13:104:21 | arguments | lib.js:104:13:104:24 | arguments[1] | -| lib.js:104:13:104:21 | arguments | lib.js:104:13:104:24 | arguments[1] | | lib.js:104:13:104:24 | arguments[1] | lib.js:104:7:104:24 | one | | lib.js:108:7:108:9 | one | lib.js:108:3:108:10 | obj[one] | -| lib.js:108:7:108:9 | one | lib.js:108:3:108:10 | obj[one] | -| lib.js:118:29:118:32 | path | lib.js:119:17:119:20 | path | | lib.js:118:29:118:32 | path | lib.js:119:17:119:20 | path | | lib.js:119:17:119:20 | path | lib.js:119:17:119:23 | path[0] | | lib.js:119:17:119:23 | path[0] | lib.js:119:13:119:24 | obj[path[0]] | -| lib.js:119:17:119:23 | path[0] | lib.js:119:13:119:24 | obj[path[0]] | -| lib.js:127:14:127:17 | path | lib.js:128:13:128:16 | path | | lib.js:127:14:127:17 | path | lib.js:128:13:128:16 | path | | lib.js:128:13:128:16 | path | lib.js:128:13:128:19 | path[0] | | lib.js:128:13:128:19 | path[0] | lib.js:128:9:128:20 | obj[path[0]] | -| lib.js:128:13:128:19 | path[0] | lib.js:128:9:128:20 | obj[path[0]] | -| otherlib/src/otherlibimpl.js:1:37:1:40 | path | otherlib/src/otherlibimpl.js:2:7:2:10 | path | | otherlib/src/otherlibimpl.js:1:37:1:40 | path | otherlib/src/otherlibimpl.js:2:7:2:10 | path | | otherlib/src/otherlibimpl.js:2:7:2:10 | path | otherlib/src/otherlibimpl.js:2:7:2:13 | path[0] | | otherlib/src/otherlibimpl.js:2:7:2:13 | path[0] | otherlib/src/otherlibimpl.js:2:3:2:14 | obj[path[0]] | -| otherlib/src/otherlibimpl.js:2:7:2:13 | path[0] | otherlib/src/otherlibimpl.js:2:3:2:14 | obj[path[0]] | -| sublib/other.js:5:28:5:31 | path | sublib/other.js:6:11:6:14 | path | | sublib/other.js:5:28:5:31 | path | sublib/other.js:6:11:6:14 | path | | sublib/other.js:6:11:6:14 | path | sublib/other.js:6:11:6:17 | path[0] | | sublib/other.js:6:11:6:17 | path[0] | sublib/other.js:6:7:6:18 | obj[path[0]] | -| sublib/other.js:6:11:6:17 | path[0] | sublib/other.js:6:7:6:18 | obj[path[0]] | -| sublib/sub.js:1:37:1:40 | path | sublib/sub.js:2:7:2:10 | path | | sublib/sub.js:1:37:1:40 | path | sublib/sub.js:2:7:2:10 | path | | sublib/sub.js:2:7:2:10 | path | sublib/sub.js:2:7:2:13 | path[0] | | sublib/sub.js:2:7:2:13 | path[0] | sublib/sub.js:2:3:2:14 | obj[path[0]] | -| sublib/sub.js:2:7:2:13 | path[0] | sublib/sub.js:2:3:2:14 | obj[path[0]] | | tst.js:5:9:5:38 | taint | tst.js:8:12:8:16 | taint | | tst.js:5:9:5:38 | taint | tst.js:9:12:9:16 | taint | | tst.js:5:9:5:38 | taint | tst.js:12:25:12:29 | taint | | tst.js:5:9:5:38 | taint | tst.js:14:27:14:31 | taint | | tst.js:5:17:5:38 | String( ... y.data) | tst.js:5:9:5:38 | taint | | tst.js:5:24:5:37 | req.query.data | tst.js:5:17:5:38 | String( ... y.data) | -| tst.js:5:24:5:37 | req.query.data | tst.js:5:17:5:38 | String( ... y.data) | | tst.js:8:12:8:16 | taint | tst.js:8:5:8:17 | object[taint] | -| tst.js:8:12:8:16 | taint | tst.js:8:5:8:17 | object[taint] | -| tst.js:9:12:9:16 | taint | tst.js:9:5:9:17 | object[taint] | | tst.js:9:12:9:16 | taint | tst.js:9:5:9:17 | object[taint] | | tst.js:12:18:12:30 | object[taint] | tst.js:33:23:33:25 | obj | | tst.js:12:25:12:29 | taint | tst.js:12:18:12:30 | object[taint] | | tst.js:14:27:14:31 | taint | tst.js:14:5:14:32 | unsafeG ... taint) | -| tst.js:14:27:14:31 | taint | tst.js:14:5:14:32 | unsafeG ... taint) | -| tst.js:33:23:33:25 | obj | tst.js:34:5:34:7 | obj | +| tst.js:14:27:14:31 | taint | tst.js:55:29:55:32 | prop | | tst.js:33:23:33:25 | obj | tst.js:34:5:34:7 | obj | | tst.js:33:23:33:25 | obj | tst.js:39:9:39:11 | obj | -| tst.js:33:23:33:25 | obj | tst.js:39:9:39:11 | obj | -| tst.js:33:23:33:25 | obj | tst.js:45:9:45:11 | obj | | tst.js:33:23:33:25 | obj | tst.js:45:9:45:11 | obj | | tst.js:33:23:33:25 | obj | tst.js:48:9:48:11 | obj | -| tst.js:33:23:33:25 | obj | tst.js:48:9:48:11 | obj | +| tst.js:55:29:55:32 | prop | tst.js:56:22:56:25 | prop | +| tst.js:56:18:56:26 | obj[prop] | tst.js:56:12:56:33 | obj ? o ... : null | +| tst.js:56:22:56:25 | prop | tst.js:56:18:56:26 | obj[prop] | | tst.js:77:9:77:38 | taint | tst.js:80:12:80:16 | taint | | tst.js:77:9:77:38 | taint | tst.js:82:17:82:21 | taint | | tst.js:77:9:77:38 | taint | tst.js:87:16:87:20 | taint | | tst.js:77:17:77:38 | String( ... y.data) | tst.js:77:9:77:38 | taint | | tst.js:77:24:77:37 | req.query.data | tst.js:77:17:77:38 | String( ... y.data) | -| tst.js:77:24:77:37 | req.query.data | tst.js:77:17:77:38 | String( ... y.data) | | tst.js:80:12:80:16 | taint | tst.js:80:5:80:17 | object[taint] | -| tst.js:80:12:80:16 | taint | tst.js:80:5:80:17 | object[taint] | -| tst.js:82:12:82:21 | "" + taint | tst.js:82:5:82:22 | object["" + taint] | | tst.js:82:12:82:21 | "" + taint | tst.js:82:5:82:22 | object["" + taint] | | tst.js:82:17:82:21 | taint | tst.js:82:12:82:21 | "" + taint | | tst.js:87:16:87:20 | taint | tst.js:87:9:87:21 | object[taint] | -| tst.js:87:16:87:20 | taint | tst.js:87:9:87:21 | object[taint] | -| tst.js:94:9:94:19 | req.query.x | tst.js:94:9:94:36 | req.que ... _', '') | | tst.js:94:9:94:19 | req.query.x | tst.js:94:9:94:36 | req.que ... _', '') | | tst.js:94:9:94:36 | req.que ... _', '') | tst.js:94:5:94:37 | obj[req ... ', '')] | -| tst.js:94:9:94:36 | req.que ... _', '') | tst.js:94:5:94:37 | obj[req ... ', '')] | | tst.js:97:9:97:19 | req.query.x | tst.js:97:9:97:45 | req.que ... /g, '') | -| tst.js:97:9:97:19 | req.query.x | tst.js:97:9:97:45 | req.que ... /g, '') | -| tst.js:97:9:97:45 | req.que ... /g, '') | tst.js:97:5:97:46 | obj[req ... g, '')] | | tst.js:97:9:97:45 | req.que ... /g, '') | tst.js:97:5:97:46 | obj[req ... g, '')] | | tst.js:102:9:102:38 | taint | tst.js:105:12:105:16 | taint | | tst.js:102:17:102:38 | String( ... y.data) | tst.js:102:9:102:38 | taint | | tst.js:102:24:102:37 | req.query.data | tst.js:102:17:102:38 | String( ... y.data) | -| tst.js:102:24:102:37 | req.query.data | tst.js:102:17:102:38 | String( ... y.data) | -| tst.js:105:12:105:16 | taint | tst.js:105:5:105:17 | object[taint] | | tst.js:105:12:105:16 | taint | tst.js:105:5:105:17 | object[taint] | +nodes +| lib.js:1:38:1:40 | obj | semmle.label | obj | +| lib.js:1:43:1:46 | path | semmle.label | path | +| lib.js:2:7:2:27 | currentPath | semmle.label | currentPath | +| lib.js:2:21:2:24 | path | semmle.label | path | +| lib.js:2:21:2:27 | path[0] | semmle.label | path[0] | +| lib.js:6:7:6:9 | obj | semmle.label | obj | +| lib.js:11:17:11:32 | obj[currentPath] | semmle.label | obj[currentPath] | +| lib.js:11:21:11:31 | currentPath | semmle.label | currentPath | +| lib.js:14:38:14:41 | path | semmle.label | path | +| lib.js:15:3:15:14 | obj[path[0]] | semmle.label | obj[path[0]] | +| lib.js:15:7:15:10 | path | semmle.label | path | +| lib.js:15:7:15:13 | path[0] | semmle.label | path[0] | +| lib.js:20:7:20:25 | path | semmle.label | path | +| lib.js:20:14:20:22 | arguments | semmle.label | arguments | +| lib.js:20:14:20:25 | arguments[1] | semmle.label | arguments[1] | +| lib.js:22:3:22:14 | obj[path[0]] | semmle.label | obj[path[0]] | +| lib.js:22:7:22:10 | path | semmle.label | path | +| lib.js:22:7:22:13 | path[0] | semmle.label | path[0] | +| lib.js:25:44:25:47 | path | semmle.label | path | +| lib.js:26:10:26:21 | obj[path[0]] | semmle.label | obj[path[0]] | +| lib.js:26:14:26:17 | path | semmle.label | path | +| lib.js:26:14:26:20 | path[0] | semmle.label | path[0] | +| lib.js:30:9:30:52 | args | semmle.label | args | +| lib.js:30:16:30:52 | Array.p ... uments) | semmle.label | Array.p ... uments) | +| lib.js:30:16:30:52 | reflective call | semmle.label | reflective call | +| lib.js:30:43:30:51 | arguments | semmle.label | arguments | +| lib.js:32:7:32:20 | path | semmle.label | path | +| lib.js:32:14:32:17 | args | semmle.label | args | +| lib.js:32:14:32:20 | args[1] | semmle.label | args[1] | +| lib.js:34:3:34:14 | obj[path[0]] | semmle.label | obj[path[0]] | +| lib.js:34:7:34:10 | path | semmle.label | path | +| lib.js:34:7:34:13 | path[0] | semmle.label | path[0] | +| lib.js:38:9:38:36 | args | semmle.label | args | +| lib.js:38:16:38:36 | Array.f ... uments) | semmle.label | Array.f ... uments) | +| lib.js:38:27:38:35 | arguments | semmle.label | arguments | +| lib.js:40:7:40:20 | path | semmle.label | path | +| lib.js:40:14:40:17 | args | semmle.label | args | +| lib.js:40:14:40:20 | args[1] | semmle.label | args[1] | +| lib.js:42:3:42:14 | obj[path[0]] | semmle.label | obj[path[0]] | +| lib.js:42:7:42:10 | path | semmle.label | path | +| lib.js:42:7:42:13 | path[0] | semmle.label | path[0] | +| lib.js:83:7:83:25 | path | semmle.label | path | +| lib.js:83:14:83:22 | arguments | semmle.label | arguments | +| lib.js:83:14:83:25 | arguments[1] | semmle.label | arguments[1] | +| lib.js:86:7:86:26 | proto | semmle.label | proto | +| lib.js:86:15:86:26 | obj[path[0]] | semmle.label | obj[path[0]] | +| lib.js:86:19:86:22 | path | semmle.label | path | +| lib.js:86:19:86:25 | path[0] | semmle.label | path[0] | +| lib.js:87:10:87:14 | proto | semmle.label | proto | +| lib.js:90:43:90:46 | path | semmle.label | path | +| lib.js:91:7:91:28 | maybeProto | semmle.label | maybeProto | +| lib.js:91:20:91:28 | obj[path] | semmle.label | obj[path] | +| lib.js:91:24:91:27 | path | semmle.label | path | +| lib.js:92:3:92:12 | maybeProto | semmle.label | maybeProto | +| lib.js:95:3:95:12 | maybeProto | semmle.label | maybeProto | +| lib.js:104:7:104:24 | one | semmle.label | one | +| lib.js:104:13:104:21 | arguments | semmle.label | arguments | +| lib.js:104:13:104:24 | arguments[1] | semmle.label | arguments[1] | +| lib.js:108:3:108:10 | obj[one] | semmle.label | obj[one] | +| lib.js:108:7:108:9 | one | semmle.label | one | +| lib.js:118:29:118:32 | path | semmle.label | path | +| lib.js:119:13:119:24 | obj[path[0]] | semmle.label | obj[path[0]] | +| lib.js:119:17:119:20 | path | semmle.label | path | +| lib.js:119:17:119:23 | path[0] | semmle.label | path[0] | +| lib.js:127:14:127:17 | path | semmle.label | path | +| lib.js:128:9:128:20 | obj[path[0]] | semmle.label | obj[path[0]] | +| lib.js:128:13:128:16 | path | semmle.label | path | +| lib.js:128:13:128:19 | path[0] | semmle.label | path[0] | +| otherlib/src/otherlibimpl.js:1:37:1:40 | path | semmle.label | path | +| otherlib/src/otherlibimpl.js:2:3:2:14 | obj[path[0]] | semmle.label | obj[path[0]] | +| otherlib/src/otherlibimpl.js:2:7:2:10 | path | semmle.label | path | +| otherlib/src/otherlibimpl.js:2:7:2:13 | path[0] | semmle.label | path[0] | +| sublib/other.js:5:28:5:31 | path | semmle.label | path | +| sublib/other.js:6:7:6:18 | obj[path[0]] | semmle.label | obj[path[0]] | +| sublib/other.js:6:11:6:14 | path | semmle.label | path | +| sublib/other.js:6:11:6:17 | path[0] | semmle.label | path[0] | +| sublib/sub.js:1:37:1:40 | path | semmle.label | path | +| sublib/sub.js:2:3:2:14 | obj[path[0]] | semmle.label | obj[path[0]] | +| sublib/sub.js:2:7:2:10 | path | semmle.label | path | +| sublib/sub.js:2:7:2:13 | path[0] | semmle.label | path[0] | +| tst.js:5:9:5:38 | taint | semmle.label | taint | +| tst.js:5:17:5:38 | String( ... y.data) | semmle.label | String( ... y.data) | +| tst.js:5:24:5:37 | req.query.data | semmle.label | req.query.data | +| tst.js:8:5:8:17 | object[taint] | semmle.label | object[taint] | +| tst.js:8:12:8:16 | taint | semmle.label | taint | +| tst.js:9:5:9:17 | object[taint] | semmle.label | object[taint] | +| tst.js:9:12:9:16 | taint | semmle.label | taint | +| tst.js:12:18:12:30 | object[taint] | semmle.label | object[taint] | +| tst.js:12:25:12:29 | taint | semmle.label | taint | +| tst.js:14:5:14:32 | unsafeG ... taint) | semmle.label | unsafeG ... taint) | +| tst.js:14:27:14:31 | taint | semmle.label | taint | +| tst.js:33:23:33:25 | obj | semmle.label | obj | +| tst.js:34:5:34:7 | obj | semmle.label | obj | +| tst.js:39:9:39:11 | obj | semmle.label | obj | +| tst.js:45:9:45:11 | obj | semmle.label | obj | +| tst.js:48:9:48:11 | obj | semmle.label | obj | +| tst.js:55:29:55:32 | prop | semmle.label | prop | +| tst.js:56:12:56:33 | obj ? o ... : null | semmle.label | obj ? o ... : null | +| tst.js:56:18:56:26 | obj[prop] | semmle.label | obj[prop] | +| tst.js:56:22:56:25 | prop | semmle.label | prop | +| tst.js:77:9:77:38 | taint | semmle.label | taint | +| tst.js:77:17:77:38 | String( ... y.data) | semmle.label | String( ... y.data) | +| tst.js:77:24:77:37 | req.query.data | semmle.label | req.query.data | +| tst.js:80:5:80:17 | object[taint] | semmle.label | object[taint] | +| tst.js:80:12:80:16 | taint | semmle.label | taint | +| tst.js:82:5:82:22 | object["" + taint] | semmle.label | object["" + taint] | +| tst.js:82:12:82:21 | "" + taint | semmle.label | "" + taint | +| tst.js:82:17:82:21 | taint | semmle.label | taint | +| tst.js:87:9:87:21 | object[taint] | semmle.label | object[taint] | +| tst.js:87:16:87:20 | taint | semmle.label | taint | +| tst.js:94:5:94:37 | obj[req ... ', '')] | semmle.label | obj[req ... ', '')] | +| tst.js:94:9:94:19 | req.query.x | semmle.label | req.query.x | +| tst.js:94:9:94:36 | req.que ... _', '') | semmle.label | req.que ... _', '') | +| tst.js:97:5:97:46 | obj[req ... g, '')] | semmle.label | obj[req ... g, '')] | +| tst.js:97:9:97:19 | req.query.x | semmle.label | req.query.x | +| tst.js:97:9:97:45 | req.que ... /g, '') | semmle.label | req.que ... /g, '') | +| tst.js:102:9:102:38 | taint | semmle.label | taint | +| tst.js:102:17:102:38 | String( ... y.data) | semmle.label | String( ... y.data) | +| tst.js:102:24:102:37 | req.query.data | semmle.label | req.query.data | +| tst.js:105:5:105:17 | object[taint] | semmle.label | object[taint] | +| tst.js:105:12:105:16 | taint | semmle.label | taint | +subpaths +| tst.js:14:27:14:31 | taint | tst.js:55:29:55:32 | prop | tst.js:56:12:56:33 | obj ? o ... : null | tst.js:14:5:14:32 | unsafeG ... taint) | #select | lib.js:6:7:6:9 | obj | lib.js:1:43:1:46 | path | lib.js:6:7:6:9 | obj | This assignment may alter Object.prototype if a malicious '__proto__' string is injected from $@. | lib.js:1:43:1:46 | path | library input | | lib.js:15:3:15:14 | obj[path[0]] | lib.js:14:38:14:41 | path | lib.js:15:3:15:14 | obj[path[0]] | This assignment may alter Object.prototype if a malicious '__proto__' string is injected from $@. | lib.js:14:38:14:41 | path | library input | @@ -373,7 +232,6 @@ edges | lib.js:26:10:26:21 | obj[path[0]] | lib.js:25:44:25:47 | path | lib.js:26:10:26:21 | obj[path[0]] | This assignment may alter Object.prototype if a malicious '__proto__' string is injected from $@. | lib.js:25:44:25:47 | path | library input | | lib.js:34:3:34:14 | obj[path[0]] | lib.js:30:43:30:51 | arguments | lib.js:34:3:34:14 | obj[path[0]] | This assignment may alter Object.prototype if a malicious '__proto__' string is injected from $@. | lib.js:30:43:30:51 | arguments | library input | | lib.js:42:3:42:14 | obj[path[0]] | lib.js:38:27:38:35 | arguments | lib.js:42:3:42:14 | obj[path[0]] | This assignment may alter Object.prototype if a malicious '__proto__' string is injected from $@. | lib.js:38:27:38:35 | arguments | library input | -| lib.js:70:13:70:24 | obj[path[0]] | lib.js:59:18:59:18 | s | lib.js:70:13:70:24 | obj[path[0]] | This assignment may alter Object.prototype if a malicious '__proto__' string is injected from $@. | lib.js:59:18:59:18 | s | library input | | lib.js:87:10:87:14 | proto | lib.js:83:14:83:22 | arguments | lib.js:87:10:87:14 | proto | This assignment may alter Object.prototype if a malicious '__proto__' string is injected from $@. | lib.js:83:14:83:22 | arguments | library input | | lib.js:108:3:108:10 | obj[one] | lib.js:104:13:104:21 | arguments | lib.js:108:3:108:10 | obj[one] | This assignment may alter Object.prototype if a malicious '__proto__' string is injected from $@. | lib.js:104:13:104:21 | arguments | library input | | lib.js:119:13:119:24 | obj[path[0]] | lib.js:118:29:118:32 | path | lib.js:119:13:119:24 | obj[path[0]] | This assignment may alter Object.prototype if a malicious '__proto__' string is injected from $@. | lib.js:118:29:118:32 | path | library input |