@@ -25,33 +25,17 @@ class Configuration extends TaintTracking::Configuration {
2525 }
2626}
2727
28- /** TODO add comment */
29- class TernaryOperatorSanitizerGuard extends TaintTracking:: SanitizerGuardNode {
30- TaintTracking:: SanitizerGuardNode originalGuard ;
31-
32- TernaryOperatorSanitizerGuard ( ) {
33- this .getAPredecessor + ( ) .asExpr ( ) .( BooleanLiteral ) .mayHaveBooleanValue ( false ) and
34- this .getAPredecessor + ( ) = originalGuard and
35- not this .asExpr ( ) instanceof LogicalBinaryExpr
36- }
37-
38- override predicate sanitizes ( boolean outcome , Expr e ) {
39- not this .asExpr ( ) instanceof LogNotExpr and
40- originalGuard .sanitizes ( outcome , e )
41- or
42- exists ( boolean originalOutcome |
43- this .asExpr ( ) instanceof LogNotExpr and
44- originalGuard .sanitizes ( originalOutcome , e ) and
45- (
46- originalOutcome = true and outcome = false
47- or
48- originalOutcome = false and outcome = true
49- )
50- )
51- }
52- }
53-
54- /** TODO add comment */
28+ /**
29+ * This sanitizers models the next example:
30+ * let valid = req.params.id ? Number.isInteger(req.params.id) : false
31+ * if (valid) { sink(req.params.id) }
32+ *
33+ * This sanitizer models this way of using ternary operators,
34+ * when the sanitizer guard is used as any of the branches
35+ * instead of being used as the condition.
36+ *
37+ * This sanitizer sanitize the corresponding if statement branch.
38+ */
5539class TernaryOperatorSanitizer extends RequestForgery:: Sanitizer {
5640 TernaryOperatorSanitizer ( ) {
5741 exists (
@@ -80,6 +64,45 @@ class TernaryOperatorSanitizer extends RequestForgery::Sanitizer {
8064 }
8165}
8266
67+ /**
68+ * This sanitizer guard is another way of modeling the example from above
69+ * In this case:
70+ * let valid = req.params.id ? Number.isInteger(req.params.id) : false
71+ * if (!valid) { return }
72+ * sink(req.params.id)
73+ *
74+ * The previous sanitizer is not enough,
75+ * because we are sanitizing the entire if statement branch
76+ * but we need to sanitize the use of this variable from now on.
77+ *
78+ * Thats why we model this sanitizer guard which says that
79+ * the result of the ternary operator execution is a sanitizer guard.
80+ */
81+ class TernaryOperatorSanitizerGuard extends TaintTracking:: SanitizerGuardNode {
82+ TaintTracking:: SanitizerGuardNode originalGuard ;
83+
84+ TernaryOperatorSanitizerGuard ( ) {
85+ this .getAPredecessor + ( ) .asExpr ( ) .( BooleanLiteral ) .mayHaveBooleanValue ( false ) and
86+ this .getAPredecessor + ( ) = originalGuard and
87+ not this .asExpr ( ) instanceof LogicalBinaryExpr
88+ }
89+
90+ override predicate sanitizes ( boolean outcome , Expr e ) {
91+ not this .asExpr ( ) instanceof LogNotExpr and
92+ originalGuard .sanitizes ( outcome , e )
93+ or
94+ exists ( boolean originalOutcome |
95+ this .asExpr ( ) instanceof LogNotExpr and
96+ originalGuard .sanitizes ( originalOutcome , e ) and
97+ (
98+ originalOutcome = true and outcome = false
99+ or
100+ originalOutcome = false and outcome = true
101+ )
102+ )
103+ }
104+ }
105+
83106/**
84107 * Number.isInteger is a sanitizer guard because a number can't be used to exploit a SSRF.
85108 */
0 commit comments