Skip to content

Commit b5dec5e

Browse files
committed
Model the OpenURI http client
1 parent ca1fc44 commit b5dec5e

File tree

5 files changed

+61
-0
lines changed

5 files changed

+61
-0
lines changed

ql/lib/codeql/ruby/frameworks/HTTPClients.qll

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,3 +8,4 @@ private import codeql.ruby.frameworks.http_clients.Faraday
88
private import codeql.ruby.frameworks.http_clients.RestClient
99
private import codeql.ruby.frameworks.http_clients.HTTParty
1010
private import codeql.ruby.frameworks.http_clients.HTTPClient
11+
private import codeql.ruby.frameworks.http_clients.OpenURI
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
private import ruby
2+
private import codeql.ruby.Concepts
3+
private import codeql.ruby.ApiGraphs
4+
private import codeql.ruby.frameworks.StandardLibrary
5+
6+
/**
7+
* A call that makes an HTTP request using `OpenURI`.
8+
* ```ruby
9+
* Kernel.open("http://example.com").read
10+
* URI.open("http://example.com").readlines
11+
* URI.parse("http://example.com").open.read
12+
* ```
13+
*/
14+
class OpenURIRequest extends HTTP::Client::Request::Range {
15+
DataFlow::Node request;
16+
DataFlow::CallNode responseBody;
17+
18+
OpenURIRequest() {
19+
exists(API::Node requestNode | request = requestNode.getAnImmediateUse() |
20+
requestNode =
21+
[API::getTopLevelMember("URI"), API::getTopLevelMember("URI").getReturn("parse")]
22+
.getReturn("open") and
23+
responseBody = requestNode.getAMethodCall(["read", "readlines"]) and
24+
this = request.asExpr().getExpr()
25+
)
26+
or
27+
// Kernel.open("http://example.com").read
28+
// open("http://example.com").read
29+
this instanceof KernelMethodCall and
30+
this.getMethodName() = "open" and
31+
request.asExpr().getExpr() = this and
32+
responseBody.asExpr().getExpr().(MethodCall).getMethodName() in ["read", "readlines"] and
33+
request.(DataFlow::LocalSourceNode).flowsTo(responseBody.getReceiver())
34+
}
35+
36+
override DataFlow::Node getResponseBody() { result = responseBody }
37+
38+
override string getFramework() { result = "OpenURI" }
39+
}
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
| OpenURI.rb:3:9:3:41 | call to open | OpenURI.rb:4:1:4:10 | call to read |
2+
| OpenURI.rb:6:9:6:34 | call to open | OpenURI.rb:7:1:7:15 | call to readlines |
3+
| OpenURI.rb:9:9:9:38 | call to open | OpenURI.rb:10:1:10:10 | call to read |
4+
| OpenURI.rb:12:9:12:45 | call to open | OpenURI.rb:13:1:13:10 | call to read |
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
import codeql.ruby.frameworks.http_clients.OpenURI
2+
import codeql.ruby.DataFlow
3+
4+
query DataFlow::Node openURIRequests(OpenURIRequest e) { result = e.getResponseBody() }
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
require "open-uri"
2+
3+
resp1 = Kernel.open("http://example.com")
4+
resp1.read
5+
6+
resp2 = open("http://example.com")
7+
resp2.readlines
8+
9+
resp3 = URI.open("http://example.com")
10+
resp3.read
11+
12+
resp4 = URI.parse("https://example.com").open
13+
resp4.read

0 commit comments

Comments
 (0)