@@ -357,6 +357,21 @@ private predicate maybeNull(Expr expr) {
357
357
)
358
358
}
359
359
360
+ /** A taint-tracking configuration for reasoning about tainted arguments. */
361
+ private module TaintedArgConfig implements DataFlow:: ConfigSig {
362
+ predicate isSource ( DataFlow:: Node src ) {
363
+ src instanceof ActiveThreatModelSource or
364
+ src instanceof ApiSourceNode or
365
+ // for InlineFlowTest
366
+ src .asExpr ( ) .( MethodCall ) .getMethod ( ) .getName ( ) = "source"
367
+ }
368
+
369
+ predicate isSink ( DataFlow:: Node sink ) { exists ( Call call | sink .asExpr ( ) = call .getAnArgument ( ) ) }
370
+ }
371
+
372
+ /** Tracks taint flow to any argument. */
373
+ private module TaintedArgFlow = TaintTracking:: Global< TaintedArgConfig > ;
374
+
360
375
/** Holds if `g` is a guard that checks for `..` components. */
361
376
private predicate pathTraversalGuard ( Guard g , Expr e , boolean branch ) {
362
377
// Local taint-flow is used here to handle cases where the validated expression comes from the
@@ -370,9 +385,12 @@ private predicate pathTraversalGuard(Guard g, Expr e, boolean branch) {
370
385
}
371
386
372
387
/**
373
- * A sanitizer that considers the second argument to a `File` constructor safe
374
- * if it is checked for `..` components (`PathTraversalGuard`) or if any internal
388
+ * A sanitizer that considers a `File` constructor safe if its second argument
389
+ * is checked for `..` components (`PathTraversalGuard`) or if any internal
375
390
* `..` components are removed from it (`PathNormalizeSanitizer`).
391
+ *
392
+ * This also requires a check to ensure that the first argument of the
393
+ * `File` constructor is not tainted.
376
394
*/
377
395
private class FileConstructorSanitizer extends PathInjectionSanitizer {
378
396
FileConstructorSanitizer ( ) {
@@ -382,6 +400,9 @@ private class FileConstructorSanitizer extends PathInjectionSanitizer {
382
400
// `java.io.File` documentation states that such cases are
383
401
// treated as if invoking the single-argument `File` constructor.
384
402
not maybeNull ( constrCall .getArgument ( 0 ) ) and
403
+ // Since we are sanitizing the constructor call, we need to check
404
+ // that the parent argument is not tainted.
405
+ not TaintedArgFlow:: flowToExpr ( constrCall .getArgument ( 0 ) ) and
385
406
arg = constrCall .getArgument ( 1 ) and
386
407
(
387
408
arg = DataFlow:: BarrierGuard< pathTraversalGuard / 3 > :: getABarrierNode ( ) .asExpr ( ) or
0 commit comments