@@ -10,6 +10,8 @@ private import python
1010private import semmle.python.Concepts
1111private import semmle.python.ApiGraphs
1212private import semmle.python.dataflow.new.DataFlow
13+ private import semmle.python.frameworks.internal.InstanceTaintStepsHelper
14+ private import semmle.python.frameworks.Stdlib
1315
1416/**
1517 * INTERNAL: Do not use.
@@ -83,4 +85,78 @@ private module Requests {
8385 private DataFlow:: LocalSourceNode verifyArgBacktracker ( DataFlow:: Node arg ) {
8486 result = verifyArgBacktracker ( DataFlow:: TypeBackTracker:: end ( ) , arg )
8587 }
88+
89+ // ---------------------------------------------------------------------------
90+ // Response
91+ // ---------------------------------------------------------------------------
92+ /**
93+ * Provides models for the `requests.models.Response` class
94+ *
95+ * See https://docs.python-requests.org/en/latest/api/#requests.Response.
96+ */
97+ module Response {
98+ /** Gets a reference to the `requests.models.Response` class. */
99+ private API:: Node classRef ( ) {
100+ result = API:: moduleImport ( "requests" ) .getMember ( "models" ) .getMember ( "Response" )
101+ or
102+ result = API:: moduleImport ( "requests" ) .getMember ( "Response" )
103+ }
104+
105+ /**
106+ * A source of instances of `requests.models.Response`, extend this class to model new instances.
107+ *
108+ * This can include instantiations of the class, return values from function
109+ * calls, or a special parameter that will be set when functions are called by an external
110+ * library.
111+ *
112+ * Use the predicate `Response::instance()` to get references to instances of `requests.models.Response`.
113+ */
114+ abstract class InstanceSource extends DataFlow:: LocalSourceNode { }
115+
116+ /** A direct instantiation of `requests.models.Response`. */
117+ private class ClassInstantiation extends InstanceSource , DataFlow:: CallCfgNode {
118+ ClassInstantiation ( ) { this = classRef ( ) .getACall ( ) }
119+ }
120+
121+ /** Return value from making a reuqest. */
122+ private class RequestReturnValue extends InstanceSource , DataFlow:: Node {
123+ RequestReturnValue ( ) { this = any ( OutgoingRequestCall c ) .getResponse ( ) }
124+ }
125+
126+ /** Gets a reference to an instance of `requests.models.Response`. */
127+ private DataFlow:: TypeTrackingNode instance ( DataFlow:: TypeTracker t ) {
128+ t .start ( ) and
129+ result instanceof InstanceSource
130+ or
131+ exists ( DataFlow:: TypeTracker t2 | result = instance ( t2 ) .track ( t2 , t ) )
132+ }
133+
134+ /** Gets a reference to an instance of `requests.models.Response`. */
135+ DataFlow:: Node instance ( ) { instance ( DataFlow:: TypeTracker:: end ( ) ) .flowsTo ( result ) }
136+
137+ /**
138+ * Taint propagation for `requests.models.Response`.
139+ */
140+ private class InstanceTaintSteps extends InstanceTaintStepsHelper {
141+ InstanceTaintSteps ( ) { this = "requests.models.Response" }
142+
143+ override DataFlow:: Node getInstance ( ) { result = instance ( ) }
144+
145+ override string getAttributeName ( ) {
146+ result in [ "text" , "content" , "raw" , "links" , "cookies" , "headers" ]
147+ }
148+
149+ override string getMethodName ( ) { result in [ "json" , "iter_content" , "iter_lines" ] }
150+
151+ override string getAsyncMethodName ( ) { none ( ) }
152+ }
153+
154+ /** An attribute read that is a file-like instance. */
155+ private class FileLikeInstances extends Stdlib:: FileLikeObject:: InstanceSource {
156+ FileLikeInstances ( ) {
157+ this .( DataFlow:: AttrRead ) .getObject ( ) = instance ( ) and
158+ this .( DataFlow:: AttrRead ) .getAttributeName ( ) = "raw"
159+ }
160+ }
161+ }
86162}
0 commit comments