ruby: add Rack::ResponseNode#getAStatusCode

This commit is contained in:
Alex Ford
2023-05-16 14:47:36 +01:00
parent e7e0cf5cb3
commit c87c266871
4 changed files with 36 additions and 5 deletions

View File

@@ -30,9 +30,25 @@ module Rack {
DataFlow::ParameterNode getEnv() { result = call.getParameter(0) }
}
private DataFlow::LocalSourceNode trackStatusCode(TypeTracker t, int i) {
t.start() and
result.getConstantValue().isInt(i)
or
exists(TypeTracker t2 | result = trackStatusCode(t2, i).track(t2, t))
}
private DataFlow::Node trackStatusCode(int i) {
trackStatusCode(TypeTracker::end(), i).flowsTo(result)
}
class ResponseNode extends DataFlow::ArrayLiteralNode {
// [status, headers, body]
ResponseNode() { this.getNumberOfArguments() = 3 }
/**
* Gets an HTTP status code that may be returned in this response.
*/
int getAStatusCode() { this.getElement(0) = trackStatusCode(result) }
}
private DataFlow::LocalSourceNode trackRackResponse(TypeTracker t) {

View File

@@ -1,4 +1,11 @@
| rack.rb:1:1:5:3 | HelloWorld | rack.rb:2:12:2:14 | env |
| rack.rb:7:1:16:3 | Proxy | rack.rb:12:12:12:18 | the_env |
| rack.rb:18:1:31:3 | Logger | rack.rb:24:12:24:14 | env |
| rack.rb:45:1:61:3 | Baz | rack.rb:46:12:46:14 | env |
rackApps
| rack.rb:1:1:9:3 | HelloWorld | rack.rb:2:12:2:14 | env |
| rack.rb:11:1:20:3 | Proxy | rack.rb:16:12:16:18 | the_env |
| rack.rb:22:1:35:3 | Logger | rack.rb:28:12:28:14 | env |
| rack.rb:49:1:65:3 | Baz | rack.rb:50:12:50:14 | env |
rackResponseStatusCodes
| rack.rb:7:5:7:63 | call to [] | 200 |
| rack.rb:7:5:7:63 | call to [] | 500 |
| rack.rb:39:5:39:13 | call to [] | 1 |
| rack.rb:56:7:56:22 | call to [] | 200 |
| rack.rb:63:5:63:21 | call to [] | 400 |

View File

@@ -2,3 +2,7 @@ private import codeql.ruby.frameworks.Rack
private import codeql.ruby.DataFlow
query predicate rackApps(Rack::AppCandidate c, DataFlow::ParameterNode env) { env = c.getEnv() }
query predicate rackResponseStatusCodes(Rack::ResponseNode resp, int status) {
status = resp.getAStatusCode()
}

View File

@@ -1,6 +1,10 @@
class HelloWorld
def call(env)
[200, {'Content-Type' => 'text/plain'}, ['Hello World']]
status = 200
if something_goes_wrong(env)
status = 500
end
[status, {'Content-Type' => 'text/plain'}, ['Hello World']]
end
end