Merge pull request #9289 from erik-krogh/es2022

JS: Support the remaining of the finished ES2022 proposals
This commit is contained in:
Erik Krogh Kristensen
2022-05-30 12:27:19 +02:00
committed by GitHub
20 changed files with 390 additions and 111 deletions

View File

@@ -0,0 +1,4 @@
---
category: minorAnalysis
---
* All new ECMAScript 2022 features are now supported.

View File

@@ -75,7 +75,7 @@ module ArrayTaintTracking {
succ.(DataFlow::SourceNode).getAMethodCall("splice") = call
or
// `e = array.pop()`, `e = array.shift()`, or similar: if `array` is tainted, then so is `e`.
call.(DataFlow::MethodCallNode).calls(pred, ["pop", "shift", "slice", "splice"]) and
call.(DataFlow::MethodCallNode).calls(pred, ["pop", "shift", "slice", "splice", "at"]) and
succ = call
or
// `e = Array.from(x)`: if `x` is tainted, then so is `e`.
@@ -199,13 +199,13 @@ private module ArrayDataFlow {
}
/**
* A step for retrieving an element from an array using `.pop()` or `.shift()`.
* A step for retrieving an element from an array using `.pop()`, `.shift()`, or `.at()`.
* E.g. `array.pop()`.
*/
private class ArrayPopStep extends DataFlow::SharedFlowStep {
override predicate loadStep(DataFlow::Node obj, DataFlow::Node element, string prop) {
exists(DataFlow::MethodCallNode call |
call.getMethodName() = ["pop", "shift"] and
call.getMethodName() = ["pop", "shift", "at"] and
prop = arrayElement() and
obj = call.getReceiver() and
element = call

View File

@@ -229,10 +229,10 @@ module MembershipCandidate {
membersNode = inExpr.getRightOperand()
)
or
exists(MethodCallExpr hasOwn |
this = hasOwn.getArgument(0).flow() and
test = hasOwn and
hasOwn.calls(membersNode, "hasOwnProperty")
exists(HasOwnPropertyCall hasOwn |
this = hasOwn.getProperty() and
test = hasOwn.asExpr() and
membersNode = hasOwn.getObject().asExpr()
)
}

View File

@@ -192,3 +192,35 @@ class StringSplitCall extends DataFlow::MethodCallNode {
bindingset[i]
DataFlow::Node getASubstringRead(int i) { result = this.getAPropertyRead(i.toString()) }
}
/**
* A call to `Object.prototype.hasOwnProperty`, `Object.hasOwn`, or a library that implements
* the same functionality.
*/
class HasOwnPropertyCall extends DataFlow::Node instanceof DataFlow::CallNode {
DataFlow::Node object;
DataFlow::Node property;
HasOwnPropertyCall() {
// Make sure we handle reflective calls since libraries love to do that.
super.getCalleeNode().getALocalSource().(DataFlow::PropRead).getPropertyName() =
"hasOwnProperty" and
object = super.getReceiver() and
property = super.getArgument(0)
or
this =
[
DataFlow::globalVarRef("Object").getAMemberCall("hasOwn"), //
DataFlow::moduleImport("has").getACall(), //
LodashUnderscore::member("has").getACall()
] and
object = super.getArgument(0) and
property = super.getArgument(1)
}
/** Gets the object whose property is being checked. */
DataFlow::Node getObject() { result = object }
/** Gets the property being checked. */
DataFlow::Node getProperty() { result = property }
}

View File

@@ -1027,18 +1027,16 @@ module TaintTracking {
class WhitelistContainmentCallSanitizer extends AdditionalSanitizerGuardNode,
DataFlow::MethodCallNode {
WhitelistContainmentCallSanitizer() {
exists(string name |
name = "contains" or
name = "has" or
name = "hasOwnProperty"
|
this.getMethodName() = name
)
this.getMethodName() = ["contains", "has", "hasOwnProperty", "hasOwn"]
}
override predicate sanitizes(boolean outcome, Expr e) {
outcome = true and
e = this.getArgument(0).asExpr()
exists(int propertyIndex |
if this.getMethodName() = "hasOwn" then propertyIndex = 1 else propertyIndex = 0
|
outcome = true and
e = this.getArgument(propertyIndex).asExpr()
)
}
override predicate appliesTo(Configuration cfg) { any() }

View File

@@ -27,6 +27,8 @@ predicate hasUnknownPropertyRead(LocalObject obj) {
or
exists(obj.getAPropertyRead("hasOwnProperty"))
or
obj.flowsTo(DataFlow::globalVarRef("Object").getAMemberCall("hasOwn").getArgument(0))
or
exists(obj.getAPropertyRead("propertyIsEnumerable"))
}

View File

@@ -339,19 +339,16 @@ class AllowListEqualityGuard extends DataFlow::LabeledBarrierGuardNode, ValueNod
* 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 {
class HasOwnPropertyGuard extends DataFlow::BarrierGuardNode instanceof HasOwnPropertyCall {
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())
not arePropertiesEnumerated(super.getObject().getALocalSource())
}
override predicate blocks(boolean outcome, Expr e) {
e = getArgument(0).asExpr() and outcome = true
e = super.getProperty().asExpr() and outcome = true
}
}

View File

@@ -11,6 +11,7 @@
| arrays.js:2:16:2:23 | "source" | arrays.js:74:8:74:29 | arr.fin ... llback) |
| arrays.js:2:16:2:23 | "source" | arrays.js:77:8:77:35 | arrayFi ... llback) |
| arrays.js:2:16:2:23 | "source" | arrays.js:81:10:81:10 | x |
| arrays.js:2:16:2:23 | "source" | arrays.js:84:8:84:17 | arr.at(-1) |
| arrays.js:18:22:18:29 | "source" | arrays.js:18:50:18:50 | e |
| arrays.js:22:15:22:22 | "source" | arrays.js:23:8:23:17 | arr2.pop() |
| arrays.js:25:15:25:22 | "source" | arrays.js:26:8:26:17 | arr3.pop() |

View File

@@ -80,4 +80,6 @@
for (const x of uniq(arr)) {
sink(x); // NOT OK
}
sink(arr.at(-1)); // NOT OK
});

View File

@@ -1,9 +1,9 @@
nodes
| arrays.js:1:1:83:2 | [ParExpr] (functi ... } }) | semmle.label | [ParExpr] (functi ... } }) |
| arrays.js:1:1:83:3 | [ExprStmt] (functi ... } }); | semmle.label | [ExprStmt] (functi ... } }); |
| arrays.js:1:1:83:3 | [ExprStmt] (functi ... } }); | semmle.order | 1 |
| arrays.js:1:2:83:1 | [FunctionExpr] functio ... K } } | semmle.label | [FunctionExpr] functio ... K } } |
| arrays.js:1:14:83:1 | [BlockStmt] { let ... K } } | semmle.label | [BlockStmt] { let ... K } } |
| arrays.js:1:1:85:2 | [ParExpr] (functi ... T OK }) | semmle.label | [ParExpr] (functi ... T OK }) |
| arrays.js:1:1:85:3 | [ExprStmt] (functi ... OK }); | semmle.label | [ExprStmt] (functi ... OK }); |
| arrays.js:1:1:85:3 | [ExprStmt] (functi ... OK }); | semmle.order | 1 |
| arrays.js:1:2:85:1 | [FunctionExpr] functio ... OT OK } | semmle.label | [FunctionExpr] functio ... OT OK } |
| arrays.js:1:14:85:1 | [BlockStmt] { let ... OT OK } | semmle.label | [BlockStmt] { let ... OT OK } |
| arrays.js:2:3:2:24 | [DeclStmt] let source = ... | semmle.label | [DeclStmt] let source = ... |
| arrays.js:2:7:2:12 | [VarDecl] source | semmle.label | [VarDecl] source |
| arrays.js:2:7:2:23 | [VariableDeclarator] source = "source" | semmle.label | [VariableDeclarator] source = "source" |
@@ -339,6 +339,17 @@ nodes
| arrays.js:81:5:81:11 | [CallExpr] sink(x) | semmle.label | [CallExpr] sink(x) |
| arrays.js:81:5:81:12 | [ExprStmt] sink(x); | semmle.label | [ExprStmt] sink(x); |
| arrays.js:81:10:81:10 | [VarRef] x | semmle.label | [VarRef] x |
| arrays.js:84:3:84:6 | [VarRef] sink | semmle.label | [VarRef] sink |
| arrays.js:84:3:84:18 | [CallExpr] sink(arr.at(-1)) | semmle.label | [CallExpr] sink(arr.at(-1)) |
| arrays.js:84:3:84:19 | [ExprStmt] sink(arr.at(-1)); | semmle.label | [ExprStmt] sink(arr.at(-1)); |
| arrays.js:84:8:84:10 | [VarRef] arr | semmle.label | [VarRef] arr |
| arrays.js:84:8:84:13 | [DotExpr] arr.at | semmle.label | [DotExpr] arr.at |
| arrays.js:84:8:84:17 | [MethodCallExpr] arr.at(-1) | semmle.label | [MethodCallExpr] arr.at(-1) |
| arrays.js:84:12:84:13 | [Label] at | semmle.label | [Label] at |
| arrays.js:84:15:84:16 | [UnaryExpr] -1 | semmle.label | [UnaryExpr] -1 |
| arrays.js:84:16:84:16 | [Literal] 1 | semmle.label | [Literal] 1 |
| file://:0:0:0:0 | (Arguments) | semmle.label | (Arguments) |
| file://:0:0:0:0 | (Arguments) | semmle.label | (Arguments) |
| file://:0:0:0:0 | (Arguments) | semmle.label | (Arguments) |
| file://:0:0:0:0 | (Arguments) | semmle.label | (Arguments) |
| file://:0:0:0:0 | (Arguments) | semmle.label | (Arguments) |
@@ -386,88 +397,90 @@ nodes
| file://:0:0:0:0 | (Parameters) | semmle.label | (Parameters) |
| file://:0:0:0:0 | (Parameters) | semmle.label | (Parameters) |
edges
| arrays.js:1:1:83:2 | [ParExpr] (functi ... } }) | arrays.js:1:2:83:1 | [FunctionExpr] functio ... K } } | semmle.label | 1 |
| arrays.js:1:1:83:2 | [ParExpr] (functi ... } }) | arrays.js:1:2:83:1 | [FunctionExpr] functio ... K } } | semmle.order | 1 |
| arrays.js:1:1:83:3 | [ExprStmt] (functi ... } }); | arrays.js:1:1:83:2 | [ParExpr] (functi ... } }) | semmle.label | 1 |
| arrays.js:1:1:83:3 | [ExprStmt] (functi ... } }); | arrays.js:1:1:83:2 | [ParExpr] (functi ... } }) | semmle.order | 1 |
| arrays.js:1:2:83:1 | [FunctionExpr] functio ... K } } | arrays.js:1:14:83:1 | [BlockStmt] { let ... K } } | semmle.label | 5 |
| arrays.js:1:2:83:1 | [FunctionExpr] functio ... K } } | arrays.js:1:14:83:1 | [BlockStmt] { let ... K } } | semmle.order | 5 |
| arrays.js:1:14:83:1 | [BlockStmt] { let ... K } } | arrays.js:2:3:2:24 | [DeclStmt] let source = ... | semmle.label | 1 |
| arrays.js:1:14:83:1 | [BlockStmt] { let ... K } } | arrays.js:2:3:2:24 | [DeclStmt] let source = ... | semmle.order | 1 |
| arrays.js:1:14:83:1 | [BlockStmt] { let ... K } } | arrays.js:4:3:4:28 | [DeclStmt] var obj = ... | semmle.label | 2 |
| arrays.js:1:14:83:1 | [BlockStmt] { let ... K } } | arrays.js:4:3:4:28 | [DeclStmt] var obj = ... | semmle.order | 2 |
| arrays.js:1:14:83:1 | [BlockStmt] { let ... K } } | arrays.js:5:3:5:16 | [ExprStmt] sink(obj.foo); | semmle.label | 3 |
| arrays.js:1:14:83:1 | [BlockStmt] { let ... K } } | arrays.js:5:3:5:16 | [ExprStmt] sink(obj.foo); | semmle.order | 3 |
| arrays.js:1:14:83:1 | [BlockStmt] { let ... K } } | arrays.js:7:3:7:15 | [DeclStmt] var arr = ... | semmle.label | 4 |
| arrays.js:1:14:83:1 | [BlockStmt] { let ... K } } | arrays.js:7:3:7:15 | [DeclStmt] var arr = ... | semmle.order | 4 |
| arrays.js:1:14:83:1 | [BlockStmt] { let ... K } } | arrays.js:8:3:8:19 | [ExprStmt] arr.push(source); | semmle.label | 5 |
| arrays.js:1:14:83:1 | [BlockStmt] { let ... K } } | arrays.js:8:3:8:19 | [ExprStmt] arr.push(source); | semmle.order | 5 |
| arrays.js:1:14:83:1 | [BlockStmt] { let ... K } } | arrays.js:10:3:12:3 | [ForStmt] for (va ... OK } | semmle.label | 6 |
| arrays.js:1:14:83:1 | [BlockStmt] { let ... K } } | arrays.js:10:3:12:3 | [ForStmt] for (va ... OK } | semmle.order | 6 |
| arrays.js:1:14:83:1 | [BlockStmt] { let ... K } } | arrays.js:15:3:15:30 | [ExprStmt] arr.for ... nk(e)); | semmle.label | 7 |
| arrays.js:1:14:83:1 | [BlockStmt] { let ... K } } | arrays.js:15:3:15:30 | [ExprStmt] arr.for ... nk(e)); | semmle.order | 7 |
| arrays.js:1:14:83:1 | [BlockStmt] { let ... K } } | arrays.js:16:3:16:26 | [ExprStmt] arr.map ... nk(e)); | semmle.label | 8 |
| arrays.js:1:14:83:1 | [BlockStmt] { let ... K } } | arrays.js:16:3:16:26 | [ExprStmt] arr.map ... nk(e)); | semmle.order | 8 |
| arrays.js:1:14:83:1 | [BlockStmt] { let ... K } } | arrays.js:18:3:18:53 | [ExprStmt] [1, 2, ... nk(e)); | semmle.label | 9 |
| arrays.js:1:14:83:1 | [BlockStmt] { let ... K } } | arrays.js:18:3:18:53 | [ExprStmt] [1, 2, ... nk(e)); | semmle.order | 9 |
| arrays.js:1:14:83:1 | [BlockStmt] { let ... K } } | arrays.js:20:3:20:18 | [ExprStmt] sink(arr.pop()); | semmle.label | 10 |
| arrays.js:1:14:83:1 | [BlockStmt] { let ... K } } | arrays.js:20:3:20:18 | [ExprStmt] sink(arr.pop()); | semmle.order | 10 |
| arrays.js:1:14:83:1 | [BlockStmt] { let ... K } } | arrays.js:22:3:22:24 | [DeclStmt] var arr2 = ... | semmle.label | 11 |
| arrays.js:1:14:83:1 | [BlockStmt] { let ... K } } | arrays.js:22:3:22:24 | [DeclStmt] var arr2 = ... | semmle.order | 11 |
| arrays.js:1:14:83:1 | [BlockStmt] { let ... K } } | arrays.js:23:3:23:19 | [ExprStmt] sink(arr2.pop()); | semmle.label | 12 |
| arrays.js:1:14:83:1 | [BlockStmt] { let ... K } } | arrays.js:23:3:23:19 | [ExprStmt] sink(arr2.pop()); | semmle.order | 12 |
| arrays.js:1:14:83:1 | [BlockStmt] { let ... K } } | arrays.js:25:3:25:24 | [DeclStmt] var arr3 = ... | semmle.label | 13 |
| arrays.js:1:14:83:1 | [BlockStmt] { let ... K } } | arrays.js:25:3:25:24 | [DeclStmt] var arr3 = ... | semmle.order | 13 |
| arrays.js:1:14:83:1 | [BlockStmt] { let ... K } } | arrays.js:26:3:26:19 | [ExprStmt] sink(arr3.pop()); | semmle.label | 14 |
| arrays.js:1:14:83:1 | [BlockStmt] { let ... K } } | arrays.js:26:3:26:19 | [ExprStmt] sink(arr3.pop()); | semmle.order | 14 |
| arrays.js:1:14:83:1 | [BlockStmt] { let ... K } } | arrays.js:28:3:28:16 | [DeclStmt] var arr4 = ... | semmle.label | 15 |
| arrays.js:1:14:83:1 | [BlockStmt] { let ... K } } | arrays.js:28:3:28:16 | [DeclStmt] var arr4 = ... | semmle.order | 15 |
| arrays.js:1:14:83:1 | [BlockStmt] { let ... K } } | arrays.js:29:3:29:30 | [ExprStmt] arr4.sp ... urce"); | semmle.label | 16 |
| arrays.js:1:14:83:1 | [BlockStmt] { let ... K } } | arrays.js:29:3:29:30 | [ExprStmt] arr4.sp ... urce"); | semmle.order | 16 |
| arrays.js:1:14:83:1 | [BlockStmt] { let ... K } } | arrays.js:30:3:30:19 | [ExprStmt] sink(arr4.pop()); | semmle.label | 17 |
| arrays.js:1:14:83:1 | [BlockStmt] { let ... K } } | arrays.js:30:3:30:19 | [ExprStmt] sink(arr4.pop()); | semmle.order | 17 |
| arrays.js:1:14:83:1 | [BlockStmt] { let ... K } } | arrays.js:32:3:32:29 | [DeclStmt] var arr5 = ... | semmle.label | 18 |
| arrays.js:1:14:83:1 | [BlockStmt] { let ... K } } | arrays.js:32:3:32:29 | [DeclStmt] var arr5 = ... | semmle.order | 18 |
| arrays.js:1:14:83:1 | [BlockStmt] { let ... K } } | arrays.js:33:3:33:19 | [ExprStmt] sink(arr5.pop()); | semmle.label | 19 |
| arrays.js:1:14:83:1 | [BlockStmt] { let ... K } } | arrays.js:33:3:33:19 | [ExprStmt] sink(arr5.pop()); | semmle.order | 19 |
| arrays.js:1:14:83:1 | [BlockStmt] { let ... K } } | arrays.js:35:3:35:28 | [ExprStmt] sink(ar ... pop()); | semmle.label | 20 |
| arrays.js:1:14:83:1 | [BlockStmt] { let ... K } } | arrays.js:35:3:35:28 | [ExprStmt] sink(ar ... pop()); | semmle.order | 20 |
| arrays.js:1:14:83:1 | [BlockStmt] { let ... K } } | arrays.js:37:3:37:16 | [DeclStmt] var arr6 = ... | semmle.label | 21 |
| arrays.js:1:14:83:1 | [BlockStmt] { let ... K } } | arrays.js:37:3:37:16 | [DeclStmt] var arr6 = ... | semmle.order | 21 |
| arrays.js:1:14:83:1 | [BlockStmt] { let ... K } } | arrays.js:38:3:40:3 | [ForStmt] for (va ... i]; } | semmle.label | 22 |
| arrays.js:1:14:83:1 | [BlockStmt] { let ... K } } | arrays.js:38:3:40:3 | [ForStmt] for (va ... i]; } | semmle.order | 22 |
| arrays.js:1:14:83:1 | [BlockStmt] { let ... K } } | arrays.js:41:3:41:19 | [ExprStmt] sink(arr6.pop()); | semmle.label | 23 |
| arrays.js:1:14:83:1 | [BlockStmt] { let ... K } } | arrays.js:41:3:41:19 | [ExprStmt] sink(arr6.pop()); | semmle.order | 23 |
| arrays.js:1:14:83:1 | [BlockStmt] { let ... K } } | arrays.js:44:3:47:5 | [ExprStmt] ["sourc ... . }); | semmle.label | 24 |
| arrays.js:1:14:83:1 | [BlockStmt] { let ... K } } | arrays.js:44:3:47:5 | [ExprStmt] ["sourc ... . }); | semmle.order | 24 |
| arrays.js:1:14:83:1 | [BlockStmt] { let ... K } } | arrays.js:49:3:49:15 | [ExprStmt] sink(arr[0]); | semmle.label | 25 |
| arrays.js:1:14:83:1 | [BlockStmt] { let ... K } } | arrays.js:49:3:49:15 | [ExprStmt] sink(arr[0]); | semmle.order | 25 |
| arrays.js:1:14:83:1 | [BlockStmt] { let ... K } } | arrays.js:51:3:53:3 | [ForOfStmt] for (co ... OK } | semmle.label | 26 |
| arrays.js:1:14:83:1 | [BlockStmt] { let ... K } } | arrays.js:51:3:53:3 | [ForOfStmt] for (co ... OK } | semmle.order | 26 |
| arrays.js:1:14:83:1 | [BlockStmt] { let ... K } } | arrays.js:55:3:57:3 | [ForOfStmt] for (co ... OK } | semmle.label | 27 |
| arrays.js:1:14:83:1 | [BlockStmt] { let ... K } } | arrays.js:55:3:57:3 | [ForOfStmt] for (co ... OK } | semmle.order | 27 |
| arrays.js:1:14:83:1 | [BlockStmt] { let ... K } } | arrays.js:59:3:61:3 | [ForOfStmt] for (co ... OK } | semmle.label | 28 |
| arrays.js:1:14:83:1 | [BlockStmt] { let ... K } } | arrays.js:59:3:61:3 | [ForOfStmt] for (co ... OK } | semmle.order | 28 |
| arrays.js:1:14:83:1 | [BlockStmt] { let ... K } } | arrays.js:63:3:63:16 | [DeclStmt] var arr7 = ... | semmle.label | 29 |
| arrays.js:1:14:83:1 | [BlockStmt] { let ... K } } | arrays.js:63:3:63:16 | [DeclStmt] var arr7 = ... | semmle.order | 29 |
| arrays.js:1:14:83:1 | [BlockStmt] { let ... K } } | arrays.js:64:3:64:20 | [ExprStmt] arr7.push(...arr); | semmle.label | 30 |
| arrays.js:1:14:83:1 | [BlockStmt] { let ... K } } | arrays.js:64:3:64:20 | [ExprStmt] arr7.push(...arr); | semmle.order | 30 |
| arrays.js:1:14:83:1 | [BlockStmt] { let ... K } } | arrays.js:65:3:67:3 | [ForOfStmt] for (co ... OK } | semmle.label | 31 |
| arrays.js:1:14:83:1 | [BlockStmt] { let ... K } } | arrays.js:65:3:67:3 | [ForOfStmt] for (co ... OK } | semmle.order | 31 |
| arrays.js:1:14:83:1 | [BlockStmt] { let ... K } } | arrays.js:69:3:69:42 | [DeclStmt] const arrayFrom = ... | semmle.label | 32 |
| arrays.js:1:14:83:1 | [BlockStmt] { let ... K } } | arrays.js:69:3:69:42 | [DeclStmt] const arrayFrom = ... | semmle.order | 32 |
| arrays.js:1:14:83:1 | [BlockStmt] { let ... K } } | arrays.js:70:3:72:3 | [ForOfStmt] for (co ... OK } | semmle.label | 33 |
| arrays.js:1:14:83:1 | [BlockStmt] { let ... K } } | arrays.js:70:3:72:3 | [ForOfStmt] for (co ... OK } | semmle.order | 33 |
| arrays.js:1:14:83:1 | [BlockStmt] { let ... K } } | arrays.js:74:3:74:31 | [ExprStmt] sink(ar ... back)); | semmle.label | 34 |
| arrays.js:1:14:83:1 | [BlockStmt] { let ... K } } | arrays.js:74:3:74:31 | [ExprStmt] sink(ar ... back)); | semmle.order | 34 |
| arrays.js:1:14:83:1 | [BlockStmt] { let ... K } } | arrays.js:76:3:76:42 | [DeclStmt] const arrayFind = ... | semmle.label | 35 |
| arrays.js:1:14:83:1 | [BlockStmt] { let ... K } } | arrays.js:76:3:76:42 | [DeclStmt] const arrayFind = ... | semmle.order | 35 |
| arrays.js:1:14:83:1 | [BlockStmt] { let ... K } } | arrays.js:77:3:77:37 | [ExprStmt] sink(ar ... back)); | semmle.label | 36 |
| arrays.js:1:14:83:1 | [BlockStmt] { let ... K } } | arrays.js:77:3:77:37 | [ExprStmt] sink(ar ... back)); | semmle.order | 36 |
| arrays.js:1:14:83:1 | [BlockStmt] { let ... K } } | arrays.js:79:3:79:31 | [DeclStmt] const uniq = ... | semmle.label | 37 |
| arrays.js:1:14:83:1 | [BlockStmt] { let ... K } } | arrays.js:79:3:79:31 | [DeclStmt] const uniq = ... | semmle.order | 37 |
| arrays.js:1:14:83:1 | [BlockStmt] { let ... K } } | arrays.js:80:3:82:3 | [ForOfStmt] for (co ... OK } | semmle.label | 38 |
| arrays.js:1:14:83:1 | [BlockStmt] { let ... K } } | arrays.js:80:3:82:3 | [ForOfStmt] for (co ... OK } | semmle.order | 38 |
| arrays.js:1:1:85:2 | [ParExpr] (functi ... T OK }) | arrays.js:1:2:85:1 | [FunctionExpr] functio ... OT OK } | semmle.label | 1 |
| arrays.js:1:1:85:2 | [ParExpr] (functi ... T OK }) | arrays.js:1:2:85:1 | [FunctionExpr] functio ... OT OK } | semmle.order | 1 |
| arrays.js:1:1:85:3 | [ExprStmt] (functi ... OK }); | arrays.js:1:1:85:2 | [ParExpr] (functi ... T OK }) | semmle.label | 1 |
| arrays.js:1:1:85:3 | [ExprStmt] (functi ... OK }); | arrays.js:1:1:85:2 | [ParExpr] (functi ... T OK }) | semmle.order | 1 |
| arrays.js:1:2:85:1 | [FunctionExpr] functio ... OT OK } | arrays.js:1:14:85:1 | [BlockStmt] { let ... OT OK } | semmle.label | 5 |
| arrays.js:1:2:85:1 | [FunctionExpr] functio ... OT OK } | arrays.js:1:14:85:1 | [BlockStmt] { let ... OT OK } | semmle.order | 5 |
| arrays.js:1:14:85:1 | [BlockStmt] { let ... OT OK } | arrays.js:2:3:2:24 | [DeclStmt] let source = ... | semmle.label | 1 |
| arrays.js:1:14:85:1 | [BlockStmt] { let ... OT OK } | arrays.js:2:3:2:24 | [DeclStmt] let source = ... | semmle.order | 1 |
| arrays.js:1:14:85:1 | [BlockStmt] { let ... OT OK } | arrays.js:4:3:4:28 | [DeclStmt] var obj = ... | semmle.label | 2 |
| arrays.js:1:14:85:1 | [BlockStmt] { let ... OT OK } | arrays.js:4:3:4:28 | [DeclStmt] var obj = ... | semmle.order | 2 |
| arrays.js:1:14:85:1 | [BlockStmt] { let ... OT OK } | arrays.js:5:3:5:16 | [ExprStmt] sink(obj.foo); | semmle.label | 3 |
| arrays.js:1:14:85:1 | [BlockStmt] { let ... OT OK } | arrays.js:5:3:5:16 | [ExprStmt] sink(obj.foo); | semmle.order | 3 |
| arrays.js:1:14:85:1 | [BlockStmt] { let ... OT OK } | arrays.js:7:3:7:15 | [DeclStmt] var arr = ... | semmle.label | 4 |
| arrays.js:1:14:85:1 | [BlockStmt] { let ... OT OK } | arrays.js:7:3:7:15 | [DeclStmt] var arr = ... | semmle.order | 4 |
| arrays.js:1:14:85:1 | [BlockStmt] { let ... OT OK } | arrays.js:8:3:8:19 | [ExprStmt] arr.push(source); | semmle.label | 5 |
| arrays.js:1:14:85:1 | [BlockStmt] { let ... OT OK } | arrays.js:8:3:8:19 | [ExprStmt] arr.push(source); | semmle.order | 5 |
| arrays.js:1:14:85:1 | [BlockStmt] { let ... OT OK } | arrays.js:10:3:12:3 | [ForStmt] for (va ... OK } | semmle.label | 6 |
| arrays.js:1:14:85:1 | [BlockStmt] { let ... OT OK } | arrays.js:10:3:12:3 | [ForStmt] for (va ... OK } | semmle.order | 6 |
| arrays.js:1:14:85:1 | [BlockStmt] { let ... OT OK } | arrays.js:15:3:15:30 | [ExprStmt] arr.for ... nk(e)); | semmle.label | 7 |
| arrays.js:1:14:85:1 | [BlockStmt] { let ... OT OK } | arrays.js:15:3:15:30 | [ExprStmt] arr.for ... nk(e)); | semmle.order | 7 |
| arrays.js:1:14:85:1 | [BlockStmt] { let ... OT OK } | arrays.js:16:3:16:26 | [ExprStmt] arr.map ... nk(e)); | semmle.label | 8 |
| arrays.js:1:14:85:1 | [BlockStmt] { let ... OT OK } | arrays.js:16:3:16:26 | [ExprStmt] arr.map ... nk(e)); | semmle.order | 8 |
| arrays.js:1:14:85:1 | [BlockStmt] { let ... OT OK } | arrays.js:18:3:18:53 | [ExprStmt] [1, 2, ... nk(e)); | semmle.label | 9 |
| arrays.js:1:14:85:1 | [BlockStmt] { let ... OT OK } | arrays.js:18:3:18:53 | [ExprStmt] [1, 2, ... nk(e)); | semmle.order | 9 |
| arrays.js:1:14:85:1 | [BlockStmt] { let ... OT OK } | arrays.js:20:3:20:18 | [ExprStmt] sink(arr.pop()); | semmle.label | 10 |
| arrays.js:1:14:85:1 | [BlockStmt] { let ... OT OK } | arrays.js:20:3:20:18 | [ExprStmt] sink(arr.pop()); | semmle.order | 10 |
| arrays.js:1:14:85:1 | [BlockStmt] { let ... OT OK } | arrays.js:22:3:22:24 | [DeclStmt] var arr2 = ... | semmle.label | 11 |
| arrays.js:1:14:85:1 | [BlockStmt] { let ... OT OK } | arrays.js:22:3:22:24 | [DeclStmt] var arr2 = ... | semmle.order | 11 |
| arrays.js:1:14:85:1 | [BlockStmt] { let ... OT OK } | arrays.js:23:3:23:19 | [ExprStmt] sink(arr2.pop()); | semmle.label | 12 |
| arrays.js:1:14:85:1 | [BlockStmt] { let ... OT OK } | arrays.js:23:3:23:19 | [ExprStmt] sink(arr2.pop()); | semmle.order | 12 |
| arrays.js:1:14:85:1 | [BlockStmt] { let ... OT OK } | arrays.js:25:3:25:24 | [DeclStmt] var arr3 = ... | semmle.label | 13 |
| arrays.js:1:14:85:1 | [BlockStmt] { let ... OT OK } | arrays.js:25:3:25:24 | [DeclStmt] var arr3 = ... | semmle.order | 13 |
| arrays.js:1:14:85:1 | [BlockStmt] { let ... OT OK } | arrays.js:26:3:26:19 | [ExprStmt] sink(arr3.pop()); | semmle.label | 14 |
| arrays.js:1:14:85:1 | [BlockStmt] { let ... OT OK } | arrays.js:26:3:26:19 | [ExprStmt] sink(arr3.pop()); | semmle.order | 14 |
| arrays.js:1:14:85:1 | [BlockStmt] { let ... OT OK } | arrays.js:28:3:28:16 | [DeclStmt] var arr4 = ... | semmle.label | 15 |
| arrays.js:1:14:85:1 | [BlockStmt] { let ... OT OK } | arrays.js:28:3:28:16 | [DeclStmt] var arr4 = ... | semmle.order | 15 |
| arrays.js:1:14:85:1 | [BlockStmt] { let ... OT OK } | arrays.js:29:3:29:30 | [ExprStmt] arr4.sp ... urce"); | semmle.label | 16 |
| arrays.js:1:14:85:1 | [BlockStmt] { let ... OT OK } | arrays.js:29:3:29:30 | [ExprStmt] arr4.sp ... urce"); | semmle.order | 16 |
| arrays.js:1:14:85:1 | [BlockStmt] { let ... OT OK } | arrays.js:30:3:30:19 | [ExprStmt] sink(arr4.pop()); | semmle.label | 17 |
| arrays.js:1:14:85:1 | [BlockStmt] { let ... OT OK } | arrays.js:30:3:30:19 | [ExprStmt] sink(arr4.pop()); | semmle.order | 17 |
| arrays.js:1:14:85:1 | [BlockStmt] { let ... OT OK } | arrays.js:32:3:32:29 | [DeclStmt] var arr5 = ... | semmle.label | 18 |
| arrays.js:1:14:85:1 | [BlockStmt] { let ... OT OK } | arrays.js:32:3:32:29 | [DeclStmt] var arr5 = ... | semmle.order | 18 |
| arrays.js:1:14:85:1 | [BlockStmt] { let ... OT OK } | arrays.js:33:3:33:19 | [ExprStmt] sink(arr5.pop()); | semmle.label | 19 |
| arrays.js:1:14:85:1 | [BlockStmt] { let ... OT OK } | arrays.js:33:3:33:19 | [ExprStmt] sink(arr5.pop()); | semmle.order | 19 |
| arrays.js:1:14:85:1 | [BlockStmt] { let ... OT OK } | arrays.js:35:3:35:28 | [ExprStmt] sink(ar ... pop()); | semmle.label | 20 |
| arrays.js:1:14:85:1 | [BlockStmt] { let ... OT OK } | arrays.js:35:3:35:28 | [ExprStmt] sink(ar ... pop()); | semmle.order | 20 |
| arrays.js:1:14:85:1 | [BlockStmt] { let ... OT OK } | arrays.js:37:3:37:16 | [DeclStmt] var arr6 = ... | semmle.label | 21 |
| arrays.js:1:14:85:1 | [BlockStmt] { let ... OT OK } | arrays.js:37:3:37:16 | [DeclStmt] var arr6 = ... | semmle.order | 21 |
| arrays.js:1:14:85:1 | [BlockStmt] { let ... OT OK } | arrays.js:38:3:40:3 | [ForStmt] for (va ... i]; } | semmle.label | 22 |
| arrays.js:1:14:85:1 | [BlockStmt] { let ... OT OK } | arrays.js:38:3:40:3 | [ForStmt] for (va ... i]; } | semmle.order | 22 |
| arrays.js:1:14:85:1 | [BlockStmt] { let ... OT OK } | arrays.js:41:3:41:19 | [ExprStmt] sink(arr6.pop()); | semmle.label | 23 |
| arrays.js:1:14:85:1 | [BlockStmt] { let ... OT OK } | arrays.js:41:3:41:19 | [ExprStmt] sink(arr6.pop()); | semmle.order | 23 |
| arrays.js:1:14:85:1 | [BlockStmt] { let ... OT OK } | arrays.js:44:3:47:5 | [ExprStmt] ["sourc ... . }); | semmle.label | 24 |
| arrays.js:1:14:85:1 | [BlockStmt] { let ... OT OK } | arrays.js:44:3:47:5 | [ExprStmt] ["sourc ... . }); | semmle.order | 24 |
| arrays.js:1:14:85:1 | [BlockStmt] { let ... OT OK } | arrays.js:49:3:49:15 | [ExprStmt] sink(arr[0]); | semmle.label | 25 |
| arrays.js:1:14:85:1 | [BlockStmt] { let ... OT OK } | arrays.js:49:3:49:15 | [ExprStmt] sink(arr[0]); | semmle.order | 25 |
| arrays.js:1:14:85:1 | [BlockStmt] { let ... OT OK } | arrays.js:51:3:53:3 | [ForOfStmt] for (co ... OK } | semmle.label | 26 |
| arrays.js:1:14:85:1 | [BlockStmt] { let ... OT OK } | arrays.js:51:3:53:3 | [ForOfStmt] for (co ... OK } | semmle.order | 26 |
| arrays.js:1:14:85:1 | [BlockStmt] { let ... OT OK } | arrays.js:55:3:57:3 | [ForOfStmt] for (co ... OK } | semmle.label | 27 |
| arrays.js:1:14:85:1 | [BlockStmt] { let ... OT OK } | arrays.js:55:3:57:3 | [ForOfStmt] for (co ... OK } | semmle.order | 27 |
| arrays.js:1:14:85:1 | [BlockStmt] { let ... OT OK } | arrays.js:59:3:61:3 | [ForOfStmt] for (co ... OK } | semmle.label | 28 |
| arrays.js:1:14:85:1 | [BlockStmt] { let ... OT OK } | arrays.js:59:3:61:3 | [ForOfStmt] for (co ... OK } | semmle.order | 28 |
| arrays.js:1:14:85:1 | [BlockStmt] { let ... OT OK } | arrays.js:63:3:63:16 | [DeclStmt] var arr7 = ... | semmle.label | 29 |
| arrays.js:1:14:85:1 | [BlockStmt] { let ... OT OK } | arrays.js:63:3:63:16 | [DeclStmt] var arr7 = ... | semmle.order | 29 |
| arrays.js:1:14:85:1 | [BlockStmt] { let ... OT OK } | arrays.js:64:3:64:20 | [ExprStmt] arr7.push(...arr); | semmle.label | 30 |
| arrays.js:1:14:85:1 | [BlockStmt] { let ... OT OK } | arrays.js:64:3:64:20 | [ExprStmt] arr7.push(...arr); | semmle.order | 30 |
| arrays.js:1:14:85:1 | [BlockStmt] { let ... OT OK } | arrays.js:65:3:67:3 | [ForOfStmt] for (co ... OK } | semmle.label | 31 |
| arrays.js:1:14:85:1 | [BlockStmt] { let ... OT OK } | arrays.js:65:3:67:3 | [ForOfStmt] for (co ... OK } | semmle.order | 31 |
| arrays.js:1:14:85:1 | [BlockStmt] { let ... OT OK } | arrays.js:69:3:69:42 | [DeclStmt] const arrayFrom = ... | semmle.label | 32 |
| arrays.js:1:14:85:1 | [BlockStmt] { let ... OT OK } | arrays.js:69:3:69:42 | [DeclStmt] const arrayFrom = ... | semmle.order | 32 |
| arrays.js:1:14:85:1 | [BlockStmt] { let ... OT OK } | arrays.js:70:3:72:3 | [ForOfStmt] for (co ... OK } | semmle.label | 33 |
| arrays.js:1:14:85:1 | [BlockStmt] { let ... OT OK } | arrays.js:70:3:72:3 | [ForOfStmt] for (co ... OK } | semmle.order | 33 |
| arrays.js:1:14:85:1 | [BlockStmt] { let ... OT OK } | arrays.js:74:3:74:31 | [ExprStmt] sink(ar ... back)); | semmle.label | 34 |
| arrays.js:1:14:85:1 | [BlockStmt] { let ... OT OK } | arrays.js:74:3:74:31 | [ExprStmt] sink(ar ... back)); | semmle.order | 34 |
| arrays.js:1:14:85:1 | [BlockStmt] { let ... OT OK } | arrays.js:76:3:76:42 | [DeclStmt] const arrayFind = ... | semmle.label | 35 |
| arrays.js:1:14:85:1 | [BlockStmt] { let ... OT OK } | arrays.js:76:3:76:42 | [DeclStmt] const arrayFind = ... | semmle.order | 35 |
| arrays.js:1:14:85:1 | [BlockStmt] { let ... OT OK } | arrays.js:77:3:77:37 | [ExprStmt] sink(ar ... back)); | semmle.label | 36 |
| arrays.js:1:14:85:1 | [BlockStmt] { let ... OT OK } | arrays.js:77:3:77:37 | [ExprStmt] sink(ar ... back)); | semmle.order | 36 |
| arrays.js:1:14:85:1 | [BlockStmt] { let ... OT OK } | arrays.js:79:3:79:31 | [DeclStmt] const uniq = ... | semmle.label | 37 |
| arrays.js:1:14:85:1 | [BlockStmt] { let ... OT OK } | arrays.js:79:3:79:31 | [DeclStmt] const uniq = ... | semmle.order | 37 |
| arrays.js:1:14:85:1 | [BlockStmt] { let ... OT OK } | arrays.js:80:3:82:3 | [ForOfStmt] for (co ... OK } | semmle.label | 38 |
| arrays.js:1:14:85:1 | [BlockStmt] { let ... OT OK } | arrays.js:80:3:82:3 | [ForOfStmt] for (co ... OK } | semmle.order | 38 |
| arrays.js:1:14:85:1 | [BlockStmt] { let ... OT OK } | arrays.js:84:3:84:19 | [ExprStmt] sink(arr.at(-1)); | semmle.label | 39 |
| arrays.js:1:14:85:1 | [BlockStmt] { let ... OT OK } | arrays.js:84:3:84:19 | [ExprStmt] sink(arr.at(-1)); | semmle.order | 39 |
| arrays.js:2:3:2:24 | [DeclStmt] let source = ... | arrays.js:2:7:2:23 | [VariableDeclarator] source = "source" | semmle.label | 1 |
| arrays.js:2:3:2:24 | [DeclStmt] let source = ... | arrays.js:2:7:2:23 | [VariableDeclarator] source = "source" | semmle.order | 1 |
| arrays.js:2:7:2:23 | [VariableDeclarator] source = "source" | arrays.js:2:7:2:12 | [VarDecl] source | semmle.label | 1 |
@@ -1052,6 +1065,22 @@ edges
| arrays.js:81:5:81:11 | [CallExpr] sink(x) | file://:0:0:0:0 | (Arguments) | semmle.order | 1 |
| arrays.js:81:5:81:12 | [ExprStmt] sink(x); | arrays.js:81:5:81:11 | [CallExpr] sink(x) | semmle.label | 1 |
| arrays.js:81:5:81:12 | [ExprStmt] sink(x); | arrays.js:81:5:81:11 | [CallExpr] sink(x) | semmle.order | 1 |
| arrays.js:84:3:84:18 | [CallExpr] sink(arr.at(-1)) | arrays.js:84:3:84:6 | [VarRef] sink | semmle.label | 0 |
| arrays.js:84:3:84:18 | [CallExpr] sink(arr.at(-1)) | arrays.js:84:3:84:6 | [VarRef] sink | semmle.order | 0 |
| arrays.js:84:3:84:18 | [CallExpr] sink(arr.at(-1)) | file://:0:0:0:0 | (Arguments) | semmle.label | 1 |
| arrays.js:84:3:84:18 | [CallExpr] sink(arr.at(-1)) | file://:0:0:0:0 | (Arguments) | semmle.order | 1 |
| arrays.js:84:3:84:19 | [ExprStmt] sink(arr.at(-1)); | arrays.js:84:3:84:18 | [CallExpr] sink(arr.at(-1)) | semmle.label | 1 |
| arrays.js:84:3:84:19 | [ExprStmt] sink(arr.at(-1)); | arrays.js:84:3:84:18 | [CallExpr] sink(arr.at(-1)) | semmle.order | 1 |
| arrays.js:84:8:84:13 | [DotExpr] arr.at | arrays.js:84:8:84:10 | [VarRef] arr | semmle.label | 1 |
| arrays.js:84:8:84:13 | [DotExpr] arr.at | arrays.js:84:8:84:10 | [VarRef] arr | semmle.order | 1 |
| arrays.js:84:8:84:13 | [DotExpr] arr.at | arrays.js:84:12:84:13 | [Label] at | semmle.label | 2 |
| arrays.js:84:8:84:13 | [DotExpr] arr.at | arrays.js:84:12:84:13 | [Label] at | semmle.order | 2 |
| arrays.js:84:8:84:17 | [MethodCallExpr] arr.at(-1) | arrays.js:84:8:84:13 | [DotExpr] arr.at | semmle.label | 0 |
| arrays.js:84:8:84:17 | [MethodCallExpr] arr.at(-1) | arrays.js:84:8:84:13 | [DotExpr] arr.at | semmle.order | 0 |
| arrays.js:84:8:84:17 | [MethodCallExpr] arr.at(-1) | file://:0:0:0:0 | (Arguments) | semmle.label | 1 |
| arrays.js:84:8:84:17 | [MethodCallExpr] arr.at(-1) | file://:0:0:0:0 | (Arguments) | semmle.order | 1 |
| arrays.js:84:15:84:16 | [UnaryExpr] -1 | arrays.js:84:16:84:16 | [Literal] 1 | semmle.label | 1 |
| arrays.js:84:15:84:16 | [UnaryExpr] -1 | arrays.js:84:16:84:16 | [Literal] 1 | semmle.order | 1 |
| file://:0:0:0:0 | (Arguments) | arrays.js:5:8:5:14 | [DotExpr] obj.foo | semmle.label | 0 |
| file://:0:0:0:0 | (Arguments) | arrays.js:5:8:5:14 | [DotExpr] obj.foo | semmle.order | 0 |
| file://:0:0:0:0 | (Arguments) | arrays.js:8:12:8:17 | [VarRef] source | semmle.label | 0 |
@@ -1140,6 +1169,10 @@ edges
| file://:0:0:0:0 | (Arguments) | arrays.js:80:24:80:26 | [VarRef] arr | semmle.order | 0 |
| file://:0:0:0:0 | (Arguments) | arrays.js:81:10:81:10 | [VarRef] x | semmle.label | 0 |
| file://:0:0:0:0 | (Arguments) | arrays.js:81:10:81:10 | [VarRef] x | semmle.order | 0 |
| file://:0:0:0:0 | (Arguments) | arrays.js:84:8:84:17 | [MethodCallExpr] arr.at(-1) | semmle.label | 0 |
| file://:0:0:0:0 | (Arguments) | arrays.js:84:8:84:17 | [MethodCallExpr] arr.at(-1) | semmle.order | 0 |
| file://:0:0:0:0 | (Arguments) | arrays.js:84:15:84:16 | [UnaryExpr] -1 | semmle.label | 0 |
| file://:0:0:0:0 | (Arguments) | arrays.js:84:15:84:16 | [UnaryExpr] -1 | semmle.order | 0 |
| file://:0:0:0:0 | (Parameters) | arrays.js:15:16:15:16 | [SimpleParameter] e | semmle.label | 0 |
| file://:0:0:0:0 | (Parameters) | arrays.js:15:16:15:16 | [SimpleParameter] e | semmle.order | 0 |
| file://:0:0:0:0 | (Parameters) | arrays.js:16:12:16:12 | [SimpleParameter] e | semmle.label | 0 |

View File

@@ -43,6 +43,10 @@ isLabeledBarrier
| ExampleConfiguration | tst.js:361:14:361:14 | v | taint |
| ExampleConfiguration | tst.js:371:14:371:16 | o.p | taint |
| ExampleConfiguration | tst.js:378:14:378:17 | o[p] | taint |
| ExampleConfiguration | tst.js:392:14:392:14 | v | taint |
| ExampleConfiguration | tst.js:394:14:394:16 | v.p | taint |
| ExampleConfiguration | tst.js:396:14:396:18 | v.p.q | taint |
| ExampleConfiguration | tst.js:402:14:402:14 | v | taint |
isSanitizer
| ExampleConfiguration | tst.js:176:18:176:18 | v |
sanitizingGuard
@@ -122,6 +126,12 @@ sanitizingGuard
| tst.js:370:9:370:29 | o.p == ... listed" | tst.js:370:16:370:29 | "white-listed" | true |
| tst.js:377:11:377:32 | o[p] == ... listed" | tst.js:377:11:377:14 | o[p] | true |
| tst.js:377:11:377:32 | o[p] == ... listed" | tst.js:377:19:377:32 | "white-listed" | true |
| tst.js:391:9:391:27 | o.hasOwnProperty(v) | tst.js:391:26:391:26 | v | true |
| tst.js:393:16:393:36 | o.hasOw ... ty(v.p) | tst.js:393:33:393:35 | v.p | true |
| tst.js:395:16:395:38 | o.hasOw ... (v.p.q) | tst.js:395:33:395:37 | v.p.q | true |
| tst.js:397:16:397:36 | o.hasOw ... ty(v.p) | tst.js:397:33:397:35 | v.p | true |
| tst.js:399:16:399:41 | o.hasOw ... "p.q"]) | tst.js:399:33:399:40 | v["p.q"] | true |
| tst.js:401:16:401:34 | Object.hasOwn(o, v) | tst.js:401:33:401:33 | v | true |
taintedSink
| tst.js:2:13:2:20 | SOURCE() | tst.js:3:10:3:10 | v |
| tst.js:2:13:2:20 | SOURCE() | tst.js:8:14:8:14 | v |
@@ -186,3 +196,6 @@ taintedSink
| tst.js:367:13:367:20 | SOURCE() | tst.js:373:14:373:16 | o.p |
| tst.js:367:13:367:20 | SOURCE() | tst.js:380:14:380:17 | o[p] |
| tst.js:367:13:367:20 | SOURCE() | tst.js:382:14:382:17 | o[p] |
| tst.js:388:13:388:20 | SOURCE() | tst.js:389:10:389:14 | v.p.q |
| tst.js:388:13:388:20 | SOURCE() | tst.js:398:14:398:14 | v |
| tst.js:388:13:388:20 | SOURCE() | tst.js:400:14:400:18 | v.p.q |

View File

@@ -383,3 +383,22 @@ function constantComparisonSanitizer2() {
}
}
}
function propertySanitization(o) {
var v = SOURCE();
SINK(v.p.q); // NOT OK
if (o.hasOwnProperty(v)) {
SINK(v); // OK
} else if (o.hasOwnProperty(v.p)) {
SINK(v.p); // OK
} else if (o.hasOwnProperty(v.p.q)) {
SINK(v.p.q); // OK
} else if (o.hasOwnProperty(v.p)) {
SINK(v); // NOT OK
} else if (o.hasOwnProperty(v["p.q"])) {
SINK(v.p.q); // NOT OK
} else if (Object.hasOwn(o, v)) {
SINK(v); // OK
}
}

View File

@@ -17,6 +17,7 @@ typeInferenceMismatch
| arrays.js:2:15:2:22 | source() | arrays.js:11:10:11:28 | union(["bla"], foo) |
| arrays.js:2:15:2:22 | source() | arrays.js:14:10:14:18 | flat(foo) |
| arrays.js:2:15:2:22 | source() | arrays.js:19:10:19:12 | res |
| arrays.js:2:15:2:22 | source() | arrays.js:21:10:21:19 | foo.at(-1) |
| booleanOps.js:2:11:2:18 | source() | booleanOps.js:4:8:4:8 | x |
| booleanOps.js:2:11:2:18 | source() | booleanOps.js:13:10:13:10 | x |
| booleanOps.js:2:11:2:18 | source() | booleanOps.js:19:10:19:10 | x |

View File

@@ -17,4 +17,6 @@ function test() {
return prev + '<b>' + current + '</b>';
}, '');
sink(res); // NOT OK
sink(foo.at(-1)); // NOT OK
}

View File

@@ -81,3 +81,11 @@
(function(){
({ unusedProp: 42 }, 42);
});
(function(){
var foo = {
unused: 42
};
foo.unused = 42;
Object.hasOwn(foo, blab);
});

View File

@@ -50,6 +50,13 @@ nodes
| express.js:146:16:146:24 | query.foo |
| express.js:146:16:146:24 | query.foo |
| express.js:146:16:146:24 | query.foo |
| express.js:150:7:150:34 | target |
| express.js:150:16:150:34 | req.param("target") |
| express.js:150:16:150:34 | req.param("target") |
| express.js:155:18:155:23 | target |
| express.js:155:18:155:23 | target |
| express.js:160:18:160:23 | target |
| express.js:160:18:160:23 | target |
| koa.js:6:6:6:27 | url |
| koa.js:6:12:6:27 | ctx.query.target |
| koa.js:6:12:6:27 | ctx.query.target |
@@ -140,6 +147,12 @@ edges
| express.js:136:22:136:36 | req.params.user | express.js:136:16:136:36 | 'u' + r ... ms.user |
| express.js:143:16:143:28 | req.query.foo | express.js:143:16:143:28 | req.query.foo |
| express.js:146:16:146:24 | query.foo | express.js:146:16:146:24 | query.foo |
| express.js:150:7:150:34 | target | express.js:155:18:155:23 | target |
| express.js:150:7:150:34 | target | express.js:155:18:155:23 | target |
| express.js:150:7:150:34 | target | express.js:160:18:160:23 | target |
| express.js:150:7:150:34 | target | express.js:160:18:160:23 | target |
| express.js:150:16:150:34 | req.param("target") | express.js:150:7:150:34 | target |
| express.js:150:16:150:34 | req.param("target") | express.js:150:7:150:34 | target |
| koa.js:6:6:6:27 | url | koa.js:7:15:7:17 | url |
| koa.js:6:6:6:27 | url | koa.js:7:15:7:17 | url |
| koa.js:6:6:6:27 | url | koa.js:8:18:8:20 | url |
@@ -199,6 +212,8 @@ edges
| express.js:136:16:136:36 | 'u' + r ... ms.user | express.js:136:22:136:36 | req.params.user | express.js:136:16:136:36 | 'u' + r ... ms.user | Untrusted URL redirection due to $@. | express.js:136:22:136:36 | req.params.user | user-provided value |
| express.js:143:16:143:28 | req.query.foo | express.js:143:16:143:28 | req.query.foo | express.js:143:16:143:28 | req.query.foo | Untrusted URL redirection due to $@. | express.js:143:16:143:28 | req.query.foo | user-provided value |
| express.js:146:16:146:24 | query.foo | express.js:146:16:146:24 | query.foo | express.js:146:16:146:24 | query.foo | Untrusted URL redirection due to $@. | express.js:146:16:146:24 | query.foo | user-provided value |
| express.js:155:18:155:23 | target | express.js:150:16:150:34 | req.param("target") | express.js:155:18:155:23 | target | Untrusted URL redirection due to $@. | express.js:150:16:150:34 | req.param("target") | user-provided value |
| express.js:160:18:160:23 | target | express.js:150:16:150:34 | req.param("target") | express.js:160:18:160:23 | target | Untrusted URL redirection due to $@. | express.js:150:16:150:34 | req.param("target") | user-provided value |
| koa.js:7:15:7:17 | url | koa.js:6:12:6:27 | ctx.query.target | koa.js:7:15:7:17 | url | Untrusted URL redirection due to $@. | koa.js:6:12:6:27 | ctx.query.target | user-provided value |
| koa.js:8:15:8:26 | `${url}${x}` | koa.js:6:12:6:27 | ctx.query.target | koa.js:8:15:8:26 | `${url}${x}` | Untrusted URL redirection due to $@. | koa.js:6:12:6:27 | ctx.query.target | user-provided value |
| koa.js:14:16:14:18 | url | koa.js:6:12:6:27 | ctx.query.target | koa.js:14:16:14:18 | url | Untrusted URL redirection due to $@. | koa.js:6:12:6:27 | ctx.query.target | user-provided value |

View File

@@ -144,4 +144,18 @@ app.get("foo", (req, res) => {
});
app.get("bar", ({query}, res) => {
res.redirect(query.foo); // NOT OK
})
})
app.get('/some/path', function(req, res) {
let target = req.param("target");
if (SAFE_TARGETS.hasOwnProperty(target))
res.redirect(target); // OK: request parameter is checked against whitelist
else
res.redirect(target); // NOT OK
if (Object.hasOwn(SAFE_TARGETS, target))
res.redirect(target); // OK: request parameter is checked against whitelist
else
res.redirect(target); // NOT OK
});

View File

@@ -1478,6 +1478,56 @@ nodes
| tests.js:547:24:547:28 | value |
| tests.js:547:24:547:28 | value |
| tests.js:547:24:547:28 | value |
| tests.js:552:35:552:37 | src |
| tests.js:552:35:552:37 | src |
| tests.js:553:14:553:16 | key |
| tests.js:553:14:553:16 | key |
| tests.js:553:14:553:16 | key |
| tests.js:557:43:557:45 | src |
| tests.js:557:43:557:45 | src |
| tests.js:557:43:557:50 | src[key] |
| tests.js:557:43:557:50 | src[key] |
| tests.js:557:43:557:50 | src[key] |
| tests.js:557:43:557:50 | src[key] |
| tests.js:557:43:557:50 | src[key] |
| tests.js:559:17:559:19 | key |
| tests.js:559:17:559:19 | key |
| tests.js:559:17:559:19 | key |
| tests.js:559:24:559:26 | src |
| tests.js:559:24:559:26 | src |
| tests.js:559:24:559:31 | src[key] |
| tests.js:559:24:559:31 | src[key] |
| tests.js:559:24:559:31 | src[key] |
| tests.js:559:24:559:31 | src[key] |
| tests.js:559:24:559:31 | src[key] |
| tests.js:559:24:559:31 | src[key] |
| tests.js:559:28:559:30 | key |
| tests.js:559:28:559:30 | key |
| tests.js:564:35:564:37 | src |
| tests.js:564:35:564:37 | src |
| tests.js:565:14:565:16 | key |
| tests.js:565:14:565:16 | key |
| tests.js:565:14:565:16 | key |
| tests.js:569:43:569:45 | src |
| tests.js:569:43:569:45 | src |
| tests.js:569:43:569:50 | src[key] |
| tests.js:569:43:569:50 | src[key] |
| tests.js:569:43:569:50 | src[key] |
| tests.js:569:43:569:50 | src[key] |
| tests.js:569:43:569:50 | src[key] |
| tests.js:571:17:571:19 | key |
| tests.js:571:17:571:19 | key |
| tests.js:571:17:571:19 | key |
| tests.js:571:24:571:26 | src |
| tests.js:571:24:571:26 | src |
| tests.js:571:24:571:31 | src[key] |
| tests.js:571:24:571:31 | src[key] |
| tests.js:571:24:571:31 | src[key] |
| tests.js:571:24:571:31 | src[key] |
| tests.js:571:24:571:31 | src[key] |
| tests.js:571:24:571:31 | src[key] |
| tests.js:571:28:571:30 | key |
| tests.js:571:28:571:30 | key |
edges
| examples/PrototypePollutingFunction.js:1:16:1:18 | dst | examples/PrototypePollutingFunction.js:5:19:5:21 | dst |
| examples/PrototypePollutingFunction.js:1:16:1:18 | dst | examples/PrototypePollutingFunction.js:5:19:5:21 | dst |
@@ -3347,6 +3397,70 @@ edges
| tests.js:545:43:545:47 | value | tests.js:542:35:542:37 | src |
| tests.js:545:43:545:47 | value | tests.js:542:35:542:37 | src |
| tests.js:545:43:545:47 | value | tests.js:542:35:542:37 | src |
| tests.js:552:35:552:37 | src | tests.js:557:43:557:45 | src |
| tests.js:552:35:552:37 | src | tests.js:557:43:557:45 | src |
| tests.js:552:35:552:37 | src | tests.js:559:24:559:26 | src |
| tests.js:552:35:552:37 | src | tests.js:559:24:559:26 | src |
| tests.js:553:14:553:16 | key | tests.js:559:17:559:19 | key |
| tests.js:553:14:553:16 | key | tests.js:559:17:559:19 | key |
| tests.js:553:14:553:16 | key | tests.js:559:17:559:19 | key |
| tests.js:553:14:553:16 | key | tests.js:559:17:559:19 | key |
| tests.js:553:14:553:16 | key | tests.js:559:17:559:19 | key |
| tests.js:553:14:553:16 | key | tests.js:559:17:559:19 | key |
| tests.js:553:14:553:16 | key | tests.js:559:17:559:19 | key |
| tests.js:553:14:553:16 | key | tests.js:559:28:559:30 | key |
| tests.js:553:14:553:16 | key | tests.js:559:28:559:30 | key |
| tests.js:553:14:553:16 | key | tests.js:559:28:559:30 | key |
| tests.js:553:14:553:16 | key | tests.js:559:28:559:30 | key |
| tests.js:557:43:557:45 | src | tests.js:557:43:557:50 | src[key] |
| tests.js:557:43:557:45 | src | tests.js:557:43:557:50 | src[key] |
| tests.js:557:43:557:50 | src[key] | tests.js:552:35:552:37 | src |
| tests.js:557:43:557:50 | src[key] | tests.js:552:35:552:37 | src |
| tests.js:557:43:557:50 | src[key] | tests.js:552:35:552:37 | src |
| tests.js:557:43:557:50 | src[key] | tests.js:552:35:552:37 | src |
| tests.js:557:43:557:50 | src[key] | tests.js:552:35:552:37 | src |
| tests.js:557:43:557:50 | src[key] | tests.js:552:35:552:37 | src |
| tests.js:559:24:559:26 | src | tests.js:559:24:559:31 | src[key] |
| tests.js:559:24:559:26 | src | tests.js:559:24:559:31 | src[key] |
| tests.js:559:24:559:26 | src | tests.js:559:24:559:31 | src[key] |
| tests.js:559:24:559:26 | src | tests.js:559:24:559:31 | src[key] |
| tests.js:559:24:559:31 | src[key] | tests.js:559:24:559:31 | src[key] |
| tests.js:559:28:559:30 | key | tests.js:559:24:559:31 | src[key] |
| tests.js:559:28:559:30 | key | tests.js:559:24:559:31 | src[key] |
| tests.js:559:28:559:30 | key | tests.js:559:24:559:31 | src[key] |
| tests.js:559:28:559:30 | key | tests.js:559:24:559:31 | src[key] |
| tests.js:564:35:564:37 | src | tests.js:569:43:569:45 | src |
| tests.js:564:35:564:37 | src | tests.js:569:43:569:45 | src |
| tests.js:564:35:564:37 | src | tests.js:571:24:571:26 | src |
| tests.js:564:35:564:37 | src | tests.js:571:24:571:26 | src |
| tests.js:565:14:565:16 | key | tests.js:571:17:571:19 | key |
| tests.js:565:14:565:16 | key | tests.js:571:17:571:19 | key |
| tests.js:565:14:565:16 | key | tests.js:571:17:571:19 | key |
| tests.js:565:14:565:16 | key | tests.js:571:17:571:19 | key |
| tests.js:565:14:565:16 | key | tests.js:571:17:571:19 | key |
| tests.js:565:14:565:16 | key | tests.js:571:17:571:19 | key |
| tests.js:565:14:565:16 | key | tests.js:571:17:571:19 | key |
| tests.js:565:14:565:16 | key | tests.js:571:28:571:30 | key |
| tests.js:565:14:565:16 | key | tests.js:571:28:571:30 | key |
| tests.js:565:14:565:16 | key | tests.js:571:28:571:30 | key |
| tests.js:565:14:565:16 | key | tests.js:571:28:571:30 | key |
| tests.js:569:43:569:45 | src | tests.js:569:43:569:50 | src[key] |
| tests.js:569:43:569:45 | src | tests.js:569:43:569:50 | src[key] |
| tests.js:569:43:569:50 | src[key] | tests.js:564:35:564:37 | src |
| tests.js:569:43:569:50 | src[key] | tests.js:564:35:564:37 | src |
| tests.js:569:43:569:50 | src[key] | tests.js:564:35:564:37 | src |
| tests.js:569:43:569:50 | src[key] | tests.js:564:35:564:37 | src |
| tests.js:569:43:569:50 | src[key] | tests.js:564:35:564:37 | src |
| tests.js:569:43:569:50 | src[key] | tests.js:564:35:564:37 | src |
| tests.js:571:24:571:26 | src | tests.js:571:24:571:31 | src[key] |
| tests.js:571:24:571:26 | src | tests.js:571:24:571:31 | src[key] |
| tests.js:571:24:571:26 | src | tests.js:571:24:571:31 | src[key] |
| tests.js:571:24:571:26 | src | tests.js:571:24:571:31 | src[key] |
| tests.js:571:24:571:31 | src[key] | tests.js:571:24:571:31 | src[key] |
| tests.js:571:28:571:30 | key | tests.js:571:24:571:31 | src[key] |
| tests.js:571:28:571:30 | key | tests.js:571:24:571:31 | src[key] |
| tests.js:571:28:571:30 | key | tests.js:571:24:571:31 | src[key] |
| tests.js:571:28:571:30 | key | tests.js:571:24:571:31 | src[key] |
#select
| examples/PrototypePollutingFunction.js:7:13:7:15 | dst | examples/PrototypePollutingFunction.js:2:14:2:16 | key | examples/PrototypePollutingFunction.js:7:13:7:15 | dst | Properties are copied from $@ to $@ without guarding against prototype pollution. | examples/PrototypePollutingFunction.js:2:21:2:23 | src | src | examples/PrototypePollutingFunction.js:7:13:7:15 | dst | dst |
| path-assignment.js:15:13:15:18 | target | path-assignment.js:8:19:8:25 | keys[i] | path-assignment.js:15:13:15:18 | target | The property chain $@ is recursively assigned to $@ without guarding against prototype pollution. | path-assignment.js:8:19:8:25 | keys[i] | here | path-assignment.js:15:13:15:18 | target | target |

View File

@@ -548,3 +548,27 @@ function mergeUsingCallback3(dst, src) {
}
});
}
function copyHasOwnProperty2(dst, src) {
for (let key in src) {
// Guarding the recursive case by dst.hasOwnProperty (or Object.hasOwn) is safe,
// since '__proto__' and 'constructor' are not own properties of the destination object.
if (Object.hasOwn(dst, key)) {
copyHasOwnProperty2(dst[key], src[key]);
} else {
dst[key] = src[key]; // OK
}
}
}
function copyHasOwnProperty3(dst, src) {
for (let key in src) {
// Guarding the recursive case by dst.hasOwnProperty (or Object.hasOwn) is safe,
// since '__proto__' and 'constructor' are not own properties of the destination object.
if (_.has(dst, key)) {
copyHasOwnProperty3(dst[key], src[key]);
} else {
dst[key] = src[key]; // OK
}
}
}