diff --git a/ruby/ql/lib/change-notes/2022-03-09-http-client-getaurlpart.md b/ruby/ql/lib/change-notes/2022-03-09-http-client-getaurlpart.md new file mode 100644 index 000000000000..ded66d09e01e --- /dev/null +++ b/ruby/ql/lib/change-notes/2022-03-09-http-client-getaurlpart.md @@ -0,0 +1,4 @@ +--- +category: breaking +--- +* The `getURL` member-predicates of the `HTTP::Client::Request` and `HTTP::Client::Request::Range` classes from `Concepts.qll` have been renamed to `getAUrlPart`. diff --git a/ruby/ql/lib/codeql/ruby/Concepts.qll b/ruby/ql/lib/codeql/ruby/Concepts.qll index b9bf59b95c84..412ce530b146 100644 --- a/ruby/ql/lib/codeql/ruby/Concepts.qll +++ b/ruby/ql/lib/codeql/ruby/Concepts.qll @@ -485,10 +485,18 @@ module HTTP { DataFlow::Node getResponseBody() { result = super.getResponseBody() } /** + * DEPRECATED: Use `getAUrlPart` instead. + * * Gets a node that contributes to the URL of the request. * Depending on the framework, a request may have multiple nodes which contribute to the URL. */ - DataFlow::Node getURL() { result = super.getURL() } + deprecated DataFlow::Node getURL() { result = super.getURL() or result = super.getAUrlPart() } + + /** + * Gets a data-flow node that contributes to the URL of the request. + * Depending on the framework, a request may have multiple nodes which contribute to the URL. + */ + DataFlow::Node getAUrlPart() { result = super.getAUrlPart() } /** Gets a string that identifies the framework used for this request. */ string getFramework() { result = super.getFramework() } @@ -516,10 +524,18 @@ module HTTP { abstract DataFlow::Node getResponseBody(); /** + * DEPRECATED: overwrite `getAUrlPart` instead. + * * Gets a node that contributes to the URL of the request. * Depending on the framework, a request may have multiple nodes which contribute to the URL. */ - abstract DataFlow::Node getURL(); + deprecated DataFlow::Node getURL() { none() } + + /** + * Gets a data-flow node that contributes to the URL of the request. + * Depending on the framework, a request may have multiple nodes which contribute to the URL. + */ + abstract DataFlow::Node getAUrlPart(); /** Gets a string that identifies the framework used for this request. */ abstract string getFramework(); diff --git a/ruby/ql/lib/codeql/ruby/frameworks/http_clients/Excon.qll b/ruby/ql/lib/codeql/ruby/frameworks/http_clients/Excon.qll index 9c56ed32c923..b6cb26c0631e 100644 --- a/ruby/ql/lib/codeql/ruby/frameworks/http_clients/Excon.qll +++ b/ruby/ql/lib/codeql/ruby/frameworks/http_clients/Excon.qll @@ -52,7 +52,7 @@ class ExconHttpRequest extends HTTP::Client::Request::Range { override DataFlow::Node getResponseBody() { result = requestNode.getAMethodCall("body") } - override DataFlow::Node getURL() { + override DataFlow::Node getAUrlPart() { // For one-off requests, the URL is in the first argument of the request method call. // For connection re-use, the URL is split between the first argument of the `new` call // and the `path` keyword argument of the request method call. diff --git a/ruby/ql/lib/codeql/ruby/frameworks/http_clients/Faraday.qll b/ruby/ql/lib/codeql/ruby/frameworks/http_clients/Faraday.qll index a4d420dc8c78..e0ac48bd1f1c 100644 --- a/ruby/ql/lib/codeql/ruby/frameworks/http_clients/Faraday.qll +++ b/ruby/ql/lib/codeql/ruby/frameworks/http_clients/Faraday.qll @@ -45,7 +45,7 @@ class FaradayHttpRequest extends HTTP::Client::Request::Range { override DataFlow::Node getResponseBody() { result = requestNode.getAMethodCall("body") } - override DataFlow::Node getURL() { + override DataFlow::Node getAUrlPart() { result = requestUse.getArgument(0) or result = connectionUse.(DataFlow::CallNode).getArgument(0) or result = connectionUse.(DataFlow::CallNode).getKeywordArgument("url") diff --git a/ruby/ql/lib/codeql/ruby/frameworks/http_clients/HttpClient.qll b/ruby/ql/lib/codeql/ruby/frameworks/http_clients/HttpClient.qll index 6e4e7ded9a88..5a3ef8c355cf 100644 --- a/ruby/ql/lib/codeql/ruby/frameworks/http_clients/HttpClient.qll +++ b/ruby/ql/lib/codeql/ruby/frameworks/http_clients/HttpClient.qll @@ -36,7 +36,7 @@ class HttpClientRequest extends HTTP::Client::Request::Range { this = requestUse.asExpr().getExpr() } - override DataFlow::Node getURL() { result = requestUse.getArgument(0) } + override DataFlow::Node getAUrlPart() { result = requestUse.getArgument(0) } override DataFlow::Node getResponseBody() { // The `get_content` and `post_content` methods return the response body as diff --git a/ruby/ql/lib/codeql/ruby/frameworks/http_clients/Httparty.qll b/ruby/ql/lib/codeql/ruby/frameworks/http_clients/Httparty.qll index 664749c85ac0..3cf5b82571ee 100644 --- a/ruby/ql/lib/codeql/ruby/frameworks/http_clients/Httparty.qll +++ b/ruby/ql/lib/codeql/ruby/frameworks/http_clients/Httparty.qll @@ -35,7 +35,7 @@ class HttpartyRequest extends HTTP::Client::Request::Range { this = requestUse.asExpr().getExpr() } - override DataFlow::Node getURL() { result = requestUse.getArgument(0) } + override DataFlow::Node getAUrlPart() { result = requestUse.getArgument(0) } override DataFlow::Node getResponseBody() { // If HTTParty can recognise the response type, it will parse and return it 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 7973f86fbc1f..23f31c817951 100644 --- a/ruby/ql/lib/codeql/ruby/frameworks/http_clients/NetHttp.qll +++ b/ruby/ql/lib/codeql/ruby/frameworks/http_clients/NetHttp.qll @@ -51,7 +51,7 @@ class NetHttpRequest extends HTTP::Client::Request::Range { * Gets the node representing the URL of the request. * Currently unused, but may be useful in future, e.g. to filter out certain requests. */ - override DataFlow::Node getURL() { result = request.getArgument(0) } + override DataFlow::Node getAUrlPart() { result = request.getArgument(0) } override DataFlow::Node getResponseBody() { result = responseBody } diff --git a/ruby/ql/lib/codeql/ruby/frameworks/http_clients/OpenURI.qll b/ruby/ql/lib/codeql/ruby/frameworks/http_clients/OpenURI.qll index 8cede7b464a2..c5cf83948efd 100644 --- a/ruby/ql/lib/codeql/ruby/frameworks/http_clients/OpenURI.qll +++ b/ruby/ql/lib/codeql/ruby/frameworks/http_clients/OpenURI.qll @@ -32,7 +32,7 @@ class OpenUriRequest extends HTTP::Client::Request::Range { this = requestUse.asExpr().getExpr() } - override DataFlow::Node getURL() { result = requestUse.getArgument(0) } + override DataFlow::Node getAUrlPart() { result = requestUse.getArgument(0) } override DataFlow::Node getResponseBody() { result = requestNode.getAMethodCall(["read", "readlines"]) @@ -65,7 +65,7 @@ class OpenUriKernelOpenRequest extends HTTP::Client::Request::Range { this = requestUse.asExpr().getExpr() } - override DataFlow::Node getURL() { result = requestUse.getArgument(0) } + override DataFlow::Node getAUrlPart() { result = requestUse.getArgument(0) } override DataFlow::CallNode getResponseBody() { result.asExpr().getExpr().(MethodCall).getMethodName() in ["read", "readlines"] and diff --git a/ruby/ql/lib/codeql/ruby/frameworks/http_clients/RestClient.qll b/ruby/ql/lib/codeql/ruby/frameworks/http_clients/RestClient.qll index 4305405618d4..60462db28f30 100644 --- a/ruby/ql/lib/codeql/ruby/frameworks/http_clients/RestClient.qll +++ b/ruby/ql/lib/codeql/ruby/frameworks/http_clients/RestClient.qll @@ -38,7 +38,7 @@ class RestClientHttpRequest extends HTTP::Client::Request::Range { ) } - override DataFlow::Node getURL() { + override DataFlow::Node getAUrlPart() { result = requestUse.getKeywordArgument("url") or result = requestUse.getArgument(0) and diff --git a/ruby/ql/lib/codeql/ruby/frameworks/http_clients/Typhoeus.qll b/ruby/ql/lib/codeql/ruby/frameworks/http_clients/Typhoeus.qll index 3124cd6704dd..b02fb4bd88d6 100644 --- a/ruby/ql/lib/codeql/ruby/frameworks/http_clients/Typhoeus.qll +++ b/ruby/ql/lib/codeql/ruby/frameworks/http_clients/Typhoeus.qll @@ -26,7 +26,7 @@ class TyphoeusHttpRequest extends HTTP::Client::Request::Range { this = requestUse.asExpr().getExpr() } - override DataFlow::Node getURL() { result = requestUse.getArgument(0) } + override DataFlow::Node getAUrlPart() { result = requestUse.getArgument(0) } override DataFlow::Node getResponseBody() { result = requestNode.getAMethodCall("body") } diff --git a/ruby/ql/lib/codeql/ruby/security/ServerSideRequestForgeryCustomizations.qll b/ruby/ql/lib/codeql/ruby/security/ServerSideRequestForgeryCustomizations.qll index ffccdd529da0..c43d9c2fb1eb 100644 --- a/ruby/ql/lib/codeql/ruby/security/ServerSideRequestForgeryCustomizations.qll +++ b/ruby/ql/lib/codeql/ruby/security/ServerSideRequestForgeryCustomizations.qll @@ -43,7 +43,7 @@ module ServerSideRequestForgery { /** The URL of an HTTP request, considered as a sink. */ class HttpRequestAsSink extends Sink { - HttpRequestAsSink() { exists(HTTP::Client::Request req | req.getURL() = this) } + HttpRequestAsSink() { exists(HTTP::Client::Request req | req.getAUrlPart() = this) } } /** A string interpolation with a fixed prefix, considered as a flow sanitizer. */ diff --git a/ruby/ql/test/library-tests/frameworks/http_clients/HttpClients.ql b/ruby/ql/test/library-tests/frameworks/http_clients/HttpClients.ql index 2d01110f0446..17f328ad2eda 100644 --- a/ruby/ql/test/library-tests/frameworks/http_clients/HttpClients.ql +++ b/ruby/ql/test/library-tests/frameworks/http_clients/HttpClients.ql @@ -2,9 +2,9 @@ import codeql.ruby.Concepts import codeql.ruby.DataFlow query predicate httpRequests( - HTTP::Client::Request r, string framework, DataFlow::Node url, DataFlow::Node responseBody + HTTP::Client::Request r, string framework, DataFlow::Node urlPart, DataFlow::Node responseBody ) { r.getFramework() = framework and - r.getURL() = url and + r.getAUrlPart() = urlPart and r.getResponseBody() = responseBody }