@@ -85,14 +85,20 @@ private class AllowedPrefixGuard extends Guard instanceof MethodAccess {
8585 */
8686private predicate allowedPrefixGuard ( Guard g , Expr e , boolean branch ) {
8787 branch = true and
88+ // Local taint-flow is used here to handle cases where the validated expression comes from the
89+ // expression reaching the sink, but it's not the same one, e.g.:
90+ // File file = source();
91+ // String strPath = file.getCanonicalPath();
92+ // if (strPath.startsWith("/safe/dir"))
93+ // sink(file);
8894 TaintTracking:: localExprTaint ( e , g .( AllowedPrefixGuard ) .getCheckedExpr ( ) ) and
8995 exists ( Expr previousGuard |
9096 TaintTracking:: localExprTaint ( previousGuard .( PathNormalizeSanitizer ) ,
9197 g .( AllowedPrefixGuard ) .getCheckedExpr ( ) )
9298 or
9399 previousGuard
94100 .( PathTraversalGuard )
95- .controls ( g .getBasicBlock ( ) . ( ConditionBlock ) , previousGuard .( PathTraversalGuard ) .getBranch ( ) )
101+ .controls ( g .getBasicBlock ( ) , previousGuard .( PathTraversalGuard ) .getBranch ( ) )
96102 )
97103}
98104
@@ -108,12 +114,18 @@ private class AllowedPrefixSanitizer extends PathInjectionSanitizer {
108114 * been checked for a trusted prefix.
109115 */
110116private predicate dotDotCheckGuard ( Guard g , Expr e , boolean branch ) {
117+ // Local taint-flow is used here to handle cases where the validated expression comes from the
118+ // expression reaching the sink, but it's not the same one, e.g.:
119+ // Path path = source();
120+ // String strPath = path.toString();
121+ // if (!strPath.contains("..") && strPath.startsWith("/safe/dir"))
122+ // sink(path);
111123 branch = g .( PathTraversalGuard ) .getBranch ( ) and
112124 TaintTracking:: localExprTaint ( e , g .( PathTraversalGuard ) .getCheckedExpr ( ) ) and
113125 exists ( Guard previousGuard |
114- previousGuard .( AllowedPrefixGuard ) .controls ( g .getBasicBlock ( ) . ( ConditionBlock ) , true )
126+ previousGuard .( AllowedPrefixGuard ) .controls ( g .getBasicBlock ( ) , true )
115127 or
116- previousGuard .( BlockListGuard ) .controls ( g .getBasicBlock ( ) . ( ConditionBlock ) , false )
128+ previousGuard .( BlockListGuard ) .controls ( g .getBasicBlock ( ) , false )
117129 )
118130}
119131
@@ -140,14 +152,20 @@ private class BlockListGuard extends Guard instanceof MethodAccess {
140152 */
141153private predicate blockListGuard ( Guard g , Expr e , boolean branch ) {
142154 branch = false and
155+ // Local taint-flow is used here to handle cases where the validated expression comes from the
156+ // expression reaching the sink, but it's not the same one, e.g.:
157+ // File file = source();
158+ // String strPath = file.getCanonicalPath();
159+ // if (!strPath.contains("..") && !strPath.startsWith("/dangerous/dir"))
160+ // sink(file);
143161 TaintTracking:: localExprTaint ( e , g .( BlockListGuard ) .getCheckedExpr ( ) ) and
144162 exists ( Expr previousGuard |
145163 TaintTracking:: localExprTaint ( previousGuard .( PathNormalizeSanitizer ) ,
146164 g .( BlockListGuard ) .getCheckedExpr ( ) )
147165 or
148166 previousGuard
149167 .( PathTraversalGuard )
150- .controls ( g .getBasicBlock ( ) . ( ConditionBlock ) , previousGuard .( PathTraversalGuard ) .getBranch ( ) )
168+ .controls ( g .getBasicBlock ( ) , previousGuard .( PathTraversalGuard ) .getBranch ( ) )
151169 )
152170}
153171
@@ -245,10 +263,3 @@ private class PathNormalizeSanitizer extends MethodAccess {
245263 this .getMethod ( ) .hasName ( [ "getCanonicalPath" , "getCanonicalFile" ] )
246264 }
247265}
248-
249- /** A node with path normalization. */
250- class NormalizedPathNode extends DataFlow:: Node {
251- NormalizedPathNode ( ) {
252- TaintTracking:: localExprTaint ( this .asExpr ( ) , any ( PathNormalizeSanitizer ma ) )
253- }
254- }
0 commit comments