Skip to content

Commit 4a82025

Browse files
committed
Ruby: Base HTTP::Client::Request on shared concept
Fixing up deprecation errors in next commit
1 parent e2b78df commit 4a82025

File tree

10 files changed

+79
-34
lines changed

10 files changed

+79
-34
lines changed

ruby/ql/lib/codeql/ruby/Concepts.qll

Lines changed: 14 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -474,13 +474,15 @@ module HTTP {
474474

475475
/** Provides classes for modeling HTTP clients. */
476476
module Client {
477+
import codeql.ruby.internal.ConceptsShared::Http::Client as SC
478+
477479
/**
478480
* A method call that makes an outgoing HTTP request.
479481
*
480482
* Extend this class to refine existing API models. If you want to model new APIs,
481483
* extend `Request::Range` instead.
482484
*/
483-
class Request extends DataFlow::Node instanceof Request::Range {
485+
class Request extends SC::Request instanceof Request::Range {
484486
/** Gets a node which returns the body of the response */
485487
DataFlow::Node getResponseBody() { result = super.getResponseBody() }
486488

@@ -490,24 +492,19 @@ module HTTP {
490492
* Gets a node that contributes to the URL of the request.
491493
* Depending on the framework, a request may have multiple nodes which contribute to the URL.
492494
*/
493-
deprecated DataFlow::Node getURL() { result = super.getURL() or result = super.getAUrlPart() }
494-
495-
/**
496-
* Gets a data-flow node that contributes to the URL of the request.
497-
* Depending on the framework, a request may have multiple nodes which contribute to the URL.
498-
*/
499-
DataFlow::Node getAUrlPart() { result = super.getAUrlPart() }
500-
501-
/** Gets a string that identifies the framework used for this request. */
502-
string getFramework() { result = super.getFramework() }
495+
deprecated DataFlow::Node getURL() {
496+
result = super.getURL() or result = Request::Range.super.getAUrlPart()
497+
}
503498

504499
/**
505500
* Holds if this request is made using a mode that disables SSL/TLS
506501
* certificate validation, where `disablingNode` represents the point at
507502
* which the validation was disabled.
508503
*/
509-
predicate disablesCertificateValidation(DataFlow::Node disablingNode) {
510-
super.disablesCertificateValidation(disablingNode)
504+
deprecated predicate disablesCertificateValidation(DataFlow::Node disablingNode) {
505+
Request::Range.super.disablesCertificateValidation(disablingNode, _)
506+
or
507+
Request::Range.super.disablesCertificateValidation(disablingNode)
511508
}
512509
}
513510

@@ -519,7 +516,7 @@ module HTTP {
519516
* Extend this class to model new APIs. If you want to refine existing API models,
520517
* extend `Request` instead.
521518
*/
522-
abstract class Range extends DataFlow::Node {
519+
abstract class Range extends SC::Request::Range {
523520
/** Gets a node which returns the body of the response */
524521
abstract DataFlow::Node getResponseBody();
525522

@@ -532,20 +529,13 @@ module HTTP {
532529
deprecated DataFlow::Node getURL() { none() }
533530

534531
/**
535-
* Gets a data-flow node that contributes to the URL of the request.
536-
* Depending on the framework, a request may have multiple nodes which contribute to the URL.
537-
*/
538-
abstract DataFlow::Node getAUrlPart();
539-
540-
/** Gets a string that identifies the framework used for this request. */
541-
abstract string getFramework();
542-
543-
/**
532+
* DEPRECATED: overwrite `disablesCertificateValidation/2` instead.
533+
*
544534
* Holds if this request is made using a mode that disables SSL/TLS
545535
* certificate validation, where `disablingNode` represents the point at
546536
* which the validation was disabled.
547537
*/
548-
abstract predicate disablesCertificateValidation(DataFlow::Node disablingNode);
538+
deprecated predicate disablesCertificateValidation(DataFlow::Node disablingNode) { none() }
549539
}
550540
}
551541

ruby/ql/lib/codeql/ruby/frameworks/http_clients/Excon.qll

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,13 @@ class ExconHttpRequest extends HTTP::Client::Request::Range, DataFlow::CallNode
8686
)
8787
}
8888

89+
override predicate disablesCertificateValidation(
90+
DataFlow::Node disablingNode, DataFlow::Node argumentOrigin
91+
) {
92+
disablesCertificateValidation(disablingNode) and
93+
argumentOrigin = disablingNode
94+
}
95+
8996
override string getFramework() { result = "Excon" }
9097
}
9198

ruby/ql/lib/codeql/ruby/frameworks/http_clients/Faraday.qll

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -22,13 +22,11 @@ private import codeql.ruby.DataFlow
2222
* connection.get("/").body
2323
* ```
2424
*/
25-
2625
class FaradayHttpRequest extends HTTP::Client::Request::Range, DataFlow::CallNode {
2726
API::Node requestNode;
2827
API::Node connectionNode;
2928
DataFlow::Node connectionUse;
3029

31-
3230
FaradayHttpRequest() {
3331
connectionNode =
3432
[
@@ -41,7 +39,6 @@ class FaradayHttpRequest extends HTTP::Client::Request::Range, DataFlow::CallNod
4139
connectionNode.getReturn(["get", "head", "delete", "post", "put", "patch", "trace"]) and
4240
this = requestNode.asSource() and
4341
connectionUse = connectionNode.asSource()
44-
4542
}
4643

4744
override DataFlow::Node getResponseBody() { result = requestNode.getAMethodCall("body") }
@@ -78,6 +75,13 @@ class FaradayHttpRequest extends HTTP::Client::Request::Range, DataFlow::CallNod
7875
)
7976
}
8077

78+
override predicate disablesCertificateValidation(
79+
DataFlow::Node disablingNode, DataFlow::Node argumentOrigin
80+
) {
81+
disablesCertificateValidation(disablingNode) and
82+
argumentOrigin = disablingNode
83+
}
84+
8185
override string getFramework() { result = "Faraday" }
8286
}
8387

ruby/ql/lib/codeql/ruby/frameworks/http_clients/HttpClient.qll

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,5 +58,12 @@ class HttpClientRequest extends HTTP::Client::Request::Range, DataFlow::CallNode
5858
.getAValueReachableFromSource()
5959
}
6060

61+
override predicate disablesCertificateValidation(
62+
DataFlow::Node disablingNode, DataFlow::Node argumentOrigin
63+
) {
64+
disablesCertificateValidation(disablingNode) and
65+
argumentOrigin = disablingNode
66+
}
67+
6168
override string getFramework() { result = "HTTPClient" }
6269
}

ruby/ql/lib/codeql/ruby/frameworks/http_clients/Httparty.qll

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -23,16 +23,14 @@ private import codeql.ruby.DataFlow
2323
* MyClass.new("http://example.com")
2424
* ```
2525
*/
26-
class HttpartyRequest extends HTTP::Client::Request::Range,DataFlow::CallNode {
26+
class HttpartyRequest extends HTTP::Client::Request::Range, DataFlow::CallNode {
2727
API::Node requestNode;
2828

29-
3029
HttpartyRequest() {
3130
this = requestNode.asSource() and
3231
requestNode =
3332
API::getTopLevelMember("HTTParty")
3433
.getReturn(["get", "head", "delete", "options", "post", "put", "patch"])
35-
3634
}
3735

3836
override DataFlow::Node getAUrlPart() { result = this.getArgument(0) }
@@ -73,6 +71,13 @@ class HttpartyRequest extends HTTP::Client::Request::Range,DataFlow::CallNode {
7371
)
7472
}
7573

74+
override predicate disablesCertificateValidation(
75+
DataFlow::Node disablingNode, DataFlow::Node argumentOrigin
76+
) {
77+
disablesCertificateValidation(disablingNode) and
78+
argumentOrigin = disablingNode
79+
}
80+
7681
override string getFramework() { result = "HTTParty" }
7782
}
7883

ruby/ql/lib/codeql/ruby/frameworks/http_clients/NetHttp.qll

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -83,5 +83,12 @@ class NetHttpRequest extends HTTP::Client::Request::Range, DataFlow::CallNode {
8383
)
8484
}
8585

86+
override predicate disablesCertificateValidation(
87+
DataFlow::Node disablingNode, DataFlow::Node argumentOrigin
88+
) {
89+
disablesCertificateValidation(disablingNode) and
90+
argumentOrigin = disablingNode
91+
}
92+
8693
override string getFramework() { result = "Net::HTTP" }
8794
}

ruby/ql/lib/codeql/ruby/frameworks/http_clients/OpenURI.qll

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,13 @@ class OpenUriRequest extends HTTP::Client::Request::Range, DataFlow::CallNode {
4343
)
4444
}
4545

46+
override predicate disablesCertificateValidation(
47+
DataFlow::Node disablingNode, DataFlow::Node argumentOrigin
48+
) {
49+
disablesCertificateValidation(disablingNode) and
50+
argumentOrigin = disablingNode
51+
}
52+
4653
override string getFramework() { result = "OpenURI" }
4754
}
4855

@@ -75,6 +82,13 @@ class OpenUriKernelOpenRequest extends HTTP::Client::Request::Range, DataFlow::C
7582
)
7683
}
7784

85+
override predicate disablesCertificateValidation(
86+
DataFlow::Node disablingNode, DataFlow::Node argumentOrigin
87+
) {
88+
disablesCertificateValidation(disablingNode) and
89+
argumentOrigin = disablingNode
90+
}
91+
7892
override string getFramework() { result = "OpenURI" }
7993
}
8094

ruby/ql/lib/codeql/ruby/frameworks/http_clients/RestClient.qll

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,13 +17,11 @@ private import codeql.ruby.DataFlow
1717
* ```
1818
*/
1919
class RestClientHttpRequest extends HTTP::Client::Request::Range, DataFlow::CallNode {
20-
2120
API::Node requestNode;
2221
API::Node connectionNode;
2322

2423
RestClientHttpRequest() {
2524
this = requestNode.asSource() and
26-
2725
(
2826
connectionNode =
2927
[
@@ -71,6 +69,13 @@ class RestClientHttpRequest extends HTTP::Client::Request::Range, DataFlow::Call
7169
)
7270
}
7371

72+
override predicate disablesCertificateValidation(
73+
DataFlow::Node disablingNode, DataFlow::Node argumentOrigin
74+
) {
75+
disablesCertificateValidation(disablingNode) and
76+
argumentOrigin = disablingNode
77+
}
78+
7479
override string getFramework() { result = "RestClient" }
7580
}
7681

ruby/ql/lib/codeql/ruby/frameworks/http_clients/Typhoeus.qll

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,15 +15,13 @@ private import codeql.ruby.DataFlow
1515
* ```
1616
*/
1717
class TyphoeusHttpRequest extends HTTP::Client::Request::Range, DataFlow::CallNode {
18-
1918
API::Node requestNode;
2019

2120
TyphoeusHttpRequest() {
2221
this = requestNode.asSource() and
2322
requestNode =
2423
API::getTopLevelMember("Typhoeus")
2524
.getReturn(["get", "head", "delete", "options", "post", "put", "patch"])
26-
2725
}
2826

2927
override DataFlow::Node getAUrlPart() { result = this.getArgument(0) }
@@ -51,6 +49,13 @@ class TyphoeusHttpRequest extends HTTP::Client::Request::Range, DataFlow::CallNo
5149
)
5250
}
5351

52+
override predicate disablesCertificateValidation(
53+
DataFlow::Node disablingNode, DataFlow::Node argumentOrigin
54+
) {
55+
disablesCertificateValidation(disablingNode) and
56+
argumentOrigin = disablingNode
57+
}
58+
5459
override string getFramework() { result = "Typhoeus" }
5560
}
5661

ruby/ql/test/query-tests/security/cwe-295/RequestWithoutValidation.expected

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
WARNING: Predicate disablesCertificateValidation has been deprecated and may be removed in future (/home/rasmus/work/code/ql/ruby/ql/src/queries/security/cwe-295/RequestWithoutValidation.ql:19,15-44)
12
| Excon.rb:6:3:6:34 | call to get | This request may run with $@. | Excon.rb:5:3:5:34 | call to []= | certificate validation disabled |
23
| Excon.rb:12:3:12:34 | call to get | This request may run with $@. | Excon.rb:11:3:11:23 | call to ssl_verify_peer= | certificate validation disabled |
34
| Excon.rb:18:3:18:34 | call to get | This request may run with $@. | Excon.rb:17:3:17:34 | call to []= | certificate validation disabled |

0 commit comments

Comments
 (0)