Skip to content

Commit 96c6e4d

Browse files
committed
JS: Update with new AdditionalTaintStep subclasses
1 parent 561b9d0 commit 96c6e4d

File tree

14 files changed

+169
-187
lines changed

14 files changed

+169
-187
lines changed

javascript/ql/src/Security/CWE-094/ImproperCodeSanitization.ql

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ private DataFlow::Node remoteFlow(DataFlow::TypeTracker t) {
2727
exists(DataFlow::TypeTracker t2, DataFlow::Node prev | prev = remoteFlow(t2) |
2828
t2 = t.smallstep(prev, result)
2929
or
30-
any(TaintTracking::AdditionalTaintStep dts).step(prev, result) and
30+
TaintTracking::sharedTaintStep(prev, result) and
3131
t = t2
3232
)
3333
}

javascript/ql/src/experimental/semmle/javascript/security/dataflow/ResourceExhaustion.qll

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ module ResourceExhaustion {
3737
}
3838

3939
predicate isRestrictedAdditionalTaintStep(DataFlow::Node src, DataFlow::Node dst) {
40-
any(TaintTracking::AdditionalTaintStep dts).step(src, dst) and
40+
TaintTracking::sharedTaintStep(src, dst) and
4141
not dst.asExpr() instanceof AddExpr and
4242
not dst.(DataFlow::MethodCallNode).calls(src, "toString")
4343
}

javascript/ql/src/meta/analysis-quality/TaintSteps.ql

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ import CallGraphQuality
1313

1414
predicate relevantStep(DataFlow::Node pred, DataFlow::Node succ) {
1515
(
16-
any(TaintTracking::AdditionalTaintStep dts).step(pred, succ)
16+
TaintTracking::sharedTaintStep(pred, succ)
1717
or
1818
any(DataFlow::AdditionalFlowStep cfg).step(pred, succ)
1919
or

javascript/ql/src/semmle/javascript/Promises.qll

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -491,14 +491,13 @@ private module AsyncReturnSteps {
491491
/**
492492
* A data-flow step for ordinary return from an async function in a taint configuration.
493493
*/
494-
private class AsyncTaintReturn extends TaintTracking::AdditionalTaintStep, DataFlow::FunctionNode {
495-
Function f;
496-
497-
AsyncTaintReturn() { this.getFunction() = f and f.isAsync() }
498-
494+
private class AsyncTaintReturn extends TaintTracking::SharedTaintStep {
499495
override predicate step(DataFlow::Node pred, DataFlow::Node succ) {
500-
returnExpr(f, pred, _) and
501-
succ.(DataFlow::FunctionReturnNode).getFunction() = f
496+
exists(Function f |
497+
f.isAsync() and
498+
returnExpr(f, pred, _) and
499+
succ.(DataFlow::FunctionReturnNode).getFunction() = f
500+
)
502501
}
503502
}
504503
}

javascript/ql/src/semmle/javascript/frameworks/Angular2.qll

Lines changed: 34 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -180,9 +180,7 @@ module Angular2 {
180180
)
181181
}
182182

183-
private class AngularTaintStep extends TaintTracking::AdditionalTaintStep {
184-
AngularTaintStep() { taintStep(_, this) }
185-
183+
private class AngularTaintStep extends TaintTracking::SharedTaintStep {
186184
override predicate step(DataFlow::Node pred, DataFlow::Node succ) { taintStep(pred, succ) }
187185
}
188186

@@ -483,14 +481,12 @@ module Angular2 {
483481
* A taint step `array -> elem` in `*ngFor="let elem of array"`, or more precisely,
484482
* a step from `array` to each access to `elem`.
485483
*/
486-
private class ForLoopStep extends TaintTracking::AdditionalTaintStep {
487-
ForLoopAttribute attrib;
488-
489-
ForLoopStep() { this = attrib.getIterationDomain() }
490-
484+
private class ForLoopStep extends TaintTracking::SharedTaintStep {
491485
override predicate step(DataFlow::Node pred, DataFlow::Node succ) {
492-
pred = this and
493-
succ = attrib.getAnIteratorAccess()
486+
exists(ForLoopAttribute attrib |
487+
pred = attrib.getIterationDomain() and
488+
succ = attrib.getAnIteratorAccess()
489+
)
494490
}
495491
}
496492

@@ -513,27 +509,26 @@ module Angular2 {
513509
result.getCalleeNode().asExpr().(PipeRefExpr).getName() = name
514510
}
515511

516-
private class BuiltinPipeStep extends TaintTracking::AdditionalTaintStep, DataFlow::CallNode {
517-
string name;
518-
519-
BuiltinPipeStep() { this = getAPipeCall(name) }
520-
512+
private class BuiltinPipeStep extends TaintTracking::SharedTaintStep {
521513
override predicate step(DataFlow::Node pred, DataFlow::Node succ) {
522-
succ = this and
523-
exists(int i | pred = getArgument(i) |
524-
i = 0 and
525-
name =
526-
[
527-
"async", "i18nPlural", "json", "keyvalue", "lowercase", "uppercase", "titlecase",
528-
"slice"
529-
]
514+
exists(DataFlow::CallNode call, string name |
515+
call = getAPipeCall(name) and
516+
succ = call
517+
|
518+
exists(int i | pred = call.getArgument(i) |
519+
i = 0 and
520+
name =
521+
[
522+
"async", "i18nPlural", "json", "keyvalue", "lowercase", "uppercase", "titlecase",
523+
"slice"
524+
]
525+
or
526+
i = 1 and name = "date" // date format string
527+
)
530528
or
531-
i = 1 and name = "date" // date format string
529+
name = "translate" and
530+
pred = [call.getArgument(1), call.getOptionArgument(1, _)]
532531
)
533-
or
534-
name = "translate" and
535-
succ = this and
536-
pred = [getArgument(1), getOptionArgument(1, _)]
537532
}
538533
}
539534

@@ -582,27 +577,23 @@ module Angular2 {
582577
* </mat-table>
583578
* ```
584579
*/
585-
private class MatTableTaintStep extends TaintTracking::AdditionalTaintStep {
586-
MatTableElement table;
587-
588-
MatTableTaintStep() { this = table.getDataSourceNode() }
589-
580+
private class MatTableTaintStep extends TaintTracking::SharedTaintStep {
590581
override predicate step(DataFlow::Node pred, DataFlow::Node succ) {
591-
pred = this and
592-
succ = table.getARowRef()
582+
exists(MatTableElement table |
583+
pred = table.getDataSourceNode() and
584+
succ = table.getARowRef()
585+
)
593586
}
594587
}
595588

596589
/** A taint step into the data array of a `MatTableDataSource` instance. */
597-
private class MatTableDataSourceStep extends TaintTracking::AdditionalTaintStep, DataFlow::NewNode {
598-
MatTableDataSourceStep() {
599-
this =
600-
DataFlow::moduleMember("@angular/material/table", "MatTableDataSource").getAnInstantiation()
601-
}
602-
590+
private class MatTableDataSourceStep extends TaintTracking::SharedTaintStep {
603591
override predicate step(DataFlow::Node pred, DataFlow::Node succ) {
604-
pred = [getArgument(0), getAPropertyWrite("data").getRhs()] and
605-
succ = this
592+
exists(DataFlow::NewNode invoke |
593+
invoke = DataFlow::moduleMember("@angular/material/table", "MatTableDataSource").getAnInstantiation() and
594+
pred = [invoke.getArgument(0), invoke.getAPropertyWrite("data").getRhs()] and
595+
succ = invoke
596+
)
606597
}
607598
}
608599
}

javascript/ql/src/semmle/javascript/frameworks/Classnames.qll

Lines changed: 11 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -8,32 +8,24 @@ private DataFlow::SourceNode classnames() {
88
result = DataFlow::moduleImport(["classnames", "classnames/dedupe", "classnames/bind"])
99
}
1010

11-
private class PlainStep extends TaintTracking::AdditionalTaintStep, DataFlow::CallNode {
12-
PlainStep() {
13-
this = classnames().getACall()
14-
or
15-
this = DataFlow::moduleImport("clsx").getACall()
16-
}
17-
11+
private class PlainStep extends TaintTracking::SharedTaintStep {
1812
override predicate step(DataFlow::Node pred, DataFlow::Node succ) {
19-
pred = getAnArgument() and
20-
succ = this
13+
exists(DataFlow::CallNode call |
14+
call = [classnames().getACall(), DataFlow::moduleImport("clsx").getACall()] and
15+
pred = call.getAnArgument() and
16+
succ = call
17+
)
2118
}
2219
}
2320

2421
/**
2522
* Step from `x` or `y` to the result of `classnames.bind(x)(y)`.
2623
*/
27-
private class BindStep extends TaintTracking::AdditionalTaintStep, DataFlow::CallNode {
28-
DataFlow::CallNode bind;
29-
30-
BindStep() {
31-
bind = classnames().getAMemberCall("bind") and
32-
this = bind.getACall()
33-
}
34-
24+
private class BindStep extends TaintTracking::SharedTaintStep {
3525
override predicate step(DataFlow::Node pred, DataFlow::Node succ) {
36-
pred = [getAnArgument(), bind.getAnArgument(), bind.getOptionArgument(_, _)] and
37-
succ = this
26+
exists(DataFlow::CallNode bind | bind = classnames().getAMemberCall("bind") |
27+
pred = [succ.(DataFlow::CallNode).getAnArgument(), bind.getAnArgument(), bind.getOptionArgument(_, _)] and
28+
succ = bind.getACall()
29+
)
3830
}
3931
}

javascript/ql/src/semmle/javascript/frameworks/DateFunctions.qll

Lines changed: 28 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -29,24 +29,26 @@ private module DateFns {
2929
*
3030
* A format string can use single-quotes to include mostly arbitrary text.
3131
*/
32-
private class FormatStep extends TaintTracking::AdditionalTaintStep, DataFlow::CallNode {
33-
FormatStep() { this = formatFunction().getACall() }
34-
35-
override predicate step(DataFlow::Node pred, DataFlow::Node succ) {
36-
pred = getArgument(1) and
37-
succ = this
32+
private class FormatStep extends TaintTracking::SharedTaintStep {
33+
override predicate stringManipulationStep(DataFlow::Node pred, DataFlow::Node succ) {
34+
exists(DataFlow::CallNode call |
35+
call = formatFunction().getACall() and
36+
pred = call.getArgument(1) and
37+
succ = call
38+
)
3839
}
3940
}
4041

4142
/**
4243
* Taint step of form: `f -> format(f)(date)`
4344
*/
44-
private class CurriedFormatStep extends TaintTracking::AdditionalTaintStep, DataFlow::CallNode {
45-
CurriedFormatStep() { this = curriedFormatFunction().getACall() }
46-
47-
override predicate step(DataFlow::Node pred, DataFlow::Node succ) {
48-
pred = getArgument(0) and
49-
succ = getACall()
45+
private class CurriedFormatStep extends TaintTracking::SharedTaintStep {
46+
override predicate stringManipulationStep(DataFlow::Node pred, DataFlow::Node succ) {
47+
exists(DataFlow::CallNode call |
48+
call = curriedFormatFunction().getACall() and
49+
pred = call.getArgument(0) and
50+
succ = call.getACall()
51+
)
5052
}
5153
}
5254
}
@@ -66,12 +68,13 @@ private module Moment {
6668
*
6769
* The format string can use backslash-escaping to include mostly arbitrary text.
6870
*/
69-
private class MomentFormatStep extends TaintTracking::AdditionalTaintStep, DataFlow::CallNode {
70-
MomentFormatStep() { this = moment().getMember("format").getACall() }
71-
72-
override predicate step(DataFlow::Node pred, DataFlow::Node succ) {
73-
pred = getArgument(0) and
74-
succ = this
71+
private class MomentFormatStep extends TaintTracking::SharedTaintStep {
72+
override predicate stringManipulationStep(DataFlow::Node pred, DataFlow::Node succ) {
73+
exists(DataFlow::CallNode call |
74+
call = moment().getMember("format").getACall() and
75+
pred = call.getArgument(0) and
76+
succ = call
77+
)
7578
}
7679
}
7780
}
@@ -82,12 +85,13 @@ private module DateFormat {
8285
*
8386
* The format string can use single-quotes to include mostly arbitrary text.
8487
*/
85-
private class DateFormatStep extends TaintTracking::AdditionalTaintStep, DataFlow::CallNode {
86-
DateFormatStep() { this = DataFlow::moduleImport("dateformat").getACall() }
87-
88-
override predicate step(DataFlow::Node pred, DataFlow::Node succ) {
89-
pred = getArgument(1) and
90-
succ = this
88+
private class DateFormatStep extends TaintTracking::SharedTaintStep {
89+
override predicate stringManipulationStep(DataFlow::Node pred, DataFlow::Node succ) {
90+
exists(DataFlow::CallNode call |
91+
call = DataFlow::moduleImport("dateformat").getACall() and
92+
pred = call.getArgument(1) and
93+
succ = call
94+
)
9195
}
9296
}
9397
}

javascript/ql/src/semmle/javascript/frameworks/JWT.qll

Lines changed: 13 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -11,12 +11,13 @@ private module JwtDecode {
1111
/**
1212
* A taint-step for `succ = require("jwt-decode")(pred)`.
1313
*/
14-
private class JwtDecodeStep extends TaintTracking::AdditionalTaintStep, DataFlow::CallNode {
15-
JwtDecodeStep() { this = DataFlow::moduleImport("jwt-decode").getACall() }
16-
17-
override predicate step(DataFlow::Node pred, DataFlow::Node succ) {
18-
pred = this.getArgument(0) and
19-
succ = this
14+
private class JwtDecodeStep extends TaintTracking::SharedTaintStep {
15+
override predicate deserializeStep(DataFlow::Node pred, DataFlow::Node succ) {
16+
exists(DataFlow::CallNode call |
17+
call = DataFlow::moduleImport("jwt-decode").getACall() and
18+
pred = call.getArgument(0) and
19+
succ = call
20+
)
2021
}
2122
}
2223
}
@@ -28,12 +29,13 @@ private module JsonWebToken {
2829
/**
2930
* A taint-step for `require("jsonwebtoken").verify(pred, "key", (err succ) => {...})`.
3031
*/
31-
private class VerifyStep extends TaintTracking::AdditionalTaintStep, DataFlow::CallNode {
32-
VerifyStep() { this = DataFlow::moduleMember("jsonwebtoken", "verify").getACall() }
33-
32+
private class VerifyStep extends TaintTracking::SharedTaintStep {
3433
override predicate step(DataFlow::Node pred, DataFlow::Node succ) {
35-
pred = this.getArgument(0) and
36-
succ = this.getABoundCallbackParameter(2, 1)
34+
exists(DataFlow::CallNode call |
35+
call = DataFlow::moduleMember("jsonwebtoken", "verify").getACall() and
36+
pred = call.getArgument(0) and
37+
succ = call.getABoundCallbackParameter(2, 1)
38+
)
3739
}
3840
}
3941

javascript/ql/src/semmle/javascript/frameworks/LodashUnderscore.qll

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -440,11 +440,9 @@ module LodashUnderscore {
440440
/**
441441
* A model for taint-steps involving (non-function) underscore methods.
442442
*/
443-
private class UnderscoreTaintStep extends TaintTracking::AdditionalTaintStep {
444-
UnderscoreTaintStep() { underscoreTaintStep(this, _) }
445-
443+
private class UnderscoreTaintStep extends TaintTracking::SharedTaintStep {
446444
override predicate step(DataFlow::Node pred, DataFlow::Node succ) {
447-
underscoreTaintStep(pred, succ) and pred = this
445+
underscoreTaintStep(pred, succ)
448446
}
449447
}
450448
}

0 commit comments

Comments
 (0)