mirror of
https://github.com/github/codeql.git
synced 2026-04-28 18:25:24 +02:00
Ruby: Implement new disablesCertificateValidation for all HTTP client models
Sadly most alert text changed, but the two important changes are: 1. The request on RestClient.rb:19 now has an expanded alert text, highlighting where the origin of the value that disables certificate validation comes from. (in this case, it's trivial since it's the line right above) 2. We handle passing `false`/`OpenSSL::SSL::VERIFY_NONE` the same in the argument passing examples in Faraday.rb
This commit is contained in:
@@ -7,6 +7,7 @@ private import codeql.ruby.CFG
|
||||
private import codeql.ruby.Concepts
|
||||
private import codeql.ruby.ApiGraphs
|
||||
private import codeql.ruby.DataFlow
|
||||
private import codeql.ruby.dataflow.internal.DataFlowImplForLibraries as DataFlowImplForLibraries
|
||||
|
||||
/**
|
||||
* A call that makes an HTTP request using `Excon`.
|
||||
@@ -61,27 +62,27 @@ class ExconHttpRequest extends HTTP::Client::Request::Range, DataFlow::CallNode
|
||||
result = connectionUse.(DataFlow::CallNode).getArgument(0)
|
||||
}
|
||||
|
||||
override predicate disablesCertificateValidation(DataFlow::Node disablingNode) {
|
||||
// Check for `ssl_verify_peer: false` in the options hash.
|
||||
exists(DataFlow::Node arg, int i |
|
||||
i > 0 and
|
||||
arg = connectionNode.getAValueReachableFromSource().(DataFlow::CallNode).getArgument(i)
|
||||
|
|
||||
argSetsVerifyPeer(arg, false, disablingNode)
|
||||
)
|
||||
or
|
||||
// Or we see a call to `Excon.defaults[:ssl_verify_peer] = false` before the
|
||||
// request, and no `ssl_verify_peer: true` in the explicit options hash for
|
||||
// the request call.
|
||||
exists(DataFlow::CallNode disableCall |
|
||||
setsDefaultVerification(disableCall, false) and
|
||||
disableCall.asExpr().getASuccessor+() = this.asExpr() and
|
||||
disablingNode = disableCall and
|
||||
not exists(DataFlow::Node arg, int i |
|
||||
i > 0 and
|
||||
arg = connectionNode.getAValueReachableFromSource().(DataFlow::CallNode).getArgument(i)
|
||||
/** Gets the value that controls certificate validation, if any. */
|
||||
DataFlow::Node getCertificateValidationControllingValue() {
|
||||
exists(DataFlow::CallNode newCall | newCall = connectionNode.getAValueReachableFromSource() |
|
||||
// Check for `ssl_verify_peer: false`
|
||||
result = newCall.getKeywordArgument("ssl_verify_peer")
|
||||
or
|
||||
// using a hashliteral
|
||||
exists(
|
||||
DataFlow::LocalSourceNode optionsNode, CfgNodes::ExprNodes::PairCfgNode p,
|
||||
DataFlow::Node key
|
||||
|
|
||||
argSetsVerifyPeer(arg, true, _)
|
||||
// can't flow to argument 0, since that's the URL
|
||||
optionsNode.flowsTo(newCall.getArgument(any(int i | i > 0))) and
|
||||
p = optionsNode.asExpr().(CfgNodes::ExprNodes::HashLiteralCfgNode).getAKeyValuePair() and
|
||||
key.asExpr() = p.getKey() and
|
||||
key.getALocalSource()
|
||||
.asExpr()
|
||||
.getExpr()
|
||||
.getConstantValue()
|
||||
.isStringlikeValue("ssl_verify_peer") and
|
||||
result.asExpr() = p.getValue()
|
||||
)
|
||||
)
|
||||
}
|
||||
@@ -89,68 +90,59 @@ class ExconHttpRequest extends HTTP::Client::Request::Range, DataFlow::CallNode
|
||||
override predicate disablesCertificateValidation(
|
||||
DataFlow::Node disablingNode, DataFlow::Node argumentOrigin
|
||||
) {
|
||||
disablesCertificateValidation(disablingNode) and
|
||||
argumentOrigin = disablingNode
|
||||
any(ExconDisablesCertificateValidationConfiguration config)
|
||||
.hasFlow(argumentOrigin, disablingNode) and
|
||||
disablingNode = this.getCertificateValidationControllingValue()
|
||||
or
|
||||
// We set `Excon.defaults[:ssl_verify_peer]` or `Excon.ssl_verify_peer` = false`
|
||||
// before the request, and no `ssl_verify_peer: true` in the explicit options hash
|
||||
// for the request call.
|
||||
exists(DataFlow::CallNode disableCall, BooleanLiteral value |
|
||||
// Excon.defaults[:ssl_verify_peer]
|
||||
disableCall = API::getTopLevelMember("Excon").getReturn("defaults").getAMethodCall("[]=") and
|
||||
disableCall
|
||||
.getArgument(0)
|
||||
.getALocalSource()
|
||||
.asExpr()
|
||||
.getExpr()
|
||||
.getConstantValue()
|
||||
.isStringlikeValue("ssl_verify_peer") and
|
||||
disablingNode = disableCall.getArgument(1) and
|
||||
argumentOrigin = disablingNode.getALocalSource() and
|
||||
value = argumentOrigin.asExpr().getExpr()
|
||||
or
|
||||
// Excon.ssl_verify_peer
|
||||
disableCall = API::getTopLevelMember("Excon").getAMethodCall("ssl_verify_peer=") and
|
||||
disablingNode = disableCall.getArgument(0) and
|
||||
argumentOrigin = disablingNode.getALocalSource() and
|
||||
value = argumentOrigin.asExpr().getExpr()
|
||||
|
|
||||
value.getValue() = false and
|
||||
disableCall.asExpr().getASuccessor+() = this.asExpr() and
|
||||
// no `ssl_verify_peer: true` in the request call.
|
||||
not this.getCertificateValidationControllingValue()
|
||||
.getALocalSource()
|
||||
.asExpr()
|
||||
.getExpr()
|
||||
.(BooleanLiteral)
|
||||
.getValue() = true
|
||||
)
|
||||
}
|
||||
|
||||
override string getFramework() { result = "Excon" }
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if `arg` represents an options hash that contains the key
|
||||
* `:ssl_verify_peer` with `value`, where `kvNode` is the data-flow node for
|
||||
* this key-value pair.
|
||||
*/
|
||||
predicate argSetsVerifyPeer(DataFlow::Node arg, boolean value, DataFlow::Node kvNode) {
|
||||
// Either passed as an individual key:value argument, e.g.:
|
||||
// Excon.get(..., ssl_verify_peer: false)
|
||||
isSslVerifyPeerPair(arg.asExpr(), value) and
|
||||
kvNode = arg
|
||||
or
|
||||
// Or as a single hash argument, e.g.:
|
||||
// Excon.get(..., { ssl_verify_peer: false, ... })
|
||||
exists(DataFlow::LocalSourceNode optionsNode, CfgNodes::ExprNodes::PairCfgNode p |
|
||||
p = optionsNode.asExpr().(CfgNodes::ExprNodes::HashLiteralCfgNode).getAKeyValuePair() and
|
||||
isSslVerifyPeerPair(p, value) and
|
||||
optionsNode.flowsTo(arg) and
|
||||
kvNode.asExpr() = p
|
||||
)
|
||||
}
|
||||
/** A configuration to track values that can disable certificate validation for Excon. */
|
||||
private class ExconDisablesCertificateValidationConfiguration extends DataFlowImplForLibraries::Configuration {
|
||||
ExconDisablesCertificateValidationConfiguration() {
|
||||
this = "ExconDisablesCertificateValidationConfiguration"
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if `callNode` sets `Excon.defaults[:ssl_verify_peer]` or
|
||||
* `Excon.ssl_verify_peer` to `value`.
|
||||
*/
|
||||
private predicate setsDefaultVerification(DataFlow::CallNode callNode, boolean value) {
|
||||
callNode = API::getTopLevelMember("Excon").getReturn("defaults").getAMethodCall("[]=") and
|
||||
isSslVerifyPeerLiteral(callNode.getArgument(0)) and
|
||||
hasBooleanValue(callNode.getArgument(1), value)
|
||||
or
|
||||
callNode = API::getTopLevelMember("Excon").getAMethodCall("ssl_verify_peer=") and
|
||||
hasBooleanValue(callNode.getArgument(0), value)
|
||||
}
|
||||
override predicate isSource(DataFlow::Node source) {
|
||||
source.asExpr().getExpr().(BooleanLiteral).isFalse()
|
||||
}
|
||||
|
||||
private predicate isSslVerifyPeerLiteral(DataFlow::Node node) {
|
||||
exists(DataFlow::LocalSourceNode literal |
|
||||
literal.asExpr().getExpr().getConstantValue().isStringlikeValue("ssl_verify_peer") and
|
||||
literal.flowsTo(node)
|
||||
)
|
||||
}
|
||||
|
||||
/** Holds if `node` can contain `value`. */
|
||||
private predicate hasBooleanValue(DataFlow::Node node, boolean value) {
|
||||
exists(DataFlow::LocalSourceNode literal |
|
||||
literal.asExpr().getExpr().(BooleanLiteral).getValue() = value and
|
||||
literal.flowsTo(node)
|
||||
)
|
||||
}
|
||||
|
||||
/** Holds if `p` is the pair `ssl_verify_peer: <value>`. */
|
||||
private predicate isSslVerifyPeerPair(CfgNodes::ExprNodes::PairCfgNode p, boolean value) {
|
||||
exists(DataFlow::Node key, DataFlow::Node valueNode |
|
||||
key.asExpr() = p.getKey() and
|
||||
valueNode.asExpr() = p.getValue() and
|
||||
isSslVerifyPeerLiteral(key) and
|
||||
hasBooleanValue(valueNode, value)
|
||||
)
|
||||
override predicate isSink(DataFlow::Node sink) {
|
||||
sink = any(ExconHttpRequest req).getCertificateValidationControllingValue()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,6 +7,7 @@ private import codeql.ruby.CFG
|
||||
private import codeql.ruby.Concepts
|
||||
private import codeql.ruby.ApiGraphs
|
||||
private import codeql.ruby.DataFlow
|
||||
private import codeql.ruby.dataflow.internal.DataFlowImplForLibraries as DataFlowImplForLibraries
|
||||
|
||||
/**
|
||||
* A call that makes an HTTP request using `Faraday`.
|
||||
@@ -49,28 +50,36 @@ class FaradayHttpRequest extends HTTP::Client::Request::Range, DataFlow::CallNod
|
||||
result = connectionUse.(DataFlow::CallNode).getKeywordArgument("url")
|
||||
}
|
||||
|
||||
override predicate disablesCertificateValidation(DataFlow::Node disablingNode) {
|
||||
/** Gets the value that controls certificate validation, if any, with argument name `name`. */
|
||||
DataFlow::Node getCertificateValidationControllingValue(string argName) {
|
||||
// `Faraday::new` takes an options hash as its second argument, and we're
|
||||
// looking for
|
||||
// `{ ssl: { verify: false } }`
|
||||
// or
|
||||
// `{ ssl: { verify_mode: OpenSSL::SSL::VERIFY_NONE } }`
|
||||
exists(DataFlow::Node arg, int i |
|
||||
i > 0 and
|
||||
arg = connectionNode.getAValueReachableFromSource().(DataFlow::CallNode).getArgument(i)
|
||||
|
|
||||
// Either passed as an individual key:value argument, e.g.:
|
||||
// Faraday.new(..., ssl: {...})
|
||||
isSslOptionsPairDisablingValidation(arg.asExpr()) and
|
||||
disablingNode = arg
|
||||
argName in ["verify", "verify_mode"] and
|
||||
exists(DataFlow::Node sslValue, DataFlow::CallNode newCall |
|
||||
newCall = connectionNode.getAValueReachableFromSource() and
|
||||
sslValue = newCall.getKeywordArgument("ssl")
|
||||
or
|
||||
// Or as a single hash argument, e.g.:
|
||||
// Faraday.new(..., { ssl: {...} })
|
||||
exists(DataFlow::LocalSourceNode optionsNode, CfgNodes::ExprNodes::PairCfgNode p |
|
||||
// using a hashliteral
|
||||
exists(
|
||||
DataFlow::LocalSourceNode optionsNode, CfgNodes::ExprNodes::PairCfgNode p,
|
||||
DataFlow::Node key
|
||||
|
|
||||
// can't flow to argument 0, since that's the URL
|
||||
optionsNode.flowsTo(newCall.getArgument(any(int i | i > 0))) and
|
||||
p = optionsNode.asExpr().(CfgNodes::ExprNodes::HashLiteralCfgNode).getAKeyValuePair() and
|
||||
isSslOptionsPairDisablingValidation(p) and
|
||||
optionsNode.flowsTo(arg) and
|
||||
disablingNode.asExpr() = p
|
||||
key.asExpr() = p.getKey() and
|
||||
key.getALocalSource().asExpr().getExpr().getConstantValue().isStringlikeValue("ssl") and
|
||||
sslValue.asExpr() = p.getValue()
|
||||
)
|
||||
|
|
||||
exists(CfgNodes::ExprNodes::PairCfgNode p, DataFlow::Node key |
|
||||
p = sslValue.asExpr().(CfgNodes::ExprNodes::HashLiteralCfgNode).getAKeyValuePair() and
|
||||
key.asExpr() = p.getKey() and
|
||||
key.getALocalSource().asExpr().getExpr().getConstantValue().isStringlikeValue(argName) and
|
||||
result.asExpr() = p.getValue()
|
||||
)
|
||||
)
|
||||
}
|
||||
@@ -78,90 +87,29 @@ class FaradayHttpRequest extends HTTP::Client::Request::Range, DataFlow::CallNod
|
||||
override predicate disablesCertificateValidation(
|
||||
DataFlow::Node disablingNode, DataFlow::Node argumentOrigin
|
||||
) {
|
||||
disablesCertificateValidation(disablingNode) and
|
||||
argumentOrigin = disablingNode
|
||||
any(FaradayDisablesCertificateValidationConfiguration config)
|
||||
.hasFlow(argumentOrigin, disablingNode) and
|
||||
disablingNode = this.getCertificateValidationControllingValue(_)
|
||||
}
|
||||
|
||||
override string getFramework() { result = "Faraday" }
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if the pair `p` contains the key `:ssl` for which the value is a hash
|
||||
* containing either `verify: false` or
|
||||
* `verify_mode: OpenSSL::SSL::VERIFY_NONE`.
|
||||
*/
|
||||
private predicate isSslOptionsPairDisablingValidation(CfgNodes::ExprNodes::PairCfgNode p) {
|
||||
exists(DataFlow::Node key, DataFlow::Node value |
|
||||
key.asExpr() = p.getKey() and
|
||||
value.asExpr() = p.getValue() and
|
||||
isSymbolLiteral(key, "ssl") and
|
||||
(isHashWithVerifyFalse(value) or isHashWithVerifyModeNone(value))
|
||||
)
|
||||
}
|
||||
/** A configuration to track values that can disable certificate validation for Faraday. */
|
||||
private class FaradayDisablesCertificateValidationConfiguration extends DataFlowImplForLibraries::Configuration {
|
||||
FaradayDisablesCertificateValidationConfiguration() {
|
||||
this = "FaradayDisablesCertificateValidationConfiguration"
|
||||
}
|
||||
|
||||
/** Holds if `node` represents the symbol literal with the given `valueText`. */
|
||||
private predicate isSymbolLiteral(DataFlow::Node node, string valueText) {
|
||||
exists(DataFlow::LocalSourceNode literal |
|
||||
literal.asExpr().getExpr().getConstantValue().isStringlikeValue(valueText) and
|
||||
literal.flowsTo(node)
|
||||
)
|
||||
}
|
||||
override predicate isSource(DataFlow::Node source, DataFlowImplForLibraries::FlowState state) {
|
||||
source.asExpr().getExpr().(BooleanLiteral).isFalse() and
|
||||
state = "verify"
|
||||
or
|
||||
source = API::getTopLevelMember("OpenSSL").getMember("SSL").getMember("VERIFY_NONE").asSource() and
|
||||
state = "verify_mode"
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if `node` represents a hash containing the key-value pair
|
||||
* `verify: false`.
|
||||
*/
|
||||
private predicate isHashWithVerifyFalse(DataFlow::Node node) {
|
||||
exists(DataFlow::LocalSourceNode hash |
|
||||
isVerifyFalsePair(hash.asExpr().(CfgNodes::ExprNodes::HashLiteralCfgNode).getAKeyValuePair()) and
|
||||
hash.flowsTo(node)
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if `node` represents a hash containing the key-value pair
|
||||
* `verify_mode: OpenSSL::SSL::VERIFY_NONE`.
|
||||
*/
|
||||
private predicate isHashWithVerifyModeNone(DataFlow::Node node) {
|
||||
exists(DataFlow::LocalSourceNode hash |
|
||||
isVerifyModeNonePair(hash.asExpr().(CfgNodes::ExprNodes::HashLiteralCfgNode).getAKeyValuePair()) and
|
||||
hash.flowsTo(node)
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if the pair `p` has the key `:verify_mode` and the value
|
||||
* `OpenSSL::SSL::VERIFY_NONE`.
|
||||
*/
|
||||
private predicate isVerifyModeNonePair(CfgNodes::ExprNodes::PairCfgNode p) {
|
||||
exists(DataFlow::Node key, DataFlow::Node value |
|
||||
key.asExpr() = p.getKey() and
|
||||
value.asExpr() = p.getValue() and
|
||||
isSymbolLiteral(key, "verify_mode") and
|
||||
value =
|
||||
API::getTopLevelMember("OpenSSL")
|
||||
.getMember("SSL")
|
||||
.getMember("VERIFY_NONE")
|
||||
.getAValueReachableFromSource()
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if the pair `p` has the key `:verify` and the value `false`.
|
||||
*/
|
||||
private predicate isVerifyFalsePair(CfgNodes::ExprNodes::PairCfgNode p) {
|
||||
exists(DataFlow::Node key, DataFlow::Node value |
|
||||
key.asExpr() = p.getKey() and
|
||||
value.asExpr() = p.getValue() and
|
||||
isSymbolLiteral(key, "verify") and
|
||||
isFalse(value)
|
||||
)
|
||||
}
|
||||
|
||||
/** Holds if `node` can contain the Boolean value `false`. */
|
||||
private predicate isFalse(DataFlow::Node node) {
|
||||
exists(DataFlow::LocalSourceNode literal |
|
||||
literal.asExpr().getExpr().(BooleanLiteral).isFalse() and
|
||||
literal.flowsTo(node)
|
||||
)
|
||||
override predicate isSink(DataFlow::Node sink, DataFlowImplForLibraries::FlowState state) {
|
||||
sink = any(FaradayHttpRequest req).getCertificateValidationControllingValue(state)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,6 +6,7 @@ private import ruby
|
||||
private import codeql.ruby.Concepts
|
||||
private import codeql.ruby.ApiGraphs
|
||||
private import codeql.ruby.DataFlow
|
||||
private import codeql.ruby.dataflow.internal.DataFlowImplForLibraries as DataFlowImplForLibraries
|
||||
|
||||
/**
|
||||
* A call that makes an HTTP request using `HTTPClient`.
|
||||
@@ -46,24 +47,42 @@ class HttpClientRequest extends HTTP::Client::Request::Range, DataFlow::CallNode
|
||||
result = requestNode.getAMethodCall(["body", "http_body", "content", "dump"])
|
||||
}
|
||||
|
||||
override predicate disablesCertificateValidation(DataFlow::Node disablingNode) {
|
||||
/** Gets the value that controls certificate validation, if any. */
|
||||
DataFlow::Node getCertificateValidationControllingValue() {
|
||||
// Look for calls to set
|
||||
// `c.ssl_config.verify_mode = OpenSSL::SSL::VERIFY_NONE`
|
||||
// on an HTTPClient connection object `c`.
|
||||
disablingNode = connectionNode.getReturn("ssl_config").getReturn("verify_mode=").asSource() and
|
||||
disablingNode.(DataFlow::CallNode).getArgument(0) =
|
||||
API::getTopLevelMember("OpenSSL")
|
||||
.getMember("SSL")
|
||||
.getMember("VERIFY_NONE")
|
||||
.getAValueReachableFromSource()
|
||||
result =
|
||||
connectionNode
|
||||
.getReturn("ssl_config")
|
||||
.getReturn("verify_mode=")
|
||||
.asSource()
|
||||
.(DataFlow::CallNode)
|
||||
.getArgument(0)
|
||||
}
|
||||
|
||||
override predicate disablesCertificateValidation(
|
||||
DataFlow::Node disablingNode, DataFlow::Node argumentOrigin
|
||||
) {
|
||||
disablesCertificateValidation(disablingNode) and
|
||||
argumentOrigin = disablingNode
|
||||
any(HttpClientDisablesCertificateValidationConfiguration config)
|
||||
.hasFlow(argumentOrigin, disablingNode) and
|
||||
disablingNode = this.getCertificateValidationControllingValue()
|
||||
}
|
||||
|
||||
override string getFramework() { result = "HTTPClient" }
|
||||
}
|
||||
|
||||
/** A configuration to track values that can disable certificate validation for HttpClient. */
|
||||
private class HttpClientDisablesCertificateValidationConfiguration extends DataFlowImplForLibraries::Configuration {
|
||||
HttpClientDisablesCertificateValidationConfiguration() {
|
||||
this = "HttpClientDisablesCertificateValidationConfiguration"
|
||||
}
|
||||
|
||||
override predicate isSource(DataFlow::Node source) {
|
||||
source = API::getTopLevelMember("OpenSSL").getMember("SSL").getMember("VERIFY_NONE").asSource()
|
||||
}
|
||||
|
||||
override predicate isSink(DataFlow::Node sink) {
|
||||
sink = any(HttpClientRequest req).getCertificateValidationControllingValue()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,6 +7,7 @@ private import codeql.ruby.CFG
|
||||
private import codeql.ruby.Concepts
|
||||
private import codeql.ruby.ApiGraphs
|
||||
private import codeql.ruby.DataFlow
|
||||
private import codeql.ruby.dataflow.internal.DataFlowImplForLibraries as DataFlowImplForLibraries
|
||||
|
||||
/**
|
||||
* A call that makes an HTTP request using `HTTParty`.
|
||||
@@ -47,64 +48,49 @@ class HttpartyRequest extends HTTP::Client::Request::Range, DataFlow::CallNode {
|
||||
result = this
|
||||
}
|
||||
|
||||
override predicate disablesCertificateValidation(DataFlow::Node disablingNode) {
|
||||
// The various request methods take an options hash as their second
|
||||
// argument, and we're looking for `{ verify: false }` or
|
||||
// `{ verify_peer: false }`.
|
||||
exists(DataFlow::Node arg, int i |
|
||||
i > 0 and
|
||||
arg.asExpr() = this.asExpr().(CfgNodes::ExprNodes::MethodCallCfgNode).getArgument(i)
|
||||
/** Gets the value that controls certificate validation, if any. */
|
||||
DataFlow::Node getCertificateValidationControllingValue() {
|
||||
result = this.getKeywordArgument(["verify", "verify_peer"])
|
||||
or
|
||||
// using a hashliteral
|
||||
exists(
|
||||
DataFlow::LocalSourceNode optionsNode, CfgNodes::ExprNodes::PairCfgNode p, DataFlow::Node key
|
||||
|
|
||||
// Either passed as an individual key:value argument, e.g.:
|
||||
// HTTParty.get(..., verify: false)
|
||||
isVerifyFalsePair(arg.asExpr()) and
|
||||
disablingNode = arg
|
||||
or
|
||||
// Or as a single hash argument, e.g.:
|
||||
// HTTParty.get(..., { verify: false, ... })
|
||||
exists(DataFlow::LocalSourceNode optionsNode, CfgNodes::ExprNodes::PairCfgNode p |
|
||||
p = optionsNode.asExpr().(CfgNodes::ExprNodes::HashLiteralCfgNode).getAKeyValuePair() and
|
||||
isVerifyFalsePair(p) and
|
||||
optionsNode.flowsTo(arg) and
|
||||
disablingNode.asExpr() = p
|
||||
)
|
||||
// can't flow to argument 0, since that's the URL
|
||||
optionsNode.flowsTo(this.getArgument(any(int i | i > 0))) and
|
||||
p = optionsNode.asExpr().(CfgNodes::ExprNodes::HashLiteralCfgNode).getAKeyValuePair() and
|
||||
key.asExpr() = p.getKey() and
|
||||
key.getALocalSource()
|
||||
.asExpr()
|
||||
.getExpr()
|
||||
.getConstantValue()
|
||||
.isStringlikeValue(["verify", "verify_peer"]) and
|
||||
result.asExpr() = p.getValue()
|
||||
)
|
||||
}
|
||||
|
||||
override predicate disablesCertificateValidation(
|
||||
DataFlow::Node disablingNode, DataFlow::Node argumentOrigin
|
||||
) {
|
||||
disablesCertificateValidation(disablingNode) and
|
||||
argumentOrigin = disablingNode
|
||||
any(HttpartyDisablesCertificateValidationConfiguration config)
|
||||
.hasFlow(argumentOrigin, disablingNode) and
|
||||
disablingNode = this.getCertificateValidationControllingValue()
|
||||
}
|
||||
|
||||
override string getFramework() { result = "HTTParty" }
|
||||
}
|
||||
|
||||
/** Holds if `node` represents the symbol literal `verify` or `verify_peer`. */
|
||||
private predicate isVerifyLiteral(DataFlow::Node node) {
|
||||
exists(DataFlow::LocalSourceNode literal |
|
||||
literal.asExpr().getExpr().getConstantValue().isStringlikeValue(["verify", "verify_peer"]) and
|
||||
literal.flowsTo(node)
|
||||
)
|
||||
}
|
||||
/** A configuration to track values that can disable certificate validation for Httparty. */
|
||||
private class HttpartyDisablesCertificateValidationConfiguration extends DataFlowImplForLibraries::Configuration {
|
||||
HttpartyDisablesCertificateValidationConfiguration() {
|
||||
this = "HttpartyDisablesCertificateValidationConfiguration"
|
||||
}
|
||||
|
||||
/** Holds if `node` can contain the Boolean value `false`. */
|
||||
private predicate isFalse(DataFlow::Node node) {
|
||||
exists(DataFlow::LocalSourceNode literal |
|
||||
literal.asExpr().getExpr().(BooleanLiteral).isFalse() and
|
||||
literal.flowsTo(node)
|
||||
)
|
||||
}
|
||||
override predicate isSource(DataFlow::Node source) {
|
||||
source.asExpr().getExpr().(BooleanLiteral).isFalse()
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if `p` is the pair `verify: false` or `verify_peer: false`.
|
||||
*/
|
||||
private predicate isVerifyFalsePair(CfgNodes::ExprNodes::PairCfgNode p) {
|
||||
exists(DataFlow::Node key, DataFlow::Node value |
|
||||
key.asExpr() = p.getKey() and
|
||||
value.asExpr() = p.getValue() and
|
||||
isVerifyLiteral(key) and
|
||||
isFalse(value)
|
||||
)
|
||||
override predicate isSink(DataFlow::Node sink) {
|
||||
sink = any(HttpartyRequest req).getCertificateValidationControllingValue()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,6 +8,7 @@ private import codeql.ruby.dataflow.RemoteFlowSources
|
||||
private import codeql.ruby.ApiGraphs
|
||||
private import codeql.ruby.dataflow.internal.DataFlowPublic
|
||||
private import codeql.ruby.DataFlow
|
||||
private import codeql.ruby.dataflow.internal.DataFlowImplForLibraries as DataFlowImplForLibraries
|
||||
|
||||
/**
|
||||
* A `Net::HTTP` call which initiates an HTTP request.
|
||||
@@ -65,20 +66,16 @@ class NetHttpRequest extends HTTP::Client::Request::Range, DataFlow::CallNode {
|
||||
|
||||
override DataFlow::Node getResponseBody() { result = responseBody }
|
||||
|
||||
override predicate disablesCertificateValidation(DataFlow::Node disablingNode) {
|
||||
/** Gets the value that controls certificate validation, if any. */
|
||||
DataFlow::Node getCertificateValidationControllingValue() {
|
||||
// A Net::HTTP request bypasses certificate validation if we see a setter
|
||||
// call like this:
|
||||
// foo.verify_mode = OpenSSL::SSL::VERIFY_NONE
|
||||
// and then the receiver of that call flows to the receiver in the request:
|
||||
// foo.request(...)
|
||||
exists(DataFlow::CallNode setter |
|
||||
disablingNode =
|
||||
API::getTopLevelMember("OpenSSL")
|
||||
.getMember("SSL")
|
||||
.getMember("VERIFY_NONE")
|
||||
.getAValueReachableFromSource() and
|
||||
setter.asExpr().getExpr().(SetterMethodCall).getMethodName() = "verify_mode=" and
|
||||
disablingNode = setter.getArgument(0) and
|
||||
result = setter.getArgument(0) and
|
||||
localFlow(setter.getReceiver(), request.getReceiver())
|
||||
)
|
||||
}
|
||||
@@ -86,9 +83,25 @@ class NetHttpRequest extends HTTP::Client::Request::Range, DataFlow::CallNode {
|
||||
override predicate disablesCertificateValidation(
|
||||
DataFlow::Node disablingNode, DataFlow::Node argumentOrigin
|
||||
) {
|
||||
disablesCertificateValidation(disablingNode) and
|
||||
argumentOrigin = disablingNode
|
||||
any(NetHttpDisablesCertificateValidationConfiguration config)
|
||||
.hasFlow(argumentOrigin, disablingNode) and
|
||||
disablingNode = this.getCertificateValidationControllingValue()
|
||||
}
|
||||
|
||||
override string getFramework() { result = "Net::HTTP" }
|
||||
}
|
||||
|
||||
/** A configuration to track values that can disable certificate validation for NetHttp. */
|
||||
private class NetHttpDisablesCertificateValidationConfiguration extends DataFlowImplForLibraries::Configuration {
|
||||
NetHttpDisablesCertificateValidationConfiguration() {
|
||||
this = "NetHttpDisablesCertificateValidationConfiguration"
|
||||
}
|
||||
|
||||
override predicate isSource(DataFlow::Node source) {
|
||||
source = API::getTopLevelMember("OpenSSL").getMember("SSL").getMember("VERIFY_NONE").asSource()
|
||||
}
|
||||
|
||||
override predicate isSink(DataFlow::Node sink) {
|
||||
sink = any(NetHttpRequest req).getCertificateValidationControllingValue()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,6 +8,7 @@ private import codeql.ruby.Concepts
|
||||
private import codeql.ruby.ApiGraphs
|
||||
private import codeql.ruby.DataFlow
|
||||
private import codeql.ruby.frameworks.Core
|
||||
private import codeql.ruby.dataflow.internal.DataFlowImplForLibraries as DataFlowImplForLibraries
|
||||
|
||||
/**
|
||||
* A call that makes an HTTP request using `OpenURI` via `URI.open` or
|
||||
@@ -36,18 +37,32 @@ class OpenUriRequest extends HTTP::Client::Request::Range, DataFlow::CallNode {
|
||||
result = requestNode.getAMethodCall(["read", "readlines"])
|
||||
}
|
||||
|
||||
override predicate disablesCertificateValidation(DataFlow::Node disablingNode) {
|
||||
exists(DataFlow::Node arg |
|
||||
arg.asExpr() = this.asExpr().(CfgNodes::ExprNodes::MethodCallCfgNode).getAnArgument() and
|
||||
argumentDisablesValidation(arg, disablingNode)
|
||||
/** Gets the value that controls certificate validation, if any. */
|
||||
DataFlow::Node getCertificateValidationControllingValue() {
|
||||
result = this.getKeywordArgument("ssl_verify_mode")
|
||||
or
|
||||
// using a hashliteral
|
||||
exists(
|
||||
DataFlow::LocalSourceNode optionsNode, CfgNodes::ExprNodes::PairCfgNode p, DataFlow::Node key
|
||||
|
|
||||
optionsNode.flowsTo(this.getArgument(_)) and
|
||||
p = optionsNode.asExpr().(CfgNodes::ExprNodes::HashLiteralCfgNode).getAKeyValuePair() and
|
||||
key.asExpr() = p.getKey() and
|
||||
key.getALocalSource()
|
||||
.asExpr()
|
||||
.getExpr()
|
||||
.getConstantValue()
|
||||
.isStringlikeValue("ssl_verify_mode") and
|
||||
result.asExpr() = p.getValue()
|
||||
)
|
||||
}
|
||||
|
||||
override predicate disablesCertificateValidation(
|
||||
DataFlow::Node disablingNode, DataFlow::Node argumentOrigin
|
||||
) {
|
||||
disablesCertificateValidation(disablingNode) and
|
||||
argumentOrigin = disablingNode
|
||||
any(OpenUriDisablesCertificateValidationConfiguration config)
|
||||
.hasFlow(argumentOrigin, disablingNode) and
|
||||
disablingNode = this.getCertificateValidationControllingValue()
|
||||
}
|
||||
|
||||
override string getFramework() { result = "OpenURI" }
|
||||
@@ -74,63 +89,51 @@ class OpenUriKernelOpenRequest extends HTTP::Client::Request::Range, DataFlow::C
|
||||
this.(DataFlow::LocalSourceNode).flowsTo(result.getReceiver())
|
||||
}
|
||||
|
||||
override predicate disablesCertificateValidation(DataFlow::Node disablingNode) {
|
||||
exists(DataFlow::Node arg, int i |
|
||||
i > 0 and
|
||||
arg.asExpr() = this.asExpr().(CfgNodes::ExprNodes::MethodCallCfgNode).getArgument(i) and
|
||||
argumentDisablesValidation(arg, disablingNode)
|
||||
/** Gets the value that controls certificate validation, if any. */
|
||||
DataFlow::Node getCertificateValidationControllingValue() {
|
||||
result = this.getKeywordArgument("ssl_verify_mode")
|
||||
or
|
||||
// using a hashliteral
|
||||
exists(
|
||||
DataFlow::LocalSourceNode optionsNode, CfgNodes::ExprNodes::PairCfgNode p, DataFlow::Node key
|
||||
|
|
||||
// can't flow to argument 0, since that's the URL
|
||||
optionsNode.flowsTo(this.getArgument(any(int i | i > 0))) and
|
||||
p = optionsNode.asExpr().(CfgNodes::ExprNodes::HashLiteralCfgNode).getAKeyValuePair() and
|
||||
key.asExpr() = p.getKey() and
|
||||
key.getALocalSource()
|
||||
.asExpr()
|
||||
.getExpr()
|
||||
.getConstantValue()
|
||||
.isStringlikeValue("ssl_verify_mode") and
|
||||
result.asExpr() = p.getValue()
|
||||
)
|
||||
}
|
||||
|
||||
override predicate disablesCertificateValidation(
|
||||
DataFlow::Node disablingNode, DataFlow::Node argumentOrigin
|
||||
) {
|
||||
disablesCertificateValidation(disablingNode) and
|
||||
argumentOrigin = disablingNode
|
||||
any(OpenUriDisablesCertificateValidationConfiguration config)
|
||||
.hasFlow(argumentOrigin, disablingNode) and
|
||||
disablingNode = this.getCertificateValidationControllingValue()
|
||||
}
|
||||
|
||||
override string getFramework() { result = "OpenURI" }
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if the argument `arg` is an options hash that disables certificate
|
||||
* validation, and `disablingNode` is the specific node representing the
|
||||
* `ssl_verify_mode: OpenSSL::SSL_VERIFY_NONE` pair.
|
||||
*/
|
||||
private predicate argumentDisablesValidation(DataFlow::Node arg, DataFlow::Node disablingNode) {
|
||||
// Either passed as an individual key:value argument, e.g.:
|
||||
// URI.open(..., ssl_verify_mode: OpenSSL::SSL::VERIFY_NONE)
|
||||
isSslVerifyModeNonePair(arg.asExpr()) and
|
||||
disablingNode = arg
|
||||
or
|
||||
// Or as a single hash argument, e.g.:
|
||||
// URI.open(..., { ssl_verify_mode: OpenSSL::SSL::VERIFY_NONE, ... })
|
||||
exists(DataFlow::LocalSourceNode optionsNode, CfgNodes::ExprNodes::PairCfgNode p |
|
||||
p = optionsNode.asExpr().(CfgNodes::ExprNodes::HashLiteralCfgNode).getAKeyValuePair() and
|
||||
isSslVerifyModeNonePair(p) and
|
||||
optionsNode.flowsTo(arg) and
|
||||
disablingNode.asExpr() = p
|
||||
)
|
||||
}
|
||||
/** A configuration to track values that can disable certificate validation for OpenURI. */
|
||||
private class OpenUriDisablesCertificateValidationConfiguration extends DataFlowImplForLibraries::Configuration {
|
||||
OpenUriDisablesCertificateValidationConfiguration() {
|
||||
this = "OpenUriDisablesCertificateValidationConfiguration"
|
||||
}
|
||||
|
||||
/** Holds if `p` is the pair `ssl_verify_mode: OpenSSL::SSL::VERIFY_NONE`. */
|
||||
private predicate isSslVerifyModeNonePair(CfgNodes::ExprNodes::PairCfgNode p) {
|
||||
exists(DataFlow::Node key, DataFlow::Node value |
|
||||
key.asExpr() = p.getKey() and
|
||||
value.asExpr() = p.getValue() and
|
||||
isSslVerifyModeLiteral(key) and
|
||||
value =
|
||||
API::getTopLevelMember("OpenSSL")
|
||||
.getMember("SSL")
|
||||
.getMember("VERIFY_NONE")
|
||||
.getAValueReachableFromSource()
|
||||
)
|
||||
}
|
||||
override predicate isSource(DataFlow::Node source) {
|
||||
source = API::getTopLevelMember("OpenSSL").getMember("SSL").getMember("VERIFY_NONE").asSource()
|
||||
}
|
||||
|
||||
/** Holds if `node` can represent the symbol literal `:ssl_verify_mode`. */
|
||||
private predicate isSslVerifyModeLiteral(DataFlow::Node node) {
|
||||
exists(DataFlow::LocalSourceNode literal |
|
||||
literal.asExpr().getExpr().getConstantValue().isStringlikeValue("ssl_verify_mode") and
|
||||
literal.flowsTo(node)
|
||||
)
|
||||
override predicate isSink(DataFlow::Node sink) {
|
||||
sink = any(OpenUriRequest req).getCertificateValidationControllingValue()
|
||||
or
|
||||
sink = any(OpenUriKernelOpenRequest req).getCertificateValidationControllingValue()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -49,8 +49,6 @@ class RestClientHttpRequest extends HTTP::Client::Request::Range, DataFlow::Call
|
||||
|
||||
/** Gets the value that controls certificate validation, if any. */
|
||||
DataFlow::Node getCertificateValidationControllingValue() {
|
||||
// `RestClient::Resource::new` takes an options hash argument, and we're
|
||||
// looking for `{ verify_ssl: OpenSSL::SSL::VERIFY_NONE }`.
|
||||
exists(DataFlow::CallNode newCall | newCall = connectionNode.getAValueReachableFromSource() |
|
||||
result = newCall.getKeywordArgument("verify_ssl")
|
||||
or
|
||||
|
||||
@@ -7,6 +7,7 @@ private import codeql.ruby.CFG
|
||||
private import codeql.ruby.Concepts
|
||||
private import codeql.ruby.ApiGraphs
|
||||
private import codeql.ruby.DataFlow
|
||||
private import codeql.ruby.dataflow.internal.DataFlowImplForLibraries as DataFlowImplForLibraries
|
||||
|
||||
/**
|
||||
* A call that makes an HTTP request using `Typhoeus`.
|
||||
@@ -28,59 +29,46 @@ class TyphoeusHttpRequest extends HTTP::Client::Request::Range, DataFlow::CallNo
|
||||
|
||||
override DataFlow::Node getResponseBody() { result = requestNode.getAMethodCall("body") }
|
||||
|
||||
override predicate disablesCertificateValidation(DataFlow::Node disablingNode) {
|
||||
// Check for `ssl_verifypeer: false` in the options hash.
|
||||
exists(DataFlow::Node arg, int i |
|
||||
i > 0 and arg.asExpr().getExpr() = this.asExpr().getExpr().(MethodCall).getArgument(i)
|
||||
/** Gets the value that controls certificate validation, if any. */
|
||||
DataFlow::Node getCertificateValidationControllingValue() {
|
||||
result = this.getKeywordArgument("ssl_verifypeer")
|
||||
or
|
||||
// using a hashliteral
|
||||
exists(
|
||||
DataFlow::LocalSourceNode optionsNode, CfgNodes::ExprNodes::PairCfgNode p,
|
||||
DataFlow::Node key
|
||||
|
|
||||
// Either passed as an individual key:value argument, e.g.:
|
||||
// Typhoeus.get(..., ssl_verifypeer: false)
|
||||
isSslVerifyPeerFalsePair(arg.asExpr()) and
|
||||
disablingNode = arg
|
||||
or
|
||||
// Or as a single hash argument, e.g.:
|
||||
// Typhoeus.get(..., { ssl_verifypeer: false, ... })
|
||||
exists(DataFlow::LocalSourceNode optionsNode, CfgNodes::ExprNodes::PairCfgNode p |
|
||||
p = optionsNode.asExpr().(CfgNodes::ExprNodes::HashLiteralCfgNode).getAKeyValuePair() and
|
||||
isSslVerifyPeerFalsePair(p) and
|
||||
optionsNode.flowsTo(arg) and
|
||||
disablingNode.asExpr() = p
|
||||
)
|
||||
// can't flow to argument 0, since that's the URL
|
||||
optionsNode.flowsTo(this.getArgument(any(int i | i > 0))) and
|
||||
p = optionsNode.asExpr().(CfgNodes::ExprNodes::HashLiteralCfgNode).getAKeyValuePair() and
|
||||
key.asExpr() = p.getKey() and
|
||||
key.getALocalSource().asExpr().getExpr().getConstantValue().isStringlikeValue("ssl_verifypeer") and
|
||||
result.asExpr() = p.getValue()
|
||||
)
|
||||
}
|
||||
|
||||
override predicate disablesCertificateValidation(
|
||||
DataFlow::Node disablingNode, DataFlow::Node argumentOrigin
|
||||
) {
|
||||
disablesCertificateValidation(disablingNode) and
|
||||
argumentOrigin = disablingNode
|
||||
any(TyphoeusDisablesCertificateValidationConfiguration config)
|
||||
.hasFlow(argumentOrigin, disablingNode) and
|
||||
disablingNode = this.getCertificateValidationControllingValue()
|
||||
}
|
||||
|
||||
override string getFramework() { result = "Typhoeus" }
|
||||
}
|
||||
|
||||
/** Holds if `p` is the pair `ssl_verifypeer: false`. */
|
||||
private predicate isSslVerifyPeerFalsePair(CfgNodes::ExprNodes::PairCfgNode p) {
|
||||
exists(DataFlow::Node key, DataFlow::Node value |
|
||||
key.asExpr() = p.getKey() and
|
||||
value.asExpr() = p.getValue() and
|
||||
isSslVerifyPeerLiteral(key) and
|
||||
isFalse(value)
|
||||
)
|
||||
}
|
||||
/** A configuration to track values that can disable certificate validation for Typhoeus. */
|
||||
private class TyphoeusDisablesCertificateValidationConfiguration extends DataFlowImplForLibraries::Configuration {
|
||||
TyphoeusDisablesCertificateValidationConfiguration() {
|
||||
this = "TyphoeusDisablesCertificateValidationConfiguration"
|
||||
}
|
||||
|
||||
/** Holds if `node` represents the symbol literal `verify` or `verify_peer`. */
|
||||
private predicate isSslVerifyPeerLiteral(DataFlow::Node node) {
|
||||
exists(DataFlow::LocalSourceNode literal |
|
||||
literal.asExpr().getExpr().getConstantValue().isStringlikeValue("ssl_verifypeer") and
|
||||
literal.flowsTo(node)
|
||||
)
|
||||
}
|
||||
override predicate isSource(DataFlow::Node source) {
|
||||
source.asExpr().getExpr().(BooleanLiteral).isFalse()
|
||||
}
|
||||
|
||||
/** Holds if `node` can contain the Boolean value `false`. */
|
||||
private predicate isFalse(DataFlow::Node node) {
|
||||
exists(DataFlow::LocalSourceNode literal |
|
||||
literal.asExpr().getExpr().(BooleanLiteral).isFalse() and
|
||||
literal.flowsTo(node)
|
||||
)
|
||||
override predicate isSink(DataFlow::Node sink) {
|
||||
sink = any(TyphoeusHttpRequest req).getCertificateValidationControllingValue()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,27 +1,28 @@
|
||||
| Excon.rb:6:3:6:34 | call to get | This request may run without certificate validation because it is $@. | Excon.rb:5:3:5:34 | call to []= | disabled here | Excon.rb:5:3:5:34 | call to []= | here |
|
||||
| Excon.rb:12:3:12:34 | call to get | This request may run without certificate validation because it is $@. | Excon.rb:11:3:11:23 | call to ssl_verify_peer= | disabled here | Excon.rb:11:3:11:23 | call to ssl_verify_peer= | here |
|
||||
| Excon.rb:18:3:18:34 | call to get | This request may run without certificate validation because it is $@. | Excon.rb:17:3:17:34 | call to []= | disabled here | Excon.rb:17:3:17:34 | call to []= | here |
|
||||
| Excon.rb:24:3:24:10 | call to get | This request may run without certificate validation because it is $@. | Excon.rb:23:55:23:76 | Pair | disabled here | Excon.rb:23:55:23:76 | Pair | here |
|
||||
| Excon.rb:30:3:30:62 | call to get | This request may run without certificate validation because it is $@. | Excon.rb:30:36:30:57 | Pair | disabled here | Excon.rb:30:36:30:57 | Pair | here |
|
||||
| Faraday.rb:5:12:5:30 | call to get | This request may run without certificate validation because it is $@. | Faraday.rb:4:48:4:69 | Pair | disabled here | Faraday.rb:4:48:4:69 | Pair | here |
|
||||
| Faraday.rb:9:12:9:30 | call to get | This request may run without certificate validation because it is $@. | Faraday.rb:8:48:8:94 | Pair | disabled here | Faraday.rb:8:48:8:94 | Pair | here |
|
||||
| Faraday.rb:44:16:44:35 | call to get | This request may run without certificate validation because it is $@. | Faraday.rb:43:36:43:60 | Pair | disabled here | Faraday.rb:43:36:43:60 | Pair | here |
|
||||
| HttpClient.rb:6:1:6:33 | call to get | This request may run without certificate validation because it is $@. | HttpClient.rb:5:1:5:29 | call to verify_mode= | disabled here | HttpClient.rb:5:1:5:29 | call to verify_mode= | here |
|
||||
| Httparty.rb:4:1:4:50 | call to get | This request may run without certificate validation because it is $@. | Httparty.rb:4:37:4:49 | Pair | disabled here | Httparty.rb:4:37:4:49 | Pair | here |
|
||||
| Httparty.rb:7:1:7:55 | call to get | This request may run without certificate validation because it is $@. | Httparty.rb:7:37:7:54 | Pair | disabled here | Httparty.rb:7:37:7:54 | Pair | here |
|
||||
| Httparty.rb:10:1:10:59 | call to get | This request may run without certificate validation because it is $@. | Httparty.rb:10:39:10:56 | Pair | disabled here | Httparty.rb:10:39:10:56 | Pair | here |
|
||||
| Httparty.rb:13:1:13:70 | call to post | This request may run without certificate validation because it is $@. | Httparty.rb:13:57:13:69 | Pair | disabled here | Httparty.rb:13:57:13:69 | Pair | here |
|
||||
| Httparty.rb:16:1:16:74 | call to post | This request may run without certificate validation because it is $@. | Httparty.rb:16:59:16:71 | Pair | disabled here | Httparty.rb:16:59:16:71 | Pair | here |
|
||||
| NetHttp.rb:9:12:9:31 | call to request | This request may run without certificate validation because it is $@. | NetHttp.rb:7:20:7:44 | ... = ... | disabled here | NetHttp.rb:7:20:7:44 | ... = ... | here |
|
||||
| OpenURI.rb:4:1:4:78 | call to open | This request may run without certificate validation because it is $@. | OpenURI.rb:4:36:4:77 | Pair | disabled here | OpenURI.rb:4:36:4:77 | Pair | here |
|
||||
| OpenURI.rb:7:1:7:82 | call to open | This request may run without certificate validation because it is $@. | OpenURI.rb:7:38:7:79 | Pair | disabled here | OpenURI.rb:7:38:7:79 | Pair | here |
|
||||
| OpenURI.rb:11:1:11:43 | call to open | This request may run without certificate validation because it is $@. | OpenURI.rb:10:13:10:54 | Pair | disabled here | OpenURI.rb:10:13:10:54 | Pair | here |
|
||||
| OpenURI.rb:14:1:14:81 | call to open | This request may run without certificate validation because it is $@. | OpenURI.rb:14:39:14:80 | Pair | disabled here | OpenURI.rb:14:39:14:80 | Pair | here |
|
||||
| OpenURI.rb:17:1:17:85 | call to open | This request may run without certificate validation because it is $@. | OpenURI.rb:17:41:17:82 | Pair | disabled here | OpenURI.rb:17:41:17:82 | Pair | here |
|
||||
| OpenURI.rb:21:1:21:46 | call to open | This request may run without certificate validation because it is $@. | OpenURI.rb:20:13:20:54 | Pair | disabled here | OpenURI.rb:20:13:20:54 | Pair | here |
|
||||
| Excon.rb:6:3:6:34 | call to get | This request may run without certificate validation because it is $@ by the value from $@. | Excon.rb:5:38:5:42 | ... = ... | disabled here | Excon.rb:5:38:5:42 | false | here |
|
||||
| Excon.rb:12:3:12:34 | call to get | This request may run without certificate validation because it is $@ by the value from $@. | Excon.rb:11:27:11:31 | ... = ... | disabled here | Excon.rb:11:27:11:31 | false | here |
|
||||
| Excon.rb:18:3:18:34 | call to get | This request may run without certificate validation because it is $@ by the value from $@. | Excon.rb:17:38:17:60 | ... = ... | disabled here | Excon.rb:17:55:17:59 | false | here |
|
||||
| Excon.rb:24:3:24:10 | call to get | This request may run without certificate validation because it is $@. | Excon.rb:23:72:23:76 | false | disabled here | Excon.rb:23:72:23:76 | false | here |
|
||||
| Excon.rb:30:3:30:62 | call to get | This request may run without certificate validation because it is $@. | Excon.rb:30:53:30:57 | false | disabled here | Excon.rb:30:53:30:57 | false | here |
|
||||
| Faraday.rb:5:12:5:30 | call to get | This request may run without certificate validation because it is $@. | Faraday.rb:4:63:4:67 | false | disabled here | Faraday.rb:4:63:4:67 | false | here |
|
||||
| Faraday.rb:9:12:9:30 | call to get | This request may run without certificate validation because it is $@. | Faraday.rb:8:68:8:92 | VERIFY_NONE | disabled here | Faraday.rb:8:68:8:92 | VERIFY_NONE | here |
|
||||
| Faraday.rb:35:16:35:35 | call to get | This request may run without certificate validation because it is $@ by the value from $@. | Faraday.rb:34:51:34:53 | arg | disabled here | Faraday.rb:38:42:38:46 | false | here |
|
||||
| Faraday.rb:44:16:44:35 | call to get | This request may run without certificate validation because it is $@ by the value from $@. | Faraday.rb:43:56:43:58 | arg | disabled here | Faraday.rb:47:47:47:71 | VERIFY_NONE | here |
|
||||
| HttpClient.rb:6:1:6:33 | call to get | This request may run without certificate validation because it is $@ by the value from $@. | HttpClient.rb:5:33:5:57 | ... = ... | disabled here | HttpClient.rb:5:33:5:57 | VERIFY_NONE | here |
|
||||
| Httparty.rb:4:1:4:50 | call to get | This request may run without certificate validation because it is $@. | Httparty.rb:4:45:4:49 | false | disabled here | Httparty.rb:4:45:4:49 | false | here |
|
||||
| Httparty.rb:7:1:7:55 | call to get | This request may run without certificate validation because it is $@. | Httparty.rb:7:50:7:54 | false | disabled here | Httparty.rb:7:50:7:54 | false | here |
|
||||
| Httparty.rb:10:1:10:59 | call to get | This request may run without certificate validation because it is $@. | Httparty.rb:10:52:10:56 | false | disabled here | Httparty.rb:10:52:10:56 | false | here |
|
||||
| Httparty.rb:13:1:13:70 | call to post | This request may run without certificate validation because it is $@. | Httparty.rb:13:65:13:69 | false | disabled here | Httparty.rb:13:65:13:69 | false | here |
|
||||
| Httparty.rb:16:1:16:74 | call to post | This request may run without certificate validation because it is $@. | Httparty.rb:16:67:16:71 | false | disabled here | Httparty.rb:16:67:16:71 | false | here |
|
||||
| NetHttp.rb:9:12:9:31 | call to request | This request may run without certificate validation because it is $@ by the value from $@. | NetHttp.rb:7:20:7:44 | ... = ... | disabled here | NetHttp.rb:7:20:7:44 | VERIFY_NONE | here |
|
||||
| OpenURI.rb:4:1:4:78 | call to open | This request may run without certificate validation because it is $@. | OpenURI.rb:4:53:4:77 | VERIFY_NONE | disabled here | OpenURI.rb:4:53:4:77 | VERIFY_NONE | here |
|
||||
| OpenURI.rb:7:1:7:82 | call to open | This request may run without certificate validation because it is $@. | OpenURI.rb:7:55:7:79 | VERIFY_NONE | disabled here | OpenURI.rb:7:55:7:79 | VERIFY_NONE | here |
|
||||
| OpenURI.rb:11:1:11:43 | call to open | This request may run without certificate validation because it is $@. | OpenURI.rb:10:30:10:54 | VERIFY_NONE | disabled here | OpenURI.rb:10:30:10:54 | VERIFY_NONE | here |
|
||||
| OpenURI.rb:14:1:14:81 | call to open | This request may run without certificate validation because it is $@. | OpenURI.rb:14:56:14:80 | VERIFY_NONE | disabled here | OpenURI.rb:14:56:14:80 | VERIFY_NONE | here |
|
||||
| OpenURI.rb:17:1:17:85 | call to open | This request may run without certificate validation because it is $@. | OpenURI.rb:17:58:17:82 | VERIFY_NONE | disabled here | OpenURI.rb:17:58:17:82 | VERIFY_NONE | here |
|
||||
| OpenURI.rb:21:1:21:46 | call to open | This request may run without certificate validation because it is $@. | OpenURI.rb:20:30:20:54 | VERIFY_NONE | disabled here | OpenURI.rb:20:30:20:54 | VERIFY_NONE | here |
|
||||
| RestClient.rb:5:12:5:23 | call to get | This request may run without certificate validation because it is $@. | RestClient.rb:4:72:4:96 | VERIFY_NONE | disabled here | RestClient.rb:4:72:4:96 | VERIFY_NONE | here |
|
||||
| RestClient.rb:9:12:9:23 | call to get | This request may run without certificate validation because it is $@. | RestClient.rb:8:74:8:98 | VERIFY_NONE | disabled here | RestClient.rb:8:74:8:98 | VERIFY_NONE | here |
|
||||
| RestClient.rb:14:12:14:23 | call to get | This request may run without certificate validation because it is $@. | RestClient.rb:12:25:12:49 | VERIFY_NONE | disabled here | RestClient.rb:12:25:12:49 | VERIFY_NONE | here |
|
||||
| RestClient.rb:19:12:19:23 | call to get | This request may run without certificate validation because it is $@ by the value from $@. | RestClient.rb:18:72:18:76 | value | disabled here | RestClient.rb:17:9:17:33 | VERIFY_NONE | here |
|
||||
| Typhoeus.rb:4:1:4:62 | call to get | This request may run without certificate validation because it is $@. | Typhoeus.rb:4:41:4:61 | Pair | disabled here | Typhoeus.rb:4:41:4:61 | Pair | here |
|
||||
| Typhoeus.rb:8:1:8:54 | call to post | This request may run without certificate validation because it is $@. | Typhoeus.rb:7:37:7:57 | Pair | disabled here | Typhoeus.rb:7:37:7:57 | Pair | here |
|
||||
| Typhoeus.rb:4:1:4:62 | call to get | This request may run without certificate validation because it is $@. | Typhoeus.rb:4:57:4:61 | false | disabled here | Typhoeus.rb:4:57:4:61 | false | here |
|
||||
| Typhoeus.rb:8:1:8:54 | call to post | This request may run without certificate validation because it is $@. | Typhoeus.rb:7:53:7:57 | false | disabled here | Typhoeus.rb:7:53:7:57 | false | here |
|
||||
|
||||
Reference in New Issue
Block a user