@@ -357,27 +357,6 @@ private predicate maybeNull(Expr expr) {
357357 )
358358}
359359
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 ) {
370- sink .asExpr ( ) =
371- any ( ConstructorCall constrCall |
372- constrCall .getConstructedType ( ) instanceof TypeFile and
373- constrCall .getNumArgument ( ) = 2
374- ) .getArgument ( 0 )
375- }
376- }
377-
378- /** Tracks taint flow to the parent argument of a `File` constructor. */
379- private module TaintedArgFlow = TaintTracking:: Global< TaintedArgConfig > ;
380-
381360/** Holds if `g` is a guard that checks for `..` components. */
382361private predicate pathTraversalGuard ( Guard g , Expr e , boolean branch ) {
383362 // Local taint-flow is used here to handle cases where the validated expression comes from the
@@ -391,31 +370,27 @@ private predicate pathTraversalGuard(Guard g, Expr e, boolean branch) {
391370}
392371
393372/**
394- * A sanitizer that considers a `File` constructor safe if its second argument
395- * is checked for `..` components (`PathTraversalGuard`) or if any internal
396- * `..` components are removed from it (`PathNormalizeSanitizer`).
373+ * A taint step from a child argument of a `java.io.File` constructor to the
374+ * constructor call.
397375 *
398- * This also requires a check to ensure that the first argument of the
399- * `File` constructor is not tainted.
376+ * This step only applies if the argument is not guarded by a check for `..`
377+ * components (`PathTraversalGuard`), or it does not have any internal `..`
378+ * components removed from it (`PathNormalizeSanitizer`), or if the parent
379+ * argument of the constructor may be null.
400380 */
401- private class FileConstructorSanitizer extends PathInjectionSanitizer {
402- FileConstructorSanitizer ( ) {
403- exists ( ConstructorCall constrCall , Argument arg |
381+ private class FileConstructorChildArgumentStep extends AdditionalTaintStep {
382+ override predicate step ( DataFlow :: Node n1 , DataFlow :: Node n2 ) {
383+ exists ( ConstructorCall constrCall |
404384 constrCall .getConstructedType ( ) instanceof TypeFile and
405- // Exclude cases where the parent argument is null since the
406- // `java.io.File` documentation states that such cases are
407- // treated as if invoking the single-argument `File` constructor.
408- not maybeNull ( constrCall .getArgument ( 0 ) ) and
409- // Since we are sanitizing the constructor call, we need to check
410- // that the parent argument is not tainted.
411- not TaintedArgFlow:: flowToExpr ( constrCall .getArgument ( 0 ) ) and
412- arg = constrCall .getArgument ( 1 ) and
385+ n1 .asExpr ( ) = constrCall .getArgument ( 1 ) and
386+ n2 .asExpr ( ) = constrCall and
413387 (
414- arg = DataFlow:: BarrierGuard< pathTraversalGuard / 3 > :: getABarrierNode ( ) .asExpr ( ) or
415- arg = ValidationMethod< pathTraversalGuard / 3 > :: getAValidatedNode ( ) .asExpr ( ) or
416- TaintTracking:: localExprTaint ( any ( PathNormalizeSanitizer p ) , arg )
417- ) and
418- this .asExpr ( ) = constrCall
388+ not n1 = DataFlow:: BarrierGuard< pathTraversalGuard / 3 > :: getABarrierNode ( ) and
389+ not n1 = ValidationMethod< pathTraversalGuard / 3 > :: getAValidatedNode ( ) and
390+ not TaintTracking:: localExprTaint ( any ( PathNormalizeSanitizer p ) , n1 .asExpr ( ) )
391+ or
392+ maybeNull ( constrCall .getArgument ( 0 ) )
393+ )
419394 )
420395 }
421396}
0 commit comments