Skip to content

Commit c65839b

Browse files
committed
Python: improve urllib3 modeling
1 parent 7d6d8be commit c65839b

File tree

2 files changed

+64
-28
lines changed
  • python/ql

2 files changed

+64
-28
lines changed

python/ql/lib/semmle/python/frameworks/Urllib3.qll

Lines changed: 38 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -1,49 +1,64 @@
11
/**
22
* Provides classes modeling security-relevant aspects of the `urllib3` PyPI package.
3-
* See https://urllib3.readthedocs.io/en/stable/reference/
3+
*
4+
* See
5+
* - https://pypi.org/project/urllib3/
6+
* - https://urllib3.readthedocs.io/en/stable/reference/
47
*/
58

69
private import python
710
private import semmle.python.Concepts
811
private import semmle.python.ApiGraphs
912

1013
/**
11-
* Provides models for the `Urllib3` PyPI package.
12-
* see https://urllib3.readthedocs.io/en/stable/reference/
14+
* Provides models for the `urllib3` PyPI package.
15+
*
16+
* See
17+
* - https://pypi.org/project/urllib3/
18+
* - https://urllib3.readthedocs.io/en/stable/reference/
1319
*/
1420
private module Urllib3 {
1521
/**
16-
* Provides models for the `urllib3.PoolManager` class
22+
* Provides models for the `urllib3.request.RequestMethods` class and subclasses, such
23+
* as the `urllib3.PoolManager` class
1724
*
18-
* See https://urllib3.readthedocs.io/en/stable/reference/urllib3.poolmanager.html.
25+
* See
26+
* - https://urllib3.readthedocs.io/en/stable/reference/urllib3.request.html#urllib3.request.RequestMethods
27+
*
28+
*
29+
* https://urllib3.readthedocs.io/en/stable/reference/urllib3.poolmanager.html.
1930
*/
2031
module PoolManager {
2132
/** Gets a reference to the `urllib3.PoolManager` class. */
22-
private API::Node classRef() { result = API::moduleImport("urllib3").getMember("PoolManager") }
33+
private API::Node classRef() {
34+
result =
35+
API::moduleImport("urllib3")
36+
.getMember(["PoolManager", "ProxyManager", "HTTPConnectionPool", "HTTPSConnectionPool"])
37+
or
38+
result =
39+
API::moduleImport("urllib3")
40+
.getMember("request")
41+
.getMember("RequestMethods")
42+
.getASubclass+()
43+
}
2344

24-
/** Gets a reference to an instance of `urllib3.PoolManager`. */
45+
/** Gets a reference to an instance of a `urllib3.request.RequestMethods` subclass. */
2546
private API::Node instance() { result = classRef().getReturn() }
2647

48+
/**
49+
* A call to a method making an outgoing request.
50+
*
51+
* See
52+
* - https://urllib3.readthedocs.io/en/stable/reference/urllib3.request.html#urllib3.request.RequestMethods
53+
* - https://urllib3.readthedocs.io/en/stable/reference/urllib3.connectionpool.html#urllib3.HTTPConnectionPool.urlopen
54+
*/
2755
private class RequestCall extends HTTP::Client::Request::Range, DataFlow::CallCfgNode {
2856
RequestCall() {
2957
this =
30-
instance().getMember(["request", "request_encode_url", "request_encode_body"]).getACall()
31-
}
32-
33-
override DataFlow::Node getAUrlPart() { result in [this.getArg(1), this.getArgByName("url")] }
34-
35-
override string getFramework() { result = "urllib3.PoolManager" }
36-
37-
override predicate disablesCertificateValidation(
38-
DataFlow::Node disablingNode, DataFlow::Node argumentOrigin
39-
) {
40-
// TODO: Look into disabling certificate validation
41-
none()
58+
instance()
59+
.getMember(["request", "request_encode_url", "request_encode_body", "urlopen"])
60+
.getACall()
4261
}
43-
}
44-
45-
private class UrlOpenCall extends HTTP::Client::Request::Range, DataFlow::CallCfgNode {
46-
UrlOpenCall() { this = instance().getMember("urlopen").getACall() }
4762

4863
override DataFlow::Node getAUrlPart() { result in [this.getArg(1), this.getArgByName("url")] }
4964

Lines changed: 26 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,29 @@
11
import urllib3
22

3-
http = urllib3.PoolManager()
3+
pool = urllib3.PoolManager()
44

5-
resp = http.request("method", "url") # $ clientRequestUrlPart="url"
6-
resp = http.request("method", url="url") # $ clientRequestUrlPart="url"
7-
resp = http.urlopen("method", "url") # $ clientRequestUrlPart="url"
8-
resp = http.urlopen("method", url="url") # $ clientRequestUrlPart="url"
5+
resp = pool.request("method", "url") # $ clientRequestUrlPart="url"
6+
resp = pool.request("method", url="url") # $ clientRequestUrlPart="url"
7+
resp = pool.urlopen("method", "url") # $ clientRequestUrlPart="url"
8+
resp = pool.urlopen("method", url="url") # $ clientRequestUrlPart="url"
9+
10+
pool = urllib3.ProxyManager("http://proxy")
11+
12+
resp = pool.request("method", "url") # $ clientRequestUrlPart="url"
13+
resp = pool.request("method", url="url") # $ clientRequestUrlPart="url"
14+
resp = pool.urlopen("method", "url") # $ clientRequestUrlPart="url"
15+
resp = pool.urlopen("method", url="url") # $ clientRequestUrlPart="url"
16+
17+
pool = urllib3.HTTPConnectionPool("host")
18+
19+
resp = pool.request("method", "url") # $ clientRequestUrlPart="url"
20+
resp = pool.request("method", url="url") # $ clientRequestUrlPart="url"
21+
resp = pool.urlopen("method", "url") # $ clientRequestUrlPart="url"
22+
resp = pool.urlopen("method", url="url") # $ clientRequestUrlPart="url"
23+
24+
pool = urllib3.HTTPSConnectionPool("host")
25+
26+
resp = pool.request("method", "url") # $ clientRequestUrlPart="url"
27+
resp = pool.request("method", url="url") # $ clientRequestUrlPart="url"
28+
resp = pool.urlopen("method", "url") # $ clientRequestUrlPart="url"
29+
resp = pool.urlopen("method", url="url") # $ clientRequestUrlPart="url"

0 commit comments

Comments
 (0)