Python: Add HTTP::Client::Request concept

Taken from Ruby, except that `getURL` member predicate was changed to
`getUrl` to keep consistency with the rest of our concepts, and stick
to our naming convention.
This commit is contained in:
Rasmus Wriedt Larsen
2021-12-13 11:09:09 +01:00
parent a6360215f3
commit 5de79b4ffe
2 changed files with 88 additions and 0 deletions

View File

@@ -812,6 +812,77 @@ module HTTP {
}
}
}
/** Provides classes for modeling HTTP clients. */
module Client {
/**
* A method call that makes an outgoing HTTP request.
*
* Extend this class to refine existing API models. If you want to model new APIs,
* extend `Request::Range` instead.
*/
class Request extends DataFlow::Node instanceof Request::Range {
/** Gets a node which returns the body of the response */
DataFlow::Node getResponseBody() { result = super.getResponseBody() }
/**
* 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() }
/** Gets a string that identifies the framework used for this request. */
string getFramework() { result = super.getFramework() }
/**
* Holds if this request is made using a mode that disables SSL/TLS
* certificate validation, where `disablingNode` represents the point at
* which the validation was disabled.
*/
predicate disablesCertificateValidation(DataFlow::Node disablingNode) {
super.disablesCertificateValidation(disablingNode)
}
}
/** Provides a class for modeling new HTTP requests. */
module Request {
/**
* A method call that makes an outgoing HTTP request.
*
* Extend this class to model new APIs. If you want to refine existing API models,
* extend `Request` instead.
*/
abstract class Range extends DataFlow::Node {
/** Gets a node which returns the body of the response */
abstract DataFlow::Node getResponseBody();
/**
* 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();
/** Gets a string that identifies the framework used for this request. */
abstract string getFramework();
/**
* Holds if this request is made using a mode that disables SSL/TLS
* certificate validation, where `disablingNode` represents the point at
* which the validation was disabled.
*/
abstract predicate disablesCertificateValidation(DataFlow::Node disablingNode);
}
}
/** The response body from an outgoing HTTP request, considered as a remote flow source */
private class RequestResponseBody extends RemoteFlowSource::Range, DataFlow::Node {
Request request;
RequestResponseBody() { this = request.getResponseBody() }
override string getSourceType() { result = request.getFramework() }
}
}
}
/**

View File

@@ -475,3 +475,20 @@ class CryptographicOperationTest extends InlineExpectationsTest {
)
}
}
class HttpClientRequestTest extends InlineExpectationsTest {
HttpClientRequestTest() { this = "HttpClientRequestTest" }
override string getARelevantTag() { result = "clientRequestUrl" }
override predicate hasActualResult(Location location, string element, string tag, string value) {
exists(location.getFile().getRelativePath()) and
exists(HTTP::Client::Request req, DataFlow::Node url |
url = req.getUrl() and
location = url.getLocation() and
element = url.toString() and
value = prettyNodeForInlineTest(url) and
tag = "clientRequestUrl"
)
}
}