-
Notifications
You must be signed in to change notification settings - Fork 2k
Expand file tree
/
Copy pathHttpx.qll
More file actions
107 lines (95 loc) · 3.53 KB
/
Httpx.qll
File metadata and controls
107 lines (95 loc) · 3.53 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
/**
* Provides classes modeling security-relevant aspects of the `httpx` PyPI package.
*
* See
* - https://pypi.org/project/httpx/
* - https://www.python-httpx.org/
*/
private import python
private import semmle.python.Concepts
private import semmle.python.ApiGraphs
private import semmle.python.frameworks.data.ModelsAsData
/**
* INTERNAL: Do not use.
*
* Provides models for the `httpx` PyPI package.
*
* See
* - https://pypi.org/project/httpx/
* - https://www.python-httpx.org/
*/
module HttpxModel {
/**
* An outgoing HTTP request, from the `httpx` library.
*
* See https://www.python-httpx.org/api/
*/
private class RequestCall extends Http::Client::Request::Range instanceof API::CallNode {
string methodName;
RequestCall() {
methodName in [Http::httpVerbLower(), "request", "stream"] and
this = API::moduleImport("httpx").getMember(methodName).getACall()
}
override DataFlow::Node getAUrlPart() {
result = super.getArgByName("url")
or
if methodName in ["request", "stream"]
then result = super.getArg(1)
else result = super.getArg(0)
}
override string getFramework() { result = "httpx" }
override predicate disablesCertificateValidation(
DataFlow::Node disablingNode, DataFlow::Node argumentOrigin
) {
disablingNode = super.getKeywordParameter("verify").asSink() and
argumentOrigin = super.getKeywordParameter("verify").getAValueReachingSink() and
// unlike `requests`, httpx treats `None` as turning off verify (and not as the default)
argumentOrigin.asExpr().(ImmutableLiteral).booleanValue() = false
// TODO: Handling of insecure SSLContext passed to verify argument
}
}
/**
* Provides models for the `httpx.[Async]Client` class
*
* See https://www.python-httpx.org/api/#client
*/
module Client {
/** Get a reference to the `httpx.Client` or `httpx.AsyncClient` class. */
API::Node classRef() {
result = API::moduleImport("httpx").getMember(["Client", "AsyncClient"])
or
result = ModelOutput::getATypeNode("httpx.Client~Subclass").getASubclass*()
}
/** A method call on a Client that sends off a request */
private class OutgoingRequestCall extends Http::Client::Request::Range instanceof DataFlow::CallCfgNode
{
string methodName;
OutgoingRequestCall() {
methodName in [Http::httpVerbLower(), "request", "stream"] and
this = classRef().getReturn().getMember(methodName).getACall()
}
override DataFlow::Node getAUrlPart() {
result = super.getArgByName("url")
or
if methodName in ["request", "stream"]
then result = super.getArg(1)
else result = super.getArg(0)
}
override string getFramework() { result = "httpx.[Async]Client" }
override predicate disablesCertificateValidation(
DataFlow::Node disablingNode, DataFlow::Node argumentOrigin
) {
exists(API::CallNode constructor |
constructor = classRef().getACall() and
this = constructor.getReturn().getMember(methodName).getACall()
|
disablingNode = constructor.getKeywordParameter("verify").asSink() and
argumentOrigin = constructor.getKeywordParameter("verify").getAValueReachingSink() and
// unlike `requests`, httpx treats `None` as turning off verify (and not as the default)
argumentOrigin.asExpr().(ImmutableLiteral).booleanValue() = false
// TODO: Handling of insecure SSLContext passed to verify argument
)
}
}
}
}