Skip to content

Commit 4cf520c

Browse files
committed
Model the Faraday HTTP client
1 parent ee51298 commit 4cf520c

File tree

5 files changed

+84
-0
lines changed

5 files changed

+84
-0
lines changed

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

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,3 +4,4 @@
44

55
private import codeql.ruby.frameworks.http_clients.NetHTTP
66
private import codeql.ruby.frameworks.http_clients.Excon
7+
private import codeql.ruby.frameworks.http_clients.Faraday
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
private import ruby
2+
private import codeql.ruby.Concepts
3+
private import codeql.ruby.ApiGraphs
4+
5+
/**
6+
* A call that makes an HTTP request using `Faraday`.
7+
* ```ruby
8+
* # one-off request
9+
* Faraday.get("http://example.com").body
10+
*
11+
* # connection re-use
12+
* connection = Faraday.new("http://example.com")
13+
* connection.get("/").body
14+
* ```
15+
*/
16+
class FaradayHTTPRequest extends HTTP::Client::Request::Range {
17+
DataFlow::Node request;
18+
DataFlow::CallNode responseBody;
19+
20+
FaradayHTTPRequest() {
21+
exists(API::Node requestNode |
22+
requestNode =
23+
[
24+
// one-off requests
25+
API::getTopLevelMember("Faraday"),
26+
// connection re-use
27+
API::getTopLevelMember("Faraday").getInstance()
28+
].getReturn(["get", "head", "delete", "post", "put", "patch", "trace"]) and
29+
responseBody = requestNode.getAMethodCall("body") and
30+
request = requestNode.getAnImmediateUse() and
31+
this = request.asExpr().getExpr()
32+
)
33+
}
34+
35+
override DataFlow::Node getResponseBody() { result = responseBody }
36+
37+
override string getFramework() { result = "Faraday" }
38+
}
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
| Faraday.rb:3:9:3:42 | call to get | Faraday.rb:4:1:4:10 | call to body |
2+
| Faraday.rb:6:9:6:62 | call to post | Faraday.rb:7:1:7:10 | call to body |
3+
| Faraday.rb:9:9:9:61 | call to put | Faraday.rb:10:1:10:10 | call to body |
4+
| Faraday.rb:12:9:12:63 | call to patch | Faraday.rb:13:1:13:10 | call to body |
5+
| Faraday.rb:15:9:15:45 | call to delete | Faraday.rb:16:1:16:10 | call to body |
6+
| Faraday.rb:18:9:18:43 | call to head | Faraday.rb:19:1:19:10 | call to body |
7+
| Faraday.rb:24:9:24:44 | call to trace | Faraday.rb:25:1:25:10 | call to body |
8+
| Faraday.rb:28:9:28:27 | call to get | Faraday.rb:29:1:29:10 | call to body |
9+
| Faraday.rb:31:10:31:46 | call to post | Faraday.rb:32:1:32:11 | call to body |
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.Faraday
2+
import codeql.ruby.DataFlow
3+
4+
query DataFlow::Node faradayHTTPRequests(FaradayHTTPRequest e) { result = e.getResponseBody() }
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
require "faraday"
2+
3+
resp1 = Faraday.get("http://example.com/")
4+
resp1.body
5+
6+
resp2 = Faraday.post("http://example.com/", body: "some_data")
7+
resp2.body
8+
9+
resp3 = Faraday.put("http://example.com/", body: "some_data")
10+
resp3.body
11+
12+
resp4 = Faraday.patch("http://example.com/", body: "some_data")
13+
resp4.body
14+
15+
resp5 = Faraday.delete("http://example.com/")
16+
resp5.body
17+
18+
resp6 = Faraday.head("http://example.com/")
19+
resp6.body
20+
21+
resp7 = Faraday.options("http://example.com/")
22+
resp7.body
23+
24+
resp8 = Faraday.trace("http://example.com/")
25+
resp8.body
26+
27+
connection = Faraday.new("http://example.com")
28+
resp9 = connection.get("/")
29+
resp9.body
30+
31+
resp10 = connection.post("/foo", some: "data")
32+
resp10.body

0 commit comments

Comments
 (0)