Skip to content

Commit ef82617

Browse files
parkerbxyzCopilot
andcommitted
Python: fix py/insecure-protocol false positive on ssl.create_default_context()
Since Python 3.10, `ssl.create_default_context()` returns a context whose `minimum_version` defaults to `TLSVersion.TLSv1_2`, so TLS 1.0 and TLS 1.1 are not allowed. The model previously encoded the pre-3.10 behavior and flagged these versions as allowed, producing false positives. Update `SslDefaultContextCreation` to allow only TLSv1_2 and TLSv1_3, refresh the test expectations, and add a regression test for the common safe case. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Signed-off-by: Parker Brown <17183625+parkerbxyz@users.noreply.github.com>
1 parent d86ec1a commit ef82617

4 files changed

Lines changed: 20 additions & 4 deletions

File tree

python/ql/src/Security/CWE-327/Ssl.qll

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -33,9 +33,12 @@ class SslDefaultContextCreation extends ContextCreation {
3333
this = API::moduleImport("ssl").getMember("create_default_context").getACall()
3434
}
3535

36-
// Allowed insecure versions are "TLSv1" and "TLSv1_1"
36+
// Since Python 3.10, `ssl.create_default_context` returns a context whose
37+
// `minimum_version` defaults to `TLSVersion.TLSv1_2`, so TLSv1 and TLSv1_1 are not allowed.
38+
// (Earlier Python versions also allowed TLSv1 and TLSv1_1.)
3739
// see https://docs.python.org/3/library/ssl.html#context-creation
38-
override ProtocolVersion getProtocol() { result in ["TLSv1", "TLSv1_1", "TLSv1_2", "TLSv1_3"] }
40+
// and https://docs.python.org/3/whatsnew/3.10.html#ssl
41+
override ProtocolVersion getProtocol() { result in ["TLSv1_2", "TLSv1_3"] }
3942
}
4043

4144
/** Gets a reference to an `ssl.Context` instance. */
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
---
2+
category: minorAnalysis
3+
---
4+
* The `py/insecure-protocol` query no longer reports `ssl.create_default_context` as allowing TLS 1.0 or TLS 1.1. Since Python 3.10, the context returned by `ssl.create_default_context` has its `minimum_version` set to `TLSVersion.TLSv1_2` by default, so these protocol versions are not allowed and the previous alerts were false positives.

python/ql/test/query-tests/Security/CWE-327-InsecureProtocol/InsecureProtocol.expected

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -41,5 +41,3 @@
4141
| ssl_fluent.py:97:14:97:20 | ControlFlowNode for context | Insecure SSL/TLS protocol version TLSv1_1 allowed by $@. | ssl_fluent.py:65:15:65:46 | ControlFlowNode for Attribute() | call to ssl.SSLContext |
4242
| ssl_fluent.py:146:14:146:20 | ControlFlowNode for context | Insecure SSL/TLS protocol version TLSv1_1 allowed by $@. | ssl_fluent.py:142:15:142:46 | ControlFlowNode for Attribute() | call to ssl.SSLContext |
4343
| ssl_fluent.py:165:14:165:20 | ControlFlowNode for context | Insecure SSL/TLS protocol version SSLv3 allowed by $@. | ssl_fluent.py:161:15:161:65 | ControlFlowNode for Attribute() | call to ssl.create_default_context |
44-
| ssl_fluent.py:165:14:165:20 | ControlFlowNode for context | Insecure SSL/TLS protocol version TLSv1 allowed by $@. | ssl_fluent.py:161:15:161:65 | ControlFlowNode for Attribute() | call to ssl.create_default_context |
45-
| ssl_fluent.py:165:14:165:20 | ControlFlowNode for context | Insecure SSL/TLS protocol version TLSv1_1 allowed by $@. | ssl_fluent.py:161:15:161:65 | ControlFlowNode for Attribute() | call to ssl.create_default_context |

python/ql/test/query-tests/Security/CWE-327-InsecureProtocol/ssl_fluent.py

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -164,3 +164,14 @@ def test_fluent_explicitly_unsafe():
164164
with socket.create_connection((hostname, 443)) as sock:
165165
with context.wrap_socket(sock, server_hostname=hostname) as ssock: # $ Alert
166166
print(ssock.version())
167+
168+
# Since Python 3.10, `ssl.create_default_context` sets `minimum_version` to
169+
# `TLSVersion.TLSv1_2`, so TLSv1 and TLSv1_1 are not allowed.
170+
# see https://docs.python.org/3/library/ssl.html#context-creation
171+
def test_fluent_default_context_safe():
172+
hostname = 'www.python.org'
173+
context = ssl.create_default_context(ssl.Purpose.SERVER_AUTH)
174+
175+
with socket.create_connection((hostname, 443)) as sock:
176+
with context.wrap_socket(sock, server_hostname=hostname) as ssock: # No alert
177+
print(ssock.version())

0 commit comments

Comments
 (0)