mirror of
https://github.com/github/codeql.git
synced 2026-04-28 18:25:24 +02:00
Merge pull request #7442 from hvitved/ruby/dataflow/keyword-params
Ruby: Data flow for keyword arguments/parameters
This commit is contained in:
@@ -23,10 +23,10 @@ module SummaryComponent {
|
||||
predicate content = SC::content/1;
|
||||
|
||||
/** Gets a summary component that represents a qualifier. */
|
||||
SummaryComponent qualifier() { result = argument(-1) }
|
||||
SummaryComponent qualifier() { result = argument(any(ParameterPosition pos | pos.isSelf())) }
|
||||
|
||||
/** Gets a summary component that represents a block argument. */
|
||||
SummaryComponent block() { result = argument(-2) }
|
||||
SummaryComponent block() { result = argument(any(ParameterPosition pos | pos.isBlock())) }
|
||||
|
||||
/** Gets a summary component that represents the return value of a call. */
|
||||
SummaryComponent return() { result = SC::return(any(NormalReturnKind rk)) }
|
||||
@@ -102,10 +102,10 @@ abstract class SummarizedCallable extends LibraryCallable {
|
||||
|
||||
/**
|
||||
* Holds if values stored inside `content` are cleared on objects passed as
|
||||
* the `i`th argument to this callable.
|
||||
* arguments at position `pos` to this callable.
|
||||
*/
|
||||
pragma[nomagic]
|
||||
predicate clearsContent(int i, DataFlow::Content content) { none() }
|
||||
predicate clearsContent(ParameterPosition pos, DataFlow::Content content) { none() }
|
||||
}
|
||||
|
||||
private class SummarizedCallableAdapter extends Impl::Public::SummarizedCallable {
|
||||
@@ -119,8 +119,8 @@ private class SummarizedCallableAdapter extends Impl::Public::SummarizedCallable
|
||||
sc.propagatesFlow(input, output, preservesValue)
|
||||
}
|
||||
|
||||
final override predicate clearsContent(ParameterPosition i, DataFlow::Content content) {
|
||||
sc.clearsContent(i, content)
|
||||
final override predicate clearsContent(ParameterPosition pos, DataFlow::Content content) {
|
||||
sc.clearsContent(pos, content)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -4,6 +4,7 @@ private import DataFlowPrivate
|
||||
private import codeql.ruby.typetracking.TypeTracker
|
||||
private import codeql.ruby.ast.internal.Module
|
||||
private import FlowSummaryImpl as FlowSummaryImpl
|
||||
private import FlowSummaryImplSpecific as FlowSummaryImplSpecific
|
||||
private import codeql.ruby.dataflow.FlowSummary
|
||||
|
||||
newtype TReturnKind =
|
||||
@@ -230,6 +231,30 @@ private module Cached {
|
||||
result = yieldCall(call)
|
||||
)
|
||||
}
|
||||
|
||||
cached
|
||||
newtype TArgumentPosition =
|
||||
TSelfArgumentPosition() or
|
||||
TBlockArgumentPosition() or
|
||||
TPositionalArgumentPosition(int pos) {
|
||||
exists(Call c | exists(c.getArgument(pos)))
|
||||
or
|
||||
FlowSummaryImplSpecific::ParsePositions::isParsedParameterPosition(_, pos)
|
||||
} or
|
||||
TKeywordArgumentPosition(string name) { name = any(KeywordParameter kp).getName() }
|
||||
|
||||
cached
|
||||
newtype TParameterPosition =
|
||||
TSelfParameterPosition() or
|
||||
TBlockParameterPosition() or
|
||||
TPositionalParameterPosition(int pos) {
|
||||
pos = any(Parameter p).getPosition()
|
||||
or
|
||||
pos in [0 .. 10] // TODO: remove once `Argument[_]` summaries are replaced with `Argument[i..]`
|
||||
or
|
||||
FlowSummaryImplSpecific::ParsePositions::isParsedArgumentPosition(_, pos)
|
||||
} or
|
||||
TKeywordParameterPosition(string name) { name = any(KeywordParameter kp).getName() }
|
||||
}
|
||||
|
||||
import Cached
|
||||
@@ -458,18 +483,66 @@ predicate exprNodeReturnedFrom(DataFlow::ExprNode e, Callable c) {
|
||||
)
|
||||
}
|
||||
|
||||
private int parameterPosition() { result in [-2 .. max([any(Parameter p).getPosition(), 10])] }
|
||||
/** A parameter position. */
|
||||
class ParameterPosition extends TParameterPosition {
|
||||
/** Holds if this position represents a `self` parameter. */
|
||||
predicate isSelf() { this = TSelfParameterPosition() }
|
||||
|
||||
/** A parameter position represented by an integer. */
|
||||
class ParameterPosition extends int {
|
||||
ParameterPosition() { this = parameterPosition() }
|
||||
/** Holds if this position represents a block parameter. */
|
||||
predicate isBlock() { this = TBlockParameterPosition() }
|
||||
|
||||
/** Holds if this position represents a positional parameter at position `pos`. */
|
||||
predicate isPositional(int pos) { this = TPositionalParameterPosition(pos) }
|
||||
|
||||
/** Holds if this position represents a keyword parameter named `name`. */
|
||||
predicate isKeyword(string name) { this = TKeywordParameterPosition(name) }
|
||||
|
||||
/** Gets a textual representation of this position. */
|
||||
string toString() {
|
||||
this.isSelf() and result = "self"
|
||||
or
|
||||
this.isBlock() and result = "block"
|
||||
or
|
||||
exists(int pos | this.isPositional(pos) and result = "position " + pos)
|
||||
or
|
||||
exists(string name | this.isKeyword(name) and result = "keyword " + name)
|
||||
}
|
||||
}
|
||||
|
||||
/** An argument position represented by an integer. */
|
||||
class ArgumentPosition extends int {
|
||||
ArgumentPosition() { this = parameterPosition() }
|
||||
/** An argument position. */
|
||||
class ArgumentPosition extends TArgumentPosition {
|
||||
/** Holds if this position represents a `self` argument. */
|
||||
predicate isSelf() { this = TSelfArgumentPosition() }
|
||||
|
||||
/** Holds if this position represents a block argument. */
|
||||
predicate isBlock() { this = TBlockArgumentPosition() }
|
||||
|
||||
/** Holds if this position represents a positional argument at position `pos`. */
|
||||
predicate isPositional(int pos) { this = TPositionalArgumentPosition(pos) }
|
||||
|
||||
/** Holds if this position represents a keyword argument named `name`. */
|
||||
predicate isKeyword(string name) { this = TKeywordArgumentPosition(name) }
|
||||
|
||||
/** Gets a textual representation of this position. */
|
||||
string toString() {
|
||||
this.isSelf() and result = "self"
|
||||
or
|
||||
this.isBlock() and result = "block"
|
||||
or
|
||||
exists(int pos | this.isPositional(pos) and result = "position " + pos)
|
||||
or
|
||||
exists(string name | this.isKeyword(name) and result = "keyword " + name)
|
||||
}
|
||||
}
|
||||
|
||||
/** Holds if arguments at position `apos` match parameters at position `ppos`. */
|
||||
pragma[inline]
|
||||
predicate parameterMatch(ParameterPosition ppos, ArgumentPosition apos) { ppos = apos }
|
||||
predicate parameterMatch(ParameterPosition ppos, ArgumentPosition apos) {
|
||||
ppos.isSelf() and apos.isSelf()
|
||||
or
|
||||
ppos.isBlock() and apos.isBlock()
|
||||
or
|
||||
exists(int pos | ppos.isPositional(pos) and apos.isPositional(pos))
|
||||
or
|
||||
exists(string name | ppos.isKeyword(name) and apos.isKeyword(name))
|
||||
}
|
||||
|
||||
@@ -161,17 +161,29 @@ module LocalFlow {
|
||||
/** An argument of a call (including qualifier arguments, excluding block arguments). */
|
||||
private class Argument extends CfgNodes::ExprCfgNode {
|
||||
private CfgNodes::ExprNodes::CallCfgNode call;
|
||||
private int arg;
|
||||
private ArgumentPosition arg;
|
||||
|
||||
Argument() {
|
||||
this = call.getArgument(arg) and
|
||||
not this.getExpr() instanceof BlockArgument
|
||||
exists(int i |
|
||||
this = call.getArgument(i) and
|
||||
not this.getExpr() instanceof BlockArgument and
|
||||
not exists(this.getExpr().(Pair).getKey().getValueText()) and
|
||||
arg.isPositional(i)
|
||||
)
|
||||
or
|
||||
this = call.getReceiver() and arg = -1
|
||||
exists(CfgNodes::ExprNodes::PairCfgNode p |
|
||||
p = call.getArgument(_) and
|
||||
this = p.getValue() and
|
||||
arg.isKeyword(p.getKey().getValueText())
|
||||
)
|
||||
or
|
||||
this = call.getReceiver() and arg.isSelf()
|
||||
}
|
||||
|
||||
/** Holds if this expression is the `i`th argument of `c`. */
|
||||
predicate isArgumentOf(CfgNodes::ExprNodes::CallCfgNode c, int i) { c = call and i = arg }
|
||||
predicate isArgumentOf(CfgNodes::ExprNodes::CallCfgNode c, ArgumentPosition pos) {
|
||||
c = call and pos = arg
|
||||
}
|
||||
}
|
||||
|
||||
/** A collection of cached types and predicates to be evaluated in the same stage. */
|
||||
@@ -188,7 +200,11 @@ private module Cached {
|
||||
)
|
||||
} or
|
||||
TSsaDefinitionNode(Ssa::Definition def) or
|
||||
TNormalParameterNode(Parameter p) { not p instanceof BlockParameter } or
|
||||
TNormalParameterNode(Parameter p) {
|
||||
p instanceof SimpleParameter or
|
||||
p instanceof OptionalParameter or
|
||||
p instanceof KeywordParameter
|
||||
} or
|
||||
TSelfParameterNode(MethodBase m) or
|
||||
TBlockParameterNode(MethodBase m) or
|
||||
TExprPostUpdateNode(CfgNodes::ExprCfgNode n) { n instanceof Argument } or
|
||||
@@ -198,8 +214,8 @@ private module Cached {
|
||||
) {
|
||||
FlowSummaryImpl::Private::summaryNodeRange(c, state)
|
||||
} or
|
||||
TSummaryParameterNode(FlowSummaryImpl::Public::SummarizedCallable c, int i) {
|
||||
FlowSummaryImpl::Private::summaryParameterNodeRange(c, i)
|
||||
TSummaryParameterNode(FlowSummaryImpl::Public::SummarizedCallable c, ParameterPosition pos) {
|
||||
FlowSummaryImpl::Private::summaryParameterNodeRange(c, pos)
|
||||
}
|
||||
|
||||
class TParameterNode =
|
||||
@@ -340,10 +356,10 @@ private module ParameterNodes {
|
||||
abstract class ParameterNodeImpl extends NodeImpl {
|
||||
abstract Parameter getParameter();
|
||||
|
||||
abstract predicate isSourceParameterOf(Callable c, int i);
|
||||
abstract predicate isSourceParameterOf(Callable c, ParameterPosition pos);
|
||||
|
||||
predicate isParameterOf(DataFlowCallable c, int i) {
|
||||
this.isSourceParameterOf(c.asCallable(), i)
|
||||
predicate isParameterOf(DataFlowCallable c, ParameterPosition pos) {
|
||||
this.isSourceParameterOf(c.asCallable(), pos)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -358,10 +374,18 @@ private module ParameterNodes {
|
||||
|
||||
override Parameter getParameter() { result = parameter }
|
||||
|
||||
override predicate isSourceParameterOf(Callable c, int i) { c.getParameter(i) = parameter }
|
||||
|
||||
override predicate isParameterOf(DataFlowCallable c, int i) {
|
||||
this.isSourceParameterOf(c.asCallable(), i)
|
||||
override predicate isSourceParameterOf(Callable c, ParameterPosition pos) {
|
||||
exists(int i | pos.isPositional(i) and c.getParameter(i) = parameter |
|
||||
parameter instanceof SimpleParameter
|
||||
or
|
||||
parameter instanceof OptionalParameter
|
||||
)
|
||||
or
|
||||
parameter =
|
||||
any(KeywordParameter kp |
|
||||
c.getAParameter() = kp and
|
||||
pos.isKeyword(kp.getName())
|
||||
)
|
||||
}
|
||||
|
||||
override CfgScope getCfgScope() { result = parameter.getCallable() }
|
||||
@@ -384,10 +408,8 @@ private module ParameterNodes {
|
||||
|
||||
override Parameter getParameter() { none() }
|
||||
|
||||
override predicate isSourceParameterOf(Callable c, int i) { method = c and i = -1 }
|
||||
|
||||
override predicate isParameterOf(DataFlowCallable c, int i) {
|
||||
this.isSourceParameterOf(c.asCallable(), i)
|
||||
override predicate isSourceParameterOf(Callable c, ParameterPosition pos) {
|
||||
method = c and pos.isSelf()
|
||||
}
|
||||
|
||||
override CfgScope getCfgScope() { result = method }
|
||||
@@ -412,10 +434,8 @@ private module ParameterNodes {
|
||||
result = method.getAParameter() and result instanceof BlockParameter
|
||||
}
|
||||
|
||||
override predicate isSourceParameterOf(Callable c, int i) { c = method and i = -2 }
|
||||
|
||||
override predicate isParameterOf(DataFlowCallable c, int i) {
|
||||
this.isSourceParameterOf(c.asCallable(), i)
|
||||
override predicate isSourceParameterOf(Callable c, ParameterPosition pos) {
|
||||
c = method and pos.isBlock()
|
||||
}
|
||||
|
||||
override CfgScope getCfgScope() { result = method }
|
||||
@@ -436,15 +456,17 @@ private module ParameterNodes {
|
||||
/** A parameter for a library callable with a flow summary. */
|
||||
class SummaryParameterNode extends ParameterNodeImpl, TSummaryParameterNode {
|
||||
private FlowSummaryImpl::Public::SummarizedCallable sc;
|
||||
private int pos;
|
||||
private ParameterPosition pos_;
|
||||
|
||||
SummaryParameterNode() { this = TSummaryParameterNode(sc, pos) }
|
||||
SummaryParameterNode() { this = TSummaryParameterNode(sc, pos_) }
|
||||
|
||||
override Parameter getParameter() { none() }
|
||||
|
||||
override predicate isSourceParameterOf(Callable c, int i) { none() }
|
||||
override predicate isSourceParameterOf(Callable c, ParameterPosition pos) { none() }
|
||||
|
||||
override predicate isParameterOf(DataFlowCallable c, int i) { sc = c and i = pos }
|
||||
override predicate isParameterOf(DataFlowCallable c, ParameterPosition pos) {
|
||||
sc = c and pos = pos_
|
||||
}
|
||||
|
||||
override CfgScope getCfgScope() { none() }
|
||||
|
||||
@@ -452,7 +474,7 @@ private module ParameterNodes {
|
||||
|
||||
override EmptyLocation getLocationImpl() { any() }
|
||||
|
||||
override string toStringImpl() { result = "parameter " + pos + " of " + sc }
|
||||
override string toStringImpl() { result = "parameter " + pos_ + " of " + sc }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -477,9 +499,9 @@ class SummaryNode extends NodeImpl, TSummaryNode {
|
||||
/** A data-flow node that represents a call argument. */
|
||||
abstract class ArgumentNode extends Node {
|
||||
/** Holds if this argument occurs at the given position in the given call. */
|
||||
abstract predicate argumentOf(DataFlowCall call, int pos);
|
||||
abstract predicate argumentOf(DataFlowCall call, ArgumentPosition pos);
|
||||
|
||||
abstract predicate sourceArgumentOf(CfgNodes::ExprNodes::CallCfgNode call, int pos);
|
||||
abstract predicate sourceArgumentOf(CfgNodes::ExprNodes::CallCfgNode call, ArgumentPosition pos);
|
||||
|
||||
/** Gets the call in which this node is an argument. */
|
||||
final DataFlowCall getCall() { this.argumentOf(result, _) }
|
||||
@@ -492,18 +514,18 @@ private module ArgumentNodes {
|
||||
|
||||
ExplicitArgumentNode() { this.asExpr() = arg }
|
||||
|
||||
override predicate argumentOf(DataFlowCall call, int pos) {
|
||||
override predicate argumentOf(DataFlowCall call, ArgumentPosition pos) {
|
||||
this.sourceArgumentOf(call.asCall(), pos)
|
||||
}
|
||||
|
||||
override predicate sourceArgumentOf(CfgNodes::ExprNodes::CallCfgNode call, int pos) {
|
||||
override predicate sourceArgumentOf(CfgNodes::ExprNodes::CallCfgNode call, ArgumentPosition pos) {
|
||||
arg.isArgumentOf(call, pos)
|
||||
}
|
||||
}
|
||||
|
||||
/** A data-flow node that represents the `self` argument of a call. */
|
||||
class SelfArgumentNode extends ExplicitArgumentNode {
|
||||
SelfArgumentNode() { arg.isArgumentOf(_, -1) }
|
||||
SelfArgumentNode() { arg.isArgumentOf(_, any(ArgumentPosition pos | pos.isSelf())) }
|
||||
}
|
||||
|
||||
/** A data-flow node that represents a block argument. */
|
||||
@@ -513,12 +535,12 @@ private module ArgumentNodes {
|
||||
exists(CfgNodes::ExprNodes::CallCfgNode c | c.getBlock() = this.asExpr())
|
||||
}
|
||||
|
||||
override predicate argumentOf(DataFlowCall call, int pos) {
|
||||
override predicate argumentOf(DataFlowCall call, ArgumentPosition pos) {
|
||||
this.sourceArgumentOf(call.asCall(), pos)
|
||||
}
|
||||
|
||||
override predicate sourceArgumentOf(CfgNodes::ExprNodes::CallCfgNode call, int pos) {
|
||||
pos = -2 and
|
||||
override predicate sourceArgumentOf(CfgNodes::ExprNodes::CallCfgNode call, ArgumentPosition pos) {
|
||||
pos.isBlock() and
|
||||
(
|
||||
this.asExpr() = call.getBlock()
|
||||
or
|
||||
@@ -534,9 +556,11 @@ private module ArgumentNodes {
|
||||
private class SummaryArgumentNode extends SummaryNode, ArgumentNode {
|
||||
SummaryArgumentNode() { FlowSummaryImpl::Private::summaryArgumentNode(_, this, _) }
|
||||
|
||||
override predicate sourceArgumentOf(CfgNodes::ExprNodes::CallCfgNode call, int pos) { none() }
|
||||
override predicate sourceArgumentOf(CfgNodes::ExprNodes::CallCfgNode call, ArgumentPosition pos) {
|
||||
none()
|
||||
}
|
||||
|
||||
override predicate argumentOf(DataFlowCall call, int pos) {
|
||||
override predicate argumentOf(DataFlowCall call, ArgumentPosition pos) {
|
||||
FlowSummaryImpl::Private::summaryArgumentNode(call, this, pos)
|
||||
}
|
||||
}
|
||||
@@ -847,7 +871,7 @@ predicate lambdaCall(DataFlowCall call, LambdaCallKind kind, Node receiver) {
|
||||
)
|
||||
or
|
||||
receiver = call.(SummaryCall).getReceiver() and
|
||||
if receiver.(ParameterNodeImpl).isParameterOf(_, -2)
|
||||
if receiver.(ParameterNodeImpl).isParameterOf(_, any(ParameterPosition pos | pos.isBlock()))
|
||||
then kind = TYieldCallKind()
|
||||
else kind = TLambdaCallKind()
|
||||
}
|
||||
|
||||
@@ -736,10 +736,17 @@ module Private {
|
||||
}
|
||||
|
||||
pragma[nomagic]
|
||||
private ParamNode summaryArgParam(ArgNode arg, ReturnKindExt rk, OutNodeExt out) {
|
||||
exists(DataFlowCall call, ParameterPosition ppos, SummarizedCallable sc |
|
||||
private ParamNode summaryArgParam0(DataFlowCall call, ArgNode arg) {
|
||||
exists(ParameterPosition ppos, SummarizedCallable sc |
|
||||
argumentPositionMatch(call, arg, ppos) and
|
||||
viableParam(call, sc, ppos, result) and
|
||||
viableParam(call, sc, ppos, result)
|
||||
)
|
||||
}
|
||||
|
||||
pragma[nomagic]
|
||||
private ParamNode summaryArgParam(ArgNode arg, ReturnKindExt rk, OutNodeExt out) {
|
||||
exists(DataFlowCall call |
|
||||
result = summaryArgParam0(call, arg) and
|
||||
out = rk.getAnOutNode(call)
|
||||
)
|
||||
}
|
||||
|
||||
@@ -12,7 +12,7 @@ private import FlowSummaryImpl::Public
|
||||
private import codeql.ruby.dataflow.FlowSummary as FlowSummary
|
||||
|
||||
/** Gets the parameter position of the instance parameter. */
|
||||
int instanceParameterPosition() { none() } // disables implicit summary flow to `self` for callbacks
|
||||
ArgumentPosition instanceParameterPosition() { none() } // disables implicit summary flow to `self` for callbacks
|
||||
|
||||
/** Gets the synthesized summary data-flow node for the given values. */
|
||||
Node summaryNode(SummarizedCallable c, SummaryNodeState state) { result = TSummaryNode(c, state) }
|
||||
@@ -31,8 +31,8 @@ DataFlowType getReturnType(SummarizedCallable c, ReturnKind rk) { any() }
|
||||
* Gets the type of the `i`th parameter in a synthesized call that targets a
|
||||
* callback of type `t`.
|
||||
*/
|
||||
bindingset[t, i]
|
||||
DataFlowType getCallbackParameterType(DataFlowType t, int i) { any() }
|
||||
bindingset[t, pos]
|
||||
DataFlowType getCallbackParameterType(DataFlowType t, ArgumentPosition pos) { any() }
|
||||
|
||||
/**
|
||||
* Gets the return type of kind `rk` in a synthesized call that targets a
|
||||
@@ -63,12 +63,13 @@ SummaryComponent interpretComponentSpecific(string c) {
|
||||
result = FlowSummary::SummaryComponent::block()
|
||||
or
|
||||
c = "Argument[_]" and
|
||||
result = FlowSummary::SummaryComponent::argument(any(int i | i >= 0))
|
||||
result = FlowSummary::SummaryComponent::argument(any(ParameterPosition pos | pos.isPositional(_)))
|
||||
}
|
||||
|
||||
/** Gets the textual representation of a summary component in the format used for flow summaries. */
|
||||
string getComponentSpecificCsv(SummaryComponent sc) {
|
||||
sc = TArgumentSummaryComponent(-2) and result = "BlockArgument"
|
||||
sc = TArgumentSummaryComponent(any(ParameterPosition pos | pos.isBlock())) and
|
||||
result = "BlockArgument"
|
||||
}
|
||||
|
||||
/** Gets the textual representation of a parameter position in the format used for flow summaries. */
|
||||
@@ -127,21 +128,57 @@ private module UnusedSourceSinkInterpretation {
|
||||
|
||||
import UnusedSourceSinkInterpretation
|
||||
|
||||
bindingset[s]
|
||||
private int parsePosition(string s) {
|
||||
result = s.regexpCapture("([-0-9]+)", 1).toInt()
|
||||
or
|
||||
exists(int n1, int n2 |
|
||||
s.regexpCapture("([-0-9]+)\\.\\.([0-9]+)", 1).toInt() = n1 and
|
||||
s.regexpCapture("([-0-9]+)\\.\\.([0-9]+)", 2).toInt() = n2 and
|
||||
result in [n1 .. n2]
|
||||
)
|
||||
module ParsePositions {
|
||||
private import FlowSummaryImpl
|
||||
|
||||
private predicate isParamBody(string body) {
|
||||
exists(string c |
|
||||
Private::External::specSplit(_, c, _) and
|
||||
body = c.regexpCapture("Parameter\\[([^\\]]*)\\]", 1)
|
||||
)
|
||||
}
|
||||
|
||||
private predicate isArgBody(string body) {
|
||||
exists(string c |
|
||||
Private::External::specSplit(_, c, _) and
|
||||
body = c.regexpCapture("Argument\\[([^\\]]*)\\]", 1)
|
||||
)
|
||||
}
|
||||
|
||||
bindingset[s]
|
||||
private int parsePosition(string s) {
|
||||
result = s.regexpCapture("([-0-9]+)", 1).toInt()
|
||||
or
|
||||
exists(int n1, int n2 |
|
||||
s.regexpCapture("([-0-9]+)\\.\\.([0-9]+)", 1).toInt() = n1 and
|
||||
s.regexpCapture("([-0-9]+)\\.\\.([0-9]+)", 2).toInt() = n2 and
|
||||
result in [n1 .. n2]
|
||||
)
|
||||
}
|
||||
|
||||
predicate isParsedParameterPosition(string c, int i) {
|
||||
isParamBody(c) and
|
||||
i = parsePosition(c)
|
||||
}
|
||||
|
||||
predicate isParsedArgumentPosition(string c, int i) {
|
||||
isArgBody(c) and
|
||||
i = parsePosition(c)
|
||||
}
|
||||
}
|
||||
|
||||
/** Gets the argument position obtained by parsing `X` in `Parameter[X]`. */
|
||||
bindingset[s]
|
||||
ArgumentPosition parseParamBody(string s) { result = parsePosition(s) }
|
||||
ArgumentPosition parseParamBody(string s) {
|
||||
exists(int i |
|
||||
ParsePositions::isParsedParameterPosition(s, i) and
|
||||
result.isPositional(i)
|
||||
)
|
||||
}
|
||||
|
||||
/** Gets the parameter position obtained by parsing `X` in `Argument[X]`. */
|
||||
bindingset[s]
|
||||
ParameterPosition parseArgBody(string s) { result = parsePosition(s) }
|
||||
ParameterPosition parseArgBody(string s) {
|
||||
exists(int i |
|
||||
ParsePositions::isParsedArgumentPosition(s, i) and
|
||||
result.isPositional(i)
|
||||
)
|
||||
}
|
||||
|
||||
@@ -23,6 +23,28 @@ predicate jumpStep = DataFlowPrivate::jumpStep/2;
|
||||
*/
|
||||
string getPossibleContentName() { result = getSetterCallAttributeName(_) }
|
||||
|
||||
pragma[noinline]
|
||||
private predicate argumentPositionMatch(
|
||||
ExprNodes::CallCfgNode call, DataFlowPrivate::ArgumentNode arg,
|
||||
DataFlowDispatch::ParameterPosition ppos
|
||||
) {
|
||||
exists(DataFlowDispatch::ArgumentPosition apos |
|
||||
arg.sourceArgumentOf(call, apos) and
|
||||
DataFlowDispatch::parameterMatch(ppos, apos)
|
||||
)
|
||||
}
|
||||
|
||||
pragma[noinline]
|
||||
private predicate viableParam(
|
||||
ExprNodes::CallCfgNode call, DataFlowPrivate::ParameterNodeImpl p,
|
||||
DataFlowDispatch::ParameterPosition ppos
|
||||
) {
|
||||
exists(CFG::CfgScope callable |
|
||||
DataFlowDispatch::getTarget(call) = callable and
|
||||
p.isSourceParameterOf(callable, ppos)
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if `nodeFrom` steps to `nodeTo` by being passed as a parameter in a call.
|
||||
*
|
||||
@@ -31,10 +53,9 @@ string getPossibleContentName() { result = getSetterCallAttributeName(_) }
|
||||
* methods is done using API graphs (which uses type tracking).
|
||||
*/
|
||||
predicate callStep(Node nodeFrom, Node nodeTo) {
|
||||
exists(ExprNodes::CallCfgNode call, CFG::CfgScope callable, int i |
|
||||
DataFlowDispatch::getTarget(call) = callable and
|
||||
nodeFrom.(DataFlowPrivate::ArgumentNode).sourceArgumentOf(call, i) and
|
||||
nodeTo.(DataFlowPrivate::ParameterNodeImpl).isSourceParameterOf(callable, i)
|
||||
exists(ExprNodes::CallCfgNode call, DataFlowDispatch::ParameterPosition pos |
|
||||
argumentPositionMatch(call, nodeFrom, pos) and
|
||||
viableParam(call, nodeTo, pos)
|
||||
)
|
||||
or
|
||||
// In normal data-flow, this will be a local flow step. But for type tracking
|
||||
|
||||
@@ -14,38 +14,38 @@ ret
|
||||
| local_dataflow.rb:52:3:52:10 | "normal" |
|
||||
| local_dataflow.rb:69:3:76:5 | ... = ... |
|
||||
arg
|
||||
| local_dataflow.rb:3:8:3:10 | self | local_dataflow.rb:3:8:3:10 | call to p | -1 |
|
||||
| local_dataflow.rb:3:10:3:10 | a | local_dataflow.rb:3:8:3:10 | call to p | 0 |
|
||||
| local_dataflow.rb:6:8:6:8 | a | local_dataflow.rb:6:10:6:11 | ... + ... | -1 |
|
||||
| local_dataflow.rb:6:13:6:13 | b | local_dataflow.rb:6:10:6:11 | ... + ... | 0 |
|
||||
| local_dataflow.rb:9:9:9:15 | Array | local_dataflow.rb:9:9:9:15 | call to [] | -1 |
|
||||
| local_dataflow.rb:9:10:9:10 | 1 | local_dataflow.rb:9:9:9:15 | call to [] | 0 |
|
||||
| local_dataflow.rb:9:12:9:12 | 2 | local_dataflow.rb:9:9:9:15 | call to [] | 1 |
|
||||
| local_dataflow.rb:9:14:9:14 | 3 | local_dataflow.rb:9:9:9:15 | call to [] | 2 |
|
||||
| local_dataflow.rb:10:5:13:3 | { ... } | local_dataflow.rb:10:5:13:3 | call to each | -2 |
|
||||
| local_dataflow.rb:10:14:10:18 | array | local_dataflow.rb:10:5:13:3 | call to each | -1 |
|
||||
| local_dataflow.rb:11:1:11:2 | self | local_dataflow.rb:11:1:11:2 | call to do | -1 |
|
||||
| local_dataflow.rb:12:3:12:5 | self | local_dataflow.rb:12:3:12:5 | call to p | -1 |
|
||||
| local_dataflow.rb:12:5:12:5 | x | local_dataflow.rb:12:3:12:5 | call to p | 0 |
|
||||
| local_dataflow.rb:15:1:17:3 | { ... } | local_dataflow.rb:15:1:17:3 | call to each | -2 |
|
||||
| local_dataflow.rb:15:10:15:14 | array | local_dataflow.rb:15:1:17:3 | call to each | -1 |
|
||||
| local_dataflow.rb:19:1:21:3 | { ... } | local_dataflow.rb:19:1:21:3 | call to each | -2 |
|
||||
| local_dataflow.rb:19:10:19:14 | array | local_dataflow.rb:19:1:21:3 | call to each | -1 |
|
||||
| local_dataflow.rb:20:6:20:6 | x | local_dataflow.rb:20:6:20:10 | ... > ... | -1 |
|
||||
| local_dataflow.rb:20:10:20:10 | 1 | local_dataflow.rb:20:6:20:10 | ... > ... | 0 |
|
||||
| local_dataflow.rb:35:6:35:6 | x | local_dataflow.rb:35:6:35:11 | ... == ... | -1 |
|
||||
| local_dataflow.rb:35:11:35:11 | 4 | local_dataflow.rb:35:6:35:11 | ... == ... | 0 |
|
||||
| local_dataflow.rb:42:6:42:6 | x | local_dataflow.rb:42:6:42:11 | ... == ... | -1 |
|
||||
| local_dataflow.rb:42:11:42:11 | 4 | local_dataflow.rb:42:6:42:11 | ... == ... | 0 |
|
||||
| local_dataflow.rb:49:1:53:3 | self | local_dataflow.rb:49:1:53:3 | call to m | -1 |
|
||||
| local_dataflow.rb:49:3:53:3 | do ... end | local_dataflow.rb:49:1:53:3 | call to m | -2 |
|
||||
| local_dataflow.rb:50:18:50:18 | x | local_dataflow.rb:50:18:50:22 | ... < ... | -1 |
|
||||
| local_dataflow.rb:50:22:50:22 | 4 | local_dataflow.rb:50:18:50:22 | ... < ... | 0 |
|
||||
| local_dataflow.rb:51:20:51:20 | x | local_dataflow.rb:51:20:51:24 | ... < ... | -1 |
|
||||
| local_dataflow.rb:51:24:51:24 | 9 | local_dataflow.rb:51:20:51:24 | ... < ... | 0 |
|
||||
| local_dataflow.rb:55:1:55:14 | self | local_dataflow.rb:55:1:55:14 | call to foo | -1 |
|
||||
| local_dataflow.rb:55:5:55:13 | Array | local_dataflow.rb:55:5:55:13 | call to [] | -1 |
|
||||
| local_dataflow.rb:55:5:55:13 | call to [] | local_dataflow.rb:55:1:55:14 | call to foo | 0 |
|
||||
| local_dataflow.rb:55:6:55:6 | 1 | local_dataflow.rb:55:5:55:13 | call to [] | 0 |
|
||||
| local_dataflow.rb:55:9:55:9 | 2 | local_dataflow.rb:55:5:55:13 | call to [] | 1 |
|
||||
| local_dataflow.rb:55:12:55:12 | 3 | local_dataflow.rb:55:5:55:13 | call to [] | 2 |
|
||||
| local_dataflow.rb:3:8:3:10 | self | local_dataflow.rb:3:8:3:10 | call to p | self |
|
||||
| local_dataflow.rb:3:10:3:10 | a | local_dataflow.rb:3:8:3:10 | call to p | position 0 |
|
||||
| local_dataflow.rb:6:8:6:8 | a | local_dataflow.rb:6:10:6:11 | ... + ... | self |
|
||||
| local_dataflow.rb:6:13:6:13 | b | local_dataflow.rb:6:10:6:11 | ... + ... | position 0 |
|
||||
| local_dataflow.rb:9:9:9:15 | Array | local_dataflow.rb:9:9:9:15 | call to [] | self |
|
||||
| local_dataflow.rb:9:10:9:10 | 1 | local_dataflow.rb:9:9:9:15 | call to [] | position 0 |
|
||||
| local_dataflow.rb:9:12:9:12 | 2 | local_dataflow.rb:9:9:9:15 | call to [] | position 1 |
|
||||
| local_dataflow.rb:9:14:9:14 | 3 | local_dataflow.rb:9:9:9:15 | call to [] | position 2 |
|
||||
| local_dataflow.rb:10:5:13:3 | { ... } | local_dataflow.rb:10:5:13:3 | call to each | block |
|
||||
| local_dataflow.rb:10:14:10:18 | array | local_dataflow.rb:10:5:13:3 | call to each | self |
|
||||
| local_dataflow.rb:11:1:11:2 | self | local_dataflow.rb:11:1:11:2 | call to do | self |
|
||||
| local_dataflow.rb:12:3:12:5 | self | local_dataflow.rb:12:3:12:5 | call to p | self |
|
||||
| local_dataflow.rb:12:5:12:5 | x | local_dataflow.rb:12:3:12:5 | call to p | position 0 |
|
||||
| local_dataflow.rb:15:1:17:3 | { ... } | local_dataflow.rb:15:1:17:3 | call to each | block |
|
||||
| local_dataflow.rb:15:10:15:14 | array | local_dataflow.rb:15:1:17:3 | call to each | self |
|
||||
| local_dataflow.rb:19:1:21:3 | { ... } | local_dataflow.rb:19:1:21:3 | call to each | block |
|
||||
| local_dataflow.rb:19:10:19:14 | array | local_dataflow.rb:19:1:21:3 | call to each | self |
|
||||
| local_dataflow.rb:20:6:20:6 | x | local_dataflow.rb:20:6:20:10 | ... > ... | self |
|
||||
| local_dataflow.rb:20:10:20:10 | 1 | local_dataflow.rb:20:6:20:10 | ... > ... | position 0 |
|
||||
| local_dataflow.rb:35:6:35:6 | x | local_dataflow.rb:35:6:35:11 | ... == ... | self |
|
||||
| local_dataflow.rb:35:11:35:11 | 4 | local_dataflow.rb:35:6:35:11 | ... == ... | position 0 |
|
||||
| local_dataflow.rb:42:6:42:6 | x | local_dataflow.rb:42:6:42:11 | ... == ... | self |
|
||||
| local_dataflow.rb:42:11:42:11 | 4 | local_dataflow.rb:42:6:42:11 | ... == ... | position 0 |
|
||||
| local_dataflow.rb:49:1:53:3 | self | local_dataflow.rb:49:1:53:3 | call to m | self |
|
||||
| local_dataflow.rb:49:3:53:3 | do ... end | local_dataflow.rb:49:1:53:3 | call to m | block |
|
||||
| local_dataflow.rb:50:18:50:18 | x | local_dataflow.rb:50:18:50:22 | ... < ... | self |
|
||||
| local_dataflow.rb:50:22:50:22 | 4 | local_dataflow.rb:50:18:50:22 | ... < ... | position 0 |
|
||||
| local_dataflow.rb:51:20:51:20 | x | local_dataflow.rb:51:20:51:24 | ... < ... | self |
|
||||
| local_dataflow.rb:51:24:51:24 | 9 | local_dataflow.rb:51:20:51:24 | ... < ... | position 0 |
|
||||
| local_dataflow.rb:55:1:55:14 | self | local_dataflow.rb:55:1:55:14 | call to foo | self |
|
||||
| local_dataflow.rb:55:5:55:13 | Array | local_dataflow.rb:55:5:55:13 | call to [] | self |
|
||||
| local_dataflow.rb:55:5:55:13 | call to [] | local_dataflow.rb:55:1:55:14 | call to foo | position 0 |
|
||||
| local_dataflow.rb:55:6:55:6 | 1 | local_dataflow.rb:55:5:55:13 | call to [] | position 0 |
|
||||
| local_dataflow.rb:55:9:55:9 | 2 | local_dataflow.rb:55:5:55:13 | call to [] | position 1 |
|
||||
| local_dataflow.rb:55:12:55:12 | 3 | local_dataflow.rb:55:5:55:13 | call to [] | position 2 |
|
||||
|
||||
@@ -4,4 +4,6 @@ import codeql.ruby.dataflow.internal.DataFlowDispatch
|
||||
|
||||
query predicate ret(ReturningNode node) { any() }
|
||||
|
||||
query predicate arg(ArgumentNode n, DataFlowCall call, int pos) { n.argumentOf(call, pos) }
|
||||
query predicate arg(ArgumentNode n, DataFlowCall call, ArgumentPosition pos) {
|
||||
n.argumentOf(call, pos)
|
||||
}
|
||||
|
||||
@@ -0,0 +1,35 @@
|
||||
failures
|
||||
edges
|
||||
| params_flow.rb:9:16:9:17 | p1 : | params_flow.rb:10:10:10:11 | p1 |
|
||||
| params_flow.rb:9:20:9:21 | p2 : | params_flow.rb:11:10:11:11 | p2 |
|
||||
| params_flow.rb:14:12:14:19 | call to taint : | params_flow.rb:9:16:9:17 | p1 : |
|
||||
| params_flow.rb:14:22:14:29 | call to taint : | params_flow.rb:9:20:9:21 | p2 : |
|
||||
| params_flow.rb:16:13:16:14 | p1 : | params_flow.rb:17:10:17:11 | p1 |
|
||||
| params_flow.rb:16:18:16:19 | p2 : | params_flow.rb:18:10:18:11 | p2 |
|
||||
| params_flow.rb:21:13:21:20 | call to taint : | params_flow.rb:16:13:16:14 | p1 : |
|
||||
| params_flow.rb:21:27:21:34 | call to taint : | params_flow.rb:16:18:16:19 | p2 : |
|
||||
| params_flow.rb:22:13:22:20 | call to taint : | params_flow.rb:16:18:16:19 | p2 : |
|
||||
| params_flow.rb:22:27:22:34 | call to taint : | params_flow.rb:16:13:16:14 | p1 : |
|
||||
nodes
|
||||
| params_flow.rb:9:16:9:17 | p1 : | semmle.label | p1 : |
|
||||
| params_flow.rb:9:20:9:21 | p2 : | semmle.label | p2 : |
|
||||
| params_flow.rb:10:10:10:11 | p1 | semmle.label | p1 |
|
||||
| params_flow.rb:11:10:11:11 | p2 | semmle.label | p2 |
|
||||
| params_flow.rb:14:12:14:19 | call to taint : | semmle.label | call to taint : |
|
||||
| params_flow.rb:14:22:14:29 | call to taint : | semmle.label | call to taint : |
|
||||
| params_flow.rb:16:13:16:14 | p1 : | semmle.label | p1 : |
|
||||
| params_flow.rb:16:18:16:19 | p2 : | semmle.label | p2 : |
|
||||
| params_flow.rb:17:10:17:11 | p1 | semmle.label | p1 |
|
||||
| params_flow.rb:18:10:18:11 | p2 | semmle.label | p2 |
|
||||
| params_flow.rb:21:13:21:20 | call to taint : | semmle.label | call to taint : |
|
||||
| params_flow.rb:21:27:21:34 | call to taint : | semmle.label | call to taint : |
|
||||
| params_flow.rb:22:13:22:20 | call to taint : | semmle.label | call to taint : |
|
||||
| params_flow.rb:22:27:22:34 | call to taint : | semmle.label | call to taint : |
|
||||
subpaths
|
||||
#select
|
||||
| params_flow.rb:10:10:10:11 | p1 | params_flow.rb:14:12:14:19 | call to taint : | params_flow.rb:10:10:10:11 | p1 | $@ | params_flow.rb:14:12:14:19 | call to taint : | call to taint : |
|
||||
| params_flow.rb:11:10:11:11 | p2 | params_flow.rb:14:22:14:29 | call to taint : | params_flow.rb:11:10:11:11 | p2 | $@ | params_flow.rb:14:22:14:29 | call to taint : | call to taint : |
|
||||
| params_flow.rb:17:10:17:11 | p1 | params_flow.rb:21:13:21:20 | call to taint : | params_flow.rb:17:10:17:11 | p1 | $@ | params_flow.rb:21:13:21:20 | call to taint : | call to taint : |
|
||||
| params_flow.rb:17:10:17:11 | p1 | params_flow.rb:22:27:22:34 | call to taint : | params_flow.rb:17:10:17:11 | p1 | $@ | params_flow.rb:22:27:22:34 | call to taint : | call to taint : |
|
||||
| params_flow.rb:18:10:18:11 | p2 | params_flow.rb:21:27:21:34 | call to taint : | params_flow.rb:18:10:18:11 | p2 | $@ | params_flow.rb:21:27:21:34 | call to taint : | call to taint : |
|
||||
| params_flow.rb:18:10:18:11 | p2 | params_flow.rb:22:13:22:20 | call to taint : | params_flow.rb:18:10:18:11 | p2 | $@ | params_flow.rb:22:13:22:20 | call to taint : | call to taint : |
|
||||
15
ruby/ql/test/library-tests/dataflow/params/params-flow.ql
Normal file
15
ruby/ql/test/library-tests/dataflow/params/params-flow.ql
Normal file
@@ -0,0 +1,15 @@
|
||||
/**
|
||||
* @kind path-problem
|
||||
*/
|
||||
|
||||
import ruby
|
||||
import TestUtilities.InlineFlowTest
|
||||
import PathGraph
|
||||
|
||||
class HasFlowTest extends InlineFlowTest {
|
||||
override DataFlow::Configuration getTaintFlowConfig() { none() }
|
||||
}
|
||||
|
||||
from DataFlow::PathNode source, DataFlow::PathNode sink, DefaultValueFlowConf conf
|
||||
where conf.hasFlowPath(source, sink)
|
||||
select sink, source, sink, "$@", source, source.toString()
|
||||
22
ruby/ql/test/library-tests/dataflow/params/params_flow.rb
Normal file
22
ruby/ql/test/library-tests/dataflow/params/params_flow.rb
Normal file
@@ -0,0 +1,22 @@
|
||||
def taint x
|
||||
x
|
||||
end
|
||||
|
||||
def sink x
|
||||
puts x
|
||||
end
|
||||
|
||||
def positional(p1, p2)
|
||||
sink p1 # $ hasValueFlow=1
|
||||
sink p2 # $ hasValueFlow=2
|
||||
end
|
||||
|
||||
positional(taint(1), taint(2))
|
||||
|
||||
def keyword(p1:, p2:)
|
||||
sink p1 # $ hasValueFlow=3 $ hasValueFlow=6
|
||||
sink p2 # $ hasValueFlow=4 $ hasValueFlow=5
|
||||
end
|
||||
|
||||
keyword(p1: taint(3), p2: taint(4))
|
||||
keyword(p2: taint(5), p1: taint(6))
|
||||
@@ -1,5 +1,6 @@
|
||||
edges
|
||||
| HardcodedCredentials.rb:12:19:12:64 | "4NQX/CqB5Ae98zFUmwj1DMpF7azsh..." : | HardcodedCredentials.rb:1:23:1:30 | password |
|
||||
| HardcodedCredentials.rb:15:30:15:75 | "WLC17dLQ9P8YlQvqm77qplOMm5pd1..." : | HardcodedCredentials.rb:1:33:1:36 | cert |
|
||||
| HardcodedCredentials.rb:18:19:18:72 | ... + ... : | HardcodedCredentials.rb:1:23:1:30 | password |
|
||||
| HardcodedCredentials.rb:18:27:18:72 | "ogH6qSYWGdbR/2WOGYa7eZ/tObL+G..." : | HardcodedCredentials.rb:18:19:18:72 | ... + ... : |
|
||||
| HardcodedCredentials.rb:20:11:20:76 | "3jOe7sXKX6Tx52qHWUVqh2t9LNsE+..." : | HardcodedCredentials.rb:23:19:23:20 | pw : |
|
||||
@@ -10,10 +11,12 @@ edges
|
||||
| HardcodedCredentials.rb:43:57:43:70 | "abcdef123456" : | HardcodedCredentials.rb:43:46:43:53 | password |
|
||||
nodes
|
||||
| HardcodedCredentials.rb:1:23:1:30 | password | semmle.label | password |
|
||||
| HardcodedCredentials.rb:1:33:1:36 | cert | semmle.label | cert |
|
||||
| HardcodedCredentials.rb:4:20:4:65 | "xwjVWdfzfRlbcgKkbSfG/xSrUeHYq..." | semmle.label | "xwjVWdfzfRlbcgKkbSfG/xSrUeHYq..." |
|
||||
| HardcodedCredentials.rb:8:30:8:75 | "X6BLgRWSAtAWG/GaHS+WGGW2K7zZF..." | semmle.label | "X6BLgRWSAtAWG/GaHS+WGGW2K7zZF..." |
|
||||
| HardcodedCredentials.rb:12:19:12:64 | "4NQX/CqB5Ae98zFUmwj1DMpF7azsh..." : | semmle.label | "4NQX/CqB5Ae98zFUmwj1DMpF7azsh..." : |
|
||||
| HardcodedCredentials.rb:15:30:15:75 | "WLC17dLQ9P8YlQvqm77qplOMm5pd1..." | semmle.label | "WLC17dLQ9P8YlQvqm77qplOMm5pd1..." |
|
||||
| HardcodedCredentials.rb:15:30:15:75 | "WLC17dLQ9P8YlQvqm77qplOMm5pd1..." : | semmle.label | "WLC17dLQ9P8YlQvqm77qplOMm5pd1..." : |
|
||||
| HardcodedCredentials.rb:18:19:18:72 | ... + ... : | semmle.label | ... + ... : |
|
||||
| HardcodedCredentials.rb:18:27:18:72 | "ogH6qSYWGdbR/2WOGYa7eZ/tObL+G..." : | semmle.label | "ogH6qSYWGdbR/2WOGYa7eZ/tObL+G..." : |
|
||||
| HardcodedCredentials.rb:20:11:20:76 | "3jOe7sXKX6Tx52qHWUVqh2t9LNsE+..." : | semmle.label | "3jOe7sXKX6Tx52qHWUVqh2t9LNsE+..." : |
|
||||
@@ -31,6 +34,7 @@ subpaths
|
||||
| HardcodedCredentials.rb:8:30:8:75 | "X6BLgRWSAtAWG/GaHS+WGGW2K7zZF..." | HardcodedCredentials.rb:8:30:8:75 | "X6BLgRWSAtAWG/GaHS+WGGW2K7zZF..." | HardcodedCredentials.rb:8:30:8:75 | "X6BLgRWSAtAWG/GaHS+WGGW2K7zZF..." | Use of $@. | HardcodedCredentials.rb:8:30:8:75 | "X6BLgRWSAtAWG/GaHS+WGGW2K7zZF..." | hardcoded credentials |
|
||||
| HardcodedCredentials.rb:12:19:12:64 | "4NQX/CqB5Ae98zFUmwj1DMpF7azsh..." | HardcodedCredentials.rb:12:19:12:64 | "4NQX/CqB5Ae98zFUmwj1DMpF7azsh..." : | HardcodedCredentials.rb:1:23:1:30 | password | Use of $@. | HardcodedCredentials.rb:12:19:12:64 | "4NQX/CqB5Ae98zFUmwj1DMpF7azsh..." | hardcoded credentials |
|
||||
| HardcodedCredentials.rb:15:30:15:75 | "WLC17dLQ9P8YlQvqm77qplOMm5pd1..." | HardcodedCredentials.rb:15:30:15:75 | "WLC17dLQ9P8YlQvqm77qplOMm5pd1..." | HardcodedCredentials.rb:15:30:15:75 | "WLC17dLQ9P8YlQvqm77qplOMm5pd1..." | Use of $@. | HardcodedCredentials.rb:15:30:15:75 | "WLC17dLQ9P8YlQvqm77qplOMm5pd1..." | hardcoded credentials |
|
||||
| HardcodedCredentials.rb:15:30:15:75 | "WLC17dLQ9P8YlQvqm77qplOMm5pd1..." | HardcodedCredentials.rb:15:30:15:75 | "WLC17dLQ9P8YlQvqm77qplOMm5pd1..." : | HardcodedCredentials.rb:1:33:1:36 | cert | Use of $@. | HardcodedCredentials.rb:15:30:15:75 | "WLC17dLQ9P8YlQvqm77qplOMm5pd1..." | hardcoded credentials |
|
||||
| HardcodedCredentials.rb:18:27:18:72 | "ogH6qSYWGdbR/2WOGYa7eZ/tObL+G..." | HardcodedCredentials.rb:18:27:18:72 | "ogH6qSYWGdbR/2WOGYa7eZ/tObL+G..." : | HardcodedCredentials.rb:1:23:1:30 | password | Use of $@. | HardcodedCredentials.rb:18:27:18:72 | "ogH6qSYWGdbR/2WOGYa7eZ/tObL+G..." | hardcoded credentials |
|
||||
| HardcodedCredentials.rb:20:11:20:76 | "3jOe7sXKX6Tx52qHWUVqh2t9LNsE+..." | HardcodedCredentials.rb:20:11:20:76 | "3jOe7sXKX6Tx52qHWUVqh2t9LNsE+..." : | HardcodedCredentials.rb:1:23:1:30 | password | Use of $@. | HardcodedCredentials.rb:20:11:20:76 | "3jOe7sXKX6Tx52qHWUVqh2t9LNsE+..." | hardcoded credentials |
|
||||
| HardcodedCredentials.rb:21:12:21:37 | "4fQuzXef4f2yow8KWvIJTA==" | HardcodedCredentials.rb:21:12:21:37 | "4fQuzXef4f2yow8KWvIJTA==" : | HardcodedCredentials.rb:1:23:1:30 | password | Use of $@. | HardcodedCredentials.rb:21:12:21:37 | "4fQuzXef4f2yow8KWvIJTA==" | hardcoded credentials |
|
||||
|
||||
Reference in New Issue
Block a user