From 9da94fb880b13f60d087079cafe37184e22242ff Mon Sep 17 00:00:00 2001 From: Matt Schwager Date: Mon, 21 Jul 2025 15:17:54 -0400 Subject: [PATCH 1/3] Fix #19294, Ruby NetHttpRequest improvements --- .../ruby/frameworks/http_clients/NetHttp.qll | 22 +++++++++++++++---- .../frameworks/http_clients/NetHttp.rb | 8 +++++++ 2 files changed, 26 insertions(+), 4 deletions(-) diff --git a/ruby/ql/lib/codeql/ruby/frameworks/http_clients/NetHttp.qll b/ruby/ql/lib/codeql/ruby/frameworks/http_clients/NetHttp.qll index 3a0b484e5465..0b4156ff813d 100644 --- a/ruby/ql/lib/codeql/ruby/frameworks/http_clients/NetHttp.qll +++ b/ruby/ql/lib/codeql/ruby/frameworks/http_clients/NetHttp.qll @@ -12,15 +12,22 @@ private import codeql.ruby.DataFlow /** * A `Net::HTTP` call which initiates an HTTP request. * ```ruby + * # one-off request * Net::HTTP.get("http://example.com/") * Net::HTTP.post("http://example.com/", "some_data") * req = Net::HTTP.new("example.com") * response = req.get("/") + * + * # connection re-use + * Net::HTTP.start("http://example.com") do |http| + * http.get("/") + * end * ``` */ class NetHttpRequest extends Http::Client::Request::Range instanceof DataFlow::CallNode { private DataFlow::CallNode request; - private API::Node requestNode; + API::Node requestNode; + API::Node connectionNode; private boolean returnsResponseBody; NetHttpRequest() { @@ -30,20 +37,27 @@ class NetHttpRequest extends Http::Client::Request::Range instanceof DataFlow::C | // Net::HTTP.get(...) method in ["get", "get_response"] and - requestNode = API::getTopLevelMember("Net").getMember("HTTP").getReturn(method) and + connectionNode = API::getTopLevelMember("Net").getMember("HTTP") and + requestNode = connectionNode.getReturn(method) and returnsResponseBody = true or // Net::HTTP.post(...).body method in ["post", "post_form"] and - requestNode = API::getTopLevelMember("Net").getMember("HTTP").getReturn(method) and + connectionNode = API::getTopLevelMember("Net").getMember("HTTP") and + requestNode = connectionNode.getReturn(method) and returnsResponseBody = false or // Net::HTTP.new(..).get(..).body + // Net::HTTP.start(..) do |http| http.get(..) end method in [ "get", "get2", "request_get", "head", "head2", "request_head", "delete", "put", "patch", "post", "post2", "request_post", "request" ] and - requestNode = API::getTopLevelMember("Net").getMember("HTTP").getInstance().getReturn(method) and + connectionNode = [ + API::getTopLevelMember("Net").getMember("HTTP").getInstance(), + API::getTopLevelMember("Net").getMember("HTTP").getMethod("start").getBlock().getParameter(0) + ] and + requestNode = connectionNode.getReturn(method) and returnsResponseBody = false ) } diff --git a/ruby/ql/test/library-tests/frameworks/http_clients/NetHttp.rb b/ruby/ql/test/library-tests/frameworks/http_clients/NetHttp.rb index 608b46ece9aa..63f1522dfad4 100644 --- a/ruby/ql/test/library-tests/frameworks/http_clients/NetHttp.rb +++ b/ruby/ql/test/library-tests/frameworks/http_clients/NetHttp.rb @@ -27,3 +27,11 @@ def get(domain, path) get("example.com", "/").body Net::HTTP.post(uri, "some_body") # note: response body not accessed + +http = Net::HTTP.new("https://example.com") +root_get = Net::HTTP::Get.new("/") +http.request(root_get) + +Net::HTTP.start("https://example.com") do |http| + http.get("/") +end From 5192f3128aca095cbb04ff9226b31a5453dc2ccc Mon Sep 17 00:00:00 2001 From: Matt Schwager Date: Mon, 21 Jul 2025 15:26:39 -0400 Subject: [PATCH 2/3] Update expected test output --- .../frameworks/http_clients/HttpClients.expected | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/ruby/ql/test/library-tests/frameworks/http_clients/HttpClients.expected b/ruby/ql/test/library-tests/frameworks/http_clients/HttpClients.expected index f6275da34ace..e3a36c04819d 100644 --- a/ruby/ql/test/library-tests/frameworks/http_clients/HttpClients.expected +++ b/ruby/ql/test/library-tests/frameworks/http_clients/HttpClients.expected @@ -46,6 +46,8 @@ httpRequests | NetHttp.rb:16:6:16:19 | call to patch | | NetHttp.rb:24:3:24:33 | call to get | | NetHttp.rb:29:1:29:32 | call to post | +| NetHttp.rb:33:1:33:22 | call to request | +| NetHttp.rb:36:3:36:15 | call to get | | OpenURI.rb:3:9:3:41 | call to open | | OpenURI.rb:6:9:6:34 | call to open | | OpenURI.rb:9:9:9:38 | call to open | @@ -123,6 +125,8 @@ getFramework | NetHttp.rb:16:6:16:19 | call to patch | Net::HTTP | | NetHttp.rb:24:3:24:33 | call to get | Net::HTTP | | NetHttp.rb:29:1:29:32 | call to post | Net::HTTP | +| NetHttp.rb:33:1:33:22 | call to request | Net::HTTP | +| NetHttp.rb:36:3:36:15 | call to get | Net::HTTP | | OpenURI.rb:3:9:3:41 | call to open | OpenURI | | OpenURI.rb:6:9:6:34 | call to open | OpenURI | | OpenURI.rb:9:9:9:38 | call to open | OpenURI | @@ -292,6 +296,9 @@ getAUrlPart | NetHttp.rb:24:3:24:33 | call to get | NetHttp.rb:24:17:24:22 | domain | | NetHttp.rb:24:3:24:33 | call to get | NetHttp.rb:24:29:24:32 | path | | NetHttp.rb:29:1:29:32 | call to post | NetHttp.rb:29:16:29:18 | uri | +| NetHttp.rb:33:1:33:22 | call to request | NetHttp.rb:31:22:31:42 | "https://example.com" | +| NetHttp.rb:33:1:33:22 | call to request | NetHttp.rb:33:14:33:21 | root_get | +| NetHttp.rb:36:3:36:15 | call to get | NetHttp.rb:36:12:36:14 | "/" | | OpenURI.rb:3:9:3:41 | call to open | OpenURI.rb:3:21:3:40 | "http://example.com" | | OpenURI.rb:6:9:6:34 | call to open | OpenURI.rb:6:14:6:33 | "http://example.com" | | OpenURI.rb:9:9:9:38 | call to open | OpenURI.rb:9:18:9:37 | "http://example.com" | From d8b9d4d17aa087d7bb64cb44da0972e4a068f88c Mon Sep 17 00:00:00 2001 From: Matt Schwager Date: Wed, 23 Jul 2025 07:03:26 -0400 Subject: [PATCH 3/3] Add change-note --- .../change-notes/2025-07-21-nethttprequest-improvements.md | 7 +++++++ 1 file changed, 7 insertions(+) create mode 100644 ruby/ql/lib/change-notes/2025-07-21-nethttprequest-improvements.md diff --git a/ruby/ql/lib/change-notes/2025-07-21-nethttprequest-improvements.md b/ruby/ql/lib/change-notes/2025-07-21-nethttprequest-improvements.md new file mode 100644 index 000000000000..7de3ed050e2f --- /dev/null +++ b/ruby/ql/lib/change-notes/2025-07-21-nethttprequest-improvements.md @@ -0,0 +1,7 @@ +--- +category: fix +--- +* Made the following changes to `NetHttpRequest` + * Adds `connectionNode`, like other Ruby HTTP clients + * Makes `requestNode` and `connectionNode` public so subclasses can use them + * Adds detection of `Net::HTTP.start`, a common way to make HTTP requests in Ruby pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy