@@ -72,7 +72,8 @@ private class ExactPathMatchSanitizer extends PathInjectionSanitizer {
7272private class AllowListGuard extends Guard instanceof MethodAccess {
7373 AllowListGuard ( ) {
7474 ( isStringPrefixMatch ( this ) or isPathPrefixMatch ( this ) ) and
75- not isDisallowedPrefix ( super .getAnArgument ( ) )
75+ not isDisallowedPrefix ( super .getAnArgument ( ) ) and
76+ not isDisallowedWord ( super .getAnArgument ( ) )
7677 }
7778
7879 Expr getCheckedExpr ( ) { result = super .getQualifier ( ) }
@@ -86,11 +87,13 @@ private class AllowListGuard extends Guard instanceof MethodAccess {
8687private predicate allowListGuard ( Guard g , Expr e , boolean branch ) {
8788 branch = true and
8889 TaintTracking:: localExprTaint ( e , g .( AllowListGuard ) .getCheckedExpr ( ) ) and
89- exists ( MethodAccess previousGuard |
90+ exists ( Expr previousGuard |
9091 TaintTracking:: localExprTaint ( previousGuard .( PathNormalizeSanitizer ) ,
9192 g .( AllowListGuard ) .getCheckedExpr ( ) )
9293 or
93- previousGuard .( PathTraversalGuard ) .controls ( g .getBasicBlock ( ) .( ConditionBlock ) , false )
94+ previousGuard
95+ .( PathTraversalGuard )
96+ .controls ( g .getBasicBlock ( ) .( ConditionBlock ) , previousGuard .( PathTraversalGuard ) .getBranch ( ) )
9497 )
9598}
9699
@@ -106,9 +109,9 @@ private class AllowListSanitizer extends PathInjectionSanitizer {
106109 * been checked for a trusted prefix.
107110 */
108111private predicate dotDotCheckGuard ( Guard g , Expr e , boolean branch ) {
109- branch = false and
112+ branch = g . ( PathTraversalGuard ) . getBranch ( ) and
110113 TaintTracking:: localExprTaint ( e , g .( PathTraversalGuard ) .getCheckedExpr ( ) ) and
111- exists ( MethodAccess previousGuard |
114+ exists ( Guard previousGuard |
112115 previousGuard .( AllowListGuard ) .controls ( g .getBasicBlock ( ) .( ConditionBlock ) , true )
113116 or
114117 previousGuard .( BlockListGuard ) .controls ( g .getBasicBlock ( ) .( ConditionBlock ) , false )
@@ -142,11 +145,13 @@ private class BlockListGuard extends Guard instanceof MethodAccess {
142145private predicate blockListGuard ( Guard g , Expr e , boolean branch ) {
143146 branch = false and
144147 TaintTracking:: localExprTaint ( e , g .( BlockListGuard ) .getCheckedExpr ( ) ) and
145- exists ( MethodAccess previousGuard |
148+ exists ( Expr previousGuard |
146149 TaintTracking:: localExprTaint ( previousGuard .( PathNormalizeSanitizer ) ,
147150 g .( BlockListGuard ) .getCheckedExpr ( ) )
148151 or
149- previousGuard .( PathTraversalGuard ) .controls ( g .getBasicBlock ( ) .( ConditionBlock ) , false )
152+ previousGuard
153+ .( PathTraversalGuard )
154+ .controls ( g .getBasicBlock ( ) .( ConditionBlock ) , previousGuard .( PathTraversalGuard ) .getBranch ( ) )
150155 )
151156}
152157
@@ -200,14 +205,35 @@ private predicate isDisallowedWord(CompileTimeConstantExpr word) {
200205}
201206
202207/** 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 {
204209 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+ )
208224 }
209225
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+ }
211237}
212238
213239/** A complementary sanitizer that protects against path traversal using path normalization. */
0 commit comments