Skip to content

Commit 16683ae

Browse files
authored
Merge pull request #21590 from github/tausbn/python-improve-bind-all-interfaces-query
Python: Improve "bind all interfaces" query
2 parents e7d3eed + a0b3c2f commit 16683ae

File tree

9 files changed

+156
-53
lines changed

9 files changed

+156
-53
lines changed
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
extensions:
2+
- addsTo:
3+
pack: codeql/python-all
4+
extensible: typeModel
5+
data:
6+
# See https://eventlet.readthedocs.io/en/latest/patching.html
7+
- ['socket.socket', 'eventlet', 'Member[green].Member[socket].Member[socket].ReturnValue']
8+
# eventlet also re-exports as eventlet.socket for convenience
9+
- ['socket.socket', 'eventlet', 'Member[socket].Member[socket].ReturnValue']
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
extensions:
2+
- addsTo:
3+
pack: codeql/python-all
4+
extensible: typeModel
5+
data:
6+
# See https://www.gevent.org/api/gevent.socket.html
7+
- ['socket.socket', 'gevent', 'Member[socket].Member[socket].ReturnValue']

python/ql/lib/semmle/python/frameworks/Stdlib.model.yml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,8 @@ extensions:
2727
extensible: sinkModel
2828
data:
2929
- ["zipfile.ZipFile","Member[extractall].Argument[0,path:]", "path-injection"]
30+
# See https://docs.python.org/3/library/socket.html#socket.socket.bind
31+
- ["socket.socket", "Member[bind].Argument[0,address:]", "bind-socket-all-interfaces"]
3032

3133
- addsTo:
3234
pack: codeql/python-all
@@ -184,6 +186,8 @@ extensions:
184186
pack: codeql/python-all
185187
extensible: typeModel
186188
data:
189+
# See https://docs.python.org/3/library/socket.html#socket.socket
190+
- ['socket.socket', 'socket', 'Member[socket].ReturnValue']
187191
# See https://docs.python.org/3/library/urllib.parse.html#urllib.parse.urlparse
188192
- ["urllib.parse.ParseResult~Subclass", 'urllib', 'Member[parse].Member[urlparse]']
189193

python/ql/src/Security/CVE-2018-1281/BindToAllInterfaces.ql

Lines changed: 23 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
* @name Binding a socket to all network interfaces
33
* @description Binding a socket to all interfaces opens it up to traffic from any IPv4 address
44
* and is therefore associated with security risks.
5-
* @kind problem
5+
* @kind path-problem
66
* @tags security
77
* external/cwe/cwe-200
88
* @problem.severity error
@@ -14,7 +14,9 @@
1414

1515
import python
1616
import semmle.python.dataflow.new.DataFlow
17-
import semmle.python.ApiGraphs
17+
import semmle.python.dataflow.new.TaintTracking
18+
private import semmle.python.frameworks.data.ModelsAsData
19+
import BindToAllInterfacesFlow::PathGraph
1820

1921
/** Gets a hostname that can be used to bind to all interfaces. */
2022
private string vulnerableHostname() {
@@ -26,45 +28,26 @@ private string vulnerableHostname() {
2628
]
2729
}
2830

29-
/** Gets a reference to a hostname that can be used to bind to all interfaces. */
30-
private DataFlow::TypeTrackingNode vulnerableHostnameRef(DataFlow::TypeTracker t, string hostname) {
31-
t.start() and
32-
exists(StringLiteral allInterfacesStringLiteral | hostname = vulnerableHostname() |
33-
allInterfacesStringLiteral.getText() = hostname and
34-
result.asExpr() = allInterfacesStringLiteral
35-
)
36-
or
37-
exists(DataFlow::TypeTracker t2 | result = vulnerableHostnameRef(t2, hostname).track(t2, t))
31+
private module BindToAllInterfacesConfig implements DataFlow::ConfigSig {
32+
predicate isSource(DataFlow::Node source) {
33+
source.asExpr().(StringLiteral).getText() = vulnerableHostname()
34+
}
35+
36+
predicate isSink(DataFlow::Node sink) {
37+
ModelOutput::sinkNode(sink, "bind-socket-all-interfaces") and
38+
// Network socket addresses are tuples like (host, port), so we require
39+
// the bind() argument to originate from a tuple expression. This excludes
40+
// AF_UNIX sockets, which pass a plain string path to bind().
41+
any(DataFlow::LocalSourceNode n | n.asExpr() instanceof Tuple).flowsTo(sink)
42+
}
3843
}
3944

40-
/** Gets a reference to a hostname that can be used to bind to all interfaces. */
41-
DataFlow::Node vulnerableHostnameRef(string hostname) {
42-
vulnerableHostnameRef(DataFlow::TypeTracker::end(), hostname).flowsTo(result)
43-
}
44-
45-
/** Gets a reference to a tuple for which the first element is a hostname that can be used to bind to all interfaces. */
46-
private DataFlow::TypeTrackingNode vulnerableAddressTuple(DataFlow::TypeTracker t, string hostname) {
47-
t.start() and
48-
result.asExpr() = any(Tuple tup | tup.getElt(0) = vulnerableHostnameRef(hostname).asExpr())
49-
or
50-
exists(DataFlow::TypeTracker t2 | result = vulnerableAddressTuple(t2, hostname).track(t2, t))
51-
}
45+
private module BindToAllInterfacesFlow = TaintTracking::Global<BindToAllInterfacesConfig>;
5246

53-
/** Gets a reference to a tuple for which the first element is a hostname that can be used to bind to all interfaces. */
54-
DataFlow::Node vulnerableAddressTuple(string hostname) {
55-
vulnerableAddressTuple(DataFlow::TypeTracker::end(), hostname).flowsTo(result)
56-
}
57-
58-
/**
59-
* Gets an instance of `socket.socket` using _some_ address family.
60-
*
61-
* See https://docs.python.org/3/library/socket.html
62-
*/
63-
API::Node socketInstance() { result = API::moduleImport("socket").getMember("socket").getReturn() }
47+
private import BindToAllInterfacesFlow
6448

65-
from DataFlow::CallCfgNode bindCall, DataFlow::Node addressArg, string hostname
66-
where
67-
bindCall = socketInstance().getMember("bind").getACall() and
68-
addressArg = bindCall.getArg(0) and
69-
addressArg = vulnerableAddressTuple(hostname)
70-
select bindCall.asExpr(), "'" + hostname + "' binds a socket to all interfaces."
49+
from PathNode source, PathNode sink
50+
where flowPath(source, sink)
51+
select sink.getNode(), source, sink,
52+
"Binding a socket to all interfaces (using $@) is a security risk.", source.getNode(),
53+
"'" + source.getNode().asExpr().(StringLiteral).getText() + "'"
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
category: minorAnalysis
3+
---
4+
5+
- The `py/bind-socket-all-network-interfaces` query now uses the global data-flow library, leading to better precision and more results. Also, wrappers of `socket.socket` in the `eventlet` and `gevent` libraries are now also recognized as socket binding operations.
Lines changed: 63 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,63 @@
1-
| BindToAllInterfaces_test.py:5:1:5:26 | Attribute() | '0.0.0.0' binds a socket to all interfaces. |
2-
| BindToAllInterfaces_test.py:9:1:9:18 | Attribute() | '' binds a socket to all interfaces. |
3-
| BindToAllInterfaces_test.py:17:1:17:26 | Attribute() | '0.0.0.0' binds a socket to all interfaces. |
4-
| BindToAllInterfaces_test.py:21:1:21:11 | Attribute() | '0.0.0.0' binds a socket to all interfaces. |
5-
| BindToAllInterfaces_test.py:26:1:26:20 | Attribute() | '::' binds a socket to all interfaces. |
1+
#select
2+
| BindToAllInterfaces_test.py:5:9:5:24 | ControlFlowNode for Tuple | BindToAllInterfaces_test.py:5:9:5:17 | ControlFlowNode for StringLiteral | BindToAllInterfaces_test.py:5:9:5:24 | ControlFlowNode for Tuple | Binding a socket to all interfaces (using $@) is a security risk. | BindToAllInterfaces_test.py:5:9:5:17 | ControlFlowNode for StringLiteral | '0.0.0.0' |
3+
| BindToAllInterfaces_test.py:9:9:9:16 | ControlFlowNode for Tuple | BindToAllInterfaces_test.py:9:9:9:10 | ControlFlowNode for StringLiteral | BindToAllInterfaces_test.py:9:9:9:16 | ControlFlowNode for Tuple | Binding a socket to all interfaces (using $@) is a security risk. | BindToAllInterfaces_test.py:9:9:9:10 | ControlFlowNode for StringLiteral | '' |
4+
| BindToAllInterfaces_test.py:17:9:17:24 | ControlFlowNode for Tuple | BindToAllInterfaces_test.py:16:14:16:22 | ControlFlowNode for StringLiteral | BindToAllInterfaces_test.py:17:9:17:24 | ControlFlowNode for Tuple | Binding a socket to all interfaces (using $@) is a security risk. | BindToAllInterfaces_test.py:16:14:16:22 | ControlFlowNode for StringLiteral | '0.0.0.0' |
5+
| BindToAllInterfaces_test.py:21:8:21:10 | ControlFlowNode for tup | BindToAllInterfaces_test.py:16:14:16:22 | ControlFlowNode for StringLiteral | BindToAllInterfaces_test.py:21:8:21:10 | ControlFlowNode for tup | Binding a socket to all interfaces (using $@) is a security risk. | BindToAllInterfaces_test.py:16:14:16:22 | ControlFlowNode for StringLiteral | '0.0.0.0' |
6+
| BindToAllInterfaces_test.py:26:9:26:18 | ControlFlowNode for Tuple | BindToAllInterfaces_test.py:26:9:26:12 | ControlFlowNode for StringLiteral | BindToAllInterfaces_test.py:26:9:26:18 | ControlFlowNode for Tuple | Binding a socket to all interfaces (using $@) is a security risk. | BindToAllInterfaces_test.py:26:9:26:12 | ControlFlowNode for StringLiteral | '::' |
7+
| BindToAllInterfaces_test.py:39:17:39:41 | ControlFlowNode for Tuple | BindToAllInterfaces_test.py:34:26:34:34 | ControlFlowNode for StringLiteral | BindToAllInterfaces_test.py:39:17:39:41 | ControlFlowNode for Tuple | Binding a socket to all interfaces (using $@) is a security risk. | BindToAllInterfaces_test.py:34:26:34:34 | ControlFlowNode for StringLiteral | '0.0.0.0' |
8+
| BindToAllInterfaces_test.py:48:9:48:18 | ControlFlowNode for Tuple | BindToAllInterfaces_test.py:46:35:46:43 | ControlFlowNode for StringLiteral | BindToAllInterfaces_test.py:48:9:48:18 | ControlFlowNode for Tuple | Binding a socket to all interfaces (using $@) is a security risk. | BindToAllInterfaces_test.py:46:35:46:43 | ControlFlowNode for StringLiteral | '0.0.0.0' |
9+
| BindToAllInterfaces_test.py:53:10:53:25 | ControlFlowNode for Tuple | BindToAllInterfaces_test.py:53:10:53:18 | ControlFlowNode for StringLiteral | BindToAllInterfaces_test.py:53:10:53:25 | ControlFlowNode for Tuple | Binding a socket to all interfaces (using $@) is a security risk. | BindToAllInterfaces_test.py:53:10:53:18 | ControlFlowNode for StringLiteral | '0.0.0.0' |
10+
| BindToAllInterfaces_test.py:58:10:58:25 | ControlFlowNode for Tuple | BindToAllInterfaces_test.py:58:10:58:18 | ControlFlowNode for StringLiteral | BindToAllInterfaces_test.py:58:10:58:25 | ControlFlowNode for Tuple | Binding a socket to all interfaces (using $@) is a security risk. | BindToAllInterfaces_test.py:58:10:58:18 | ControlFlowNode for StringLiteral | '0.0.0.0' |
11+
edges
12+
| BindToAllInterfaces_test.py:5:9:5:17 | ControlFlowNode for StringLiteral | BindToAllInterfaces_test.py:5:9:5:24 | ControlFlowNode for Tuple | provenance | Sink:MaD:63 |
13+
| BindToAllInterfaces_test.py:9:9:9:10 | ControlFlowNode for StringLiteral | BindToAllInterfaces_test.py:9:9:9:16 | ControlFlowNode for Tuple | provenance | Sink:MaD:63 |
14+
| BindToAllInterfaces_test.py:16:1:16:10 | ControlFlowNode for ALL_LOCALS | BindToAllInterfaces_test.py:17:9:17:24 | ControlFlowNode for Tuple | provenance | Sink:MaD:63 |
15+
| BindToAllInterfaces_test.py:16:1:16:10 | ControlFlowNode for ALL_LOCALS | BindToAllInterfaces_test.py:20:1:20:3 | ControlFlowNode for tup | provenance | |
16+
| BindToAllInterfaces_test.py:16:14:16:22 | ControlFlowNode for StringLiteral | BindToAllInterfaces_test.py:16:1:16:10 | ControlFlowNode for ALL_LOCALS | provenance | |
17+
| BindToAllInterfaces_test.py:20:1:20:3 | ControlFlowNode for tup | BindToAllInterfaces_test.py:21:8:21:10 | ControlFlowNode for tup | provenance | Sink:MaD:63 |
18+
| BindToAllInterfaces_test.py:26:9:26:12 | ControlFlowNode for StringLiteral | BindToAllInterfaces_test.py:26:9:26:18 | ControlFlowNode for Tuple | provenance | Sink:MaD:63 |
19+
| BindToAllInterfaces_test.py:33:18:33:21 | ControlFlowNode for self [Return] [Attribute bind_addr] | BindToAllInterfaces_test.py:41:10:41:17 | ControlFlowNode for Server() [Attribute bind_addr] | provenance | |
20+
| BindToAllInterfaces_test.py:34:9:34:12 | [post] ControlFlowNode for self [Attribute bind_addr] | BindToAllInterfaces_test.py:33:18:33:21 | ControlFlowNode for self [Return] [Attribute bind_addr] | provenance | |
21+
| BindToAllInterfaces_test.py:34:26:34:34 | ControlFlowNode for StringLiteral | BindToAllInterfaces_test.py:34:9:34:12 | [post] ControlFlowNode for self [Attribute bind_addr] | provenance | |
22+
| BindToAllInterfaces_test.py:37:15:37:18 | ControlFlowNode for self [Attribute bind_addr] | BindToAllInterfaces_test.py:39:17:39:20 | ControlFlowNode for self [Attribute bind_addr] | provenance | |
23+
| BindToAllInterfaces_test.py:39:17:39:20 | ControlFlowNode for self [Attribute bind_addr] | BindToAllInterfaces_test.py:39:17:39:30 | ControlFlowNode for Attribute | provenance | |
24+
| BindToAllInterfaces_test.py:39:17:39:30 | ControlFlowNode for Attribute | BindToAllInterfaces_test.py:39:17:39:41 | ControlFlowNode for Tuple | provenance | Sink:MaD:63 |
25+
| BindToAllInterfaces_test.py:41:1:41:6 | ControlFlowNode for server [Attribute bind_addr] | BindToAllInterfaces_test.py:42:1:42:6 | ControlFlowNode for server [Attribute bind_addr] | provenance | |
26+
| BindToAllInterfaces_test.py:41:10:41:17 | ControlFlowNode for Server() [Attribute bind_addr] | BindToAllInterfaces_test.py:41:1:41:6 | ControlFlowNode for server [Attribute bind_addr] | provenance | |
27+
| BindToAllInterfaces_test.py:42:1:42:6 | ControlFlowNode for server [Attribute bind_addr] | BindToAllInterfaces_test.py:37:15:37:18 | ControlFlowNode for self [Attribute bind_addr] | provenance | |
28+
| BindToAllInterfaces_test.py:46:1:46:4 | ControlFlowNode for host | BindToAllInterfaces_test.py:48:9:48:18 | ControlFlowNode for Tuple | provenance | Sink:MaD:63 |
29+
| BindToAllInterfaces_test.py:46:8:46:44 | ControlFlowNode for Attribute() | BindToAllInterfaces_test.py:46:1:46:4 | ControlFlowNode for host | provenance | |
30+
| BindToAllInterfaces_test.py:46:35:46:43 | ControlFlowNode for StringLiteral | BindToAllInterfaces_test.py:46:8:46:44 | ControlFlowNode for Attribute() | provenance | dict.get |
31+
| BindToAllInterfaces_test.py:53:10:53:18 | ControlFlowNode for StringLiteral | BindToAllInterfaces_test.py:53:10:53:25 | ControlFlowNode for Tuple | provenance | Sink:MaD:63 |
32+
| BindToAllInterfaces_test.py:58:10:58:18 | ControlFlowNode for StringLiteral | BindToAllInterfaces_test.py:58:10:58:25 | ControlFlowNode for Tuple | provenance | Sink:MaD:63 |
33+
nodes
34+
| BindToAllInterfaces_test.py:5:9:5:17 | ControlFlowNode for StringLiteral | semmle.label | ControlFlowNode for StringLiteral |
35+
| BindToAllInterfaces_test.py:5:9:5:24 | ControlFlowNode for Tuple | semmle.label | ControlFlowNode for Tuple |
36+
| BindToAllInterfaces_test.py:9:9:9:10 | ControlFlowNode for StringLiteral | semmle.label | ControlFlowNode for StringLiteral |
37+
| BindToAllInterfaces_test.py:9:9:9:16 | ControlFlowNode for Tuple | semmle.label | ControlFlowNode for Tuple |
38+
| BindToAllInterfaces_test.py:16:1:16:10 | ControlFlowNode for ALL_LOCALS | semmle.label | ControlFlowNode for ALL_LOCALS |
39+
| BindToAllInterfaces_test.py:16:14:16:22 | ControlFlowNode for StringLiteral | semmle.label | ControlFlowNode for StringLiteral |
40+
| BindToAllInterfaces_test.py:17:9:17:24 | ControlFlowNode for Tuple | semmle.label | ControlFlowNode for Tuple |
41+
| BindToAllInterfaces_test.py:20:1:20:3 | ControlFlowNode for tup | semmle.label | ControlFlowNode for tup |
42+
| BindToAllInterfaces_test.py:21:8:21:10 | ControlFlowNode for tup | semmle.label | ControlFlowNode for tup |
43+
| BindToAllInterfaces_test.py:26:9:26:12 | ControlFlowNode for StringLiteral | semmle.label | ControlFlowNode for StringLiteral |
44+
| BindToAllInterfaces_test.py:26:9:26:18 | ControlFlowNode for Tuple | semmle.label | ControlFlowNode for Tuple |
45+
| BindToAllInterfaces_test.py:33:18:33:21 | ControlFlowNode for self [Return] [Attribute bind_addr] | semmle.label | ControlFlowNode for self [Return] [Attribute bind_addr] |
46+
| BindToAllInterfaces_test.py:34:9:34:12 | [post] ControlFlowNode for self [Attribute bind_addr] | semmle.label | [post] ControlFlowNode for self [Attribute bind_addr] |
47+
| BindToAllInterfaces_test.py:34:26:34:34 | ControlFlowNode for StringLiteral | semmle.label | ControlFlowNode for StringLiteral |
48+
| BindToAllInterfaces_test.py:37:15:37:18 | ControlFlowNode for self [Attribute bind_addr] | semmle.label | ControlFlowNode for self [Attribute bind_addr] |
49+
| BindToAllInterfaces_test.py:39:17:39:20 | ControlFlowNode for self [Attribute bind_addr] | semmle.label | ControlFlowNode for self [Attribute bind_addr] |
50+
| BindToAllInterfaces_test.py:39:17:39:30 | ControlFlowNode for Attribute | semmle.label | ControlFlowNode for Attribute |
51+
| BindToAllInterfaces_test.py:39:17:39:41 | ControlFlowNode for Tuple | semmle.label | ControlFlowNode for Tuple |
52+
| BindToAllInterfaces_test.py:41:1:41:6 | ControlFlowNode for server [Attribute bind_addr] | semmle.label | ControlFlowNode for server [Attribute bind_addr] |
53+
| BindToAllInterfaces_test.py:41:10:41:17 | ControlFlowNode for Server() [Attribute bind_addr] | semmle.label | ControlFlowNode for Server() [Attribute bind_addr] |
54+
| BindToAllInterfaces_test.py:42:1:42:6 | ControlFlowNode for server [Attribute bind_addr] | semmle.label | ControlFlowNode for server [Attribute bind_addr] |
55+
| BindToAllInterfaces_test.py:46:1:46:4 | ControlFlowNode for host | semmle.label | ControlFlowNode for host |
56+
| BindToAllInterfaces_test.py:46:8:46:44 | ControlFlowNode for Attribute() | semmle.label | ControlFlowNode for Attribute() |
57+
| BindToAllInterfaces_test.py:46:35:46:43 | ControlFlowNode for StringLiteral | semmle.label | ControlFlowNode for StringLiteral |
58+
| BindToAllInterfaces_test.py:48:9:48:18 | ControlFlowNode for Tuple | semmle.label | ControlFlowNode for Tuple |
59+
| BindToAllInterfaces_test.py:53:10:53:18 | ControlFlowNode for StringLiteral | semmle.label | ControlFlowNode for StringLiteral |
60+
| BindToAllInterfaces_test.py:53:10:53:25 | ControlFlowNode for Tuple | semmle.label | ControlFlowNode for Tuple |
61+
| BindToAllInterfaces_test.py:58:10:58:18 | ControlFlowNode for StringLiteral | semmle.label | ControlFlowNode for StringLiteral |
62+
| BindToAllInterfaces_test.py:58:10:58:25 | ControlFlowNode for Tuple | semmle.label | ControlFlowNode for Tuple |
63+
subpaths
Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1,2 @@
1-
Security/CVE-2018-1281/BindToAllInterfaces.ql
1+
query: Security/CVE-2018-1281/BindToAllInterfaces.ql
2+
postprocess: utils/test/InlineExpectationsTestQuery.ql

python/ql/test/query-tests/Security/CVE-2018-1281/BindToAllInterfaces_test.py

Lines changed: 42 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2,25 +2,61 @@
22

33
# binds to all interfaces, insecure
44
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
5-
s.bind(('0.0.0.0', 31137))
5+
s.bind(('0.0.0.0', 31137)) # $ Alert[py/bind-socket-all-network-interfaces]
66

77
# binds to all interfaces, insecure
88
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
9-
s.bind(('', 4040))
9+
s.bind(('', 4040)) # $ Alert[py/bind-socket-all-network-interfaces]
1010

1111
# binds only to a dedicated interface, secure
1212
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
1313
s.bind(('84.68.10.12', 8080))
1414

1515
# binds to all interfaces, insecure
16-
ALL_LOCALS = "0.0.0.0"
17-
s.bind((ALL_LOCALS, 9090))
16+
ALL_LOCALS = "0.0.0.0" # $ Source
17+
s.bind((ALL_LOCALS, 9090)) # $ Alert[py/bind-socket-all-network-interfaces]
1818

1919
# binds to all interfaces, insecure
2020
tup = (ALL_LOCALS, 8080)
21-
s.bind(tup)
21+
s.bind(tup) # $ Alert[py/bind-socket-all-network-interfaces]
2222

2323

2424
# IPv6
2525
s = socket.socket(socket.AF_INET6, socket.SOCK_STREAM)
26-
s.bind(("::", 8080)) # NOT OK
26+
s.bind(("::", 8080)) # $ Alert[py/bind-socket-all-network-interfaces]
27+
28+
29+
# FN cases from https://github.com/github/codeql/issues/21582
30+
31+
# Address stored in a class attribute
32+
class Server:
33+
def __init__(self):
34+
self.bind_addr = '0.0.0.0' # $ Source
35+
self.port = 31137
36+
37+
def start(self):
38+
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
39+
s.bind((self.bind_addr, self.port)) # $ Alert[py/bind-socket-all-network-interfaces]
40+
41+
server = Server()
42+
server.start()
43+
44+
# os.environ.get with insecure default
45+
import os
46+
host = os.environ.get('APP_HOST', '0.0.0.0') # $ Source
47+
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
48+
s.bind((host, 8080)) # $ Alert[py/bind-socket-all-network-interfaces]
49+
50+
# gevent.socket (alternative socket module)
51+
from gevent import socket as gsocket
52+
gs = gsocket.socket(gsocket.AF_INET, gsocket.SOCK_STREAM)
53+
gs.bind(('0.0.0.0', 31137)) # $ Alert[py/bind-socket-all-network-interfaces]
54+
55+
# eventlet.green.socket (another alternative socket module)
56+
from eventlet.green import socket as esocket
57+
es = esocket.socket(esocket.AF_INET, esocket.SOCK_STREAM)
58+
es.bind(('0.0.0.0', 31137)) # $ Alert[py/bind-socket-all-network-interfaces]
59+
60+
# AF_UNIX socket binding should not be flagged
61+
us = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
62+
us.bind('')

shared/mad/codeql/mad/ModelValidation.qll

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,7 @@ module KindValidation<KindValidationConfigSig Config> {
4848
// CPP-only currently
4949
"remote-sink",
5050
// Python-only currently, but may be shared in the future
51-
"prompt-injection"
51+
"bind-socket-all-interfaces", "prompt-injection"
5252
]
5353
or
5454
this.matches([

0 commit comments

Comments
 (0)