@@ -72,7 +72,8 @@ private class ExactPathMatchSanitizer extends PathInjectionSanitizer {
72
72
private class AllowListGuard extends Guard instanceof MethodAccess {
73
73
AllowListGuard ( ) {
74
74
( isStringPrefixMatch ( this ) or isPathPrefixMatch ( this ) ) and
75
- not isDisallowedPrefix ( super .getAnArgument ( ) )
75
+ not isDisallowedPrefix ( super .getAnArgument ( ) ) and
76
+ not isDisallowedWord ( super .getAnArgument ( ) )
76
77
}
77
78
78
79
Expr getCheckedExpr ( ) { result = super .getQualifier ( ) }
@@ -86,11 +87,13 @@ private class AllowListGuard extends Guard instanceof MethodAccess {
86
87
private predicate allowListGuard ( Guard g , Expr e , boolean branch ) {
87
88
branch = true and
88
89
TaintTracking:: localExprTaint ( e , g .( AllowListGuard ) .getCheckedExpr ( ) ) and
89
- exists ( MethodAccess previousGuard |
90
+ exists ( Expr previousGuard |
90
91
TaintTracking:: localExprTaint ( previousGuard .( PathNormalizeSanitizer ) ,
91
92
g .( AllowListGuard ) .getCheckedExpr ( ) )
92
93
or
93
- previousGuard .( PathTraversalGuard ) .controls ( g .getBasicBlock ( ) .( ConditionBlock ) , false )
94
+ previousGuard
95
+ .( PathTraversalGuard )
96
+ .controls ( g .getBasicBlock ( ) .( ConditionBlock ) , previousGuard .( PathTraversalGuard ) .getBranch ( ) )
94
97
)
95
98
}
96
99
@@ -106,9 +109,9 @@ private class AllowListSanitizer extends PathInjectionSanitizer {
106
109
* been checked for a trusted prefix.
107
110
*/
108
111
private predicate dotDotCheckGuard ( Guard g , Expr e , boolean branch ) {
109
- branch = false and
112
+ branch = g . ( PathTraversalGuard ) . getBranch ( ) and
110
113
TaintTracking:: localExprTaint ( e , g .( PathTraversalGuard ) .getCheckedExpr ( ) ) and
111
- exists ( MethodAccess previousGuard |
114
+ exists ( Guard previousGuard |
112
115
previousGuard .( AllowListGuard ) .controls ( g .getBasicBlock ( ) .( ConditionBlock ) , true )
113
116
or
114
117
previousGuard .( BlockListGuard ) .controls ( g .getBasicBlock ( ) .( ConditionBlock ) , false )
@@ -142,11 +145,13 @@ private class BlockListGuard extends Guard instanceof MethodAccess {
142
145
private predicate blockListGuard ( Guard g , Expr e , boolean branch ) {
143
146
branch = false and
144
147
TaintTracking:: localExprTaint ( e , g .( BlockListGuard ) .getCheckedExpr ( ) ) and
145
- exists ( MethodAccess previousGuard |
148
+ exists ( Expr previousGuard |
146
149
TaintTracking:: localExprTaint ( previousGuard .( PathNormalizeSanitizer ) ,
147
150
g .( BlockListGuard ) .getCheckedExpr ( ) )
148
151
or
149
- previousGuard .( PathTraversalGuard ) .controls ( g .getBasicBlock ( ) .( ConditionBlock ) , false )
152
+ previousGuard
153
+ .( PathTraversalGuard )
154
+ .controls ( g .getBasicBlock ( ) .( ConditionBlock ) , previousGuard .( PathTraversalGuard ) .getBranch ( ) )
150
155
)
151
156
}
152
157
@@ -200,14 +205,35 @@ private predicate isDisallowedWord(CompileTimeConstantExpr word) {
200
205
}
201
206
202
207
/** A complementary guard that protects against path traversal, by looking for the literal `..`. */
203
- private class PathTraversalGuard extends Guard instanceof MethodAccess {
208
+ private class PathTraversalGuard extends Guard {
204
209
PathTraversalGuard ( ) {
205
- super .getMethod ( ) .getDeclaringType ( ) instanceof TypeString and
206
- super .getMethod ( ) .hasName ( [ "contains" , "indexOf" ] ) and
207
- super .getAnArgument ( ) .( CompileTimeConstantExpr ) .getStringValue ( ) = ".."
210
+ exists ( MethodAccess ma |
211
+ ma .getMethod ( ) .getDeclaringType ( ) instanceof TypeString and
212
+ ma .getAnArgument ( ) .( CompileTimeConstantExpr ) .getStringValue ( ) = ".."
213
+ |
214
+ this = ma and
215
+ ma .getMethod ( ) .hasName ( "contains" )
216
+ or
217
+ exists ( EqualityTest eq |
218
+ this = eq and
219
+ ma .getMethod ( ) .hasName ( [ "indexOf" , "lastIndexOf" ] ) and
220
+ eq .getAnOperand ( ) = ma and
221
+ eq .getAnOperand ( ) .( CompileTimeConstantExpr ) .getIntValue ( ) = - 1
222
+ )
223
+ )
208
224
}
209
225
210
- Expr getCheckedExpr ( ) { result = super .getQualifier ( ) }
226
+ Expr getCheckedExpr ( ) {
227
+ exists ( MethodAccess ma | ma = this .( BinaryExpr ) .getAnOperand ( ) or ma = this |
228
+ result = ma .getQualifier ( )
229
+ )
230
+ }
231
+
232
+ boolean getBranch ( ) {
233
+ this instanceof MethodAccess and result = false
234
+ or
235
+ result = this .( EqualityTest ) .polarity ( )
236
+ }
211
237
}
212
238
213
239
/** A complementary sanitizer that protects against path traversal using path normalization. */
0 commit comments