@@ -18,6 +18,7 @@ import semmle.python.ApiGraphs
1818import semmle.python.dataflow.new.RemoteFlowSources
1919import semmle.python.dataflow.new.internal.DataFlowPublic
2020import experimental.semmle.python.security.DecompressionBomb
21+ import FileAndFormRemoteFlowSource:: FileAndFormRemoteFlowSource
2122
2223/**
2324 * `io.TextIOWrapper(ip, encoding='utf-8')` like following:
@@ -39,59 +40,12 @@ predicate isAdditionalTaintStepTextIOWrapper(DataFlow::Node nodeFrom, DataFlow::
3940 )
4041}
4142
42- module FileAndFormRemoteFlowSource {
43- class FastAPI extends RemoteFlowSource:: Range {
44- FastAPI ( ) {
45- exists ( API:: Node fastApiParam , Expr fastApiUploadFile |
46- fastApiParam =
47- API:: moduleImport ( "fastapi" )
48- .getMember ( "FastAPI" )
49- .getReturn ( )
50- .getMember ( "post" )
51- .getReturn ( )
52- .getParameter ( 0 )
53- .getKeywordParameter ( _) and
54- fastApiUploadFile =
55- API:: moduleImport ( "fastapi" )
56- .getMember ( "UploadFile" )
57- .getASubclass * ( )
58- .getAValueReachableFromSource ( )
59- .asExpr ( )
60- |
61- fastApiUploadFile =
62- fastApiParam .asSource ( ) .asExpr ( ) .( Parameter ) .getAnnotation ( ) .getASubExpression * ( ) and
63- // Multiple Uploaded files as list of fastapi.UploadFile
64- exists ( For f , Attribute attr |
65- fastApiParam .getAValueReachableFromSource ( ) .asExpr ( ) = f .getIter ( ) .getASubExpression * ( )
66- |
67- TaintTracking:: localExprTaint ( f .getIter ( ) , attr .getObject ( ) ) and
68- attr .getName ( ) = [ "filename" , "content_type" , "headers" , "file" , "read" ] and
69- this .asExpr ( ) = attr
70- )
71- or
72- // one Uploaded file as fastapi.UploadFile
73- this =
74- [
75- fastApiParam .getMember ( [ "filename" , "content_type" , "headers" ] ) .asSource ( ) ,
76- fastApiParam
77- .getMember ( "file" )
78- .getMember ( [ "readlines" , "readline" , "read" ] )
79- .getReturn ( )
80- .asSource ( ) , fastApiParam .getMember ( "read" ) .getReturn ( ) .asSource ( )
81- ]
82- )
83- }
84-
85- override string getSourceType ( ) { result = "fastapi HTTP FORM files" }
86- }
87- }
88-
8943module BombsConfig implements DataFlow:: ConfigSig {
9044 predicate isSource ( DataFlow:: Node source ) {
9145 (
9246 source instanceof RemoteFlowSource
9347 or
94- source instanceof FileAndFormRemoteFlowSource :: FastAPI
48+ source instanceof FastAPI
9549 ) and
9650 not source .getLocation ( ) .getFile ( ) .inStdlib ( ) and
9751 not source .getLocation ( ) .getFile ( ) .getRelativePath ( ) .matches ( "%venv%" )
@@ -113,11 +67,11 @@ module BombsConfig implements DataFlow::ConfigSig {
11367 }
11468}
11569
116- module Bombs = TaintTracking:: Global< BombsConfig > ;
70+ module BombsFlow = TaintTracking:: Global< BombsConfig > ;
11771
118- import Bombs :: PathGraph
72+ import BombsFlow :: PathGraph
11973
120- from Bombs :: PathNode source , Bombs :: PathNode sink
121- where Bombs :: flowPath ( source , sink )
74+ from BombsFlow :: PathNode source , BombsFlow :: PathNode sink
75+ where BombsFlow :: flowPath ( source , sink )
12276select sink .getNode ( ) , source , sink , "This uncontrolled file extraction is $@." , source .getNode ( ) ,
12377 "depends on this user controlled data"
0 commit comments