Skip to content

Commit 6969466

Browse files
authored
Merge pull request #83 from esben-semmle/js/bitwise-indexof-sanitizer
Approved by xiemaisi
2 parents ea9bff0 + 2d63524 commit 6969466

File tree

6 files changed

+53
-2
lines changed

6 files changed

+53
-2
lines changed

change-notes/1.18/analysis-javascript.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,8 @@
1212

1313
* Modelling of taint flow through the array operations `map` and `join` has been improved. This may give additional results for the security queries.
1414

15+
* The taint tracking library now recognizes additional sanitization patterns. This may give fewer false-positive results for the security queries.
16+
1517
* Support for popular libraries has been improved. Consequently, queries may produce more results on code bases that use the following libraries:
1618
- [bluebird](http://bluebirdjs.com)
1719
- [browserid-crypto](https://github.com/mozilla/browserid-crypto)

javascript/ql/src/semmle/javascript/dataflow/TaintTracking.qll

Lines changed: 26 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -587,14 +587,14 @@ module TaintTracking {
587587

588588
}
589589

590-
/** A check of the form `if(o.indexOf(x) != -1)`, which sanitizes `x` in its "then" branch. */
590+
/** A check of the form `if(whitelist.indexOf(x) != -1)`, which sanitizes `x` in its "then" branch. */
591591
class IndexOfSanitizer extends AdditionalSanitizerGuardNode, DataFlow::ValueNode {
592592
MethodCallExpr indexOf;
593593
override EqualityTest astNode;
594594

595595
IndexOfSanitizer() {
596596
exists (Expr index | astNode.hasOperands(indexOf, index) |
597-
// one operand is of the form `o.indexOf(x)`
597+
// one operand is of the form `whitelist.indexOf(x)`
598598
indexOf.getMethodName() = "indexOf" and
599599
// and the other one is -1
600600
index.getIntValue() = -1
@@ -612,6 +612,30 @@ module TaintTracking {
612612

613613
}
614614

615+
/**
616+
* A check of the form `if(~whitelist.indexOf(x))`, which sanitizes `x` in its "then" branch.
617+
*
618+
* This sanitizer is equivalent to `if(whitelist.indexOf(x) != -1)`, since `~n = 0` iff `n = -1`.
619+
*/
620+
class BitwiseIndexOfSanitizer extends AdditionalSanitizerGuardNode, DataFlow::ValueNode {
621+
MethodCallExpr indexOf;
622+
override BitNotExpr astNode;
623+
624+
BitwiseIndexOfSanitizer() {
625+
astNode.getOperand() = indexOf and
626+
indexOf.getMethodName() = "indexOf"
627+
}
628+
629+
override predicate sanitizes(boolean outcome, Expr e) {
630+
outcome = true and
631+
e = indexOf.getArgument(0)
632+
}
633+
634+
override predicate appliesTo(Configuration cfg) {
635+
any()
636+
}
637+
638+
}
615639

616640
/** A check of the form `if(x == 'some-constant')`, which sanitizes `x` in its "then" branch. */
617641
class ConstantComparison extends AdditionalSanitizerGuardNode, DataFlow::ValueNode {

javascript/ql/test/library-tests/TaintBarriers/SanitizingGuard.expected

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,3 +29,5 @@
2929
| tst.js:160:9:160:30 | v === " ... sted-1" | ExampleConfiguration | true | tst.js:160:9:160:9 | v |
3030
| tst.js:160:35:160:56 | v === " ... sted-2" | ExampleConfiguration | true | tst.js:160:35:160:35 | v |
3131
| tst.js:166:9:166:16 | v == !!0 | ExampleConfiguration | true | tst.js:166:9:166:9 | v |
32+
| tst.js:184:9:184:21 | ~o.indexOf(v) | ExampleConfiguration | true | tst.js:184:20:184:20 | v |
33+
| tst.js:190:10:190:22 | ~o.indexOf(v) | ExampleConfiguration | true | tst.js:190:21:190:21 | v |

javascript/ql/test/library-tests/TaintBarriers/TaintedSink.expected

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,3 +25,6 @@
2525
| tst.js:155:14:155:14 | v | tst.js:145:13:145:20 | SOURCE() |
2626
| tst.js:163:14:163:14 | v | tst.js:145:13:145:20 | SOURCE() |
2727
| tst.js:169:14:169:14 | v | tst.js:145:13:145:20 | SOURCE() |
28+
| tst.js:182:10:182:10 | v | tst.js:181:13:181:20 | SOURCE() |
29+
| tst.js:187:14:187:14 | v | tst.js:181:13:181:20 | SOURCE() |
30+
| tst.js:191:14:191:14 | v | tst.js:181:13:181:20 | SOURCE() |

javascript/ql/test/library-tests/TaintBarriers/isBarrier.expected

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,3 +22,5 @@
2222
| tst.js:160:35:160:56 | v | ExampleConfiguration |
2323
| tst.js:167:14:167:14 | v | ExampleConfiguration |
2424
| tst.js:176:18:176:18 | v | ExampleConfiguration |
25+
| tst.js:185:14:185:14 | v | ExampleConfiguration |
26+
| tst.js:193:14:193:14 | v | ExampleConfiguration |

javascript/ql/test/library-tests/TaintBarriers/tst.js

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -176,3 +176,21 @@ function customSanitizer() {
176176
v = SANITIZE(v);
177177
SINK(v);
178178
}
179+
180+
function BitwiseIndexOfCheckSanitizer () {
181+
var v = SOURCE();
182+
SINK(v);
183+
184+
if (~o.indexOf(v)) {
185+
SINK(v);
186+
} else {
187+
SINK(v);
188+
}
189+
190+
if (!~o.indexOf(v)) {
191+
SINK(v);
192+
} else {
193+
SINK(v);
194+
}
195+
196+
}

0 commit comments

Comments
 (0)