mirror of
https://github.com/github/codeql.git
synced 2026-04-27 01:35:13 +02:00
Merge branch 'main' into js/graph-export
This commit is contained in:
@@ -1,4 +1,4 @@
|
||||
load("@rules_pkg//:mappings.bzl", "pkg_files")
|
||||
load("@rules_pkg//pkg:mappings.bzl", "pkg_files")
|
||||
|
||||
package(default_visibility = ["//ruby:__pkg__"])
|
||||
|
||||
|
||||
@@ -26,7 +26,6 @@ private import codeql.ruby.frameworks.XmlParsing
|
||||
private import codeql.ruby.frameworks.ActionDispatch
|
||||
private import codeql.ruby.frameworks.PosixSpawn
|
||||
private import codeql.ruby.frameworks.StringFormatters
|
||||
private import codeql.ruby.frameworks.Json
|
||||
private import codeql.ruby.frameworks.Erb
|
||||
private import codeql.ruby.frameworks.Slim
|
||||
private import codeql.ruby.frameworks.Sinatra
|
||||
|
||||
@@ -560,6 +560,10 @@ private predicate isArrayExpr(Expr e, ArrayLiteralCfgNode arr) {
|
||||
// Note(hmac): I don't think this is necessary, as `getSource` will not return
|
||||
// results if the source is a phi node.
|
||||
forex(ExprCfgNode n | n = e.getAControlFlowNode() | isArrayConstant(n, arr))
|
||||
or
|
||||
// if `e` is an array, then `e.freeze` is also an array
|
||||
e.(MethodCall).getMethodName() = "freeze" and
|
||||
isArrayExpr(e.(MethodCall).getReceiver(), arr)
|
||||
}
|
||||
|
||||
private class TokenConstantAccess extends ConstantAccess, TTokenConstantAccess {
|
||||
|
||||
@@ -32,9 +32,22 @@ abstract class SummarizedCallable extends LibraryCallable, Impl::Public::Summari
|
||||
* DEPRECATED: Use `propagatesFlow` instead.
|
||||
*/
|
||||
deprecated predicate propagatesFlowExt(string input, string output, boolean preservesValue) {
|
||||
this.propagatesFlow(input, output, preservesValue)
|
||||
this.propagatesFlow(input, output, preservesValue, _)
|
||||
}
|
||||
|
||||
override predicate propagatesFlow(
|
||||
string input, string output, boolean preservesValue, string model
|
||||
) {
|
||||
this.propagatesFlow(input, output, preservesValue) and model = ""
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if data may flow from `input` to `output` through this callable.
|
||||
*
|
||||
* `preservesValue` indicates whether this is a value-preserving step or a taint-step.
|
||||
*/
|
||||
predicate propagatesFlow(string input, string output, boolean preservesValue) { none() }
|
||||
|
||||
/**
|
||||
* Gets the synthesized parameter that results from an input specification
|
||||
* that starts with `Argument[s]` for this library callable.
|
||||
@@ -100,7 +113,9 @@ private module LibraryCallbackSummaries {
|
||||
libraryCallHasLambdaArg(result.getAControlFlowNode(), _)
|
||||
}
|
||||
|
||||
override predicate propagatesFlow(string input, string output, boolean preservesValue) {
|
||||
override predicate propagatesFlow(
|
||||
string input, string output, boolean preservesValue, string model
|
||||
) {
|
||||
(
|
||||
input = "Argument[block]" and
|
||||
output = "Argument[block].Parameter[lambda-self]"
|
||||
@@ -111,7 +126,8 @@ private module LibraryCallbackSummaries {
|
||||
output = "Argument[" + i + "].Parameter[lambda-self]"
|
||||
)
|
||||
) and
|
||||
preservesValue = true
|
||||
preservesValue = true and
|
||||
model = "heuristic-callback"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -263,9 +263,10 @@ deprecated private module Config implements FullStateConfigSig {
|
||||
|
||||
predicate isBarrierOut(Node node, FlowState state) { none() }
|
||||
|
||||
predicate isAdditionalFlowStep(Node node1, Node node2) {
|
||||
predicate isAdditionalFlowStep(Node node1, Node node2, string model) {
|
||||
singleConfiguration() and
|
||||
any(Configuration config).isAdditionalFlowStep(node1, node2)
|
||||
any(Configuration config).isAdditionalFlowStep(node1, node2) and
|
||||
model = ""
|
||||
}
|
||||
|
||||
predicate isAdditionalFlowStep(Node node1, FlowState state1, Node node2, FlowState state2) {
|
||||
|
||||
@@ -263,9 +263,10 @@ deprecated private module Config implements FullStateConfigSig {
|
||||
|
||||
predicate isBarrierOut(Node node, FlowState state) { none() }
|
||||
|
||||
predicate isAdditionalFlowStep(Node node1, Node node2) {
|
||||
predicate isAdditionalFlowStep(Node node1, Node node2, string model) {
|
||||
singleConfiguration() and
|
||||
any(Configuration config).isAdditionalFlowStep(node1, node2)
|
||||
any(Configuration config).isAdditionalFlowStep(node1, node2) and
|
||||
model = ""
|
||||
}
|
||||
|
||||
predicate isAdditionalFlowStep(Node node1, FlowState state1, Node node2, FlowState state2) {
|
||||
|
||||
@@ -244,10 +244,11 @@ module LocalFlow {
|
||||
}
|
||||
|
||||
predicate flowSummaryLocalStep(
|
||||
FlowSummaryNode nodeFrom, FlowSummaryNode nodeTo, FlowSummaryImpl::Public::SummarizedCallable c
|
||||
FlowSummaryNode nodeFrom, FlowSummaryNode nodeTo, FlowSummaryImpl::Public::SummarizedCallable c,
|
||||
string model
|
||||
) {
|
||||
FlowSummaryImpl::Private::Steps::summaryLocalStep(nodeFrom.getSummaryNode(),
|
||||
nodeTo.getSummaryNode(), true) and
|
||||
nodeTo.getSummaryNode(), true, model) and
|
||||
c = nodeFrom.getSummarizedCallable()
|
||||
}
|
||||
|
||||
@@ -271,7 +272,7 @@ module LocalFlow {
|
||||
node1 =
|
||||
unique(FlowSummaryNode n1 |
|
||||
FlowSummaryImpl::Private::Steps::summaryLocalStep(n1.getSummaryNode(),
|
||||
node2.(FlowSummaryNode).getSummaryNode(), true)
|
||||
node2.(FlowSummaryNode).getSummaryNode(), true, _)
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -606,25 +607,28 @@ private module Cached {
|
||||
* data flow.
|
||||
*/
|
||||
cached
|
||||
predicate simpleLocalFlowStep(Node nodeFrom, Node nodeTo) {
|
||||
LocalFlow::localFlowStepCommon(nodeFrom, nodeTo)
|
||||
or
|
||||
exists(SsaImpl::DefinitionExt def |
|
||||
// captured variables are handled by the shared `VariableCapture` library
|
||||
not def instanceof VariableCapture::CapturedSsaDefinitionExt
|
||||
|
|
||||
LocalFlow::localSsaFlowStep(def, nodeFrom, nodeTo)
|
||||
predicate simpleLocalFlowStep(Node nodeFrom, Node nodeTo, string model) {
|
||||
(
|
||||
LocalFlow::localFlowStepCommon(nodeFrom, nodeTo)
|
||||
or
|
||||
LocalFlow::localSsaFlowStepUseUse(def, nodeFrom, nodeTo) and
|
||||
not FlowSummaryImpl::Private::Steps::prohibitsUseUseFlow(nodeFrom, _)
|
||||
exists(SsaImpl::DefinitionExt def |
|
||||
// captured variables are handled by the shared `VariableCapture` library
|
||||
not def instanceof VariableCapture::CapturedSsaDefinitionExt
|
||||
|
|
||||
LocalFlow::localSsaFlowStep(def, nodeFrom, nodeTo)
|
||||
or
|
||||
LocalFlow::localSsaFlowStepUseUse(def, nodeFrom, nodeTo) and
|
||||
not FlowSummaryImpl::Private::Steps::prohibitsUseUseFlow(nodeFrom, _)
|
||||
or
|
||||
LocalFlow::localFlowSsaInputFromRead(def, nodeFrom, nodeTo) and
|
||||
not FlowSummaryImpl::Private::Steps::prohibitsUseUseFlow(nodeFrom, _)
|
||||
)
|
||||
or
|
||||
LocalFlow::localFlowSsaInputFromRead(def, nodeFrom, nodeTo) and
|
||||
not FlowSummaryImpl::Private::Steps::prohibitsUseUseFlow(nodeFrom, _)
|
||||
)
|
||||
VariableCapture::valueStep(nodeFrom, nodeTo)
|
||||
) and
|
||||
model = ""
|
||||
or
|
||||
LocalFlow::flowSummaryLocalStep(nodeFrom, nodeTo, _)
|
||||
or
|
||||
VariableCapture::valueStep(nodeFrom, nodeTo)
|
||||
LocalFlow::flowSummaryLocalStep(nodeFrom, nodeTo, _, model)
|
||||
}
|
||||
|
||||
/** This is the local flow predicate that is exposed. */
|
||||
@@ -656,7 +660,8 @@ private module Cached {
|
||||
or
|
||||
VariableCapture::flowInsensitiveStep(nodeFrom, nodeTo)
|
||||
or
|
||||
LocalFlow::flowSummaryLocalStep(nodeFrom, nodeTo, any(LibraryCallableToIncludeInTypeTracking c))
|
||||
LocalFlow::flowSummaryLocalStep(nodeFrom, nodeTo, any(LibraryCallableToIncludeInTypeTracking c),
|
||||
_)
|
||||
}
|
||||
|
||||
/** Holds if `n` wraps an SSA definition without ingoing flow. */
|
||||
@@ -752,7 +757,7 @@ private module Cached {
|
||||
// external model data. This, unfortunately, does not included any field names used
|
||||
// in models defined in QL code.
|
||||
exists(string input, string output |
|
||||
ModelOutput::relevantSummaryModel(_, _, input, output, _)
|
||||
ModelOutput::relevantSummaryModel(_, _, input, output, _, _)
|
||||
|
|
||||
name = [input, output].regexpFind("(?<=(^|\\.)Field\\[)[^\\]]+(?=\\])", _, _).trim()
|
||||
)
|
||||
@@ -2241,6 +2246,14 @@ predicate lambdaCall(DataFlowCall call, LambdaCallKind kind, Node receiver) {
|
||||
/** Extra data-flow steps needed for lambda flow analysis. */
|
||||
predicate additionalLambdaFlowStep(Node nodeFrom, Node nodeTo, boolean preservesValue) { none() }
|
||||
|
||||
predicate knownSourceModel(Node source, string model) {
|
||||
source = ModelOutput::getASourceNode(_, model).asSource()
|
||||
}
|
||||
|
||||
predicate knownSinkModel(Node sink, string model) {
|
||||
sink = ModelOutput::getASinkNode(_, model).asSink()
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if flow is allowed to pass from parameter `p` and back to itself as a
|
||||
* side-effect, resulting in a summary from `p` to itself.
|
||||
|
||||
@@ -77,38 +77,41 @@ private module Cached {
|
||||
* in all global taint flow configurations.
|
||||
*/
|
||||
cached
|
||||
predicate defaultAdditionalTaintStep(DataFlow::Node nodeFrom, DataFlow::Node nodeTo) {
|
||||
// value of `case` expression into variables in patterns
|
||||
exists(
|
||||
CfgNodes::ExprNodes::CaseExprCfgNode case, CfgNodes::ExprCfgNode value,
|
||||
CfgNodes::ExprNodes::InClauseCfgNode clause, Ssa::Definition def
|
||||
|
|
||||
nodeFrom.asExpr() = value and
|
||||
value = case.getValue() and
|
||||
clause = case.getBranch(_) and
|
||||
def = nodeTo.(SsaDefinitionExtNode).getDefinitionExt() and
|
||||
def.getControlFlowNode() = variablesInPattern(clause.getPattern()) and
|
||||
not LocalFlow::ssaDefAssigns(def, value)
|
||||
)
|
||||
or
|
||||
// operation involving `nodeFrom`
|
||||
exists(CfgNodes::ExprNodes::OperationCfgNode op |
|
||||
op = nodeTo.asExpr() and
|
||||
op.getAnOperand() = nodeFrom.asExpr() and
|
||||
not op.getExpr() =
|
||||
any(Expr e |
|
||||
// included in normal data-flow
|
||||
e instanceof AssignExpr or
|
||||
e instanceof BinaryLogicalOperation or
|
||||
// has flow summary
|
||||
e instanceof SplatExpr
|
||||
)
|
||||
)
|
||||
predicate defaultAdditionalTaintStep(DataFlow::Node nodeFrom, DataFlow::Node nodeTo, string model) {
|
||||
(
|
||||
// value of `case` expression into variables in patterns
|
||||
exists(
|
||||
CfgNodes::ExprNodes::CaseExprCfgNode case, CfgNodes::ExprCfgNode value,
|
||||
CfgNodes::ExprNodes::InClauseCfgNode clause, Ssa::Definition def
|
||||
|
|
||||
nodeFrom.asExpr() = value and
|
||||
value = case.getValue() and
|
||||
clause = case.getBranch(_) and
|
||||
def = nodeTo.(SsaDefinitionExtNode).getDefinitionExt() and
|
||||
def.getControlFlowNode() = variablesInPattern(clause.getPattern()) and
|
||||
not LocalFlow::ssaDefAssigns(def, value)
|
||||
)
|
||||
or
|
||||
// operation involving `nodeFrom`
|
||||
exists(CfgNodes::ExprNodes::OperationCfgNode op |
|
||||
op = nodeTo.asExpr() and
|
||||
op.getAnOperand() = nodeFrom.asExpr() and
|
||||
not op.getExpr() =
|
||||
any(Expr e |
|
||||
// included in normal data-flow
|
||||
e instanceof AssignExpr or
|
||||
e instanceof BinaryLogicalOperation or
|
||||
// has flow summary
|
||||
e instanceof SplatExpr
|
||||
)
|
||||
)
|
||||
) and
|
||||
model = ""
|
||||
or
|
||||
FlowSummaryImpl::Private::Steps::summaryLocalStep(nodeFrom.(FlowSummaryNode).getSummaryNode(),
|
||||
nodeTo.(FlowSummaryNode).getSummaryNode(), false)
|
||||
nodeTo.(FlowSummaryNode).getSummaryNode(), false, model)
|
||||
or
|
||||
any(FlowSteps::AdditionalTaintStep s).step(nodeFrom, nodeTo)
|
||||
any(FlowSteps::AdditionalTaintStep s).step(nodeFrom, nodeTo) and model = "AdditionalTaintStep"
|
||||
or
|
||||
// Although flow through collections is modeled precisely using stores/reads, we still
|
||||
// allow flow out of a _tainted_ collection. This is needed in order to support taint-
|
||||
@@ -119,7 +122,8 @@ private module Cached {
|
||||
c.isKnownOrUnknownElement(_)
|
||||
or
|
||||
c.isAnyElement()
|
||||
)
|
||||
) and
|
||||
model = ""
|
||||
}
|
||||
|
||||
cached
|
||||
@@ -136,7 +140,7 @@ private module Cached {
|
||||
cached
|
||||
predicate localTaintStepCached(DataFlow::Node nodeFrom, DataFlow::Node nodeTo) {
|
||||
DataFlow::localFlowStep(nodeFrom, nodeTo) or
|
||||
defaultAdditionalTaintStep(nodeFrom, nodeTo) or
|
||||
defaultAdditionalTaintStep(nodeFrom, nodeTo, _) or
|
||||
// Simple flow through library code is included in the exposed local
|
||||
// step relation, even though flow is technically inter-procedural
|
||||
summaryThroughStepTaint(nodeFrom, nodeTo, _)
|
||||
|
||||
@@ -127,7 +127,7 @@ abstract deprecated class Configuration extends DataFlow::Configuration {
|
||||
|
||||
final override predicate isAdditionalFlowStep(DataFlow::Node node1, DataFlow::Node node2) {
|
||||
this.isAdditionalTaintStep(node1, node2) or
|
||||
defaultAdditionalTaintStep(node1, node2)
|
||||
defaultAdditionalTaintStep(node1, node2, _)
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -792,3 +792,36 @@ class ActiveRecordScopeCallTarget extends AdditionalCallTarget {
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
/** Sinks for the mass assignment query. */
|
||||
private module MassAssignmentSinks {
|
||||
private import codeql.ruby.security.MassAssignmentCustomizations
|
||||
|
||||
pragma[nomagic]
|
||||
private predicate massAssignmentCall(DataFlow::CallNode call, string name) {
|
||||
call = activeRecordBaseClass().getAMethodCall(name)
|
||||
or
|
||||
call instanceof ActiveRecordInstanceMethodCall and
|
||||
call.getMethodName() = name
|
||||
}
|
||||
|
||||
/** A call to a method that sets attributes of an database record using a hash. */
|
||||
private class MassAssignmentSink extends MassAssignment::Sink {
|
||||
MassAssignmentSink() {
|
||||
exists(DataFlow::CallNode call, string name | massAssignmentCall(call, name) |
|
||||
name =
|
||||
[
|
||||
"build", "create", "create!", "create_with", "create_or_find_by", "create_or_find_by!",
|
||||
"find_or_create_by", "find_or_create_by!", "find_or_initialize_by", "insert", "insert!",
|
||||
"insert_all", "insert_all!", "instantiate", "new", "update", "update!", "upsert",
|
||||
"upsert_all"
|
||||
] and
|
||||
this = call.getArgument(0)
|
||||
or
|
||||
// These methods have an optional first id parameter.
|
||||
name = ["update", "update!"] and
|
||||
this = call.getArgument(1)
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
22
ruby/ql/lib/codeql/ruby/frameworks/ActiveStorage.model.yml
Normal file
22
ruby/ql/lib/codeql/ruby/frameworks/ActiveStorage.model.yml
Normal file
@@ -0,0 +1,22 @@
|
||||
extensions:
|
||||
- addsTo:
|
||||
pack: codeql/ruby-all
|
||||
extensible: summaryModel
|
||||
data:
|
||||
- ['ActiveStorage::Filename!', 'Method[new]', 'Argument[0]', 'ReturnValue', 'taint']
|
||||
- ['ActiveStorage::Filename', 'Method[sanitized]', 'Argument[self]', 'ReturnValue', 'taint']
|
||||
|
||||
- addsTo:
|
||||
pack: codeql/ruby-all
|
||||
extensible: typeModel
|
||||
data:
|
||||
# ActiveStorage::Blob.compose(blobs : [Blob]) : Blob
|
||||
- ['ActiveStorage::Blob', 'ActiveStorage::Blob!', 'Method[compose].ReturnValue']
|
||||
# ActiveStorage::Blob.create_and_upload! : Blob
|
||||
- ['ActiveStorage::Blob', 'ActiveStorage::Blob!', 'Method[create_and_upload!].ReturnValue']
|
||||
# ActiveStorage::Blob.create_before_direct_upload! : Blob
|
||||
- ['ActiveStorage::Blob', 'ActiveStorage::Blob!', 'Method[create_before_direct_upload!].ReturnValue']
|
||||
# ActiveStorage::Blob.find_signed(!) : Blob
|
||||
- ['ActiveStorage::Blob', 'ActiveStorage::Blob!', 'Method[find_signed,find_signed!].ReturnValue']
|
||||
# gives error: Invalid name 'Element' in access path
|
||||
# - ['ActiveStorage::Blob', 'ActiveStorage::Blob!', 'Method[compose].Argument[0].Element[any]']
|
||||
@@ -26,39 +26,6 @@ module ActiveStorage {
|
||||
}
|
||||
}
|
||||
|
||||
/** Taint related to `ActiveStorage::Filename`. */
|
||||
private class FilenameSummaries extends ModelInput::SummaryModelCsv {
|
||||
override predicate row(string row) {
|
||||
row =
|
||||
[
|
||||
"ActiveStorage::Filename!;Method[new];Argument[0];ReturnValue;taint",
|
||||
"ActiveStorage::Filename;Method[sanitized];Argument[self];ReturnValue;taint",
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* `Blob` is an instance of `ActiveStorage::Blob`.
|
||||
*/
|
||||
private class BlobTypeSummary extends ModelInput::TypeModelCsv {
|
||||
override predicate row(string row) {
|
||||
// package1;type1;package2;type2;path
|
||||
row =
|
||||
[
|
||||
// ActiveStorage::Blob.create_and_upload! : Blob
|
||||
"ActiveStorage::Blob;ActiveStorage::Blob!;Method[create_and_upload!].ReturnValue",
|
||||
// ActiveStorage::Blob.create_before_direct_upload! : Blob
|
||||
"ActiveStorage::Blob;ActiveStorage::Blob!;Method[create_before_direct_upload!].ReturnValue",
|
||||
// ActiveStorage::Blob.compose(blobs : [Blob]) : Blob
|
||||
"ActiveStorage::Blob;ActiveStorage::Blob!;Method[compose].ReturnValue",
|
||||
// gives error: Invalid name 'Element' in access path
|
||||
// "ActiveStorage::Blob;ActiveStorage::Blob!;Method[compose].Argument[0].Element[any]",
|
||||
// ActiveStorage::Blob.find_signed(!) : Blob
|
||||
"ActiveStorage::Blob;ActiveStorage::Blob!;Method[find_signed,find_signed!].ReturnValue",
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
private class BlobInstance extends DataFlow::Node {
|
||||
BlobInstance() {
|
||||
this = ModelOutput::getATypeNode("ActiveStorage::Blob").getAValueReachableFromSource()
|
||||
|
||||
30
ruby/ql/lib/codeql/ruby/frameworks/ActiveSupport.model.yml
Normal file
30
ruby/ql/lib/codeql/ruby/frameworks/ActiveSupport.model.yml
Normal file
@@ -0,0 +1,30 @@
|
||||
extensions:
|
||||
- addsTo:
|
||||
pack: codeql/ruby-all
|
||||
extensible: summaryModel
|
||||
data:
|
||||
# `ActiveSupport::SafeBuffer` wraps a string, providing HTML-safe methods
|
||||
# for concatenation.
|
||||
# It is possible to insert tainted data into `SafeBuffer` that won't get
|
||||
# sanitized, and this taint is then propagated via most of the methods.
|
||||
#
|
||||
# TODO: SafeBuffer also reponds to all String methods.
|
||||
# Can we model this without repeating all the existing summaries we have
|
||||
# for String?
|
||||
|
||||
# SafeBuffer.new(x) does not sanitize x
|
||||
- ['ActionView::SafeBuffer!', 'Method[new]', 'Argument[0]', 'ReturnValue', 'taint']
|
||||
# These methods preserve taint in self
|
||||
- ['ActionView::SafeBuffer', 'Method[concat,insert,prepend,to_s,to_param]', 'Argument[self]', 'ReturnValue', 'taint']
|
||||
# SafeBuffer#safe_concat(x) does not sanitize x
|
||||
- ['ActionView::SafeBuffer', 'Method[safe_concat]', 'Argument[0]', 'Argument[self]', 'taint']
|
||||
- ['ActionView::SafeBuffer', 'Method[safe_concat]', 'Argument[0]', 'ReturnValue', 'taint']
|
||||
- ['ActiveSupport::JSON!', 'Method[decode,load]', 'Argument[0]', 'ReturnValue', 'taint']
|
||||
- ['ActiveSupport::JSON!', 'Method[encode,dump]', 'Argument[0]', 'ReturnValue', 'taint']
|
||||
- ['Pathname', 'Method[existence]', 'Argument[self]', 'ReturnValue', 'taint']
|
||||
|
||||
- addsTo:
|
||||
pack: codeql/ruby-all
|
||||
extensible: typeModel
|
||||
data:
|
||||
- ['Pathname', 'Pathname', 'Method[existence].ReturnValue']
|
||||
@@ -478,60 +478,4 @@ module ActiveSupport {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Type summaries for extensions to the `Pathname` module.
|
||||
*/
|
||||
private class PathnameTypeSummary extends ModelInput::TypeModelCsv {
|
||||
override predicate row(string row) {
|
||||
// type1;type2;path
|
||||
// Pathname#existence : Pathname
|
||||
row = "Pathname;Pathname;Method[existence].ReturnValue"
|
||||
}
|
||||
}
|
||||
|
||||
/** Taint flow summaries for extensions to the `Pathname` module. */
|
||||
private class PathnameTaintSummary extends ModelInput::SummaryModelCsv {
|
||||
override predicate row(string row) {
|
||||
// Pathname#existence
|
||||
row = "Pathname;Method[existence];Argument[self];ReturnValue;taint"
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* `ActiveSupport::SafeBuffer` wraps a string, providing HTML-safe methods
|
||||
* for concatenation.
|
||||
* It is possible to insert tainted data into `SafeBuffer` that won't get
|
||||
* sanitized, and this taint is then propagated via most of the methods.
|
||||
*/
|
||||
private class SafeBufferSummary extends ModelInput::SummaryModelCsv {
|
||||
// TODO: SafeBuffer also reponds to all String methods.
|
||||
// Can we model this without repeating all the existing summaries we have
|
||||
// for String?
|
||||
override predicate row(string row) {
|
||||
row =
|
||||
[
|
||||
// SafeBuffer.new(x) does not sanitize x
|
||||
"ActionView::SafeBuffer!;Method[new];Argument[0];ReturnValue;taint",
|
||||
// SafeBuffer#safe_concat(x) does not sanitize x
|
||||
"ActionView::SafeBuffer;Method[safe_concat];Argument[0];ReturnValue;taint",
|
||||
"ActionView::SafeBuffer;Method[safe_concat];Argument[0];Argument[self];taint",
|
||||
// These methods preserve taint in self
|
||||
"ActionView::SafeBuffer;Method[concat,insert,prepend,to_s,to_param];Argument[self];ReturnValue;taint",
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
/** `ActiveSupport::JSON` */
|
||||
module Json {
|
||||
private class JsonSummary extends ModelInput::SummaryModelCsv {
|
||||
override predicate row(string row) {
|
||||
row =
|
||||
[
|
||||
"ActiveSupport::JSON!;Method[encode,dump];Argument[0];ReturnValue;taint",
|
||||
"ActiveSupport::JSON!;Method[decode,load];Argument[0];ReturnValue;taint",
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -13,7 +13,6 @@ import core.Module
|
||||
import core.Array
|
||||
import core.Hash
|
||||
import core.String
|
||||
import core.Regexp
|
||||
import core.IO
|
||||
import core.Digest
|
||||
import core.Base64
|
||||
|
||||
11
ruby/ql/lib/codeql/ruby/frameworks/Json.model.yml
Normal file
11
ruby/ql/lib/codeql/ruby/frameworks/Json.model.yml
Normal file
@@ -0,0 +1,11 @@
|
||||
extensions:
|
||||
- addsTo:
|
||||
pack: codeql/ruby-all
|
||||
extensible: summaryModel
|
||||
data:
|
||||
# Not all of these methods are strictly defined in the `json` gem.
|
||||
# The `JSON` namespace is heavily overloaded by other JSON parsing gems such as `oj`, `json_pure`, `multi_json` etc.
|
||||
# This summary covers common methods we've seen called on `JSON` in the wild.
|
||||
- ['JSON!', 'Method[generate,fast_generate,pretty_generate,dump,unparse,fast_unparse]', 'Argument[0]', 'ReturnValue', 'taint']
|
||||
- ['JSON!', 'Method[parse,parse!,load,restore]', 'Argument[0]', 'ReturnValue', 'taint']
|
||||
|
||||
@@ -1,22 +0,0 @@
|
||||
/** Provides modeling for the `json` gem. */
|
||||
|
||||
private import codeql.ruby.frameworks.data.ModelsAsData
|
||||
|
||||
/** Provides modeling for the `json` gem. */
|
||||
module Json {
|
||||
/**
|
||||
* Flow summaries for common `JSON` methods.
|
||||
* Not all of these methods are strictly defined in the `json` gem.
|
||||
* The `JSON` namespace is heavily overloaded by other JSON parsing gems such as `oj`, `json_pure`, `multi_json` etc.
|
||||
* This summary covers common methods we've seen called on `JSON` in the wild.
|
||||
*/
|
||||
private class JsonSummary extends ModelInput::SummaryModelCsv {
|
||||
override predicate row(string row) {
|
||||
row =
|
||||
[
|
||||
"JSON!;Method[parse,parse!,load,restore];Argument[0];ReturnValue;taint",
|
||||
"JSON!;Method[generate,fast_generate,pretty_generate,dump,unparse,fast_unparse];Argument[0];ReturnValue;taint",
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
extensions:
|
||||
- addsTo:
|
||||
pack: codeql/ruby-all
|
||||
extensible: typeModel
|
||||
data:
|
||||
- ['Mime::Type', 'Mime!', 'Method[fetch].ReturnValue']
|
||||
- ['Mime::Type', 'Mime::Type!', 'Method[lookup].ReturnValue']
|
||||
- ['Mime::Type', 'Mime::Type!', 'Method[lookup_by_extension].ReturnValue']
|
||||
- ['Mime::Type', 'Mime::Type!', 'Method[register].ReturnValue']
|
||||
- ['Mime::Type', 'Mime::Type!', 'Method[register_alias].ReturnValue']
|
||||
@@ -9,31 +9,6 @@ private import codeql.ruby.frameworks.data.ModelsAsData
|
||||
* Models MIME type handling using the `ActionDispatch` library, which is part of Rails.
|
||||
*/
|
||||
module Mime {
|
||||
/**
|
||||
* Type summaries for the `Mime::Type` class, i.e. method calls that produce new
|
||||
* `Mime::Type` instances.
|
||||
*/
|
||||
private class MimeTypeTypeSummary extends ModelInput::TypeModelCsv {
|
||||
override predicate row(string row) {
|
||||
// type1;type2;path
|
||||
row =
|
||||
[
|
||||
// Mime[type] : Mime::Type (omitted)
|
||||
// Method names with brackets like [] cannot be represented in MaD.
|
||||
// Mime.fetch(type) : Mime::Type
|
||||
"Mime::Type;Mime!;Method[fetch].ReturnValue",
|
||||
// Mime::Type.lookup(str) : Mime::Type
|
||||
"Mime::Type;Mime::Type!;Method[lookup].ReturnValue",
|
||||
// Mime::Type.lookup_by_extension(str) : Mime::Type
|
||||
"Mime::Type;Mime::Type!;Method[lookup_by_extension].ReturnValue",
|
||||
// Mime::Type.register(str) : Mime::Type
|
||||
"Mime::Type;Mime::Type!;Method[register].ReturnValue",
|
||||
// Mime::Type.register_alias(str) : Mime::Type
|
||||
"Mime::Type;Mime::Type!;Method[register_alias].ReturnValue",
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* An argument to `Mime::Type#match?`, which is converted to a RegExp via
|
||||
* `Regexp.new`.
|
||||
|
||||
7
ruby/ql/lib/codeql/ruby/frameworks/core/Regexp.model.yml
Normal file
7
ruby/ql/lib/codeql/ruby/frameworks/core/Regexp.model.yml
Normal file
@@ -0,0 +1,7 @@
|
||||
extensions:
|
||||
- addsTo:
|
||||
pack: codeql/ruby-all
|
||||
extensible: summaryModel
|
||||
data:
|
||||
- ['Regexp!', 'Method[escape,quote]', 'Argument[0]', 'ReturnValue', 'taint']
|
||||
|
||||
@@ -1,19 +0,0 @@
|
||||
/**
|
||||
* Provides modeling for the `Regexp` class.
|
||||
*/
|
||||
|
||||
private import codeql.ruby.ApiGraphs
|
||||
private import codeql.ruby.dataflow.FlowSummary
|
||||
private import codeql.ruby.frameworks.data.ModelsAsData
|
||||
|
||||
/**
|
||||
* Provides modeling for the `Regexp` class.
|
||||
*/
|
||||
module Regexp {
|
||||
/** A flow summary for `Regexp.escape` and its alias, `Regexp.quote`. */
|
||||
class RegexpEscapeSummary extends ModelInput::SummaryModelCsv {
|
||||
override predicate row(string row) {
|
||||
row = "Regexp!;Method[escape,quote];Argument[0];ReturnValue;taint"
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -37,7 +37,7 @@ private class SummarizedCallableFromModel extends SummarizedCallable {
|
||||
string path;
|
||||
|
||||
SummarizedCallableFromModel() {
|
||||
ModelOutput::relevantSummaryModel(type, path, _, _, _) and
|
||||
ModelOutput::relevantSummaryModel(type, path, _, _, _, _) and
|
||||
this = type + ";" + path
|
||||
}
|
||||
|
||||
@@ -48,8 +48,10 @@ private class SummarizedCallableFromModel extends SummarizedCallable {
|
||||
)
|
||||
}
|
||||
|
||||
override predicate propagatesFlow(string input, string output, boolean preservesValue) {
|
||||
exists(string kind | ModelOutput::relevantSummaryModel(type, path, input, output, kind) |
|
||||
override predicate propagatesFlow(
|
||||
string input, string output, boolean preservesValue, string model
|
||||
) {
|
||||
exists(string kind | ModelOutput::relevantSummaryModel(type, path, input, output, kind, model) |
|
||||
kind = "value" and
|
||||
preservesValue = true
|
||||
or
|
||||
|
||||
@@ -1,17 +1,17 @@
|
||||
/**
|
||||
* INTERNAL use only. This is an experimental API subject to change without notice.
|
||||
*
|
||||
* Provides classes and predicates for dealing with flow models specified in CSV format.
|
||||
* Provides classes and predicates for dealing with flow models specified in extensible predicates.
|
||||
*
|
||||
* The CSV specification has the following columns:
|
||||
* The extensible predicates have the following columns:
|
||||
* - Sources:
|
||||
* `type; path; kind`
|
||||
* `type, path, kind`
|
||||
* - Sinks:
|
||||
* `type; path; kind`
|
||||
* `type, path, kind`
|
||||
* - Summaries:
|
||||
* `type; path; input; output; kind`
|
||||
* `type, path, input, output, kind`
|
||||
* - Types:
|
||||
* `type1; type2; path`
|
||||
* `type1, type2, path`
|
||||
*
|
||||
* The interpretation of a row is similar to API-graphs with a left-to-right
|
||||
* reading.
|
||||
@@ -76,11 +76,13 @@ private import codeql.dataflow.internal.AccessPathSyntax
|
||||
/** Module containing hooks for providing input data to be interpreted as a model. */
|
||||
module ModelInput {
|
||||
/**
|
||||
* DEPRECATED: Use the extensible predicate `sourceModel` instead.
|
||||
*
|
||||
* A unit class for adding additional source model rows.
|
||||
*
|
||||
* Extend this class to add additional source definitions.
|
||||
*/
|
||||
class SourceModelCsv extends Unit {
|
||||
deprecated class SourceModelCsv extends Unit {
|
||||
/**
|
||||
* Holds if `row` specifies a source definition.
|
||||
*
|
||||
@@ -93,15 +95,17 @@ module ModelInput {
|
||||
*
|
||||
* The kind `remote` represents a general remote flow source.
|
||||
*/
|
||||
abstract predicate row(string row);
|
||||
abstract deprecated predicate row(string row);
|
||||
}
|
||||
|
||||
/**
|
||||
* A unit class for adding additional sink model rows.
|
||||
*
|
||||
* Extend this class to add additional sink definitions.
|
||||
*
|
||||
* DEPRECATED: Use the extensible predicate `sinkModel` instead.
|
||||
*/
|
||||
class SinkModelCsv extends Unit {
|
||||
deprecated class SinkModelCsv extends Unit {
|
||||
/**
|
||||
* Holds if `row` specifies a sink definition.
|
||||
*
|
||||
@@ -112,15 +116,17 @@ module ModelInput {
|
||||
* indicates that the value at `(type, path)` should be seen as a sink
|
||||
* of the given `kind`.
|
||||
*/
|
||||
abstract predicate row(string row);
|
||||
abstract deprecated predicate row(string row);
|
||||
}
|
||||
|
||||
/**
|
||||
* A unit class for adding additional summary model rows.
|
||||
*
|
||||
* Extend this class to add additional flow summary definitions.
|
||||
*
|
||||
* DEPRECATED: Use the extensible predicate `summaryModel` instead.
|
||||
*/
|
||||
class SummaryModelCsv extends Unit {
|
||||
deprecated class SummaryModelCsv extends Unit {
|
||||
/**
|
||||
* Holds if `row` specifies a summary definition.
|
||||
*
|
||||
@@ -134,15 +140,18 @@ module ModelInput {
|
||||
* `kind` should be either `value` or `taint`, for value-preserving or taint-preserving steps,
|
||||
* respectively.
|
||||
*/
|
||||
abstract predicate row(string row);
|
||||
abstract deprecated predicate row(string row);
|
||||
}
|
||||
|
||||
/**
|
||||
* A unit class for adding additional type model rows.
|
||||
*
|
||||
* Extend this class to add additional type definitions.
|
||||
*
|
||||
* DEPRECATED: Use the extensible predicate `typeModel` or the class
|
||||
* `TypeModel` instead.
|
||||
*/
|
||||
class TypeModelCsv extends Unit {
|
||||
deprecated class TypeModelCsv extends Unit {
|
||||
/**
|
||||
* Holds if `row` specifies a type definition.
|
||||
*
|
||||
@@ -152,7 +161,7 @@ module ModelInput {
|
||||
* ```
|
||||
* indicates that `(type2, path)` should be seen as an instance of `type1`.
|
||||
*/
|
||||
abstract predicate row(string row);
|
||||
abstract deprecated predicate row(string row);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -186,8 +195,10 @@ module ModelInput {
|
||||
|
||||
/**
|
||||
* A unit class for adding additional type variable model rows.
|
||||
*
|
||||
* DEPRECATED: Use the extensible predicate `typeVariableModel` instead.
|
||||
*/
|
||||
class TypeVariableModelCsv extends Unit {
|
||||
deprecated class TypeVariableModelCsv extends Unit {
|
||||
/**
|
||||
* Holds if `row` specifies a path through a type variable.
|
||||
*
|
||||
@@ -197,7 +208,7 @@ module ModelInput {
|
||||
* ```
|
||||
* means `path` can be substituted for a token `TypeVar[name]`.
|
||||
*/
|
||||
abstract predicate row(string row);
|
||||
abstract deprecated predicate row(string row);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -216,57 +227,121 @@ abstract class TestAllModels extends Unit { }
|
||||
* does not preserve empty trailing substrings.
|
||||
*/
|
||||
bindingset[result]
|
||||
private string inversePad(string s) { s = result + ";dummy" }
|
||||
deprecated private string inversePad(string s) { s = result + ";dummy" }
|
||||
|
||||
private predicate sourceModel(string row) { any(SourceModelCsv s).row(inversePad(row)) }
|
||||
deprecated private predicate sourceModel(string row) { any(SourceModelCsv s).row(inversePad(row)) }
|
||||
|
||||
private predicate sinkModel(string row) { any(SinkModelCsv s).row(inversePad(row)) }
|
||||
deprecated private predicate sinkModel(string row) { any(SinkModelCsv s).row(inversePad(row)) }
|
||||
|
||||
private predicate summaryModel(string row) { any(SummaryModelCsv s).row(inversePad(row)) }
|
||||
deprecated private predicate summaryModel(string row) {
|
||||
any(SummaryModelCsv s).row(inversePad(row))
|
||||
}
|
||||
|
||||
private predicate typeModel(string row) { any(TypeModelCsv s).row(inversePad(row)) }
|
||||
deprecated private predicate typeModel(string row) { any(TypeModelCsv s).row(inversePad(row)) }
|
||||
|
||||
private predicate typeVariableModel(string row) { any(TypeVariableModelCsv s).row(inversePad(row)) }
|
||||
deprecated private predicate typeVariableModel(string row) {
|
||||
any(TypeVariableModelCsv s).row(inversePad(row))
|
||||
}
|
||||
|
||||
private class DeprecationAdapter extends Unit {
|
||||
abstract predicate sourceModel(string type, string path, string kind);
|
||||
|
||||
abstract predicate sinkModel(string type, string path, string kind);
|
||||
|
||||
abstract predicate summaryModel(string type, string path, string input, string output, string kind);
|
||||
|
||||
abstract predicate typeModel(string type1, string type2, string path);
|
||||
|
||||
abstract predicate typeVariableModel(string name, string path);
|
||||
}
|
||||
|
||||
private class DeprecationAdapterImpl extends DeprecationAdapter {
|
||||
deprecated override predicate sourceModel(string type, string path, string kind) {
|
||||
exists(string row |
|
||||
sourceModel(row) and
|
||||
row.splitAt(";", 0) = type and
|
||||
row.splitAt(";", 1) = path and
|
||||
row.splitAt(";", 2) = kind
|
||||
)
|
||||
}
|
||||
|
||||
deprecated override predicate sinkModel(string type, string path, string kind) {
|
||||
exists(string row |
|
||||
sinkModel(row) and
|
||||
row.splitAt(";", 0) = type and
|
||||
row.splitAt(";", 1) = path and
|
||||
row.splitAt(";", 2) = kind
|
||||
)
|
||||
}
|
||||
|
||||
deprecated override predicate summaryModel(
|
||||
string type, string path, string input, string output, string kind
|
||||
) {
|
||||
exists(string row |
|
||||
summaryModel(row) and
|
||||
row.splitAt(";", 0) = type and
|
||||
row.splitAt(";", 1) = path and
|
||||
row.splitAt(";", 2) = input and
|
||||
row.splitAt(";", 3) = output and
|
||||
row.splitAt(";", 4) = kind
|
||||
)
|
||||
}
|
||||
|
||||
deprecated override predicate typeModel(string type1, string type2, string path) {
|
||||
exists(string row |
|
||||
typeModel(row) and
|
||||
row.splitAt(";", 0) = type1 and
|
||||
row.splitAt(";", 1) = type2 and
|
||||
row.splitAt(";", 2) = path
|
||||
)
|
||||
}
|
||||
|
||||
deprecated override predicate typeVariableModel(string name, string path) {
|
||||
exists(string row |
|
||||
typeVariableModel(row) and
|
||||
row.splitAt(";", 0) = name and
|
||||
row.splitAt(";", 1) = path
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
/** Holds if a source model exists for the given parameters. */
|
||||
predicate sourceModel(string type, string path, string kind) {
|
||||
exists(string row |
|
||||
sourceModel(row) and
|
||||
row.splitAt(";", 0) = type and
|
||||
row.splitAt(";", 1) = path and
|
||||
row.splitAt(";", 2) = kind
|
||||
)
|
||||
predicate sourceModel(string type, string path, string kind, string model) {
|
||||
any(DeprecationAdapter a).sourceModel(type, path, kind) and
|
||||
model = "SourceModelCsv"
|
||||
or
|
||||
Extensions::sourceModel(type, path, kind)
|
||||
exists(QlBuiltins::ExtensionId madId |
|
||||
Extensions::sourceModel(type, path, kind, madId) and
|
||||
model = "MaD:" + madId.toString()
|
||||
)
|
||||
}
|
||||
|
||||
/** Holds if a sink model exists for the given parameters. */
|
||||
private predicate sinkModel(string type, string path, string kind) {
|
||||
exists(string row |
|
||||
sinkModel(row) and
|
||||
row.splitAt(";", 0) = type and
|
||||
row.splitAt(";", 1) = path and
|
||||
row.splitAt(";", 2) = kind
|
||||
)
|
||||
private predicate sinkModel(string type, string path, string kind, string model) {
|
||||
any(DeprecationAdapter a).sinkModel(type, path, kind) and
|
||||
model = "SinkModelCsv"
|
||||
or
|
||||
Extensions::sinkModel(type, path, kind)
|
||||
exists(QlBuiltins::ExtensionId madId |
|
||||
Extensions::sinkModel(type, path, kind, madId) and
|
||||
model = "MaD:" + madId.toString()
|
||||
)
|
||||
}
|
||||
|
||||
/** Holds if a summary model `row` exists for the given parameters. */
|
||||
private predicate summaryModel(string type, string path, string input, string output, string kind) {
|
||||
exists(string row |
|
||||
summaryModel(row) and
|
||||
row.splitAt(";", 0) = type and
|
||||
row.splitAt(";", 1) = path and
|
||||
row.splitAt(";", 2) = input and
|
||||
row.splitAt(";", 3) = output and
|
||||
row.splitAt(";", 4) = kind
|
||||
)
|
||||
private predicate summaryModel(
|
||||
string type, string path, string input, string output, string kind, string model
|
||||
) {
|
||||
any(DeprecationAdapter a).summaryModel(type, path, input, output, kind) and
|
||||
model = "SummaryModelCsv"
|
||||
or
|
||||
Extensions::summaryModel(type, path, input, output, kind)
|
||||
exists(QlBuiltins::ExtensionId madId |
|
||||
Extensions::summaryModel(type, path, input, output, kind, madId) and
|
||||
model = "MaD:" + madId.toString()
|
||||
)
|
||||
}
|
||||
|
||||
/** Holds if a type model exists for the given parameters. */
|
||||
<<<<<<< HEAD
|
||||
predicate typeModel(string type1, string type2, string path) {
|
||||
exists(string row |
|
||||
typeModel(row) and
|
||||
@@ -274,29 +349,29 @@ predicate typeModel(string type1, string type2, string path) {
|
||||
row.splitAt(";", 1) = type2 and
|
||||
row.splitAt(";", 2) = path
|
||||
)
|
||||
=======
|
||||
private predicate typeModel(string type1, string type2, string path) {
|
||||
any(DeprecationAdapter a).typeModel(type1, type2, path)
|
||||
>>>>>>> main
|
||||
or
|
||||
Extensions::typeModel(type1, type2, path)
|
||||
}
|
||||
|
||||
/** Holds if a type variable model exists for the given parameters. */
|
||||
private predicate typeVariableModel(string name, string path) {
|
||||
exists(string row |
|
||||
typeVariableModel(row) and
|
||||
row.splitAt(";", 0) = name and
|
||||
row.splitAt(";", 1) = path
|
||||
)
|
||||
any(DeprecationAdapter a).typeVariableModel(name, path)
|
||||
or
|
||||
Extensions::typeVariableModel(name, path)
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if CSV rows involving `type` might be relevant for the analysis of this database.
|
||||
* Holds if rows involving `type` might be relevant for the analysis of this database.
|
||||
*/
|
||||
predicate isRelevantType(string type) {
|
||||
(
|
||||
sourceModel(type, _, _) or
|
||||
sinkModel(type, _, _) or
|
||||
summaryModel(type, _, _, _, _) or
|
||||
sourceModel(type, _, _, _) or
|
||||
sinkModel(type, _, _, _) or
|
||||
summaryModel(type, _, _, _, _, _) or
|
||||
typeModel(_, type, _)
|
||||
) and
|
||||
(
|
||||
@@ -313,26 +388,26 @@ predicate isRelevantType(string type) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if `type,path` is used in some CSV row.
|
||||
* Holds if `type,path` is used in some row.
|
||||
*/
|
||||
pragma[nomagic]
|
||||
predicate isRelevantFullPath(string type, string path) {
|
||||
isRelevantType(type) and
|
||||
(
|
||||
sourceModel(type, path, _) or
|
||||
sinkModel(type, path, _) or
|
||||
summaryModel(type, path, _, _, _) or
|
||||
sourceModel(type, path, _, _) or
|
||||
sinkModel(type, path, _, _) or
|
||||
summaryModel(type, path, _, _, _, _) or
|
||||
typeModel(_, type, path)
|
||||
)
|
||||
}
|
||||
|
||||
/** A string from a CSV row that should be parsed as an access path. */
|
||||
/** A string from a row that should be parsed as an access path. */
|
||||
private predicate accessPathRange(string s) {
|
||||
isRelevantFullPath(_, s)
|
||||
or
|
||||
exists(string type | isRelevantType(type) |
|
||||
summaryModel(type, _, s, _, _) or
|
||||
summaryModel(type, _, _, s, _)
|
||||
summaryModel(type, _, s, _, _, _) or
|
||||
summaryModel(type, _, _, s, _, _)
|
||||
)
|
||||
or
|
||||
typeVariableModel(_, s)
|
||||
@@ -543,7 +618,7 @@ private API::Node getNodeFromPath(string type, AccessPath path) {
|
||||
|
||||
pragma[nomagic]
|
||||
private predicate typeStepModel(string type, AccessPath basePath, AccessPath output) {
|
||||
summaryModel(type, basePath, "", output, "type")
|
||||
summaryModel(type, basePath, "", output, "type", _)
|
||||
}
|
||||
|
||||
pragma[nomagic]
|
||||
@@ -618,36 +693,36 @@ module ModelOutput {
|
||||
cached
|
||||
private module Cached {
|
||||
/**
|
||||
* Holds if a CSV source model contributed `source` with the given `kind`.
|
||||
* Holds if a source model contributed `source` with the given `kind`.
|
||||
*/
|
||||
cached
|
||||
API::Node getASourceNode(string kind) {
|
||||
API::Node getASourceNode(string kind, string model) {
|
||||
exists(string type, string path |
|
||||
sourceModel(type, path, kind) and
|
||||
sourceModel(type, path, kind, model) and
|
||||
result = getNodeFromPath(type, path)
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if a CSV sink model contributed `sink` with the given `kind`.
|
||||
* Holds if a sink model contributed `sink` with the given `kind`.
|
||||
*/
|
||||
cached
|
||||
API::Node getASinkNode(string kind) {
|
||||
API::Node getASinkNode(string kind, string model) {
|
||||
exists(string type, string path |
|
||||
sinkModel(type, path, kind) and
|
||||
sinkModel(type, path, kind, model) and
|
||||
result = getNodeFromPath(type, path)
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if a relevant CSV summary exists for these parameters.
|
||||
* Holds if a relevant summary exists for these parameters.
|
||||
*/
|
||||
cached
|
||||
predicate relevantSummaryModel(
|
||||
string type, string path, string input, string output, string kind
|
||||
string type, string path, string input, string output, string kind, string model
|
||||
) {
|
||||
isRelevantType(type) and
|
||||
summaryModel(type, path, input, output, kind)
|
||||
summaryModel(type, path, input, output, kind, model)
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -655,7 +730,7 @@ module ModelOutput {
|
||||
*/
|
||||
cached
|
||||
predicate resolvedSummaryBase(string type, string path, Specific::InvokeNode baseNode) {
|
||||
summaryModel(type, path, _, _, _) and
|
||||
summaryModel(type, path, _, _, _, _) and
|
||||
baseNode = getInvocationFromPath(type, path)
|
||||
}
|
||||
|
||||
@@ -664,13 +739,13 @@ module ModelOutput {
|
||||
*/
|
||||
cached
|
||||
predicate resolvedSummaryRefBase(string type, string path, API::Node baseNode) {
|
||||
summaryModel(type, path, _, _, _) and
|
||||
summaryModel(type, path, _, _, _, _) and
|
||||
baseNode = getNodeFromPath(type, path)
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if `node` is seen as an instance of `type` due to a type definition
|
||||
* contributed by a CSV model.
|
||||
* contributed by a model.
|
||||
*/
|
||||
cached
|
||||
API::Node getATypeNode(string type) { result = getNodeFromType(type) }
|
||||
@@ -680,12 +755,22 @@ module ModelOutput {
|
||||
import Specific::ModelOutputSpecific
|
||||
private import codeql.mad.ModelValidation as SharedModelVal
|
||||
|
||||
/**
|
||||
* Holds if a CSV source model contributed `source` with the given `kind`.
|
||||
*/
|
||||
API::Node getASourceNode(string kind) { result = getASourceNode(kind, _) }
|
||||
|
||||
/**
|
||||
* Holds if a CSV sink model contributed `sink` with the given `kind`.
|
||||
*/
|
||||
API::Node getASinkNode(string kind) { result = getASinkNode(kind, _) }
|
||||
|
||||
private module KindValConfig implements SharedModelVal::KindValidationConfigSig {
|
||||
predicate summaryKind(string kind) { summaryModel(_, _, _, _, kind) }
|
||||
predicate summaryKind(string kind) { summaryModel(_, _, _, _, kind, _) }
|
||||
|
||||
predicate sinkKind(string kind) { sinkModel(_, _, kind) }
|
||||
predicate sinkKind(string kind) { sinkModel(_, _, kind, _) }
|
||||
|
||||
predicate sourceKind(string kind) { sourceModel(_, _, kind) }
|
||||
predicate sourceKind(string kind) { sourceModel(_, _, kind, _) }
|
||||
}
|
||||
|
||||
private module KindVal = SharedModelVal::KindValidation<KindValConfig>;
|
||||
@@ -694,25 +779,6 @@ module ModelOutput {
|
||||
* Gets an error message relating to an invalid CSV row in a model.
|
||||
*/
|
||||
string getAWarning() {
|
||||
// Check number of columns
|
||||
exists(string row, string kind, int expectedArity, int actualArity |
|
||||
any(SourceModelCsv csv).row(row) and kind = "source" and expectedArity = 3
|
||||
or
|
||||
any(SinkModelCsv csv).row(row) and kind = "sink" and expectedArity = 3
|
||||
or
|
||||
any(SummaryModelCsv csv).row(row) and kind = "summary" and expectedArity = 5
|
||||
or
|
||||
any(TypeModelCsv csv).row(row) and kind = "type" and expectedArity = 3
|
||||
or
|
||||
any(TypeVariableModelCsv csv).row(row) and kind = "type-variable" and expectedArity = 2
|
||||
|
|
||||
actualArity = count(row.indexOf(";")) + 1 and
|
||||
actualArity != expectedArity and
|
||||
result =
|
||||
"CSV " + kind + " row should have " + expectedArity + " columns but has " + actualArity +
|
||||
": " + row
|
||||
)
|
||||
or
|
||||
// Check names and arguments of access path tokens
|
||||
exists(AccessPath path, AccessPathToken token |
|
||||
(isRelevantFullPath(_, path) or typeVariableModel(_, path)) and
|
||||
|
||||
@@ -8,13 +8,15 @@
|
||||
*
|
||||
* The kind `remote` represents a general remote flow source.
|
||||
*/
|
||||
extensible predicate sourceModel(string type, string path, string kind);
|
||||
extensible predicate sourceModel(
|
||||
string type, string path, string kind, QlBuiltins::ExtensionId madId
|
||||
);
|
||||
|
||||
/**
|
||||
* Holds if the value at `(type, path)` should be seen as a sink
|
||||
* of the given `kind`.
|
||||
*/
|
||||
extensible predicate sinkModel(string type, string path, string kind);
|
||||
extensible predicate sinkModel(string type, string path, string kind, QlBuiltins::ExtensionId madId);
|
||||
|
||||
/**
|
||||
* Holds if in calls to `(type, path)`, the value referred to by `input`
|
||||
@@ -23,7 +25,9 @@ extensible predicate sinkModel(string type, string path, string kind);
|
||||
* `kind` should be either `value` or `taint`, for value-preserving or taint-preserving steps,
|
||||
* respectively.
|
||||
*/
|
||||
extensible predicate summaryModel(string type, string path, string input, string output, string kind);
|
||||
extensible predicate summaryModel(
|
||||
string type, string path, string input, string output, string kind, QlBuiltins::ExtensionId madId
|
||||
);
|
||||
|
||||
/**
|
||||
* Holds if calls to `(type, path)` should be considered neutral. The meaning of this depends on the `kind`.
|
||||
|
||||
34
ruby/ql/lib/codeql/ruby/frameworks/stdlib/Pathname.model.yml
Normal file
34
ruby/ql/lib/codeql/ruby/frameworks/stdlib/Pathname.model.yml
Normal file
@@ -0,0 +1,34 @@
|
||||
extensions:
|
||||
- addsTo:
|
||||
pack: codeql/ruby-all
|
||||
extensible: summaryModel
|
||||
data:
|
||||
- ['Pathname!', 'Method[new]', 'Argument[0]', 'ReturnValue', 'taint']
|
||||
- ['Pathname', 'Method[basename]', 'Argument[self]', 'ReturnValue', 'taint']
|
||||
- ['Pathname', 'Method[cleanpath]', 'Argument[self]', 'ReturnValue', 'taint']
|
||||
- ['Pathname', 'Method[dirname]', 'Argument[self]', 'ReturnValue', 'taint']
|
||||
- ['Pathname', 'Method[each_filename]', 'Argument[self]', 'Argument[block].Parameter[0]', 'taint']
|
||||
- ['Pathname', 'Method[expand_path]', 'Argument[self]', 'ReturnValue', 'taint']
|
||||
- ['Pathname', 'Method[join]', 'Argument[self,any]', 'ReturnValue', 'taint']
|
||||
- ['Pathname', 'Method[parent]', 'Argument[self]', 'ReturnValue', 'taint']
|
||||
- ['Pathname', 'Method[realpath]', 'Argument[self]', 'ReturnValue', 'taint']
|
||||
- ['Pathname', 'Method[relative_path_from]', 'Argument[self]', 'ReturnValue', 'taint']
|
||||
- ['Pathname', 'Method[sub]', 'Argument[self]', 'ReturnValue', 'taint']
|
||||
- ['Pathname', 'Method[sub_ext]', 'Argument[self]', 'ReturnValue', 'taint']
|
||||
- ['Pathname', 'Method[to_path]', 'Argument[self]', 'ReturnValue', 'taint']
|
||||
|
||||
- addsTo:
|
||||
pack: codeql/ruby-all
|
||||
extensible: typeModel
|
||||
data:
|
||||
- ['Pathname', 'Pathname', 'Method[+].ReturnValue']
|
||||
- ['Pathname', 'Pathname', 'Method[/].ReturnValue']
|
||||
- ['Pathname', 'Pathname', 'Method[basename].ReturnValue']
|
||||
- ['Pathname', 'Pathname', 'Method[cleanpath].ReturnValue']
|
||||
- ['Pathname', 'Pathname', 'Method[expand_path].ReturnValue']
|
||||
- ['Pathname', 'Pathname', 'Method[join].ReturnValue']
|
||||
- ['Pathname', 'Pathname', 'Method[realpath].ReturnValue']
|
||||
- ['Pathname', 'Pathname', 'Method[relative_path_from].ReturnValue']
|
||||
- ['Pathname', 'Pathname', 'Method[sub].ReturnValue']
|
||||
- ['Pathname', 'Pathname', 'Method[sub_ext].ReturnValue']
|
||||
- ['Pathname', 'Pathname', 'Method[to_path].ReturnValue']
|
||||
@@ -116,74 +116,4 @@ module Pathname {
|
||||
|
||||
override DataFlow::Node getAPermissionNode() { result = permissionArg }
|
||||
}
|
||||
|
||||
/**
|
||||
* Type summaries for the `Pathname` class, i.e. method calls that produce new
|
||||
* `Pathname` instances.
|
||||
*/
|
||||
private class PathnameTypeSummary extends ModelInput::TypeModelCsv {
|
||||
override predicate row(string row) {
|
||||
// type1;type2;path
|
||||
row =
|
||||
[
|
||||
// Pathname#+(path) : Pathname
|
||||
"Pathname;Pathname;Method[+].ReturnValue",
|
||||
// Pathname#/(path) : Pathname
|
||||
"Pathname;Pathname;Method[/].ReturnValue",
|
||||
// Pathname#basename(path) : Pathname
|
||||
"Pathname;Pathname;Method[basename].ReturnValue",
|
||||
// Pathname#cleanpath(path) : Pathname
|
||||
"Pathname;Pathname;Method[cleanpath].ReturnValue",
|
||||
// Pathname#expand_path(path) : Pathname
|
||||
"Pathname;Pathname;Method[expand_path].ReturnValue",
|
||||
// Pathname#join(path) : Pathname
|
||||
"Pathname;Pathname;Method[join].ReturnValue",
|
||||
// Pathname#realpath(path) : Pathname
|
||||
"Pathname;Pathname;Method[realpath].ReturnValue",
|
||||
// Pathname#relative_path_from(path) : Pathname
|
||||
"Pathname;Pathname;Method[relative_path_from].ReturnValue",
|
||||
// Pathname#sub(path) : Pathname
|
||||
"Pathname;Pathname;Method[sub].ReturnValue",
|
||||
// Pathname#sub_ext(path) : Pathname
|
||||
"Pathname;Pathname;Method[sub_ext].ReturnValue",
|
||||
// Pathname#to_path(path) : Pathname
|
||||
"Pathname;Pathname;Method[to_path].ReturnValue",
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
/** Taint flow summaries for the `Pathname` class. */
|
||||
private class PathnameTaintSummary extends ModelInput::SummaryModelCsv {
|
||||
override predicate row(string row) {
|
||||
row =
|
||||
[
|
||||
// Pathname.new(path)
|
||||
"Pathname!;Method[new];Argument[0];ReturnValue;taint",
|
||||
// Pathname#dirname
|
||||
"Pathname;Method[dirname];Argument[self];ReturnValue;taint",
|
||||
// Pathname#each_filename
|
||||
"Pathname;Method[each_filename];Argument[self];Argument[block].Parameter[0];taint",
|
||||
// Pathname#expand_path
|
||||
"Pathname;Method[expand_path];Argument[self];ReturnValue;taint",
|
||||
// Pathname#join
|
||||
"Pathname;Method[join];Argument[self,any];ReturnValue;taint",
|
||||
// Pathname#parent
|
||||
"Pathname;Method[parent];Argument[self];ReturnValue;taint",
|
||||
// Pathname#realpath
|
||||
"Pathname;Method[realpath];Argument[self];ReturnValue;taint",
|
||||
// Pathname#relative_path_from
|
||||
"Pathname;Method[relative_path_from];Argument[self];ReturnValue;taint",
|
||||
// Pathname#to_path
|
||||
"Pathname;Method[to_path];Argument[self];ReturnValue;taint",
|
||||
// Pathname#basename
|
||||
"Pathname;Method[basename];Argument[self];ReturnValue;taint",
|
||||
// Pathname#cleanpath
|
||||
"Pathname;Method[cleanpath];Argument[self];ReturnValue;taint",
|
||||
// Pathname#sub
|
||||
"Pathname;Method[sub];Argument[self];ReturnValue;taint",
|
||||
// Pathname#sub_ext
|
||||
"Pathname;Method[sub_ext];Argument[self];ReturnValue;taint",
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,7 +16,7 @@ module CodeInjection {
|
||||
module FlowState {
|
||||
/**
|
||||
* Flow state used for normal tainted data, where an attacker might only control a substring.
|
||||
* DEPRECATED: Use `Full()`
|
||||
* DEPRECATED: Use `SubString()`
|
||||
*/
|
||||
deprecated DataFlow::FlowState substring() { result = "substring" }
|
||||
|
||||
|
||||
@@ -38,7 +38,7 @@ deprecated class Configuration extends DataFlow::Configuration {
|
||||
DataFlow::Node nodeFrom, DataFlow::FlowState stateFrom, DataFlow::Node nodeTo,
|
||||
DataFlow::FlowState stateTo
|
||||
) {
|
||||
defaultAdditionalTaintStep(nodeFrom, nodeTo) and
|
||||
defaultAdditionalTaintStep(nodeFrom, nodeTo, _) and
|
||||
// This is a taint step, so the flow state becomes `taint`.
|
||||
stateFrom = [FlowState::data(), FlowState::taint()] and
|
||||
stateTo = FlowState::taint()
|
||||
@@ -57,7 +57,7 @@ private module Config implements DataFlow::StateConfigSig {
|
||||
predicate isAdditionalFlowStep(
|
||||
DataFlow::Node nodeFrom, FlowState stateFrom, DataFlow::Node nodeTo, FlowState stateTo
|
||||
) {
|
||||
defaultAdditionalTaintStep(nodeFrom, nodeTo) and
|
||||
defaultAdditionalTaintStep(nodeFrom, nodeTo, _) and // TODO: propagate provenance
|
||||
// This is a taint step, so the flow state becomes `taint`.
|
||||
(
|
||||
stateFrom = FlowState::Taint()
|
||||
|
||||
@@ -0,0 +1,98 @@
|
||||
/**
|
||||
* Provides default sources, sinks, sanitizers, and flow steps for
|
||||
* detecting insecure mass assignment, as well as extension points for adding your own.
|
||||
*/
|
||||
|
||||
private import codeql.ruby.AST
|
||||
private import codeql.ruby.controlflow.CfgNodes
|
||||
private import codeql.ruby.DataFlow
|
||||
private import codeql.ruby.TaintTracking
|
||||
private import codeql.ruby.dataflow.RemoteFlowSources
|
||||
|
||||
/**
|
||||
* Provides default sources, sinks, sanitizers, and flow steps for
|
||||
* detecting insecure mass assignment, as well as extension points for adding your own.
|
||||
*/
|
||||
module MassAssignment {
|
||||
/**
|
||||
* A data flow source for user input used for mass assignment.
|
||||
*/
|
||||
abstract class Source extends DataFlow::Node { }
|
||||
|
||||
/**
|
||||
* A data flow sink for user input used for mass assignment.
|
||||
*/
|
||||
abstract class Sink extends DataFlow::Node { }
|
||||
|
||||
/**
|
||||
* A sanitizer for insecure mass assignment.
|
||||
*/
|
||||
abstract class Sanitizer extends DataFlow::Node { }
|
||||
|
||||
/**
|
||||
* A call that permits arbitrary parameters to be used for mass assignment.
|
||||
*/
|
||||
abstract class MassPermit extends DataFlow::Node {
|
||||
/** Gets the argument for the parameters to be permitted. */
|
||||
abstract DataFlow::Node getParamsArgument();
|
||||
|
||||
/** Gets the result node of the permitted parameters. */
|
||||
abstract DataFlow::Node getPermittedParamsResult();
|
||||
}
|
||||
|
||||
private class RemoteSource extends Source instanceof RemoteFlowSource { }
|
||||
|
||||
/** A call to `permit!`, which permits each key of its receiver. */
|
||||
private class PermitBangCall extends MassPermit instanceof DataFlow::CallNode {
|
||||
PermitBangCall() { this.(DataFlow::CallNode).getMethodName() = "permit!" }
|
||||
|
||||
override DataFlow::Node getParamsArgument() { result = this.(DataFlow::CallNode).getReceiver() }
|
||||
|
||||
override DataFlow::Node getPermittedParamsResult() {
|
||||
result = this
|
||||
or
|
||||
result.(DataFlow::PostUpdateNode).getPreUpdateNode() = this.getParamsArgument()
|
||||
}
|
||||
}
|
||||
|
||||
/** Holds if `h` is an empty hash or contains an empty hash at one if its (possibly nested) values. */
|
||||
private predicate hasEmptyHash(ExprCfgNode e) {
|
||||
e instanceof ExprNodes::HashLiteralCfgNode and
|
||||
not exists(e.(ExprNodes::HashLiteralCfgNode).getAKeyValuePair())
|
||||
or
|
||||
hasEmptyHash(e.(ExprNodes::HashLiteralCfgNode).getAKeyValuePair().getValue())
|
||||
or
|
||||
hasEmptyHash(e.(ExprNodes::PairCfgNode).getValue())
|
||||
or
|
||||
hasEmptyHash(e.(ExprNodes::ArrayLiteralCfgNode).getAnArgument())
|
||||
}
|
||||
|
||||
/** A call to `permit` that fully specifies the permitted parameters. */
|
||||
private class PermitCallSanitizer extends Sanitizer, DataFlow::CallNode {
|
||||
PermitCallSanitizer() {
|
||||
this.getMethodName() = "permit" and
|
||||
not hasEmptyHash(this.getArgument(_).getExprNode())
|
||||
}
|
||||
}
|
||||
|
||||
/** A call to `permit` that uses an empty hash, which allows arbitrary keys to be specified. */
|
||||
private class PermitCallMassPermit extends MassPermit instanceof DataFlow::CallNode {
|
||||
PermitCallMassPermit() {
|
||||
this.(DataFlow::CallNode).getMethodName() = "permit" and
|
||||
hasEmptyHash(this.(DataFlow::CallNode).getArgument(_).getExprNode())
|
||||
}
|
||||
|
||||
override DataFlow::Node getParamsArgument() { result = this.(DataFlow::CallNode).getReceiver() }
|
||||
|
||||
override DataFlow::Node getPermittedParamsResult() { result = this }
|
||||
}
|
||||
|
||||
/** A call to `to_unsafe_h`, which allows arbitrary parameter. */
|
||||
private class ToUnsafeHashCall extends MassPermit instanceof DataFlow::CallNode {
|
||||
ToUnsafeHashCall() { this.(DataFlow::CallNode).getMethodName() = "to_unsafe_h" }
|
||||
|
||||
override DataFlow::Node getParamsArgument() { result = this.(DataFlow::CallNode).getReceiver() }
|
||||
|
||||
override DataFlow::Node getPermittedParamsResult() { result = this }
|
||||
}
|
||||
}
|
||||
65
ruby/ql/lib/codeql/ruby/security/MassAssignmentQuery.qll
Normal file
65
ruby/ql/lib/codeql/ruby/security/MassAssignmentQuery.qll
Normal file
@@ -0,0 +1,65 @@
|
||||
/**
|
||||
* Provides a taint tracking configuration for reasoning about insecure mass assignment.
|
||||
*/
|
||||
|
||||
private import codeql.ruby.AST
|
||||
private import codeql.ruby.DataFlow
|
||||
private import codeql.ruby.TaintTracking
|
||||
private import codeql.ruby.dataflow.RemoteFlowSources
|
||||
private import MassAssignmentCustomizations
|
||||
|
||||
private module FlowState {
|
||||
private newtype TState =
|
||||
TUnpermitted() or
|
||||
TPermitted()
|
||||
|
||||
/** A flow state used to distinguish whether arbitrary user parameters have been permitted to be used for mass assignment. */
|
||||
class State extends TState {
|
||||
string toString() {
|
||||
this = TUnpermitted() and result = "unpermitted"
|
||||
or
|
||||
this = TPermitted() and result = "permitted"
|
||||
}
|
||||
}
|
||||
|
||||
/** A flow state used for user parameters for which arbitrary parameters have not been permitted to use for mass assignment. */
|
||||
class Unpermitted extends State, TUnpermitted { }
|
||||
|
||||
/** A flow state used for user parameters for which arbitrary parameters have been permitted to use for mass assignment. */
|
||||
class Permitted extends State, TPermitted { }
|
||||
}
|
||||
|
||||
/** A flow configuration for reasoning about insecure mass assignment. */
|
||||
private module Config implements DataFlow::StateConfigSig {
|
||||
class FlowState = FlowState::State;
|
||||
|
||||
predicate isSource(DataFlow::Node node, FlowState state) {
|
||||
node instanceof MassAssignment::Source and
|
||||
state instanceof FlowState::Unpermitted
|
||||
}
|
||||
|
||||
predicate isSink(DataFlow::Node node, FlowState state) {
|
||||
node instanceof MassAssignment::Sink and
|
||||
state instanceof FlowState::Permitted
|
||||
}
|
||||
|
||||
predicate isBarrierIn(DataFlow::Node node, FlowState state) { isSource(node, state) }
|
||||
|
||||
predicate isBarrierOut(DataFlow::Node node, FlowState state) { isSink(node, state) }
|
||||
|
||||
predicate isBarrier(DataFlow::Node node) { node instanceof MassAssignment::Sanitizer }
|
||||
|
||||
predicate isAdditionalFlowStep(
|
||||
DataFlow::Node node1, FlowState state1, DataFlow::Node node2, FlowState state2
|
||||
) {
|
||||
exists(MassAssignment::MassPermit permit |
|
||||
node1 = permit.getParamsArgument() and
|
||||
state1 instanceof FlowState::Unpermitted and
|
||||
node2 = permit.getPermittedParamsResult() and
|
||||
state2 instanceof FlowState::Permitted
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
/** Taint tracking for reasoning about user input used for mass assignment. */
|
||||
module MassAssignmentFlow = TaintTracking::GlobalWithState<Config>;
|
||||
@@ -46,12 +46,6 @@ private module UnsafeCodeConstructionConfig implements DataFlow::ConfigSig {
|
||||
|
||||
// override to require the path doesn't have unmatched return steps
|
||||
DataFlow::FlowFeature getAFeature() { result instanceof DataFlow::FeatureHasSourceCallContext }
|
||||
|
||||
predicate allowImplicitRead(DataFlow::Node node, DataFlow::ContentSet set) {
|
||||
// allow implicit reads of array elements
|
||||
isSink(node) and
|
||||
set.isElementOfTypeOrUnknown("int")
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -49,12 +49,6 @@ private module UnsafeShellCommandConstructionConfig implements DataFlow::ConfigS
|
||||
|
||||
// override to require the path doesn't have unmatched return steps
|
||||
DataFlow::FlowFeature getAFeature() { result instanceof DataFlow::FeatureHasSourceCallContext }
|
||||
|
||||
predicate allowImplicitRead(DataFlow::Node node, DataFlow::ContentSet set) {
|
||||
// allow implicit reads of array elements
|
||||
isSink(node) and
|
||||
set.isElementOfTypeOrUnknown("int")
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -83,6 +83,12 @@ module UrlRedirect {
|
||||
*/
|
||||
class StringConstCompareAsSanitizer extends Sanitizer, StringConstCompareBarrier { }
|
||||
|
||||
/**
|
||||
* A string concatenation against a constant list, considered as a sanitizer-guard.
|
||||
*/
|
||||
class StringConstArrayInclusionAsSanitizer extends Sanitizer, StringConstArrayInclusionCallBarrier
|
||||
{ }
|
||||
|
||||
/**
|
||||
* Some methods will propagate taint to their return values.
|
||||
* Here we cover a few common ones related to `ActionController::Parameters`.
|
||||
|
||||
@@ -217,7 +217,15 @@ private module SummaryTypeTrackerInput implements SummaryTypeTracker::Input {
|
||||
predicate return = FlowSummaryImpl::Private::SummaryComponent::return/0;
|
||||
|
||||
// Callables
|
||||
class SummarizedCallable = FlowSummaryImpl::Private::SummarizedCallableImpl;
|
||||
class SummarizedCallable instanceof FlowSummaryImpl::Private::SummarizedCallableImpl {
|
||||
string toString() { result = super.toString() }
|
||||
|
||||
predicate propagatesFlow(
|
||||
SummaryComponentStack input, SummaryComponentStack output, boolean preservesValue
|
||||
) {
|
||||
super.propagatesFlow(input, output, preservesValue, _)
|
||||
}
|
||||
}
|
||||
|
||||
// Relating nodes to summaries
|
||||
Node argumentOf(Node call, SummaryComponent arg, boolean isPostUpdate) {
|
||||
|
||||
@@ -15,4 +15,5 @@ dependencies:
|
||||
codeql/util: ${workspace}
|
||||
dataExtensions:
|
||||
- codeql/ruby/frameworks/**/model.yml
|
||||
- codeql/ruby/frameworks/**/*.model.yml
|
||||
warnOnImplicitThis: true
|
||||
|
||||
4
ruby/ql/src/change-notes/2024-03-22-mass-assignment.md
Normal file
4
ruby/ql/src/change-notes/2024-03-22-mass-assignment.md
Normal file
@@ -0,0 +1,4 @@
|
||||
---
|
||||
category: newQuery
|
||||
---
|
||||
* Added a new query, `rb/insecure-mass-assignment`, for finding instances of mass assignment operations accepting arbitrary parameters from remote user input.
|
||||
@@ -20,10 +20,15 @@
|
||||
<recommendation>
|
||||
|
||||
<p>
|
||||
If possible, provide the dynamic arguments to the shell as an array
|
||||
If possible, avoid concatenating shell strings
|
||||
to APIs such as <code>system(..)</code> to avoid interpretation by the shell.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
Instead, provide the arguments to the shell command as separate arguments to the
|
||||
API, such as <code>system("echo", arg1, arg2)</code>.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
Alternatively, if the shell command must be constructed
|
||||
dynamically, then add code to ensure that special characters
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
module Utils
|
||||
def download(path)
|
||||
# using an array to call `system` is safe
|
||||
# using an API that doesn't interpret the path as a shell command
|
||||
system("wget", path) # OK
|
||||
end
|
||||
end
|
||||
@@ -1,44 +1,68 @@
|
||||
<!DOCTYPE qhelp PUBLIC "-//Semmle//qhelp//EN" "qhelp.dtd">
|
||||
<!DOCTYPE qhelp PUBLIC
|
||||
"-//Semmle//qhelp//EN"
|
||||
"qhelp.dtd">
|
||||
<qhelp>
|
||||
|
||||
|
||||
<overview>
|
||||
<p>
|
||||
Directly incorporating user input into a URL redirect request without validating the input
|
||||
<p>Directly incorporating user input into a URL redirect request without validating the input
|
||||
can facilitate phishing attacks. In these attacks, unsuspecting users can be redirected to a
|
||||
malicious site that looks very similar to the real site they intend to visit, but which is
|
||||
controlled by the attacker.
|
||||
</p>
|
||||
</overview>
|
||||
controlled by the attacker.</p>
|
||||
|
||||
</overview>
|
||||
<recommendation>
|
||||
<p>
|
||||
To guard against untrusted URL redirection, it is advisable to avoid putting user input
|
||||
|
||||
<p>To guard against untrusted URL redirection, it is advisable to avoid putting user input
|
||||
directly into a redirect URL. Instead, maintain a list of authorized
|
||||
redirects on the server; then choose from that list based on the user input provided.
|
||||
redirects on the server; then choose from that list based on the user input provided.</p>
|
||||
<p>
|
||||
If this is not possible, then the user input should be validated in some other way,
|
||||
for example, by verifying that the target URL is on the same host as the current page.
|
||||
</p>
|
||||
</recommendation>
|
||||
|
||||
|
||||
<example>
|
||||
<p>
|
||||
The following example shows an HTTP request parameter being used directly in a URL redirect
|
||||
without validating the input, which facilitates phishing attacks:
|
||||
</p>
|
||||
|
||||
<sample src="examples/redirect_bad.rb"/>
|
||||
<sample src="examples/url_redirect.rb"/>
|
||||
|
||||
<p>
|
||||
One way to remedy the problem is to validate the user input against a known fixed string
|
||||
One way to remedy the problem is to validate the user input against a set of known fixed strings
|
||||
before doing the redirection:
|
||||
</p>
|
||||
|
||||
<sample src="examples/redirect_good.rb"/>
|
||||
<sample src="examples/url_redirect_good.rb"/>
|
||||
|
||||
<p>
|
||||
Alternatively, we can check that the target URL does not redirect to a different host
|
||||
by checking that the URL is either relative or on a known good host:
|
||||
</p>
|
||||
|
||||
<sample src="examples/url_redirect_domain.rb"/>
|
||||
|
||||
<p>
|
||||
Note that as written, the above code will allow redirects to URLs on <code>example.com</code>,
|
||||
which is harmless but perhaps not intended. You can substitute your own domain (if known) for
|
||||
<code>example.com</code> to prevent this.
|
||||
</p>
|
||||
|
||||
</example>
|
||||
|
||||
<references>
|
||||
<li>OWASP: <a href="https://cheatsheetseries.owasp.org/cheatsheets/Unvalidated_Redirects_and_Forwards_Cheat_Sheet.html">
|
||||
XSS Unvalidated Redirects and Forwards Cheat Sheet</a>.</li>
|
||||
<li>Rails Guides: <a href="https://guides.rubyonrails.org/security.html#redirection-and-files">
|
||||
Redirection and Files</a>.</li>
|
||||
</references>
|
||||
|
||||
<li>
|
||||
OWASP:
|
||||
<a href="https://cheatsheetseries.owasp.org/cheatsheets/Unvalidated_Redirects_and_Forwards_Cheat_Sheet.html">
|
||||
Unvalidated Redirects and Forwards Cheat Sheet</a>.
|
||||
</li>
|
||||
<li>
|
||||
Rails Guides: <a href="https://guides.rubyonrails.org/security.html#redirection-and-files">Redirection and Files</a>.
|
||||
</li>
|
||||
|
||||
</references>
|
||||
</qhelp>
|
||||
|
||||
@@ -1,11 +0,0 @@
|
||||
class HelloController < ActionController::Base
|
||||
VALID_REDIRECT = "http://cwe.mitre.org/data/definitions/601.html"
|
||||
|
||||
def hello
|
||||
if params[:url] == VALID_REDIRECT
|
||||
redirect_to params[:url]
|
||||
else
|
||||
# error
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -0,0 +1,21 @@
|
||||
require 'uri'
|
||||
|
||||
class HelloController < ActionController::Base
|
||||
KNOWN_HOST = "example.org"
|
||||
|
||||
def hello
|
||||
begin
|
||||
target_url = URI.parse(params[:url])
|
||||
|
||||
# Redirect if the URL is either relative or on a known good host
|
||||
if !target_url.host || target_url.host == KNOWN_HOST
|
||||
redirect_to target_url.to_s
|
||||
else
|
||||
redirect_to "/error.html" # Redirect to error page if the host is not known
|
||||
end
|
||||
rescue URI::InvalidURIError
|
||||
# Handle the exception, for example, by redirecting to a safe page
|
||||
redirect_to "/error.html"
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -0,0 +1,16 @@
|
||||
class HelloController < ActionController::Base
|
||||
VALID_REDIRECTS = [
|
||||
"http://cwe.mitre.org/data/definitions/601.html",
|
||||
"http://cwe.mitre.org/data/definitions/79.html"
|
||||
].freeze
|
||||
|
||||
def hello
|
||||
# GOOD: the request parameter is validated against a known list of URLs
|
||||
target_url = params[:url]
|
||||
if VALID_REDIRECTS.include?(target_url)
|
||||
redirect_to target_url
|
||||
else
|
||||
redirect_to "/error.html"
|
||||
end
|
||||
end
|
||||
end
|
||||
34
ruby/ql/src/queries/security/cwe-915/MassAssignment.qhelp
Normal file
34
ruby/ql/src/queries/security/cwe-915/MassAssignment.qhelp
Normal file
@@ -0,0 +1,34 @@
|
||||
<!DOCTYPE qhelp PUBLIC
|
||||
"-//Semmle//qhelp//EN"
|
||||
"qhelp.dtd">
|
||||
<qhelp>
|
||||
<overview>
|
||||
<p>
|
||||
Operations that allow for mass assignment (setting multiple attributes of an object using a hash), such as <code>ActiveRecord::Base.new</code>, should take care not to
|
||||
allow arbitrary parameters to be set by the user. Otherwise, unintended attributes may be set, such as an <code>is_admin</code> field for a <code>User</code> object.
|
||||
</p>
|
||||
</overview>
|
||||
<recommendation>
|
||||
<p>
|
||||
When using a mass assignment operation from user supplied parameters, use <code>ActionController::Parameters#permit</code> to restrict the possible parameters
|
||||
a user can supply, rather than <code>ActionController::Parameters#permit!</code>, which permits arbitrary parameters to be used for mass assignment.
|
||||
</p>
|
||||
</recommendation>
|
||||
<example>
|
||||
<p>
|
||||
In the following example, <code>permit!</code> is used which allows arbitrary parameters to be supplied by the user.
|
||||
</p>
|
||||
<sample src="examples/MassAssignmentBad.rb" />
|
||||
<p>
|
||||
|
||||
</p>
|
||||
<p>
|
||||
In the following example, only specific parameters are permitted, so the mass assignment is safe.
|
||||
</p>
|
||||
<sample src="examples/MassAssignmentGood.rb" />
|
||||
</example>
|
||||
|
||||
<references>
|
||||
<li>Rails guides: <a href="https://guides.rubyonrails.org/action_controller_overview.html#strong-parameters">Strong Parameters</a>.</li>
|
||||
</references>
|
||||
</qhelp>
|
||||
20
ruby/ql/src/queries/security/cwe-915/MassAssignment.ql
Normal file
20
ruby/ql/src/queries/security/cwe-915/MassAssignment.ql
Normal file
@@ -0,0 +1,20 @@
|
||||
/**
|
||||
* @name Insecure Mass Assignment
|
||||
* @description Using mass assignment with user-controlled attributes allows unintended parameters to be set.
|
||||
* @kind path-problem
|
||||
* @problem.severity error
|
||||
* @security-severity 9.8
|
||||
* @precision high
|
||||
* @id rb/insecure-mass-assignment
|
||||
* @tags security
|
||||
* external/cwe/cwe-915
|
||||
*/
|
||||
|
||||
import codeql.ruby.security.MassAssignmentQuery
|
||||
import MassAssignmentFlow::PathGraph
|
||||
|
||||
from MassAssignmentFlow::PathNode source, MassAssignmentFlow::PathNode sink
|
||||
where MassAssignmentFlow::flowPath(source, sink)
|
||||
select sink.getNode(), source, sink,
|
||||
"This mass assignment operation can assign user-controlled attributes from $@.", source.getNode(),
|
||||
"this remote flow source"
|
||||
@@ -0,0 +1,10 @@
|
||||
class UserController < ActionController::Base
|
||||
def create
|
||||
# BAD: arbitrary params are permitted to be used for this assignment
|
||||
User.new(user_params).save!
|
||||
end
|
||||
|
||||
def user_params
|
||||
params.require(:user).permit!
|
||||
end
|
||||
end
|
||||
@@ -0,0 +1,10 @@
|
||||
class UserController < ActionController::Base
|
||||
def create
|
||||
# GOOD: the permitted parameters are explicitly specified
|
||||
User.new(user_params).save!
|
||||
end
|
||||
|
||||
def user_params
|
||||
params.require(:user).permit(:name, :email)
|
||||
end
|
||||
end
|
||||
@@ -179,7 +179,7 @@ class SinkCallable extends DataFlow::MethodNode {
|
||||
exists(string type, string path, string method |
|
||||
method = path.regexpCapture("(Method\\[[^\\]]+\\]).*", 1) and
|
||||
Util::pathToMethod(this, type, method) and
|
||||
sinkModel(type, path, _)
|
||||
sinkModel(type, path, _, _)
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -192,7 +192,7 @@ class SourceCallable extends DataFlow::CallableNode {
|
||||
exists(string type, string path, string method |
|
||||
method = path.regexpCapture("(Method\\[[^\\]]+\\]).*", 1) and
|
||||
Util::pathToMethod(this, type, method) and
|
||||
sourceModel(type, path, _)
|
||||
sourceModel(type, path, _, _)
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -204,7 +204,7 @@ class SummaryCallable extends DataFlow::CallableNode {
|
||||
SummaryCallable() {
|
||||
exists(string type, string path |
|
||||
Util::pathToMethod(this, type, path) and
|
||||
summaryModel(type, path, _, _, _)
|
||||
summaryModel(type, path, _, _, _, _)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -30,6 +30,7 @@ edges
|
||||
| call_sensitivity.rb:70:30:70:30 | x | call_sensitivity.rb:71:10:71:10 | x | provenance | |
|
||||
| call_sensitivity.rb:74:18:74:18 | y | call_sensitivity.rb:75:20:77:7 | do ... end [captured y] | provenance | |
|
||||
| call_sensitivity.rb:75:20:77:7 | do ... end [captured y] | call_sensitivity.rb:76:17:76:17 | y | provenance | |
|
||||
| call_sensitivity.rb:75:20:77:7 | do ... end [captured y] | call_sensitivity.rb:76:17:76:17 | y | provenance | heuristic-callback |
|
||||
| call_sensitivity.rb:76:17:76:17 | y | call_sensitivity.rb:50:15:50:15 | x | provenance | |
|
||||
| call_sensitivity.rb:80:15:80:15 | x | call_sensitivity.rb:81:18:81:18 | x | provenance | |
|
||||
| call_sensitivity.rb:81:18:81:18 | x | call_sensitivity.rb:50:15:50:15 | x | provenance | |
|
||||
|
||||
@@ -10,11 +10,11 @@ edges
|
||||
| captured_variables.rb:20:25:20:34 | call to taint | captured_variables.rb:15:28:15:28 | x | provenance | |
|
||||
| captured_variables.rb:20:25:20:34 | call to taint | captured_variables.rb:20:2:20:34 | call to capture_escape_return1 [captured x] | provenance | |
|
||||
| captured_variables.rb:22:28:22:28 | x | captured_variables.rb:23:5:25:5 | -> { ... } [captured x] | provenance | |
|
||||
| captured_variables.rb:27:25:27:57 | call to capture_escape_return2 [captured x] | captured_variables.rb:24:14:24:14 | x | provenance | |
|
||||
| captured_variables.rb:27:25:27:57 | call to capture_escape_return2 [captured x] | captured_variables.rb:24:14:24:14 | x | provenance | heuristic-callback |
|
||||
| captured_variables.rb:27:48:27:57 | call to taint | captured_variables.rb:22:28:22:28 | x | provenance | |
|
||||
| captured_variables.rb:27:48:27:57 | call to taint | captured_variables.rb:27:25:27:57 | call to capture_escape_return2 [captured x] | provenance | |
|
||||
| captured_variables.rb:29:33:29:33 | x | captured_variables.rb:33:29:33:30 | fn [captured x] | provenance | |
|
||||
| captured_variables.rb:33:29:33:30 | fn [captured x] | captured_variables.rb:31:14:31:14 | x | provenance | |
|
||||
| captured_variables.rb:33:29:33:30 | fn [captured x] | captured_variables.rb:31:14:31:14 | x | provenance | heuristic-callback |
|
||||
| captured_variables.rb:35:29:35:38 | call to taint | captured_variables.rb:29:33:29:33 | x | provenance | |
|
||||
| captured_variables.rb:37:13:37:14 | fn [captured x] | captured_variables.rb:38:5:38:6 | fn [captured x] | provenance | |
|
||||
| captured_variables.rb:38:5:38:6 | fn [captured x] | captured_variables.rb:42:14:42:14 | x | provenance | |
|
||||
@@ -25,7 +25,9 @@ edges
|
||||
| captured_variables.rb:48:5:48:12 | call to taint | captured_variables.rb:54:6:54:6 | x | provenance | |
|
||||
| captured_variables.rb:49:16:52:3 | [post] do ... end [captured x] | captured_variables.rb:54:6:54:6 | x | provenance | |
|
||||
| captured_variables.rb:49:16:52:3 | do ... end [captured x] | captured_variables.rb:50:10:50:10 | x | provenance | |
|
||||
| captured_variables.rb:49:16:52:3 | do ... end [captured x] | captured_variables.rb:50:10:50:10 | x | provenance | heuristic-callback |
|
||||
| captured_variables.rb:51:9:51:16 | call to taint | captured_variables.rb:49:16:52:3 | [post] do ... end [captured x] | provenance | |
|
||||
| captured_variables.rb:51:9:51:16 | call to taint | captured_variables.rb:49:16:52:3 | [post] do ... end [captured x] | provenance | heuristic-callback |
|
||||
| captured_variables.rb:57:19:57:19 | x | captured_variables.rb:58:18:58:18 | x | provenance | |
|
||||
| captured_variables.rb:58:18:58:18 | x | captured_variables.rb:58:9:58:14 | [post] self [@field] | provenance | |
|
||||
| captured_variables.rb:60:5:62:7 | self in get_field [@field] | captured_variables.rb:61:16:61:21 | self [@field] | provenance | |
|
||||
@@ -38,10 +40,12 @@ edges
|
||||
| captured_variables.rb:66:15:66:22 | call to taint | instance_variables.rb:10:19:10:19 | x | provenance | |
|
||||
| captured_variables.rb:67:16:70:3 | [post] do ... end [captured foo, @field] | captured_variables.rb:72:6:72:8 | foo [@field] | provenance | |
|
||||
| captured_variables.rb:67:16:70:3 | do ... end [captured foo, @field] | captured_variables.rb:68:10:68:12 | foo [@field] | provenance | |
|
||||
| captured_variables.rb:67:16:70:3 | do ... end [captured foo, @field] | captured_variables.rb:68:10:68:12 | foo [@field] | provenance | heuristic-callback |
|
||||
| captured_variables.rb:68:10:68:12 | foo [@field] | captured_variables.rb:60:5:62:7 | self in get_field [@field] | provenance | |
|
||||
| captured_variables.rb:68:10:68:12 | foo [@field] | captured_variables.rb:68:10:68:22 | call to get_field | provenance | |
|
||||
| captured_variables.rb:68:10:68:12 | foo [@field] | instance_variables.rb:13:5:15:7 | self in get_field [@field] | provenance | |
|
||||
| captured_variables.rb:69:5:69:7 | [post] foo [@field] | captured_variables.rb:67:16:70:3 | [post] do ... end [captured foo, @field] | provenance | |
|
||||
| captured_variables.rb:69:5:69:7 | [post] foo [@field] | captured_variables.rb:67:16:70:3 | [post] do ... end [captured foo, @field] | provenance | heuristic-callback |
|
||||
| captured_variables.rb:69:19:69:26 | call to taint | captured_variables.rb:57:19:57:19 | x | provenance | |
|
||||
| captured_variables.rb:69:19:69:26 | call to taint | captured_variables.rb:69:5:69:7 | [post] foo [@field] | provenance | |
|
||||
| captured_variables.rb:69:19:69:26 | call to taint | instance_variables.rb:10:19:10:19 | x | provenance | |
|
||||
@@ -50,6 +54,7 @@ edges
|
||||
| captured_variables.rb:72:6:72:8 | foo [@field] | instance_variables.rb:13:5:15:7 | self in get_field [@field] | provenance | |
|
||||
| captured_variables.rb:78:20:80:7 | [post] do ... end [captured foo, @field] | captured_variables.rb:83:6:83:8 | foo [@field] | provenance | |
|
||||
| captured_variables.rb:79:9:79:11 | [post] foo [@field] | captured_variables.rb:78:20:80:7 | [post] do ... end [captured foo, @field] | provenance | |
|
||||
| captured_variables.rb:79:9:79:11 | [post] foo [@field] | captured_variables.rb:78:20:80:7 | [post] do ... end [captured foo, @field] | provenance | heuristic-callback |
|
||||
| captured_variables.rb:79:23:79:30 | call to taint | captured_variables.rb:57:19:57:19 | x | provenance | |
|
||||
| captured_variables.rb:79:23:79:30 | call to taint | captured_variables.rb:79:9:79:11 | [post] foo [@field] | provenance | |
|
||||
| captured_variables.rb:79:23:79:30 | call to taint | instance_variables.rb:10:19:10:19 | x | provenance | |
|
||||
|
||||
@@ -10,14 +10,14 @@ edges
|
||||
| summaries.rb:1:11:1:36 | call to identity | summaries.rb:26:31:26:37 | tainted | provenance | |
|
||||
| summaries.rb:1:11:1:36 | call to identity | summaries.rb:30:24:30:30 | tainted | provenance | |
|
||||
| summaries.rb:1:11:1:36 | call to identity | summaries.rb:31:27:31:33 | tainted | provenance | |
|
||||
| summaries.rb:1:11:1:36 | call to identity | summaries.rb:34:16:34:22 | tainted | provenance | |
|
||||
| summaries.rb:1:11:1:36 | call to identity | summaries.rb:34:16:34:22 | tainted | provenance | |
|
||||
| summaries.rb:1:11:1:36 | call to identity | summaries.rb:35:16:35:22 | tainted | provenance | |
|
||||
| summaries.rb:1:11:1:36 | call to identity | summaries.rb:35:16:35:22 | tainted | provenance | |
|
||||
| summaries.rb:1:11:1:36 | call to identity | summaries.rb:36:21:36:27 | tainted | provenance | |
|
||||
| summaries.rb:1:11:1:36 | call to identity | summaries.rb:36:21:36:27 | tainted | provenance | |
|
||||
| summaries.rb:1:11:1:36 | call to identity | summaries.rb:37:36:37:42 | tainted | provenance | |
|
||||
| summaries.rb:1:11:1:36 | call to identity | summaries.rb:37:36:37:42 | tainted | provenance | |
|
||||
| summaries.rb:1:11:1:36 | call to identity | summaries.rb:34:16:34:22 | tainted | provenance | Sink:MaD:6 |
|
||||
| summaries.rb:1:11:1:36 | call to identity | summaries.rb:34:16:34:22 | tainted | provenance | Sink:MaD:6 |
|
||||
| summaries.rb:1:11:1:36 | call to identity | summaries.rb:35:16:35:22 | tainted | provenance | Sink:MaD:6 |
|
||||
| summaries.rb:1:11:1:36 | call to identity | summaries.rb:35:16:35:22 | tainted | provenance | Sink:MaD:6 |
|
||||
| summaries.rb:1:11:1:36 | call to identity | summaries.rb:36:21:36:27 | tainted | provenance | Sink:MaD:6 |
|
||||
| summaries.rb:1:11:1:36 | call to identity | summaries.rb:36:21:36:27 | tainted | provenance | Sink:MaD:6 |
|
||||
| summaries.rb:1:11:1:36 | call to identity | summaries.rb:37:36:37:42 | tainted | provenance | Sink:MaD:6 |
|
||||
| summaries.rb:1:11:1:36 | call to identity | summaries.rb:37:36:37:42 | tainted | provenance | Sink:MaD:6 |
|
||||
| summaries.rb:1:11:1:36 | call to identity | summaries.rb:51:24:51:30 | tainted | provenance | |
|
||||
| summaries.rb:1:11:1:36 | call to identity | summaries.rb:56:22:56:28 | tainted | provenance | |
|
||||
| summaries.rb:1:11:1:36 | call to identity | summaries.rb:57:17:57:23 | tainted | provenance | |
|
||||
@@ -27,30 +27,30 @@ edges
|
||||
| summaries.rb:1:11:1:36 | call to identity | summaries.rb:122:16:122:22 | tainted | provenance | |
|
||||
| summaries.rb:1:11:1:36 | call to identity | summaries.rb:128:14:128:20 | tainted | provenance | |
|
||||
| summaries.rb:1:11:1:36 | call to identity | summaries.rb:131:16:131:22 | tainted | provenance | |
|
||||
| summaries.rb:1:11:1:36 | call to identity | summaries.rb:131:16:131:22 | tainted | provenance | |
|
||||
| summaries.rb:1:11:1:36 | call to identity | summaries.rb:131:16:131:22 | tainted | provenance | |
|
||||
| summaries.rb:1:11:1:36 | call to identity | summaries.rb:132:21:132:27 | tainted | provenance | |
|
||||
| summaries.rb:1:11:1:36 | call to identity | summaries.rb:132:21:132:27 | tainted | provenance | |
|
||||
| summaries.rb:1:11:1:36 | call to identity | summaries.rb:135:26:135:32 | tainted | provenance | |
|
||||
| summaries.rb:1:11:1:36 | call to identity | summaries.rb:135:26:135:32 | tainted | provenance | |
|
||||
| summaries.rb:1:11:1:36 | call to identity | summaries.rb:137:23:137:29 | tainted | provenance | |
|
||||
| summaries.rb:1:11:1:36 | call to identity | summaries.rb:137:23:137:29 | tainted | provenance | |
|
||||
| summaries.rb:1:11:1:36 | call to identity | summaries.rb:140:19:140:25 | tainted | provenance | |
|
||||
| summaries.rb:1:11:1:36 | call to identity | summaries.rb:140:19:140:25 | tainted | provenance | |
|
||||
| summaries.rb:1:11:1:36 | call to identity | summaries.rb:141:19:141:25 | tainted | provenance | |
|
||||
| summaries.rb:1:11:1:36 | call to identity | summaries.rb:141:19:141:25 | tainted | provenance | |
|
||||
| summaries.rb:1:11:1:36 | call to identity | summaries.rb:145:26:145:32 | tainted | provenance | |
|
||||
| summaries.rb:1:11:1:36 | call to identity | summaries.rb:145:26:145:32 | tainted | provenance | |
|
||||
| summaries.rb:1:11:1:36 | call to identity | summaries.rb:147:16:147:22 | tainted | provenance | |
|
||||
| summaries.rb:1:11:1:36 | call to identity | summaries.rb:147:16:147:22 | tainted | provenance | |
|
||||
| summaries.rb:1:11:1:36 | call to identity | summaries.rb:150:39:150:45 | tainted | provenance | |
|
||||
| summaries.rb:1:11:1:36 | call to identity | summaries.rb:150:39:150:45 | tainted | provenance | |
|
||||
| summaries.rb:1:11:1:36 | call to identity | summaries.rb:154:20:154:26 | tainted | provenance | |
|
||||
| summaries.rb:1:11:1:36 | call to identity | summaries.rb:154:20:154:26 | tainted | provenance | |
|
||||
| summaries.rb:1:11:1:36 | call to identity | summaries.rb:155:28:155:34 | tainted | provenance | |
|
||||
| summaries.rb:1:11:1:36 | call to identity | summaries.rb:155:28:155:34 | tainted | provenance | |
|
||||
| summaries.rb:1:11:1:36 | call to identity | summaries.rb:156:27:156:33 | tainted | provenance | |
|
||||
| summaries.rb:1:11:1:36 | call to identity | summaries.rb:156:27:156:33 | tainted | provenance | |
|
||||
| summaries.rb:1:11:1:36 | call to identity | summaries.rb:131:16:131:22 | tainted | provenance | Sink:MaD:3 |
|
||||
| summaries.rb:1:11:1:36 | call to identity | summaries.rb:131:16:131:22 | tainted | provenance | Sink:MaD:3 |
|
||||
| summaries.rb:1:11:1:36 | call to identity | summaries.rb:132:21:132:27 | tainted | provenance | Sink:MaD:3 |
|
||||
| summaries.rb:1:11:1:36 | call to identity | summaries.rb:132:21:132:27 | tainted | provenance | Sink:MaD:3 |
|
||||
| summaries.rb:1:11:1:36 | call to identity | summaries.rb:135:26:135:32 | tainted | provenance | Sink:MaD:4 |
|
||||
| summaries.rb:1:11:1:36 | call to identity | summaries.rb:135:26:135:32 | tainted | provenance | Sink:MaD:4 |
|
||||
| summaries.rb:1:11:1:36 | call to identity | summaries.rb:137:23:137:29 | tainted | provenance | Sink:MaD:6 |
|
||||
| summaries.rb:1:11:1:36 | call to identity | summaries.rb:137:23:137:29 | tainted | provenance | Sink:MaD:6 |
|
||||
| summaries.rb:1:11:1:36 | call to identity | summaries.rb:140:19:140:25 | tainted | provenance | Sink:MaD:6 |
|
||||
| summaries.rb:1:11:1:36 | call to identity | summaries.rb:140:19:140:25 | tainted | provenance | Sink:MaD:6 |
|
||||
| summaries.rb:1:11:1:36 | call to identity | summaries.rb:141:19:141:25 | tainted | provenance | Sink:MaD:6 |
|
||||
| summaries.rb:1:11:1:36 | call to identity | summaries.rb:141:19:141:25 | tainted | provenance | Sink:MaD:6 |
|
||||
| summaries.rb:1:11:1:36 | call to identity | summaries.rb:145:26:145:32 | tainted | provenance | Sink:MaD:1 |
|
||||
| summaries.rb:1:11:1:36 | call to identity | summaries.rb:145:26:145:32 | tainted | provenance | Sink:MaD:1 |
|
||||
| summaries.rb:1:11:1:36 | call to identity | summaries.rb:147:16:147:22 | tainted | provenance | Sink:MaD:0 |
|
||||
| summaries.rb:1:11:1:36 | call to identity | summaries.rb:147:16:147:22 | tainted | provenance | Sink:MaD:0 |
|
||||
| summaries.rb:1:11:1:36 | call to identity | summaries.rb:150:39:150:45 | tainted | provenance | Sink:MaD:2 |
|
||||
| summaries.rb:1:11:1:36 | call to identity | summaries.rb:150:39:150:45 | tainted | provenance | Sink:MaD:2 |
|
||||
| summaries.rb:1:11:1:36 | call to identity | summaries.rb:154:20:154:26 | tainted | provenance | Sink:MaD:5 |
|
||||
| summaries.rb:1:11:1:36 | call to identity | summaries.rb:154:20:154:26 | tainted | provenance | Sink:MaD:5 |
|
||||
| summaries.rb:1:11:1:36 | call to identity | summaries.rb:155:28:155:34 | tainted | provenance | Sink:MaD:5 |
|
||||
| summaries.rb:1:11:1:36 | call to identity | summaries.rb:155:28:155:34 | tainted | provenance | Sink:MaD:5 |
|
||||
| summaries.rb:1:11:1:36 | call to identity | summaries.rb:156:27:156:33 | tainted | provenance | Sink:MaD:5 |
|
||||
| summaries.rb:1:11:1:36 | call to identity | summaries.rb:156:27:156:33 | tainted | provenance | Sink:MaD:5 |
|
||||
| summaries.rb:1:11:1:36 | call to identity | summaries.rb:157:14:160:3 | do ... end [captured tainted] | provenance | |
|
||||
| summaries.rb:1:11:1:36 | call to identity | summaries.rb:157:14:160:3 | do ... end [captured tainted] | provenance | |
|
||||
| summaries.rb:1:20:1:36 | call to source | summaries.rb:1:11:1:36 | call to identity | provenance | |
|
||||
@@ -81,34 +81,34 @@ edges
|
||||
| summaries.rb:16:36:16:42 | tainted | summaries.rb:16:12:16:43 | call to apply_lambda | provenance | |
|
||||
| summaries.rb:20:1:20:8 | tainted4 | summaries.rb:21:6:21:13 | tainted4 | provenance | |
|
||||
| summaries.rb:20:12:20:32 | call to firstArg | summaries.rb:20:1:20:8 | tainted4 | provenance | |
|
||||
| summaries.rb:20:25:20:31 | tainted | summaries.rb:20:12:20:32 | call to firstArg | provenance | |
|
||||
| summaries.rb:20:25:20:31 | tainted | summaries.rb:20:12:20:32 | call to firstArg | provenance | MaD:11 |
|
||||
| summaries.rb:26:1:26:8 | tainted5 | summaries.rb:27:6:27:13 | tainted5 | provenance | |
|
||||
| summaries.rb:26:12:26:38 | call to secondArg | summaries.rb:26:1:26:8 | tainted5 | provenance | |
|
||||
| summaries.rb:26:31:26:37 | tainted | summaries.rb:26:12:26:38 | call to secondArg | provenance | |
|
||||
| summaries.rb:30:24:30:30 | tainted | summaries.rb:30:6:30:42 | call to onlyWithBlock | provenance | |
|
||||
| summaries.rb:31:27:31:33 | tainted | summaries.rb:31:6:31:34 | call to onlyWithoutBlock | provenance | |
|
||||
| summaries.rb:26:31:26:37 | tainted | summaries.rb:26:12:26:38 | call to secondArg | provenance | MaD:17 |
|
||||
| summaries.rb:30:24:30:30 | tainted | summaries.rb:30:6:30:42 | call to onlyWithBlock | provenance | MaD:15 |
|
||||
| summaries.rb:31:27:31:33 | tainted | summaries.rb:31:6:31:34 | call to onlyWithoutBlock | provenance | MaD:16 |
|
||||
| summaries.rb:40:3:40:3 | t | summaries.rb:41:24:41:24 | t | provenance | |
|
||||
| summaries.rb:40:3:40:3 | t | summaries.rb:42:24:42:24 | t | provenance | |
|
||||
| summaries.rb:40:3:40:3 | t | summaries.rb:44:8:44:8 | t | provenance | |
|
||||
| summaries.rb:40:7:40:17 | call to source | summaries.rb:40:3:40:3 | t | provenance | |
|
||||
| summaries.rb:41:24:41:24 | t | summaries.rb:41:8:41:25 | call to matchedByName | provenance | |
|
||||
| summaries.rb:42:24:42:24 | t | summaries.rb:42:8:42:25 | call to matchedByName | provenance | |
|
||||
| summaries.rb:44:8:44:8 | t | summaries.rb:44:8:44:27 | call to matchedByNameRcv | provenance | |
|
||||
| summaries.rb:48:24:48:41 | call to source | summaries.rb:48:8:48:42 | call to preserveTaint | provenance | |
|
||||
| summaries.rb:51:24:51:30 | tainted | summaries.rb:51:6:51:31 | call to namedArg | provenance | |
|
||||
| summaries.rb:41:24:41:24 | t | summaries.rb:41:8:41:25 | call to matchedByName | provenance | MaD:24 |
|
||||
| summaries.rb:42:24:42:24 | t | summaries.rb:42:8:42:25 | call to matchedByName | provenance | MaD:24 |
|
||||
| summaries.rb:44:8:44:8 | t | summaries.rb:44:8:44:27 | call to matchedByNameRcv | provenance | MaD:23 |
|
||||
| summaries.rb:48:24:48:41 | call to source | summaries.rb:48:8:48:42 | call to preserveTaint | provenance | MaD:10 |
|
||||
| summaries.rb:51:24:51:30 | tainted | summaries.rb:51:6:51:31 | call to namedArg | provenance | MaD:14 |
|
||||
| summaries.rb:53:1:53:4 | args [element :foo] | summaries.rb:54:21:54:24 | args [element :foo] | provenance | |
|
||||
| summaries.rb:53:8:53:33 | call to [] [element :foo] | summaries.rb:53:1:53:4 | args [element :foo] | provenance | |
|
||||
| summaries.rb:53:15:53:31 | call to source | summaries.rb:53:8:53:33 | call to [] [element :foo] | provenance | |
|
||||
| summaries.rb:54:19:54:24 | ** ... [element :foo] | summaries.rb:54:6:54:25 | call to namedArg | provenance | |
|
||||
| summaries.rb:54:19:54:24 | ** ... [element :foo] | summaries.rb:54:6:54:25 | call to namedArg | provenance | MaD:14 |
|
||||
| summaries.rb:54:21:54:24 | args [element :foo] | summaries.rb:54:19:54:24 | ** ... [element :foo] | provenance | |
|
||||
| summaries.rb:56:22:56:28 | tainted | summaries.rb:56:6:56:29 | call to anyArg | provenance | |
|
||||
| summaries.rb:57:17:57:23 | tainted | summaries.rb:57:6:57:24 | call to anyArg | provenance | |
|
||||
| summaries.rb:59:27:59:33 | tainted | summaries.rb:59:6:59:34 | call to anyNamedArg | provenance | |
|
||||
| summaries.rb:63:32:63:38 | tainted | summaries.rb:63:6:63:39 | call to anyPositionFromOne | provenance | |
|
||||
| summaries.rb:65:23:65:29 | tainted | summaries.rb:65:40:65:40 | x | provenance | |
|
||||
| summaries.rb:56:22:56:28 | tainted | summaries.rb:56:6:56:29 | call to anyArg | provenance | MaD:7 |
|
||||
| summaries.rb:57:17:57:23 | tainted | summaries.rb:57:6:57:24 | call to anyArg | provenance | MaD:7 |
|
||||
| summaries.rb:59:27:59:33 | tainted | summaries.rb:59:6:59:34 | call to anyNamedArg | provenance | MaD:8 |
|
||||
| summaries.rb:63:32:63:38 | tainted | summaries.rb:63:6:63:39 | call to anyPositionFromOne | provenance | MaD:9 |
|
||||
| summaries.rb:65:23:65:29 | tainted | summaries.rb:65:40:65:40 | x | provenance | MaD:12 |
|
||||
| summaries.rb:65:40:65:40 | x | summaries.rb:66:8:66:8 | x | provenance | |
|
||||
| summaries.rb:73:24:73:53 | call to source | summaries.rb:73:8:73:54 | call to preserveTaint | provenance | |
|
||||
| summaries.rb:76:26:76:56 | call to source | summaries.rb:76:8:76:57 | call to preserveTaint | provenance | |
|
||||
| summaries.rb:73:24:73:53 | call to source | summaries.rb:73:8:73:54 | call to preserveTaint | provenance | MaD:18 |
|
||||
| summaries.rb:76:26:76:56 | call to source | summaries.rb:76:8:76:57 | call to preserveTaint | provenance | MaD:19 |
|
||||
| summaries.rb:79:1:79:1 | a [element 1] | summaries.rb:82:6:82:6 | a [element 1] | provenance | |
|
||||
| summaries.rb:79:1:79:1 | a [element 1] | summaries.rb:82:6:82:6 | a [element 1] | provenance | |
|
||||
| summaries.rb:79:1:79:1 | a [element 1] | summaries.rb:83:6:83:6 | a [element 1] | provenance | |
|
||||
@@ -145,12 +145,12 @@ edges
|
||||
| summaries.rb:81:1:81:1 | [post] a [element] | summaries.rb:95:1:95:1 | a [element] | provenance | |
|
||||
| summaries.rb:81:13:81:27 | call to source | summaries.rb:81:1:81:1 | [post] a [element] | provenance | |
|
||||
| summaries.rb:81:13:81:27 | call to source | summaries.rb:81:1:81:1 | [post] a [element] | provenance | |
|
||||
| summaries.rb:82:6:82:6 | a [element 1] | summaries.rb:82:6:82:24 | call to readElementOne | provenance | |
|
||||
| summaries.rb:82:6:82:6 | a [element 1] | summaries.rb:82:6:82:24 | call to readElementOne | provenance | |
|
||||
| summaries.rb:82:6:82:6 | a [element] | summaries.rb:82:6:82:24 | call to readElementOne | provenance | |
|
||||
| summaries.rb:82:6:82:6 | a [element] | summaries.rb:82:6:82:24 | call to readElementOne | provenance | |
|
||||
| summaries.rb:83:6:83:6 | a [element 1] | summaries.rb:83:6:83:31 | call to readExactlyElementOne | provenance | |
|
||||
| summaries.rb:83:6:83:6 | a [element 1] | summaries.rb:83:6:83:31 | call to readExactlyElementOne | provenance | |
|
||||
| summaries.rb:82:6:82:6 | a [element 1] | summaries.rb:82:6:82:24 | call to readElementOne | provenance | MaD:25 |
|
||||
| summaries.rb:82:6:82:6 | a [element 1] | summaries.rb:82:6:82:24 | call to readElementOne | provenance | MaD:25 |
|
||||
| summaries.rb:82:6:82:6 | a [element] | summaries.rb:82:6:82:24 | call to readElementOne | provenance | MaD:25 |
|
||||
| summaries.rb:82:6:82:6 | a [element] | summaries.rb:82:6:82:24 | call to readElementOne | provenance | MaD:25 |
|
||||
| summaries.rb:83:6:83:6 | a [element 1] | summaries.rb:83:6:83:31 | call to readExactlyElementOne | provenance | MaD:26 |
|
||||
| summaries.rb:83:6:83:6 | a [element 1] | summaries.rb:83:6:83:31 | call to readExactlyElementOne | provenance | MaD:26 |
|
||||
| summaries.rb:84:6:84:6 | a [element] | summaries.rb:84:6:84:9 | ...[...] | provenance | |
|
||||
| summaries.rb:84:6:84:6 | a [element] | summaries.rb:84:6:84:9 | ...[...] | provenance | |
|
||||
| summaries.rb:85:6:85:6 | a [element 1] | summaries.rb:85:6:85:9 | ...[...] | provenance | |
|
||||
@@ -169,10 +169,10 @@ edges
|
||||
| summaries.rb:87:1:87:1 | b [element] | summaries.rb:89:6:89:6 | b [element] | provenance | |
|
||||
| summaries.rb:87:1:87:1 | b [element] | summaries.rb:90:6:90:6 | b [element] | provenance | |
|
||||
| summaries.rb:87:1:87:1 | b [element] | summaries.rb:90:6:90:6 | b [element] | provenance | |
|
||||
| summaries.rb:87:5:87:5 | a [element 1] | summaries.rb:87:5:87:22 | call to withElementOne [element 1] | provenance | |
|
||||
| summaries.rb:87:5:87:5 | a [element 1] | summaries.rb:87:5:87:22 | call to withElementOne [element 1] | provenance | |
|
||||
| summaries.rb:87:5:87:5 | a [element] | summaries.rb:87:5:87:22 | call to withElementOne [element] | provenance | |
|
||||
| summaries.rb:87:5:87:5 | a [element] | summaries.rb:87:5:87:22 | call to withElementOne [element] | provenance | |
|
||||
| summaries.rb:87:5:87:5 | a [element 1] | summaries.rb:87:5:87:22 | call to withElementOne [element 1] | provenance | MaD:28 |
|
||||
| summaries.rb:87:5:87:5 | a [element 1] | summaries.rb:87:5:87:22 | call to withElementOne [element 1] | provenance | MaD:28 |
|
||||
| summaries.rb:87:5:87:5 | a [element] | summaries.rb:87:5:87:22 | call to withElementOne [element] | provenance | MaD:28 |
|
||||
| summaries.rb:87:5:87:5 | a [element] | summaries.rb:87:5:87:22 | call to withElementOne [element] | provenance | MaD:28 |
|
||||
| summaries.rb:87:5:87:22 | call to withElementOne [element 1] | summaries.rb:87:1:87:1 | b [element 1] | provenance | |
|
||||
| summaries.rb:87:5:87:22 | call to withElementOne [element 1] | summaries.rb:87:1:87:1 | b [element 1] | provenance | |
|
||||
| summaries.rb:87:5:87:22 | call to withElementOne [element] | summaries.rb:87:1:87:1 | b [element] | provenance | |
|
||||
@@ -187,8 +187,8 @@ edges
|
||||
| summaries.rb:90:6:90:6 | b [element] | summaries.rb:90:6:90:9 | ...[...] | provenance | |
|
||||
| summaries.rb:91:1:91:1 | c [element 1] | summaries.rb:93:6:93:6 | c [element 1] | provenance | |
|
||||
| summaries.rb:91:1:91:1 | c [element 1] | summaries.rb:93:6:93:6 | c [element 1] | provenance | |
|
||||
| summaries.rb:91:5:91:5 | a [element 1] | summaries.rb:91:5:91:29 | call to withExactlyElementOne [element 1] | provenance | |
|
||||
| summaries.rb:91:5:91:5 | a [element 1] | summaries.rb:91:5:91:29 | call to withExactlyElementOne [element 1] | provenance | |
|
||||
| summaries.rb:91:5:91:5 | a [element 1] | summaries.rb:91:5:91:29 | call to withExactlyElementOne [element 1] | provenance | MaD:29 |
|
||||
| summaries.rb:91:5:91:5 | a [element 1] | summaries.rb:91:5:91:29 | call to withExactlyElementOne [element 1] | provenance | MaD:29 |
|
||||
| summaries.rb:91:5:91:29 | call to withExactlyElementOne [element 1] | summaries.rb:91:1:91:1 | c [element 1] | provenance | |
|
||||
| summaries.rb:91:5:91:29 | call to withExactlyElementOne [element 1] | summaries.rb:91:1:91:1 | c [element 1] | provenance | |
|
||||
| summaries.rb:93:6:93:6 | c [element 1] | summaries.rb:93:6:93:9 | ...[...] | provenance | |
|
||||
@@ -203,10 +203,10 @@ edges
|
||||
| summaries.rb:95:1:95:1 | [post] a [element] | summaries.rb:97:6:97:6 | a [element] | provenance | |
|
||||
| summaries.rb:95:1:95:1 | [post] a [element] | summaries.rb:98:6:98:6 | a [element] | provenance | |
|
||||
| summaries.rb:95:1:95:1 | [post] a [element] | summaries.rb:98:6:98:6 | a [element] | provenance | |
|
||||
| summaries.rb:95:1:95:1 | a [element 2] | summaries.rb:95:1:95:1 | [post] a [element 2] | provenance | |
|
||||
| summaries.rb:95:1:95:1 | a [element 2] | summaries.rb:95:1:95:1 | [post] a [element 2] | provenance | |
|
||||
| summaries.rb:95:1:95:1 | a [element] | summaries.rb:95:1:95:1 | [post] a [element] | provenance | |
|
||||
| summaries.rb:95:1:95:1 | a [element] | summaries.rb:95:1:95:1 | [post] a [element] | provenance | |
|
||||
| summaries.rb:95:1:95:1 | a [element 2] | summaries.rb:95:1:95:1 | [post] a [element 2] | provenance | MaD:32 |
|
||||
| summaries.rb:95:1:95:1 | a [element 2] | summaries.rb:95:1:95:1 | [post] a [element 2] | provenance | MaD:32 |
|
||||
| summaries.rb:95:1:95:1 | a [element] | summaries.rb:95:1:95:1 | [post] a [element] | provenance | MaD:32 |
|
||||
| summaries.rb:95:1:95:1 | a [element] | summaries.rb:95:1:95:1 | [post] a [element] | provenance | MaD:32 |
|
||||
| summaries.rb:96:6:96:6 | a [element] | summaries.rb:96:6:96:9 | ...[...] | provenance | |
|
||||
| summaries.rb:96:6:96:6 | a [element] | summaries.rb:96:6:96:9 | ...[...] | provenance | |
|
||||
| summaries.rb:97:6:97:6 | a [element] | summaries.rb:97:6:97:9 | ...[...] | provenance | |
|
||||
@@ -217,8 +217,8 @@ edges
|
||||
| summaries.rb:98:6:98:6 | a [element] | summaries.rb:98:6:98:9 | ...[...] | provenance | |
|
||||
| summaries.rb:99:1:99:1 | [post] a [element 2] | summaries.rb:102:6:102:6 | a [element 2] | provenance | |
|
||||
| summaries.rb:99:1:99:1 | [post] a [element 2] | summaries.rb:102:6:102:6 | a [element 2] | provenance | |
|
||||
| summaries.rb:99:1:99:1 | a [element 2] | summaries.rb:99:1:99:1 | [post] a [element 2] | provenance | |
|
||||
| summaries.rb:99:1:99:1 | a [element 2] | summaries.rb:99:1:99:1 | [post] a [element 2] | provenance | |
|
||||
| summaries.rb:99:1:99:1 | a [element 2] | summaries.rb:99:1:99:1 | [post] a [element 2] | provenance | MaD:31 |
|
||||
| summaries.rb:99:1:99:1 | a [element 2] | summaries.rb:99:1:99:1 | [post] a [element 2] | provenance | MaD:31 |
|
||||
| summaries.rb:102:6:102:6 | a [element 2] | summaries.rb:102:6:102:9 | ...[...] | provenance | |
|
||||
| summaries.rb:102:6:102:6 | a [element 2] | summaries.rb:102:6:102:9 | ...[...] | provenance | |
|
||||
| summaries.rb:103:1:103:1 | [post] d [element 3] | summaries.rb:104:1:104:1 | d [element 3] | provenance | |
|
||||
@@ -227,41 +227,41 @@ edges
|
||||
| summaries.rb:103:8:103:22 | call to source | summaries.rb:103:1:103:1 | [post] d [element 3] | provenance | |
|
||||
| summaries.rb:104:1:104:1 | [post] d [element 3] | summaries.rb:108:6:108:6 | d [element 3] | provenance | |
|
||||
| summaries.rb:104:1:104:1 | [post] d [element 3] | summaries.rb:108:6:108:6 | d [element 3] | provenance | |
|
||||
| summaries.rb:104:1:104:1 | d [element 3] | summaries.rb:104:1:104:1 | [post] d [element 3] | provenance | |
|
||||
| summaries.rb:104:1:104:1 | d [element 3] | summaries.rb:104:1:104:1 | [post] d [element 3] | provenance | |
|
||||
| summaries.rb:104:1:104:1 | d [element 3] | summaries.rb:104:1:104:1 | [post] d [element 3] | provenance | MaD:30 |
|
||||
| summaries.rb:104:1:104:1 | d [element 3] | summaries.rb:104:1:104:1 | [post] d [element 3] | provenance | MaD:30 |
|
||||
| summaries.rb:108:6:108:6 | d [element 3] | summaries.rb:108:6:108:9 | ...[...] | provenance | |
|
||||
| summaries.rb:108:6:108:6 | d [element 3] | summaries.rb:108:6:108:9 | ...[...] | provenance | |
|
||||
| summaries.rb:111:1:111:1 | [post] x [@value] | summaries.rb:112:6:112:6 | x [@value] | provenance | |
|
||||
| summaries.rb:111:1:111:1 | [post] x [@value] | summaries.rb:112:6:112:6 | x [@value] | provenance | |
|
||||
| summaries.rb:111:13:111:26 | call to source | summaries.rb:111:1:111:1 | [post] x [@value] | provenance | |
|
||||
| summaries.rb:111:13:111:26 | call to source | summaries.rb:111:1:111:1 | [post] x [@value] | provenance | |
|
||||
| summaries.rb:112:6:112:6 | x [@value] | summaries.rb:112:6:112:16 | call to get_value | provenance | |
|
||||
| summaries.rb:112:6:112:6 | x [@value] | summaries.rb:112:6:112:16 | call to get_value | provenance | |
|
||||
| summaries.rb:111:13:111:26 | call to source | summaries.rb:111:1:111:1 | [post] x [@value] | provenance | MaD:27 |
|
||||
| summaries.rb:111:13:111:26 | call to source | summaries.rb:111:1:111:1 | [post] x [@value] | provenance | MaD:27 |
|
||||
| summaries.rb:112:6:112:6 | x [@value] | summaries.rb:112:6:112:16 | call to get_value | provenance | MaD:22 |
|
||||
| summaries.rb:112:6:112:6 | x [@value] | summaries.rb:112:6:112:16 | call to get_value | provenance | MaD:22 |
|
||||
| summaries.rb:122:16:122:22 | [post] tainted | summaries.rb:128:14:128:20 | tainted | provenance | |
|
||||
| summaries.rb:122:16:122:22 | [post] tainted | summaries.rb:131:16:131:22 | tainted | provenance | |
|
||||
| summaries.rb:122:16:122:22 | [post] tainted | summaries.rb:131:16:131:22 | tainted | provenance | |
|
||||
| summaries.rb:122:16:122:22 | [post] tainted | summaries.rb:132:21:132:27 | tainted | provenance | |
|
||||
| summaries.rb:122:16:122:22 | [post] tainted | summaries.rb:135:26:135:32 | tainted | provenance | |
|
||||
| summaries.rb:122:16:122:22 | [post] tainted | summaries.rb:137:23:137:29 | tainted | provenance | |
|
||||
| summaries.rb:122:16:122:22 | [post] tainted | summaries.rb:140:19:140:25 | tainted | provenance | |
|
||||
| summaries.rb:122:16:122:22 | [post] tainted | summaries.rb:141:19:141:25 | tainted | provenance | |
|
||||
| summaries.rb:122:16:122:22 | [post] tainted | summaries.rb:145:26:145:32 | tainted | provenance | |
|
||||
| summaries.rb:122:16:122:22 | [post] tainted | summaries.rb:147:16:147:22 | tainted | provenance | |
|
||||
| summaries.rb:122:16:122:22 | [post] tainted | summaries.rb:150:39:150:45 | tainted | provenance | |
|
||||
| summaries.rb:122:16:122:22 | [post] tainted | summaries.rb:154:20:154:26 | tainted | provenance | |
|
||||
| summaries.rb:122:16:122:22 | [post] tainted | summaries.rb:155:28:155:34 | tainted | provenance | |
|
||||
| summaries.rb:122:16:122:22 | [post] tainted | summaries.rb:156:27:156:33 | tainted | provenance | |
|
||||
| summaries.rb:122:16:122:22 | [post] tainted | summaries.rb:131:16:131:22 | tainted | provenance | Sink:MaD:3 |
|
||||
| summaries.rb:122:16:122:22 | [post] tainted | summaries.rb:132:21:132:27 | tainted | provenance | Sink:MaD:3 |
|
||||
| summaries.rb:122:16:122:22 | [post] tainted | summaries.rb:135:26:135:32 | tainted | provenance | Sink:MaD:4 |
|
||||
| summaries.rb:122:16:122:22 | [post] tainted | summaries.rb:137:23:137:29 | tainted | provenance | Sink:MaD:6 |
|
||||
| summaries.rb:122:16:122:22 | [post] tainted | summaries.rb:140:19:140:25 | tainted | provenance | Sink:MaD:6 |
|
||||
| summaries.rb:122:16:122:22 | [post] tainted | summaries.rb:141:19:141:25 | tainted | provenance | Sink:MaD:6 |
|
||||
| summaries.rb:122:16:122:22 | [post] tainted | summaries.rb:145:26:145:32 | tainted | provenance | Sink:MaD:1 |
|
||||
| summaries.rb:122:16:122:22 | [post] tainted | summaries.rb:147:16:147:22 | tainted | provenance | Sink:MaD:0 |
|
||||
| summaries.rb:122:16:122:22 | [post] tainted | summaries.rb:150:39:150:45 | tainted | provenance | Sink:MaD:2 |
|
||||
| summaries.rb:122:16:122:22 | [post] tainted | summaries.rb:154:20:154:26 | tainted | provenance | Sink:MaD:5 |
|
||||
| summaries.rb:122:16:122:22 | [post] tainted | summaries.rb:155:28:155:34 | tainted | provenance | Sink:MaD:5 |
|
||||
| summaries.rb:122:16:122:22 | [post] tainted | summaries.rb:156:27:156:33 | tainted | provenance | Sink:MaD:5 |
|
||||
| summaries.rb:122:16:122:22 | [post] tainted | summaries.rb:157:14:160:3 | do ... end [captured tainted] | provenance | |
|
||||
| summaries.rb:122:16:122:22 | tainted | summaries.rb:122:16:122:22 | [post] tainted | provenance | |
|
||||
| summaries.rb:122:16:122:22 | tainted | summaries.rb:122:25:122:25 | [post] y | provenance | |
|
||||
| summaries.rb:122:16:122:22 | tainted | summaries.rb:122:33:122:33 | [post] z | provenance | |
|
||||
| summaries.rb:122:16:122:22 | tainted | summaries.rb:122:16:122:22 | [post] tainted | provenance | MaD:20 |
|
||||
| summaries.rb:122:16:122:22 | tainted | summaries.rb:122:25:122:25 | [post] y | provenance | MaD:20 |
|
||||
| summaries.rb:122:16:122:22 | tainted | summaries.rb:122:33:122:33 | [post] z | provenance | MaD:20 |
|
||||
| summaries.rb:122:25:122:25 | [post] y | summaries.rb:124:6:124:6 | y | provenance | |
|
||||
| summaries.rb:122:33:122:33 | [post] z | summaries.rb:125:6:125:6 | z | provenance | |
|
||||
| summaries.rb:128:1:128:1 | [post] x | summaries.rb:129:6:129:6 | x | provenance | |
|
||||
| summaries.rb:128:14:128:20 | tainted | summaries.rb:128:1:128:1 | [post] x | provenance | |
|
||||
| summaries.rb:131:16:131:22 | tainted | summaries.rb:131:1:131:23 | synthetic splat argument | provenance | |
|
||||
| summaries.rb:157:14:160:3 | do ... end [captured tainted] | summaries.rb:158:15:158:21 | tainted | provenance | |
|
||||
| summaries.rb:157:14:160:3 | do ... end [captured tainted] | summaries.rb:158:15:158:21 | tainted | provenance | |
|
||||
| summaries.rb:128:14:128:20 | tainted | summaries.rb:128:1:128:1 | [post] x | provenance | MaD:21 |
|
||||
| summaries.rb:131:16:131:22 | tainted | summaries.rb:131:1:131:23 | synthetic splat argument | provenance | Sink:MaD:3 |
|
||||
| summaries.rb:157:14:160:3 | do ... end [captured tainted] | summaries.rb:158:15:158:21 | tainted | provenance | heuristic-callback |
|
||||
| summaries.rb:157:14:160:3 | do ... end [captured tainted] | summaries.rb:158:15:158:21 | tainted | provenance | heuristic-callback |
|
||||
nodes
|
||||
| summaries.rb:1:11:1:36 | call to identity | semmle.label | call to identity |
|
||||
| summaries.rb:1:11:1:36 | call to identity | semmle.label | call to identity |
|
||||
@@ -638,10 +638,3 @@ invalidSpecComponent
|
||||
| summaries.rb:166:20:166:36 | call to source | summaries.rb:166:20:166:36 | call to source | summaries.rb:166:20:166:36 | call to source | $@ | summaries.rb:166:20:166:36 | call to source | call to source |
|
||||
| summaries.rb:166:20:166:36 | call to source | summaries.rb:166:20:166:36 | call to source | summaries.rb:166:20:166:36 | call to source | $@ | summaries.rb:166:20:166:36 | call to source | call to source |
|
||||
warning
|
||||
| CSV type row should have 3 columns but has 1: TooFewColumns |
|
||||
| CSV type row should have 3 columns but has 6: TooManyColumns;;Member[Foo].Instance;too;many;columns |
|
||||
| Invalid argument '0-1' in token 'Argument[0-1]' in access path: Method[foo].Argument[0-1] |
|
||||
| Invalid argument '*' in token 'Argument[*]' in access path: Method[foo].Argument[*] |
|
||||
| Invalid token 'Argument' is missing its arguments, in access path: Method[foo].Argument |
|
||||
| Invalid token 'Member' is missing its arguments, in access path: Method[foo].Member |
|
||||
| Invalid token name 'Arg' in access path: Method[foo].Arg[0] |
|
||||
|
||||
@@ -0,0 +1,51 @@
|
||||
extensions:
|
||||
- addsTo:
|
||||
pack: codeql/ruby-all
|
||||
extensible: sinkModel
|
||||
data:
|
||||
- ['Foo!', 'Method[arraySink].Argument[0].Element[any]', 'test-sink']
|
||||
- ['Foo!', 'Method[getSinks].ReturnValue.Element[any].Method[mySink].Argument[0]', 'test-sink']
|
||||
- ['Foo!', 'Method[secondArrayElementIsSink].Argument[0].Element[1]', 'test-sink']
|
||||
- ['Foo!', 'Method[sinkAnyArg].Argument[any]', 'test-sink']
|
||||
- ['Foo!', 'Method[sinkAnyNamedArg].Argument[any-named]', 'test-sink']
|
||||
- ['FuzzyLib!', 'Fuzzy.Method[fuzzyCall].Argument[0]', 'test-sink']
|
||||
- ['~FooOrBar', 'Method[method].Argument[0]', 'test-sink']
|
||||
|
||||
- addsTo:
|
||||
pack: codeql/ruby-all
|
||||
extensible: summaryModel
|
||||
data:
|
||||
- ['Foo!', 'Method[anyArg]', 'Argument[any]', 'ReturnValue', 'taint']
|
||||
- ['Foo!', 'Method[anyNamedArg]', 'Argument[any-named]', 'ReturnValue', 'taint']
|
||||
- ['Foo!', 'Method[anyPositionFromOne]', 'Argument[1..]', 'ReturnValue', 'taint']
|
||||
- ['Foo!', 'Method[blockArg].Argument[block].Parameter[0].Method[preserveTaint]', 'Argument[0]', 'ReturnValue', 'taint']
|
||||
- ['Foo!', 'Method[firstArg]', 'Argument[0]', 'ReturnValue', 'taint']
|
||||
- ['Foo!', 'Method[intoNamedCallback]', 'Argument[0]', 'Argument[foo:].Parameter[0]', 'taint']
|
||||
- ['Foo!', 'Method[intoNamedParameter]', 'Argument[0]', 'Argument[0].Parameter[foo:]', 'taint']
|
||||
- ['Foo!', 'Method[namedArg]', 'Argument[foo:]', 'ReturnValue', 'taint']
|
||||
- ['Foo!', 'Method[onlyWithBlock].WithBlock', 'Argument[0]', 'ReturnValue', 'taint']
|
||||
- ['Foo!', 'Method[onlyWithoutBlock].WithoutBlock', 'Argument[0]', 'ReturnValue', 'taint']
|
||||
- ['Foo!', 'Method[secondArg]', 'Argument[1]', 'ReturnValue', 'taint']
|
||||
- ['Foo!', 'Method[startInNamedCallback].Argument[foo:].Parameter[0].Method[preserveTaint]', 'Argument[0]', 'ReturnValue', 'taint']
|
||||
- ['Foo!', 'Method[startInNamedParameter].Argument[0].Parameter[foo:].Method[preserveTaint]', 'Argument[0]', 'ReturnValue', 'taint']
|
||||
- ['Foo', 'Method[flowToAnyArg]', 'Argument[0]', 'Argument[any]', 'taint']
|
||||
- ['Foo', 'Method[flowToSelf]', 'Argument[0]', 'Argument[self]', 'taint']
|
||||
- ['any', 'Method[get_value]', 'Argument[self].Field[@value]', 'ReturnValue', 'value']
|
||||
- ['any', 'Method[matchedByNameRcv]', 'Argument[self]', 'ReturnValue', 'taint']
|
||||
- ['any', 'Method[matchedByName]', 'Argument[0]', 'ReturnValue', 'taint']
|
||||
- ['any', 'Method[readElementOne]', 'Argument[self].Element[1]', 'ReturnValue', 'value']
|
||||
- ['any', 'Method[readExactlyElementOne]', 'Argument[self].Element[1!]', 'ReturnValue', 'value']
|
||||
- ['any', 'Method[set_value]', 'Argument[0]', 'Argument[self].Field[@value]', 'value']
|
||||
- ['any', 'Method[withElementOne]', 'Argument[self].WithElement[1]', 'ReturnValue', 'value']
|
||||
- ['any', 'Method[withExactlyElementOne]', 'Argument[self].WithElement[1!]', 'ReturnValue', 'value']
|
||||
- ['any', 'Method[withoutElementOneAndTwo]', 'Argument[self].WithoutElement[1].WithoutElement[2].WithElement[any]', 'Argument[self]', 'value']
|
||||
- ['any', 'Method[withoutElementOne]', 'Argument[self].WithoutElement[1]', 'Argument[self]', 'value']
|
||||
- ['any', 'Method[withoutExactlyElementOne]', 'Argument[self].WithoutElement[1!]', 'Argument[self]', 'value']
|
||||
|
||||
- addsTo:
|
||||
pack: codeql/ruby-all
|
||||
extensible: typeModel
|
||||
data:
|
||||
- ['~FooOrBar', 'Bar', '']
|
||||
- ['~FooOrBar', 'Foo', '']
|
||||
- ['~FooOrBar', '~FooOrBar', 'Method[next].ReturnValue']
|
||||
@@ -62,51 +62,6 @@ private class SummarizedCallableApplyLambda extends SummarizedCallable {
|
||||
}
|
||||
}
|
||||
|
||||
private class StepsFromModel extends ModelInput::SummaryModelCsv {
|
||||
override predicate row(string row) {
|
||||
row =
|
||||
[
|
||||
"any;Method[set_value];Argument[0];Argument[self].Field[@value];value",
|
||||
"any;Method[get_value];Argument[self].Field[@value];ReturnValue;value",
|
||||
"Foo!;Method[firstArg];Argument[0];ReturnValue;taint",
|
||||
"Foo!;Method[secondArg];Argument[1];ReturnValue;taint",
|
||||
"Foo!;Method[onlyWithoutBlock].WithoutBlock;Argument[0];ReturnValue;taint",
|
||||
"Foo!;Method[onlyWithBlock].WithBlock;Argument[0];ReturnValue;taint",
|
||||
"Foo!;Method[blockArg].Argument[block].Parameter[0].Method[preserveTaint];Argument[0];ReturnValue;taint",
|
||||
"Foo!;Method[namedArg];Argument[foo:];ReturnValue;taint",
|
||||
"Foo!;Method[anyArg];Argument[any];ReturnValue;taint",
|
||||
"Foo!;Method[anyNamedArg];Argument[any-named];ReturnValue;taint",
|
||||
"Foo!;Method[anyPositionFromOne];Argument[1..];ReturnValue;taint",
|
||||
"Foo!;Method[intoNamedCallback];Argument[0];Argument[foo:].Parameter[0];taint",
|
||||
"Foo!;Method[intoNamedParameter];Argument[0];Argument[0].Parameter[foo:];taint",
|
||||
"Foo!;Method[startInNamedCallback].Argument[foo:].Parameter[0].Method[preserveTaint];Argument[0];ReturnValue;taint",
|
||||
"Foo!;Method[startInNamedParameter].Argument[0].Parameter[foo:].Method[preserveTaint];Argument[0];ReturnValue;taint",
|
||||
"Foo;Method[flowToAnyArg];Argument[0];Argument[any];taint",
|
||||
"Foo;Method[flowToSelf];Argument[0];Argument[self];taint",
|
||||
"any;Method[matchedByName];Argument[0];ReturnValue;taint",
|
||||
"any;Method[matchedByNameRcv];Argument[self];ReturnValue;taint",
|
||||
"any;Method[withElementOne];Argument[self].WithElement[1];ReturnValue;value",
|
||||
"any;Method[withExactlyElementOne];Argument[self].WithElement[1!];ReturnValue;value",
|
||||
"any;Method[withoutElementOne];Argument[self].WithoutElement[1];Argument[self];value",
|
||||
"any;Method[withoutExactlyElementOne];Argument[self].WithoutElement[1!];Argument[self];value",
|
||||
"any;Method[readElementOne];Argument[self].Element[1];ReturnValue;value",
|
||||
"any;Method[readExactlyElementOne];Argument[self].Element[1!];ReturnValue;value",
|
||||
"any;Method[withoutElementOneAndTwo];Argument[self].WithoutElement[1].WithoutElement[2].WithElement[any];Argument[self];value",
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
private class TypeFromModel extends ModelInput::TypeModelCsv {
|
||||
override predicate row(string row) {
|
||||
row =
|
||||
[
|
||||
"~FooOrBar;Foo;", //
|
||||
"~FooOrBar;Bar;", //
|
||||
"~FooOrBar;~FooOrBar;Method[next].ReturnValue",
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
private class TypeFromCodeQL extends ModelInput::TypeModel {
|
||||
override DataFlow::Node getASource(string type) {
|
||||
type = "~FooOrBar" and
|
||||
@@ -119,36 +74,6 @@ private class TypeFromCodeQL extends ModelInput::TypeModel {
|
||||
}
|
||||
}
|
||||
|
||||
private class InvalidTypeModel extends ModelInput::TypeModelCsv {
|
||||
override predicate row(string row) {
|
||||
row =
|
||||
[
|
||||
"TooManyColumns;;Member[Foo].Instance;too;many;columns", //
|
||||
"TooFewColumns", //
|
||||
"Foo;Foo;Method[foo].Arg[0]", //
|
||||
"Foo;Foo;Method[foo].Argument[0-1]", //
|
||||
"Foo;Foo;Method[foo].Argument[*]", //
|
||||
"Foo;Foo;Method[foo].Argument", //
|
||||
"Foo;Foo;Method[foo].Member", //
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
private class SinkFromModel extends ModelInput::SinkModelCsv {
|
||||
override predicate row(string row) {
|
||||
row =
|
||||
[
|
||||
"~FooOrBar;Method[method].Argument[0];test-sink", //
|
||||
"Foo!;Method[sinkAnyArg].Argument[any];test-sink", //
|
||||
"Foo!;Method[sinkAnyNamedArg].Argument[any-named];test-sink", //
|
||||
"Foo!;Method[getSinks].ReturnValue.Element[any].Method[mySink].Argument[0];test-sink", //
|
||||
"Foo!;Method[arraySink].Argument[0].Element[any];test-sink", //
|
||||
"Foo!;Method[secondArrayElementIsSink].Argument[0].Element[1];test-sink", //
|
||||
"FuzzyLib!;Fuzzy.Method[fuzzyCall].Argument[0];test-sink"
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
module CustomConfig implements DataFlow::ConfigSig {
|
||||
predicate isSource(DataFlow::Node source) { DefaultFlowConfig::isSource(source) }
|
||||
|
||||
|
||||
@@ -1,15 +1,15 @@
|
||||
testFailures
|
||||
edges
|
||||
| json.rb:1:17:1:26 | call to source | json.rb:1:6:1:27 | call to parse | provenance | |
|
||||
| json.rb:2:18:2:27 | call to source | json.rb:2:6:2:28 | call to parse! | provenance | |
|
||||
| json.rb:3:16:3:25 | call to source | json.rb:3:6:3:26 | call to load | provenance | |
|
||||
| json.rb:4:19:4:28 | call to source | json.rb:4:6:4:29 | call to restore | provenance | |
|
||||
| json.rb:6:20:6:29 | call to source | json.rb:6:6:6:30 | call to generate | provenance | |
|
||||
| json.rb:7:25:7:34 | call to source | json.rb:7:6:7:35 | call to fast_generate | provenance | |
|
||||
| json.rb:8:27:8:36 | call to source | json.rb:8:6:8:37 | call to pretty_generate | provenance | |
|
||||
| json.rb:9:16:9:25 | call to source | json.rb:9:6:9:26 | call to dump | provenance | |
|
||||
| json.rb:10:19:10:28 | call to source | json.rb:10:6:10:29 | call to unparse | provenance | |
|
||||
| json.rb:11:24:11:33 | call to source | json.rb:11:6:11:34 | call to fast_unparse | provenance | |
|
||||
| json.rb:1:17:1:26 | call to source | json.rb:1:6:1:27 | call to parse | provenance | MaD:15 |
|
||||
| json.rb:2:18:2:27 | call to source | json.rb:2:6:2:28 | call to parse! | provenance | MaD:15 |
|
||||
| json.rb:3:16:3:25 | call to source | json.rb:3:6:3:26 | call to load | provenance | MaD:15 |
|
||||
| json.rb:4:19:4:28 | call to source | json.rb:4:6:4:29 | call to restore | provenance | MaD:15 |
|
||||
| json.rb:6:20:6:29 | call to source | json.rb:6:6:6:30 | call to generate | provenance | MaD:14 |
|
||||
| json.rb:7:25:7:34 | call to source | json.rb:7:6:7:35 | call to fast_generate | provenance | MaD:14 |
|
||||
| json.rb:8:27:8:36 | call to source | json.rb:8:6:8:37 | call to pretty_generate | provenance | MaD:14 |
|
||||
| json.rb:9:16:9:25 | call to source | json.rb:9:6:9:26 | call to dump | provenance | MaD:14 |
|
||||
| json.rb:10:19:10:28 | call to source | json.rb:10:6:10:29 | call to unparse | provenance | MaD:14 |
|
||||
| json.rb:11:24:11:33 | call to source | json.rb:11:6:11:34 | call to fast_unparse | provenance | MaD:14 |
|
||||
nodes
|
||||
| json.rb:1:6:1:27 | call to parse | semmle.label | call to parse |
|
||||
| json.rb:1:17:1:26 | call to source | semmle.label | call to source |
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
edges
|
||||
| LdapInjection.rb:5:5:5:6 | dc | LdapInjection.rb:25:23:25:49 | "ou=people,dc=#{...},dc=com" | provenance | |
|
||||
| LdapInjection.rb:5:5:5:6 | dc | LdapInjection.rb:25:23:25:49 | "ou=people,dc=#{...},dc=com" | provenance | AdditionalTaintStep |
|
||||
| LdapInjection.rb:5:10:5:15 | call to params | LdapInjection.rb:5:10:5:20 | ...[...] | provenance | |
|
||||
| LdapInjection.rb:5:10:5:20 | ...[...] | LdapInjection.rb:5:5:5:6 | dc | provenance | |
|
||||
| LdapInjection.rb:9:5:9:8 | name | LdapInjection.rb:29:62:29:73 | "cn=#{...}" | provenance | |
|
||||
| LdapInjection.rb:9:5:9:8 | name | LdapInjection.rb:29:62:29:73 | "cn=#{...}" | provenance | AdditionalTaintStep |
|
||||
| LdapInjection.rb:9:5:9:8 | name | LdapInjection.rb:33:88:33:91 | name | provenance | |
|
||||
| LdapInjection.rb:9:12:9:17 | call to params | LdapInjection.rb:9:12:9:29 | ...[...] | provenance | |
|
||||
| LdapInjection.rb:9:12:9:29 | ...[...] | LdapInjection.rb:9:5:9:8 | name | provenance | |
|
||||
|
||||
@@ -9,13 +9,13 @@ edges
|
||||
| ErbInjection.rb:11:11:11:14 | name | ErbInjection.rb:8:16:11:14 | ... % ... | provenance | |
|
||||
| SlimInjection.rb:5:5:5:8 | name | SlimInjection.rb:11:11:11:14 | name | provenance | |
|
||||
| SlimInjection.rb:5:5:5:8 | name | SlimInjection.rb:14:23:14:34 | { ... } [captured bad_text] | provenance | |
|
||||
| SlimInjection.rb:5:5:5:8 | name | SlimInjection.rb:23:23:23:35 | { ... } [captured bad2_text] | provenance | |
|
||||
| SlimInjection.rb:5:5:5:8 | name | SlimInjection.rb:23:23:23:35 | { ... } [captured bad2_text] | provenance | AdditionalTaintStep |
|
||||
| SlimInjection.rb:5:12:5:17 | call to params | SlimInjection.rb:5:12:5:24 | ...[...] | provenance | |
|
||||
| SlimInjection.rb:5:12:5:24 | ...[...] | SlimInjection.rb:5:5:5:8 | name | provenance | |
|
||||
| SlimInjection.rb:8:16:11:14 | ... % ... | SlimInjection.rb:14:23:14:34 | { ... } [captured bad_text] | provenance | |
|
||||
| SlimInjection.rb:11:11:11:14 | name | SlimInjection.rb:8:16:11:14 | ... % ... | provenance | |
|
||||
| SlimInjection.rb:14:23:14:34 | { ... } [captured bad_text] | SlimInjection.rb:14:25:14:32 | bad_text | provenance | |
|
||||
| SlimInjection.rb:23:23:23:35 | { ... } [captured bad2_text] | SlimInjection.rb:23:25:23:33 | bad2_text | provenance | |
|
||||
| SlimInjection.rb:14:23:14:34 | { ... } [captured bad_text] | SlimInjection.rb:14:25:14:32 | bad_text | provenance | heuristic-callback |
|
||||
| SlimInjection.rb:23:23:23:35 | { ... } [captured bad2_text] | SlimInjection.rb:23:25:23:33 | bad2_text | provenance | heuristic-callback |
|
||||
nodes
|
||||
| ErbInjection.rb:5:5:5:8 | name | semmle.label | name |
|
||||
| ErbInjection.rb:5:12:5:17 | call to params | semmle.label | call to params |
|
||||
|
||||
@@ -1,18 +1,18 @@
|
||||
edges
|
||||
| LibxmlInjection.rb:5:5:5:8 | name | LibxmlInjection.rb:21:31:21:41 | "//#{...}" | provenance | |
|
||||
| LibxmlInjection.rb:5:5:5:8 | name | LibxmlInjection.rb:27:25:27:35 | "//#{...}" | provenance | |
|
||||
| LibxmlInjection.rb:5:5:5:8 | name | LibxmlInjection.rb:21:31:21:41 | "//#{...}" | provenance | AdditionalTaintStep |
|
||||
| LibxmlInjection.rb:5:5:5:8 | name | LibxmlInjection.rb:27:25:27:35 | "//#{...}" | provenance | AdditionalTaintStep |
|
||||
| LibxmlInjection.rb:5:12:5:17 | call to params | LibxmlInjection.rb:5:12:5:29 | ...[...] | provenance | |
|
||||
| LibxmlInjection.rb:5:12:5:29 | ...[...] | LibxmlInjection.rb:5:5:5:8 | name | provenance | |
|
||||
| NokogiriInjection.rb:5:5:5:8 | name | NokogiriInjection.rb:21:23:21:33 | "//#{...}" | provenance | |
|
||||
| NokogiriInjection.rb:5:5:5:8 | name | NokogiriInjection.rb:27:26:27:36 | "//#{...}" | provenance | |
|
||||
| NokogiriInjection.rb:5:5:5:8 | name | NokogiriInjection.rb:33:29:33:39 | "//#{...}" | provenance | |
|
||||
| NokogiriInjection.rb:5:5:5:8 | name | NokogiriInjection.rb:41:15:41:25 | "//#{...}" | provenance | |
|
||||
| NokogiriInjection.rb:5:5:5:8 | name | NokogiriInjection.rb:51:16:51:26 | "//#{...}" | provenance | |
|
||||
| NokogiriInjection.rb:5:5:5:8 | name | NokogiriInjection.rb:21:23:21:33 | "//#{...}" | provenance | AdditionalTaintStep |
|
||||
| NokogiriInjection.rb:5:5:5:8 | name | NokogiriInjection.rb:27:26:27:36 | "//#{...}" | provenance | AdditionalTaintStep |
|
||||
| NokogiriInjection.rb:5:5:5:8 | name | NokogiriInjection.rb:33:29:33:39 | "//#{...}" | provenance | AdditionalTaintStep |
|
||||
| NokogiriInjection.rb:5:5:5:8 | name | NokogiriInjection.rb:41:15:41:25 | "//#{...}" | provenance | AdditionalTaintStep |
|
||||
| NokogiriInjection.rb:5:5:5:8 | name | NokogiriInjection.rb:51:16:51:26 | "//#{...}" | provenance | AdditionalTaintStep |
|
||||
| NokogiriInjection.rb:5:12:5:17 | call to params | NokogiriInjection.rb:5:12:5:29 | ...[...] | provenance | |
|
||||
| NokogiriInjection.rb:5:12:5:29 | ...[...] | NokogiriInjection.rb:5:5:5:8 | name | provenance | |
|
||||
| RexmlInjection.rb:5:5:5:8 | name | RexmlInjection.rb:21:40:21:50 | "//#{...}" | provenance | |
|
||||
| RexmlInjection.rb:5:5:5:8 | name | RexmlInjection.rb:27:40:27:50 | "//#{...}" | provenance | |
|
||||
| RexmlInjection.rb:5:5:5:8 | name | RexmlInjection.rb:35:28:35:38 | "//#{...}" | provenance | |
|
||||
| RexmlInjection.rb:5:5:5:8 | name | RexmlInjection.rb:21:40:21:50 | "//#{...}" | provenance | AdditionalTaintStep |
|
||||
| RexmlInjection.rb:5:5:5:8 | name | RexmlInjection.rb:27:40:27:50 | "//#{...}" | provenance | AdditionalTaintStep |
|
||||
| RexmlInjection.rb:5:5:5:8 | name | RexmlInjection.rb:35:28:35:38 | "//#{...}" | provenance | AdditionalTaintStep |
|
||||
| RexmlInjection.rb:5:12:5:17 | call to params | RexmlInjection.rb:5:12:5:29 | ...[...] | provenance | |
|
||||
| RexmlInjection.rb:5:12:5:29 | ...[...] | RexmlInjection.rb:5:5:5:8 | name | provenance | |
|
||||
nodes
|
||||
|
||||
@@ -8,10 +8,10 @@ edges
|
||||
| UnsafeYamlDeserialization.rb:32:5:32:13 | yaml_data | UnsafeYamlDeserialization.rb:33:32:33:40 | yaml_data | provenance | |
|
||||
| UnsafeYamlDeserialization.rb:32:5:32:13 | yaml_data | UnsafeYamlDeserialization.rb:34:37:34:45 | yaml_data | provenance | |
|
||||
| UnsafeYamlDeserialization.rb:32:5:32:13 | yaml_data | UnsafeYamlDeserialization.rb:35:32:35:40 | yaml_data | provenance | |
|
||||
| UnsafeYamlDeserialization.rb:32:5:32:13 | yaml_data | UnsafeYamlDeserialization.rb:37:14:37:33 | call to to_ruby | provenance | |
|
||||
| UnsafeYamlDeserialization.rb:32:5:32:13 | yaml_data | UnsafeYamlDeserialization.rb:38:14:38:43 | call to to_ruby | provenance | |
|
||||
| UnsafeYamlDeserialization.rb:32:5:32:13 | yaml_data | UnsafeYamlDeserialization.rb:39:14:39:48 | call to to_ruby | provenance | |
|
||||
| UnsafeYamlDeserialization.rb:32:5:32:13 | yaml_data | UnsafeYamlDeserialization.rb:49:14:49:32 | call to to_ruby | provenance | |
|
||||
| UnsafeYamlDeserialization.rb:32:5:32:13 | yaml_data | UnsafeYamlDeserialization.rb:37:14:37:33 | call to to_ruby | provenance | AdditionalTaintStep |
|
||||
| UnsafeYamlDeserialization.rb:32:5:32:13 | yaml_data | UnsafeYamlDeserialization.rb:38:14:38:43 | call to to_ruby | provenance | AdditionalTaintStep |
|
||||
| UnsafeYamlDeserialization.rb:32:5:32:13 | yaml_data | UnsafeYamlDeserialization.rb:39:14:39:48 | call to to_ruby | provenance | AdditionalTaintStep |
|
||||
| UnsafeYamlDeserialization.rb:32:5:32:13 | yaml_data | UnsafeYamlDeserialization.rb:49:14:49:32 | call to to_ruby | provenance | AdditionalTaintStep |
|
||||
| UnsafeYamlDeserialization.rb:32:17:32:22 | call to params | UnsafeYamlDeserialization.rb:32:17:32:28 | ...[...] | provenance | |
|
||||
| UnsafeYamlDeserialization.rb:32:17:32:28 | ...[...] | UnsafeYamlDeserialization.rb:32:5:32:13 | yaml_data | provenance | |
|
||||
nodes
|
||||
|
||||
@@ -6,8 +6,9 @@ edges
|
||||
| ArchiveApiPathTraversal.rb:15:9:15:14 | call to params | ArchiveApiPathTraversal.rb:15:9:15:25 | ...[...] | provenance | |
|
||||
| ArchiveApiPathTraversal.rb:15:9:15:25 | ...[...] | ArchiveApiPathTraversal.rb:75:11:75:18 | filename | provenance | |
|
||||
| ArchiveApiPathTraversal.rb:49:17:49:27 | destination | ArchiveApiPathTraversal.rb:50:36:64:7 | do ... end [captured destination] | provenance | |
|
||||
| ArchiveApiPathTraversal.rb:50:36:64:7 | do ... end [captured destination] | ArchiveApiPathTraversal.rb:51:16:63:9 | do ... end [captured destination] | provenance | |
|
||||
| ArchiveApiPathTraversal.rb:50:36:64:7 | do ... end [captured destination] | ArchiveApiPathTraversal.rb:51:16:63:9 | do ... end [captured destination] | provenance | heuristic-callback |
|
||||
| ArchiveApiPathTraversal.rb:51:16:63:9 | do ... end [captured destination] | ArchiveApiPathTraversal.rb:52:38:52:48 | destination | provenance | |
|
||||
| ArchiveApiPathTraversal.rb:51:16:63:9 | do ... end [captured destination] | ArchiveApiPathTraversal.rb:52:38:52:48 | destination | provenance | heuristic-callback |
|
||||
| ArchiveApiPathTraversal.rb:52:9:52:24 | destination_file | ArchiveApiPathTraversal.rb:59:21:59:36 | destination_file | provenance | |
|
||||
| ArchiveApiPathTraversal.rb:52:28:52:67 | call to join | ArchiveApiPathTraversal.rb:52:9:52:24 | destination_file | provenance | |
|
||||
| ArchiveApiPathTraversal.rb:52:38:52:48 | destination | ArchiveApiPathTraversal.rb:52:28:52:67 | call to join | provenance | |
|
||||
@@ -21,7 +22,7 @@ edges
|
||||
| tainted_path.rb:10:31:10:36 | call to params | tainted_path.rb:10:31:10:43 | ...[...] | provenance | |
|
||||
| tainted_path.rb:10:31:10:43 | ...[...] | tainted_path.rb:10:12:10:43 | call to absolute_path | provenance | |
|
||||
| tainted_path.rb:16:5:16:8 | path | tainted_path.rb:17:26:17:29 | path | provenance | |
|
||||
| tainted_path.rb:16:15:16:41 | call to dirname | tainted_path.rb:16:5:16:8 | path | provenance | |
|
||||
| tainted_path.rb:16:15:16:41 | call to dirname | tainted_path.rb:16:5:16:8 | path | provenance | AdditionalTaintStep |
|
||||
| tainted_path.rb:16:28:16:33 | call to params | tainted_path.rb:16:28:16:40 | ...[...] | provenance | |
|
||||
| tainted_path.rb:16:28:16:40 | ...[...] | tainted_path.rb:16:15:16:41 | call to dirname | provenance | |
|
||||
| tainted_path.rb:22:5:22:8 | path | tainted_path.rb:23:26:23:29 | path | provenance | |
|
||||
@@ -47,25 +48,25 @@ edges
|
||||
| tainted_path.rb:59:5:59:8 | path | tainted_path.rb:60:26:60:29 | path | provenance | |
|
||||
| tainted_path.rb:59:12:59:53 | call to new | tainted_path.rb:59:5:59:8 | path | provenance | |
|
||||
| tainted_path.rb:59:40:59:45 | call to params | tainted_path.rb:59:40:59:52 | ...[...] | provenance | |
|
||||
| tainted_path.rb:59:40:59:52 | ...[...] | tainted_path.rb:59:12:59:53 | call to new | provenance | |
|
||||
| tainted_path.rb:59:40:59:52 | ...[...] | tainted_path.rb:59:12:59:53 | call to new | provenance | MaD:0 |
|
||||
| tainted_path.rb:71:5:71:8 | path | tainted_path.rb:72:15:72:18 | path | provenance | |
|
||||
| tainted_path.rb:71:12:71:53 | call to new | tainted_path.rb:71:5:71:8 | path | provenance | |
|
||||
| tainted_path.rb:71:40:71:45 | call to params | tainted_path.rb:71:40:71:52 | ...[...] | provenance | |
|
||||
| tainted_path.rb:71:40:71:52 | ...[...] | tainted_path.rb:71:12:71:53 | call to new | provenance | |
|
||||
| tainted_path.rb:71:40:71:52 | ...[...] | tainted_path.rb:71:12:71:53 | call to new | provenance | MaD:0 |
|
||||
| tainted_path.rb:77:5:77:8 | path | tainted_path.rb:78:19:78:22 | path | provenance | |
|
||||
| tainted_path.rb:77:5:77:8 | path | tainted_path.rb:79:14:79:17 | path | provenance | |
|
||||
| tainted_path.rb:77:12:77:53 | call to new | tainted_path.rb:77:5:77:8 | path | provenance | |
|
||||
| tainted_path.rb:77:40:77:45 | call to params | tainted_path.rb:77:40:77:52 | ...[...] | provenance | |
|
||||
| tainted_path.rb:77:40:77:52 | ...[...] | tainted_path.rb:77:12:77:53 | call to new | provenance | |
|
||||
| tainted_path.rb:77:40:77:52 | ...[...] | tainted_path.rb:77:12:77:53 | call to new | provenance | MaD:0 |
|
||||
| tainted_path.rb:84:5:84:8 | path | tainted_path.rb:85:10:85:13 | path | provenance | |
|
||||
| tainted_path.rb:84:5:84:8 | path | tainted_path.rb:86:25:86:28 | path | provenance | |
|
||||
| tainted_path.rb:84:12:84:53 | call to new | tainted_path.rb:84:5:84:8 | path | provenance | |
|
||||
| tainted_path.rb:84:40:84:45 | call to params | tainted_path.rb:84:40:84:52 | ...[...] | provenance | |
|
||||
| tainted_path.rb:84:40:84:52 | ...[...] | tainted_path.rb:84:12:84:53 | call to new | provenance | |
|
||||
| tainted_path.rb:84:40:84:52 | ...[...] | tainted_path.rb:84:12:84:53 | call to new | provenance | MaD:0 |
|
||||
| tainted_path.rb:90:5:90:8 | path | tainted_path.rb:92:11:92:14 | path | provenance | |
|
||||
| tainted_path.rb:90:12:90:53 | call to new | tainted_path.rb:90:5:90:8 | path | provenance | |
|
||||
| tainted_path.rb:90:40:90:45 | call to params | tainted_path.rb:90:40:90:52 | ...[...] | provenance | |
|
||||
| tainted_path.rb:90:40:90:52 | ...[...] | tainted_path.rb:90:12:90:53 | call to new | provenance | |
|
||||
| tainted_path.rb:90:40:90:52 | ...[...] | tainted_path.rb:90:12:90:53 | call to new | provenance | MaD:0 |
|
||||
nodes
|
||||
| ArchiveApiPathTraversal.rb:5:26:5:31 | call to params | semmle.label | call to params |
|
||||
| ArchiveApiPathTraversal.rb:5:26:5:42 | ...[...] | semmle.label | ...[...] |
|
||||
|
||||
@@ -5,25 +5,25 @@ edges
|
||||
| CommandInjection.rb:6:9:6:11 | cmd | CommandInjection.rb:11:17:11:22 | #{...} | provenance | |
|
||||
| CommandInjection.rb:6:9:6:11 | cmd | CommandInjection.rb:13:9:13:14 | #{...} | provenance | |
|
||||
| CommandInjection.rb:6:9:6:11 | cmd | CommandInjection.rb:29:19:29:24 | #{...} | provenance | |
|
||||
| CommandInjection.rb:6:9:6:11 | cmd | CommandInjection.rb:33:24:33:36 | "echo #{...}" | provenance | |
|
||||
| CommandInjection.rb:6:9:6:11 | cmd | CommandInjection.rb:34:39:34:51 | "grep #{...}" | provenance | |
|
||||
| CommandInjection.rb:6:9:6:11 | cmd | CommandInjection.rb:33:24:33:36 | "echo #{...}" | provenance | AdditionalTaintStep |
|
||||
| CommandInjection.rb:6:9:6:11 | cmd | CommandInjection.rb:34:39:34:51 | "grep #{...}" | provenance | AdditionalTaintStep |
|
||||
| CommandInjection.rb:6:15:6:20 | call to params | CommandInjection.rb:6:15:6:26 | ...[...] | provenance | |
|
||||
| CommandInjection.rb:6:15:6:26 | ...[...] | CommandInjection.rb:6:9:6:11 | cmd | provenance | |
|
||||
| CommandInjection.rb:46:9:46:11 | cmd | CommandInjection.rb:50:24:50:36 | "echo #{...}" | provenance | |
|
||||
| CommandInjection.rb:46:9:46:11 | cmd | CommandInjection.rb:50:24:50:36 | "echo #{...}" | provenance | AdditionalTaintStep |
|
||||
| CommandInjection.rb:46:15:46:20 | call to params | CommandInjection.rb:46:15:46:26 | ...[...] | provenance | |
|
||||
| CommandInjection.rb:46:15:46:26 | ...[...] | CommandInjection.rb:46:9:46:11 | cmd | provenance | |
|
||||
| CommandInjection.rb:54:7:54:9 | cmd | CommandInjection.rb:59:14:59:16 | cmd | provenance | |
|
||||
| CommandInjection.rb:54:13:54:18 | call to params | CommandInjection.rb:54:13:54:24 | ...[...] | provenance | |
|
||||
| CommandInjection.rb:54:13:54:24 | ...[...] | CommandInjection.rb:54:7:54:9 | cmd | provenance | |
|
||||
| CommandInjection.rb:73:18:73:23 | number | CommandInjection.rb:74:14:74:29 | "echo #{...}" | provenance | |
|
||||
| CommandInjection.rb:81:23:81:33 | blah_number | CommandInjection.rb:82:14:82:34 | "echo #{...}" | provenance | |
|
||||
| CommandInjection.rb:91:22:91:37 | ...[...] | CommandInjection.rb:91:14:91:39 | "echo #{...}" | provenance | |
|
||||
| CommandInjection.rb:103:9:103:12 | file | CommandInjection.rb:104:16:104:28 | "cat #{...}" | provenance | |
|
||||
| CommandInjection.rb:73:18:73:23 | number | CommandInjection.rb:74:14:74:29 | "echo #{...}" | provenance | AdditionalTaintStep |
|
||||
| CommandInjection.rb:81:23:81:33 | blah_number | CommandInjection.rb:82:14:82:34 | "echo #{...}" | provenance | AdditionalTaintStep |
|
||||
| CommandInjection.rb:91:22:91:37 | ...[...] | CommandInjection.rb:91:14:91:39 | "echo #{...}" | provenance | AdditionalTaintStep |
|
||||
| CommandInjection.rb:103:9:103:12 | file | CommandInjection.rb:104:16:104:28 | "cat #{...}" | provenance | AdditionalTaintStep |
|
||||
| CommandInjection.rb:103:16:103:21 | call to params | CommandInjection.rb:103:16:103:28 | ...[...] | provenance | |
|
||||
| CommandInjection.rb:103:16:103:28 | ...[...] | CommandInjection.rb:103:9:103:12 | file | provenance | |
|
||||
| CommandInjection.rb:111:33:111:38 | call to params | CommandInjection.rb:111:33:111:44 | ...[...] | provenance | |
|
||||
| CommandInjection.rb:111:33:111:38 | call to params | CommandInjection.rb:111:33:111:44 | ...[...] | provenance | Sink:MaD:46 |
|
||||
| CommandInjection.rb:113:44:113:49 | call to params | CommandInjection.rb:113:44:113:54 | ...[...] | provenance | |
|
||||
| CommandInjection.rb:113:44:113:54 | ...[...] | CommandInjection.rb:113:41:113:56 | "#{...}" | provenance | |
|
||||
| CommandInjection.rb:113:44:113:54 | ...[...] | CommandInjection.rb:113:41:113:56 | "#{...}" | provenance | AdditionalTaintStep Sink:MaD:47 |
|
||||
nodes
|
||||
| CommandInjection.rb:6:9:6:11 | cmd | semmle.label | cmd |
|
||||
| CommandInjection.rb:6:15:6:20 | call to params | semmle.label | call to params |
|
||||
|
||||
@@ -25,7 +25,7 @@ edges
|
||||
| app/views/foo/stores/show.html.erb:40:64:40:87 | ... + ... [element] | app/views/foo/stores/show.html.erb:40:48:40:89 | call to [] [element :display_text, element] | provenance | |
|
||||
| app/views/foo/stores/show.html.erb:40:76:40:87 | call to display_text | app/views/foo/stores/show.html.erb:40:64:40:87 | ... + ... | provenance | |
|
||||
| app/views/foo/stores/show.html.erb:40:76:40:87 | call to display_text | app/views/foo/stores/show.html.erb:40:64:40:87 | ... + ... [element] | provenance | |
|
||||
| app/views/foo/stores/show.html.erb:86:17:86:28 | call to handle | app/views/foo/stores/show.html.erb:86:3:86:29 | call to sprintf | provenance | |
|
||||
| app/views/foo/stores/show.html.erb:86:17:86:28 | call to handle | app/views/foo/stores/show.html.erb:86:3:86:29 | call to sprintf | provenance | AdditionalTaintStep |
|
||||
nodes
|
||||
| app/controllers/foo/stores_controller.rb:8:5:8:6 | dt | semmle.label | dt |
|
||||
| app/controllers/foo/stores_controller.rb:8:10:8:29 | call to read | semmle.label | call to read |
|
||||
|
||||
@@ -1,47 +1,47 @@
|
||||
edges
|
||||
| ActiveRecordInjection.rb:8:25:8:28 | name | ActiveRecordInjection.rb:10:33:10:67 | "name='#{...}' and pass='#{...}'" | provenance | |
|
||||
| ActiveRecordInjection.rb:8:31:8:34 | pass | ActiveRecordInjection.rb:10:33:10:67 | "name='#{...}' and pass='#{...}'" | provenance | |
|
||||
| ActiveRecordInjection.rb:8:25:8:28 | name | ActiveRecordInjection.rb:10:33:10:67 | "name='#{...}' and pass='#{...}'" | provenance | AdditionalTaintStep |
|
||||
| ActiveRecordInjection.rb:8:31:8:34 | pass | ActiveRecordInjection.rb:10:33:10:67 | "name='#{...}' and pass='#{...}'" | provenance | AdditionalTaintStep |
|
||||
| ActiveRecordInjection.rb:20:22:20:30 | condition | ActiveRecordInjection.rb:23:16:23:24 | condition | provenance | |
|
||||
| ActiveRecordInjection.rb:35:30:35:35 | call to params | ActiveRecordInjection.rb:35:30:35:44 | ...[...] | provenance | |
|
||||
| ActiveRecordInjection.rb:39:18:39:23 | call to params | ActiveRecordInjection.rb:39:18:39:32 | ...[...] | provenance | |
|
||||
| ActiveRecordInjection.rb:43:29:43:34 | call to params | ActiveRecordInjection.rb:43:29:43:39 | ...[...] | provenance | |
|
||||
| ActiveRecordInjection.rb:43:29:43:39 | ...[...] | ActiveRecordInjection.rb:43:20:43:42 | "id = '#{...}'" | provenance | |
|
||||
| ActiveRecordInjection.rb:43:29:43:39 | ...[...] | ActiveRecordInjection.rb:43:20:43:42 | "id = '#{...}'" | provenance | AdditionalTaintStep |
|
||||
| ActiveRecordInjection.rb:48:30:48:35 | call to params | ActiveRecordInjection.rb:48:30:48:40 | ...[...] | provenance | |
|
||||
| ActiveRecordInjection.rb:48:30:48:40 | ...[...] | ActiveRecordInjection.rb:48:21:48:43 | "id = '#{...}'" | provenance | |
|
||||
| ActiveRecordInjection.rb:48:30:48:40 | ...[...] | ActiveRecordInjection.rb:48:21:48:43 | "id = '#{...}'" | provenance | AdditionalTaintStep |
|
||||
| ActiveRecordInjection.rb:52:21:52:45 | call to [] [element 0] | ActiveRecordInjection.rb:52:21:52:45 | call to [] | provenance | |
|
||||
| ActiveRecordInjection.rb:52:22:52:44 | "id = '#{...}'" | ActiveRecordInjection.rb:52:21:52:45 | call to [] [element 0] | provenance | |
|
||||
| ActiveRecordInjection.rb:52:31:52:36 | call to params | ActiveRecordInjection.rb:52:31:52:41 | ...[...] | provenance | |
|
||||
| ActiveRecordInjection.rb:52:31:52:41 | ...[...] | ActiveRecordInjection.rb:52:22:52:44 | "id = '#{...}'" | provenance | |
|
||||
| ActiveRecordInjection.rb:52:31:52:41 | ...[...] | ActiveRecordInjection.rb:52:22:52:44 | "id = '#{...}'" | provenance | AdditionalTaintStep |
|
||||
| ActiveRecordInjection.rb:57:22:57:46 | call to [] [element 0] | ActiveRecordInjection.rb:57:22:57:46 | call to [] | provenance | |
|
||||
| ActiveRecordInjection.rb:57:23:57:45 | "id = '#{...}'" | ActiveRecordInjection.rb:57:22:57:46 | call to [] [element 0] | provenance | |
|
||||
| ActiveRecordInjection.rb:57:32:57:37 | call to params | ActiveRecordInjection.rb:57:32:57:42 | ...[...] | provenance | |
|
||||
| ActiveRecordInjection.rb:57:32:57:42 | ...[...] | ActiveRecordInjection.rb:57:23:57:45 | "id = '#{...}'" | provenance | |
|
||||
| ActiveRecordInjection.rb:57:32:57:42 | ...[...] | ActiveRecordInjection.rb:57:23:57:45 | "id = '#{...}'" | provenance | AdditionalTaintStep |
|
||||
| ActiveRecordInjection.rb:62:21:62:26 | call to params | ActiveRecordInjection.rb:62:21:62:35 | ...[...] | provenance | |
|
||||
| ActiveRecordInjection.rb:62:21:62:35 | ...[...] | ActiveRecordInjection.rb:61:16:61:21 | <<-SQL | provenance | |
|
||||
| ActiveRecordInjection.rb:62:21:62:35 | ...[...] | ActiveRecordInjection.rb:61:16:61:21 | <<-SQL | provenance | AdditionalTaintStep |
|
||||
| ActiveRecordInjection.rb:68:34:68:39 | call to params | ActiveRecordInjection.rb:68:34:68:44 | ...[...] | provenance | |
|
||||
| ActiveRecordInjection.rb:68:34:68:44 | ...[...] | ActiveRecordInjection.rb:68:20:68:47 | "user.id = '#{...}'" | provenance | |
|
||||
| ActiveRecordInjection.rb:68:34:68:44 | ...[...] | ActiveRecordInjection.rb:68:20:68:47 | "user.id = '#{...}'" | provenance | AdditionalTaintStep |
|
||||
| ActiveRecordInjection.rb:70:23:70:28 | call to params | ActiveRecordInjection.rb:70:23:70:35 | ...[...] | provenance | |
|
||||
| ActiveRecordInjection.rb:70:23:70:35 | ...[...] | ActiveRecordInjection.rb:8:25:8:28 | name | provenance | |
|
||||
| ActiveRecordInjection.rb:70:38:70:43 | call to params | ActiveRecordInjection.rb:70:38:70:50 | ...[...] | provenance | |
|
||||
| ActiveRecordInjection.rb:70:38:70:50 | ...[...] | ActiveRecordInjection.rb:8:31:8:34 | pass | provenance | |
|
||||
| ActiveRecordInjection.rb:74:41:74:46 | call to params | ActiveRecordInjection.rb:74:41:74:51 | ...[...] | provenance | |
|
||||
| ActiveRecordInjection.rb:74:41:74:51 | ...[...] | ActiveRecordInjection.rb:74:32:74:54 | "id = '#{...}'" | provenance | |
|
||||
| ActiveRecordInjection.rb:74:41:74:51 | ...[...] | ActiveRecordInjection.rb:74:32:74:54 | "id = '#{...}'" | provenance | AdditionalTaintStep |
|
||||
| ActiveRecordInjection.rb:79:23:79:28 | call to params | ActiveRecordInjection.rb:79:23:79:35 | ...[...] | provenance | |
|
||||
| ActiveRecordInjection.rb:83:17:83:22 | call to params | ActiveRecordInjection.rb:83:17:83:31 | ...[...] | provenance | |
|
||||
| ActiveRecordInjection.rb:84:19:84:24 | call to params | ActiveRecordInjection.rb:84:19:84:33 | ...[...] | provenance | |
|
||||
| ActiveRecordInjection.rb:88:18:88:23 | call to params | ActiveRecordInjection.rb:88:18:88:35 | ...[...] | provenance | |
|
||||
| ActiveRecordInjection.rb:92:21:92:26 | call to params | ActiveRecordInjection.rb:92:21:92:35 | ...[...] | provenance | |
|
||||
| ActiveRecordInjection.rb:100:31:100:36 | call to params | ActiveRecordInjection.rb:100:31:100:52 | ...[...] | provenance | |
|
||||
| ActiveRecordInjection.rb:100:31:100:52 | ...[...] | ActiveRecordInjection.rb:100:20:100:55 | "name = '#{...}'" | provenance | |
|
||||
| ActiveRecordInjection.rb:100:31:100:52 | ...[...] | ActiveRecordInjection.rb:100:20:100:55 | "name = '#{...}'" | provenance | AdditionalTaintStep |
|
||||
| ActiveRecordInjection.rb:104:30:104:35 | call to params | ActiveRecordInjection.rb:104:30:104:51 | ...[...] | provenance | |
|
||||
| ActiveRecordInjection.rb:104:30:104:51 | ...[...] | ActiveRecordInjection.rb:104:19:104:54 | "name = '#{...}'" | provenance | |
|
||||
| ActiveRecordInjection.rb:104:30:104:51 | ...[...] | ActiveRecordInjection.rb:104:19:104:54 | "name = '#{...}'" | provenance | AdditionalTaintStep |
|
||||
| ActiveRecordInjection.rb:106:18:106:23 | call to params | ActiveRecordInjection.rb:106:18:106:35 | ...[...] | provenance | |
|
||||
| ActiveRecordInjection.rb:108:26:108:31 | call to params | ActiveRecordInjection.rb:108:26:108:40 | ...[...] | provenance | |
|
||||
| ActiveRecordInjection.rb:109:28:109:33 | call to params | ActiveRecordInjection.rb:109:28:109:42 | ...[...] | provenance | |
|
||||
| ActiveRecordInjection.rb:110:30:110:35 | call to params | ActiveRecordInjection.rb:110:30:110:47 | ...[...] | provenance | |
|
||||
| ActiveRecordInjection.rb:110:30:110:47 | ...[...] | ActiveRecordInjection.rb:110:25:110:49 | "b #{...}" | provenance | |
|
||||
| ActiveRecordInjection.rb:110:30:110:47 | ...[...] | ActiveRecordInjection.rb:110:25:110:49 | "b #{...}" | provenance | AdditionalTaintStep |
|
||||
| ActiveRecordInjection.rb:111:32:111:37 | call to params | ActiveRecordInjection.rb:111:32:111:49 | ...[...] | provenance | |
|
||||
| ActiveRecordInjection.rb:111:32:111:49 | ...[...] | ActiveRecordInjection.rb:111:27:111:51 | "b #{...}" | provenance | |
|
||||
| ActiveRecordInjection.rb:111:32:111:49 | ...[...] | ActiveRecordInjection.rb:111:27:111:51 | "b #{...}" | provenance | AdditionalTaintStep |
|
||||
| ActiveRecordInjection.rb:112:21:112:26 | call to params | ActiveRecordInjection.rb:112:21:112:35 | ...[...] | provenance | |
|
||||
| ActiveRecordInjection.rb:113:21:113:26 | call to params | ActiveRecordInjection.rb:113:21:113:35 | ...[...] | provenance | |
|
||||
| ActiveRecordInjection.rb:114:20:114:25 | call to params | ActiveRecordInjection.rb:114:20:114:34 | ...[...] | provenance | |
|
||||
@@ -50,7 +50,7 @@ edges
|
||||
| ActiveRecordInjection.rb:122:29:122:34 | call to params | ActiveRecordInjection.rb:122:29:122:39 | ...[...] | provenance | |
|
||||
| ActiveRecordInjection.rb:128:5:128:6 | ps | ActiveRecordInjection.rb:129:11:129:12 | ps | provenance | |
|
||||
| ActiveRecordInjection.rb:128:10:128:15 | call to params | ActiveRecordInjection.rb:128:5:128:6 | ps | provenance | |
|
||||
| ActiveRecordInjection.rb:129:5:129:7 | uid | ActiveRecordInjection.rb:130:5:130:9 | uidEq | provenance | |
|
||||
| ActiveRecordInjection.rb:129:5:129:7 | uid | ActiveRecordInjection.rb:130:5:130:9 | uidEq | provenance | AdditionalTaintStep |
|
||||
| ActiveRecordInjection.rb:129:11:129:12 | ps | ActiveRecordInjection.rb:129:11:129:17 | ...[...] | provenance | |
|
||||
| ActiveRecordInjection.rb:129:11:129:17 | ...[...] | ActiveRecordInjection.rb:129:5:129:7 | uid | provenance | |
|
||||
| ActiveRecordInjection.rb:130:5:130:9 | uidEq | ActiveRecordInjection.rb:134:20:134:32 | ... + ... | provenance | |
|
||||
@@ -61,32 +61,32 @@ edges
|
||||
| ActiveRecordInjection.rb:167:21:167:26 | call to params | ActiveRecordInjection.rb:167:21:167:44 | ...[...] | provenance | |
|
||||
| ActiveRecordInjection.rb:167:21:167:44 | ...[...] | ActiveRecordInjection.rb:20:22:20:30 | condition | provenance | |
|
||||
| ActiveRecordInjection.rb:181:59:181:64 | call to params | ActiveRecordInjection.rb:181:59:181:74 | ...[...] | provenance | |
|
||||
| ActiveRecordInjection.rb:181:59:181:74 | ...[...] | ActiveRecordInjection.rb:181:27:181:76 | "this is an unsafe annotation:..." | provenance | |
|
||||
| ActiveRecordInjection.rb:181:59:181:74 | ...[...] | ActiveRecordInjection.rb:181:27:181:76 | "this is an unsafe annotation:..." | provenance | AdditionalTaintStep |
|
||||
| ActiveRecordInjection.rb:192:5:192:13 | my_params | ActiveRecordInjection.rb:193:47:193:55 | my_params | provenance | |
|
||||
| ActiveRecordInjection.rb:192:17:192:32 | call to permitted_params | ActiveRecordInjection.rb:192:5:192:13 | my_params | provenance | |
|
||||
| ActiveRecordInjection.rb:193:5:193:9 | query | ActiveRecordInjection.rb:194:37:194:41 | query | provenance | |
|
||||
| ActiveRecordInjection.rb:193:47:193:55 | my_params | ActiveRecordInjection.rb:193:47:193:65 | ...[...] | provenance | |
|
||||
| ActiveRecordInjection.rb:193:47:193:65 | ...[...] | ActiveRecordInjection.rb:193:5:193:9 | query | provenance | |
|
||||
| ActiveRecordInjection.rb:193:47:193:65 | ...[...] | ActiveRecordInjection.rb:193:5:193:9 | query | provenance | AdditionalTaintStep |
|
||||
| ActiveRecordInjection.rb:199:5:199:10 | call to params | ActiveRecordInjection.rb:199:5:199:27 | call to require | provenance | |
|
||||
| ActiveRecordInjection.rb:199:5:199:27 | call to require | ActiveRecordInjection.rb:199:5:199:59 | call to permit | provenance | |
|
||||
| ActiveRecordInjection.rb:199:5:199:59 | call to permit | ActiveRecordInjection.rb:192:17:192:32 | call to permitted_params | provenance | |
|
||||
| ActiveRecordInjection.rb:199:5:199:59 | call to permit | ActiveRecordInjection.rb:203:77:203:92 | call to permitted_params | provenance | |
|
||||
| ActiveRecordInjection.rb:199:5:199:59 | call to permit | ActiveRecordInjection.rb:204:69:204:84 | call to permitted_params | provenance | |
|
||||
| ActiveRecordInjection.rb:203:77:203:92 | call to permitted_params | ActiveRecordInjection.rb:203:77:203:102 | ...[...] | provenance | |
|
||||
| ActiveRecordInjection.rb:203:77:203:102 | ...[...] | ActiveRecordInjection.rb:203:43:203:104 | "SELECT * FROM users WHERE id ..." | provenance | |
|
||||
| ActiveRecordInjection.rb:203:77:203:102 | ...[...] | ActiveRecordInjection.rb:203:43:203:104 | "SELECT * FROM users WHERE id ..." | provenance | AdditionalTaintStep |
|
||||
| ActiveRecordInjection.rb:204:69:204:84 | call to permitted_params | ActiveRecordInjection.rb:204:69:204:94 | ...[...] | provenance | |
|
||||
| ActiveRecordInjection.rb:204:69:204:94 | ...[...] | ActiveRecordInjection.rb:204:35:204:96 | "SELECT * FROM users WHERE id ..." | provenance | |
|
||||
| ActiveRecordInjection.rb:209:24:209:27 | role | ActiveRecordInjection.rb:209:38:209:53 | "role = #{...}" | provenance | |
|
||||
| ActiveRecordInjection.rb:204:69:204:94 | ...[...] | ActiveRecordInjection.rb:204:35:204:96 | "SELECT * FROM users WHERE id ..." | provenance | AdditionalTaintStep |
|
||||
| ActiveRecordInjection.rb:209:24:209:27 | role | ActiveRecordInjection.rb:209:38:209:53 | "role = #{...}" | provenance | AdditionalTaintStep |
|
||||
| ActiveRecordInjection.rb:215:29:215:34 | call to params | ActiveRecordInjection.rb:215:29:215:41 | ...[...] | provenance | |
|
||||
| ActiveRecordInjection.rb:215:29:215:41 | ...[...] | ActiveRecordInjection.rb:209:24:209:27 | role | provenance | |
|
||||
| ArelInjection.rb:4:5:4:8 | name | ArelInjection.rb:6:20:6:61 | "SELECT * FROM users WHERE nam..." | provenance | |
|
||||
| ArelInjection.rb:4:5:4:8 | name | ArelInjection.rb:7:39:7:80 | "SELECT * FROM users WHERE nam..." | provenance | |
|
||||
| ArelInjection.rb:4:5:4:8 | name | ArelInjection.rb:6:20:6:61 | "SELECT * FROM users WHERE nam..." | provenance | AdditionalTaintStep |
|
||||
| ArelInjection.rb:4:5:4:8 | name | ArelInjection.rb:7:39:7:80 | "SELECT * FROM users WHERE nam..." | provenance | AdditionalTaintStep |
|
||||
| ArelInjection.rb:4:12:4:17 | call to params | ArelInjection.rb:4:12:4:29 | ...[...] | provenance | |
|
||||
| ArelInjection.rb:4:12:4:29 | ...[...] | ArelInjection.rb:4:5:4:8 | name | provenance | |
|
||||
| PgInjection.rb:6:5:6:8 | name | PgInjection.rb:13:5:13:8 | qry1 | provenance | |
|
||||
| PgInjection.rb:6:5:6:8 | name | PgInjection.rb:19:5:19:8 | qry2 | provenance | |
|
||||
| PgInjection.rb:6:5:6:8 | name | PgInjection.rb:31:5:31:8 | qry3 | provenance | |
|
||||
| PgInjection.rb:6:5:6:8 | name | PgInjection.rb:43:5:43:8 | qry3 | provenance | |
|
||||
| PgInjection.rb:6:5:6:8 | name | PgInjection.rb:13:5:13:8 | qry1 | provenance | AdditionalTaintStep |
|
||||
| PgInjection.rb:6:5:6:8 | name | PgInjection.rb:19:5:19:8 | qry2 | provenance | AdditionalTaintStep |
|
||||
| PgInjection.rb:6:5:6:8 | name | PgInjection.rb:31:5:31:8 | qry3 | provenance | AdditionalTaintStep |
|
||||
| PgInjection.rb:6:5:6:8 | name | PgInjection.rb:43:5:43:8 | qry3 | provenance | AdditionalTaintStep |
|
||||
| PgInjection.rb:6:12:6:17 | call to params | PgInjection.rb:6:12:6:24 | ...[...] | provenance | |
|
||||
| PgInjection.rb:6:12:6:24 | ...[...] | PgInjection.rb:6:5:6:8 | name | provenance | |
|
||||
| PgInjection.rb:13:5:13:8 | qry1 | PgInjection.rb:14:15:14:18 | qry1 | provenance | |
|
||||
|
||||
@@ -14,13 +14,13 @@ edges
|
||||
| CodeInjection.rb:5:12:5:17 | call to params | CodeInjection.rb:5:12:5:24 | ...[...] | provenance | |
|
||||
| CodeInjection.rb:5:12:5:24 | ...[...] | CodeInjection.rb:5:5:5:8 | code | provenance | |
|
||||
| CodeInjection.rb:5:12:5:24 | ...[...] | CodeInjection.rb:5:5:5:8 | code | provenance | |
|
||||
| CodeInjection.rb:38:24:38:27 | code | CodeInjection.rb:38:10:38:28 | call to escape | provenance | |
|
||||
| CodeInjection.rb:38:24:38:27 | code | CodeInjection.rb:38:10:38:28 | call to escape | provenance | |
|
||||
| CodeInjection.rb:38:24:38:27 | code | CodeInjection.rb:38:10:38:28 | call to escape | provenance | MaD:21 |
|
||||
| CodeInjection.rb:38:24:38:27 | code | CodeInjection.rb:38:10:38:28 | call to escape | provenance | MaD:21 |
|
||||
| CodeInjection.rb:78:5:78:8 | code | CodeInjection.rb:80:16:80:19 | code | provenance | |
|
||||
| CodeInjection.rb:78:5:78:8 | code | CodeInjection.rb:86:10:86:25 | ... + ... | provenance | |
|
||||
| CodeInjection.rb:78:5:78:8 | code | CodeInjection.rb:86:10:86:37 | ... + ... | provenance | |
|
||||
| CodeInjection.rb:78:5:78:8 | code | CodeInjection.rb:86:22:86:25 | code | provenance | |
|
||||
| CodeInjection.rb:78:5:78:8 | code | CodeInjection.rb:88:10:88:32 | "prefix_#{...}_suffix" | provenance | |
|
||||
| CodeInjection.rb:78:5:78:8 | code | CodeInjection.rb:88:10:88:32 | "prefix_#{...}_suffix" | provenance | AdditionalTaintStep |
|
||||
| CodeInjection.rb:78:5:78:8 | code | CodeInjection.rb:90:10:90:13 | code | provenance | |
|
||||
| CodeInjection.rb:78:5:78:8 | code | CodeInjection.rb:90:10:90:13 | code | provenance | |
|
||||
| CodeInjection.rb:78:12:78:17 | call to params | CodeInjection.rb:78:12:78:24 | ...[...] | provenance | |
|
||||
|
||||
@@ -11,14 +11,14 @@ edges
|
||||
| app/controllers/users_controller.rb:23:20:23:44 | call to sub | app/controllers/users_controller.rb:24:18:26:7 | do ... end [captured unsanitized2] | provenance | |
|
||||
| app/controllers/users_controller.rb:23:20:23:44 | call to sub | app/controllers/users_controller.rb:27:16:27:39 | ... + ... | provenance | |
|
||||
| app/controllers/users_controller.rb:23:20:23:44 | call to sub | app/controllers/users_controller.rb:27:28:27:39 | unsanitized2 | provenance | |
|
||||
| app/controllers/users_controller.rb:24:18:26:7 | do ... end [captured unsanitized2] | app/controllers/users_controller.rb:25:7:25:18 | unsanitized2 | provenance | |
|
||||
| app/controllers/users_controller.rb:24:18:26:7 | do ... end [captured unsanitized2] | app/controllers/users_controller.rb:25:7:25:18 | unsanitized2 | provenance | heuristic-callback |
|
||||
| app/controllers/users_controller.rb:27:16:27:39 | ... + ... [element] | app/controllers/users_controller.rb:27:16:27:39 | ... + ... | provenance | |
|
||||
| app/controllers/users_controller.rb:27:28:27:39 | unsanitized2 | app/controllers/users_controller.rb:27:16:27:39 | ... + ... [element] | provenance | |
|
||||
| app/controllers/users_controller.rb:33:19:33:25 | call to cookies | app/controllers/users_controller.rb:33:19:33:31 | ...[...] | provenance | |
|
||||
| app/controllers/users_controller.rb:33:19:33:31 | ...[...] | app/controllers/users_controller.rb:34:31:34:45 | { ... } [captured unsanitized] | provenance | |
|
||||
| app/controllers/users_controller.rb:33:19:33:31 | ...[...] | app/controllers/users_controller.rb:35:31:35:57 | { ... } [captured unsanitized] | provenance | |
|
||||
| app/controllers/users_controller.rb:34:31:34:45 | { ... } [captured unsanitized] | app/controllers/users_controller.rb:34:33:34:43 | unsanitized | provenance | |
|
||||
| app/controllers/users_controller.rb:35:31:35:57 | { ... } [captured unsanitized] | app/controllers/users_controller.rb:35:45:35:55 | unsanitized | provenance | |
|
||||
| app/controllers/users_controller.rb:34:31:34:45 | { ... } [captured unsanitized] | app/controllers/users_controller.rb:34:33:34:43 | unsanitized | provenance | heuristic-callback |
|
||||
| app/controllers/users_controller.rb:35:31:35:57 | { ... } [captured unsanitized] | app/controllers/users_controller.rb:35:45:35:55 | unsanitized | provenance | heuristic-callback |
|
||||
| app/controllers/users_controller.rb:35:33:35:55 | ... + ... [element] | app/controllers/users_controller.rb:35:33:35:55 | ... + ... | provenance | |
|
||||
| app/controllers/users_controller.rb:35:45:35:55 | unsanitized | app/controllers/users_controller.rb:35:33:35:55 | ... + ... | provenance | |
|
||||
| app/controllers/users_controller.rb:35:45:35:55 | unsanitized | app/controllers/users_controller.rb:35:33:35:55 | ... + ... [element] | provenance | |
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
edges
|
||||
| RegExpInjection.rb:4:5:4:8 | name | RegExpInjection.rb:5:13:5:21 | /#{...}/ | provenance | |
|
||||
| RegExpInjection.rb:4:5:4:8 | name | RegExpInjection.rb:5:13:5:21 | /#{...}/ | provenance | AdditionalTaintStep |
|
||||
| RegExpInjection.rb:4:12:4:17 | call to params | RegExpInjection.rb:4:12:4:24 | ...[...] | provenance | |
|
||||
| RegExpInjection.rb:4:12:4:24 | ...[...] | RegExpInjection.rb:4:5:4:8 | name | provenance | |
|
||||
| RegExpInjection.rb:10:5:10:8 | name | RegExpInjection.rb:11:13:11:27 | /foo#{...}bar/ | provenance | |
|
||||
| RegExpInjection.rb:10:5:10:8 | name | RegExpInjection.rb:11:13:11:27 | /foo#{...}bar/ | provenance | AdditionalTaintStep |
|
||||
| RegExpInjection.rb:10:12:10:17 | call to params | RegExpInjection.rb:10:12:10:24 | ...[...] | provenance | |
|
||||
| RegExpInjection.rb:10:12:10:24 | ...[...] | RegExpInjection.rb:10:5:10:8 | name | provenance | |
|
||||
| RegExpInjection.rb:16:5:16:8 | name | RegExpInjection.rb:17:24:17:27 | name | provenance | |
|
||||
|
||||
@@ -13,11 +13,11 @@ edges
|
||||
| tainted_format_string.rb:33:32:33:46 | ...[...] | tainted_format_string.rb:33:12:33:46 | ... + ... | provenance | |
|
||||
| tainted_format_string.rb:33:32:33:46 | ...[...] | tainted_format_string.rb:33:12:33:46 | ... + ... [element] | provenance | |
|
||||
| tainted_format_string.rb:36:30:36:35 | call to params | tainted_format_string.rb:36:30:36:44 | ...[...] | provenance | |
|
||||
| tainted_format_string.rb:36:30:36:44 | ...[...] | tainted_format_string.rb:36:12:36:46 | "A log message: #{...}" | provenance | |
|
||||
| tainted_format_string.rb:36:30:36:44 | ...[...] | tainted_format_string.rb:36:12:36:46 | "A log message: #{...}" | provenance | AdditionalTaintStep |
|
||||
| tainted_format_string.rb:39:22:39:27 | call to params | tainted_format_string.rb:39:22:39:36 | ...[...] | provenance | |
|
||||
| tainted_format_string.rb:39:22:39:36 | ...[...] | tainted_format_string.rb:39:5:39:45 | "A log message #{...} %{foo}" | provenance | |
|
||||
| tainted_format_string.rb:39:22:39:36 | ...[...] | tainted_format_string.rb:39:5:39:45 | "A log message #{...} %{foo}" | provenance | AdditionalTaintStep |
|
||||
| tainted_format_string.rb:42:22:42:27 | call to params | tainted_format_string.rb:42:22:42:36 | ...[...] | provenance | |
|
||||
| tainted_format_string.rb:42:22:42:36 | ...[...] | tainted_format_string.rb:42:5:42:43 | "A log message #{...} %08x" | provenance | |
|
||||
| tainted_format_string.rb:42:22:42:36 | ...[...] | tainted_format_string.rb:42:5:42:43 | "A log message #{...} %08x" | provenance | AdditionalTaintStep |
|
||||
nodes
|
||||
| tainted_format_string.rb:4:12:4:17 | call to params | semmle.label | call to params |
|
||||
| tainted_format_string.rb:4:12:4:26 | ...[...] | semmle.label | ...[...] |
|
||||
|
||||
@@ -8,7 +8,7 @@ edges
|
||||
| logging.rb:3:1:3:8 | password | logging.rb:19:33:19:40 | password | provenance | |
|
||||
| logging.rb:3:1:3:8 | password | logging.rb:21:44:21:51 | password | provenance | |
|
||||
| logging.rb:3:1:3:8 | password | logging.rb:23:33:23:40 | password | provenance | |
|
||||
| logging.rb:3:1:3:8 | password | logging.rb:26:18:26:34 | "pw: #{...}" | provenance | |
|
||||
| logging.rb:3:1:3:8 | password | logging.rb:26:18:26:34 | "pw: #{...}" | provenance | AdditionalTaintStep |
|
||||
| logging.rb:3:1:3:8 | password | logging.rb:28:26:28:33 | password | provenance | |
|
||||
| logging.rb:3:12:3:45 | "043697b96909e03ca907599d6420555f" | logging.rb:3:1:3:8 | password | provenance | |
|
||||
| logging.rb:30:1:30:4 | hsh1 [element :password] | logging.rb:38:20:38:23 | hsh1 [element :password] | provenance | |
|
||||
|
||||
@@ -20,8 +20,8 @@ edges
|
||||
| app/controllers/users_controller.rb:35:20:35:53 | "ff295f8648a406c37fbe378377320e4c" | app/controllers/users_controller.rb:35:5:35:16 | new_password | provenance | |
|
||||
| app/controllers/users_controller.rb:42:5:42:16 | new_password | app/controllers/users_controller.rb:44:21:44:32 | new_password | provenance | |
|
||||
| app/controllers/users_controller.rb:42:20:42:53 | "78ffbec583b546bd073efd898f833184" | app/controllers/users_controller.rb:42:5:42:16 | new_password | provenance | |
|
||||
| app/controllers/users_controller.rb:58:5:58:16 | new_password | app/controllers/users_controller.rb:61:25:61:53 | "password: #{...}\\n" | provenance | |
|
||||
| app/controllers/users_controller.rb:58:5:58:16 | new_password | app/controllers/users_controller.rb:64:35:64:61 | "password: #{...}" | provenance | |
|
||||
| app/controllers/users_controller.rb:58:5:58:16 | new_password | app/controllers/users_controller.rb:61:25:61:53 | "password: #{...}\\n" | provenance | AdditionalTaintStep |
|
||||
| app/controllers/users_controller.rb:58:5:58:16 | new_password | app/controllers/users_controller.rb:64:35:64:61 | "password: #{...}" | provenance | AdditionalTaintStep |
|
||||
| app/controllers/users_controller.rb:58:20:58:53 | "0157af7c38cbdd24f1616de4e5321861" | app/controllers/users_controller.rb:58:5:58:16 | new_password | provenance | |
|
||||
| app/models/user.rb:3:5:3:16 | new_password | app/models/user.rb:5:27:5:38 | new_password | provenance | |
|
||||
| app/models/user.rb:3:20:3:53 | "06c38c6a8a9c11a9d3b209a3193047b4" | app/models/user.rb:3:5:3:16 | new_password | provenance | |
|
||||
|
||||
@@ -44,9 +44,9 @@ edges
|
||||
| UnsafeDeserialization.rb:137:5:137:13 | yaml_data | UnsafeDeserialization.rb:138:32:138:40 | yaml_data | provenance | |
|
||||
| UnsafeDeserialization.rb:137:5:137:13 | yaml_data | UnsafeDeserialization.rb:139:37:139:45 | yaml_data | provenance | |
|
||||
| UnsafeDeserialization.rb:137:5:137:13 | yaml_data | UnsafeDeserialization.rb:140:32:140:40 | yaml_data | provenance | |
|
||||
| UnsafeDeserialization.rb:137:5:137:13 | yaml_data | UnsafeDeserialization.rb:142:14:142:33 | call to to_ruby | provenance | |
|
||||
| UnsafeDeserialization.rb:137:5:137:13 | yaml_data | UnsafeDeserialization.rb:143:14:143:43 | call to to_ruby | provenance | |
|
||||
| UnsafeDeserialization.rb:137:5:137:13 | yaml_data | UnsafeDeserialization.rb:144:14:144:48 | call to to_ruby | provenance | |
|
||||
| UnsafeDeserialization.rb:137:5:137:13 | yaml_data | UnsafeDeserialization.rb:142:14:142:33 | call to to_ruby | provenance | AdditionalTaintStep |
|
||||
| UnsafeDeserialization.rb:137:5:137:13 | yaml_data | UnsafeDeserialization.rb:143:14:143:43 | call to to_ruby | provenance | AdditionalTaintStep |
|
||||
| UnsafeDeserialization.rb:137:5:137:13 | yaml_data | UnsafeDeserialization.rb:144:14:144:48 | call to to_ruby | provenance | AdditionalTaintStep |
|
||||
| UnsafeDeserialization.rb:137:17:137:22 | call to params | UnsafeDeserialization.rb:137:17:137:28 | ...[...] | provenance | |
|
||||
| UnsafeDeserialization.rb:137:17:137:28 | ...[...] | UnsafeDeserialization.rb:137:5:137:13 | yaml_data | provenance | |
|
||||
| UnsafeDeserialization.rb:149:5:149:14 | plist_data | UnsafeDeserialization.rb:150:30:150:39 | plist_data | provenance | |
|
||||
|
||||
@@ -5,7 +5,7 @@ edges
|
||||
| UrlRedirect.rb:24:31:24:36 | call to params | UrlRedirect.rb:24:17:24:37 | call to filter_params | provenance | |
|
||||
| UrlRedirect.rb:24:31:24:36 | call to params | UrlRedirect.rb:93:21:93:32 | input_params | provenance | |
|
||||
| UrlRedirect.rb:34:20:34:25 | call to params | UrlRedirect.rb:34:20:34:31 | ...[...] | provenance | |
|
||||
| UrlRedirect.rb:34:20:34:31 | ...[...] | UrlRedirect.rb:34:17:34:37 | "#{...}/foo" | provenance | |
|
||||
| UrlRedirect.rb:34:20:34:31 | ...[...] | UrlRedirect.rb:34:17:34:37 | "#{...}/foo" | provenance | AdditionalTaintStep |
|
||||
| UrlRedirect.rb:58:17:58:22 | call to params | UrlRedirect.rb:58:17:58:28 | ...[...] | provenance | |
|
||||
| UrlRedirect.rb:63:38:63:43 | call to params | UrlRedirect.rb:63:38:63:49 | ...[...] | provenance | |
|
||||
| UrlRedirect.rb:68:38:68:43 | call to params | UrlRedirect.rb:68:38:68:49 | ...[...] | provenance | |
|
||||
|
||||
@@ -98,3 +98,40 @@ end
|
||||
Rails.routes.draw do
|
||||
get "/r9", to: "users#route9"
|
||||
end
|
||||
|
||||
class DomainController < ActionController::Base
|
||||
KNOWN_HOST = "example.org"
|
||||
|
||||
def hello
|
||||
begin
|
||||
target_url = URI.parse(params[:url])
|
||||
|
||||
# Redirect if the URL is either relative or on a known good host
|
||||
if !target_url.host || target_url.host == KNOWN_HOST
|
||||
redirect_to target_url.to_s
|
||||
else
|
||||
redirect_to "/error.html" # Redirect to error page if the host is not known
|
||||
end
|
||||
rescue URI::InvalidURIError
|
||||
# Handle the exception, for example, by redirecting to a safe page
|
||||
redirect_to "/error.html"
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
class ConstController < ActionController::Base
|
||||
VALID_REDIRECTS = [
|
||||
"http://cwe.mitre.org/data/definitions/601.html",
|
||||
"http://cwe.mitre.org/data/definitions/79.html"
|
||||
].freeze
|
||||
|
||||
def hello
|
||||
# GOOD: the request parameter is validated against a known list of URLs
|
||||
target_url = params[:url]
|
||||
if VALID_REDIRECTS.include?(target_url)
|
||||
redirect_to target_url
|
||||
else
|
||||
redirect_to "/error.html"
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -0,0 +1,84 @@
|
||||
edges
|
||||
| test.rb:43:9:43:14 | call to params | test.rb:43:9:43:29 | call to require | provenance | |
|
||||
| test.rb:43:9:43:29 | call to require | test.rb:43:9:43:37 | call to permit! | provenance | |
|
||||
| test.rb:43:9:43:37 | call to permit! | test.rb:8:18:8:28 | call to user_params | provenance | |
|
||||
| test.rb:43:9:43:37 | call to permit! | test.rb:18:20:18:30 | call to user_params | provenance | |
|
||||
| test.rb:43:9:43:37 | call to permit! | test.rb:19:21:19:31 | call to user_params | provenance | |
|
||||
| test.rb:43:9:43:37 | call to permit! | test.rb:20:22:20:32 | call to user_params | provenance | |
|
||||
| test.rb:43:9:43:37 | call to permit! | test.rb:21:21:21:31 | call to user_params | provenance | |
|
||||
| test.rb:43:9:43:37 | call to permit! | test.rb:22:22:22:32 | call to user_params | provenance | |
|
||||
| test.rb:43:9:43:37 | call to permit! | test.rb:25:21:25:31 | call to user_params | provenance | |
|
||||
| test.rb:43:9:43:37 | call to permit! | test.rb:26:24:26:34 | call to user_params | provenance | |
|
||||
| test.rb:43:9:43:37 | call to permit! | test.rb:27:22:27:32 | call to user_params | provenance | |
|
||||
| test.rb:43:9:43:37 | call to permit! | test.rb:28:25:28:35 | call to user_params | provenance | |
|
||||
| test.rb:43:9:43:37 | call to permit! | test.rb:29:21:29:31 | call to user_params | provenance | |
|
||||
| test.rb:43:9:43:37 | call to permit! | test.rb:31:32:31:42 | call to user_params | provenance | |
|
||||
| test.rb:43:9:43:37 | call to permit! | test.rb:32:33:32:43 | call to user_params | provenance | |
|
||||
| test.rb:43:9:43:37 | call to permit! | test.rb:33:36:33:46 | call to user_params | provenance | |
|
||||
| test.rb:43:9:43:37 | call to permit! | test.rb:34:32:34:42 | call to user_params | provenance | |
|
||||
| test.rb:43:9:43:37 | call to permit! | test.rb:35:33:35:43 | call to user_params | provenance | |
|
||||
| test.rb:43:9:43:37 | call to permit! | test.rb:36:26:36:36 | call to user_params | provenance | |
|
||||
| test.rb:47:9:47:9 | x | test.rb:48:9:48:9 | x | provenance | |
|
||||
| test.rb:47:13:47:18 | call to params | test.rb:47:13:47:25 | ...[...] | provenance | |
|
||||
| test.rb:47:13:47:25 | ...[...] | test.rb:47:9:47:9 | x | provenance | |
|
||||
| test.rb:48:9:48:9 | [post] x | test.rb:49:18:49:18 | x | provenance | |
|
||||
| test.rb:48:9:48:9 | x | test.rb:48:9:48:9 | [post] x | provenance | |
|
||||
| test.rb:51:18:51:23 | call to params | test.rb:51:18:51:40 | call to permit | provenance | |
|
||||
| test.rb:52:18:52:23 | call to params | test.rb:52:18:52:69 | call to permit | provenance | |
|
||||
| test.rb:53:18:53:23 | call to params | test.rb:53:18:53:35 | call to to_unsafe_h | provenance | |
|
||||
nodes
|
||||
| test.rb:8:18:8:28 | call to user_params | semmle.label | call to user_params |
|
||||
| test.rb:18:20:18:30 | call to user_params | semmle.label | call to user_params |
|
||||
| test.rb:19:21:19:31 | call to user_params | semmle.label | call to user_params |
|
||||
| test.rb:20:22:20:32 | call to user_params | semmle.label | call to user_params |
|
||||
| test.rb:21:21:21:31 | call to user_params | semmle.label | call to user_params |
|
||||
| test.rb:22:22:22:32 | call to user_params | semmle.label | call to user_params |
|
||||
| test.rb:25:21:25:31 | call to user_params | semmle.label | call to user_params |
|
||||
| test.rb:26:24:26:34 | call to user_params | semmle.label | call to user_params |
|
||||
| test.rb:27:22:27:32 | call to user_params | semmle.label | call to user_params |
|
||||
| test.rb:28:25:28:35 | call to user_params | semmle.label | call to user_params |
|
||||
| test.rb:29:21:29:31 | call to user_params | semmle.label | call to user_params |
|
||||
| test.rb:31:32:31:42 | call to user_params | semmle.label | call to user_params |
|
||||
| test.rb:32:33:32:43 | call to user_params | semmle.label | call to user_params |
|
||||
| test.rb:33:36:33:46 | call to user_params | semmle.label | call to user_params |
|
||||
| test.rb:34:32:34:42 | call to user_params | semmle.label | call to user_params |
|
||||
| test.rb:35:33:35:43 | call to user_params | semmle.label | call to user_params |
|
||||
| test.rb:36:26:36:36 | call to user_params | semmle.label | call to user_params |
|
||||
| test.rb:43:9:43:14 | call to params | semmle.label | call to params |
|
||||
| test.rb:43:9:43:29 | call to require | semmle.label | call to require |
|
||||
| test.rb:43:9:43:37 | call to permit! | semmle.label | call to permit! |
|
||||
| test.rb:47:9:47:9 | x | semmle.label | x |
|
||||
| test.rb:47:13:47:18 | call to params | semmle.label | call to params |
|
||||
| test.rb:47:13:47:25 | ...[...] | semmle.label | ...[...] |
|
||||
| test.rb:48:9:48:9 | [post] x | semmle.label | [post] x |
|
||||
| test.rb:48:9:48:9 | x | semmle.label | x |
|
||||
| test.rb:49:18:49:18 | x | semmle.label | x |
|
||||
| test.rb:51:18:51:23 | call to params | semmle.label | call to params |
|
||||
| test.rb:51:18:51:40 | call to permit | semmle.label | call to permit |
|
||||
| test.rb:52:18:52:23 | call to params | semmle.label | call to params |
|
||||
| test.rb:52:18:52:69 | call to permit | semmle.label | call to permit |
|
||||
| test.rb:53:18:53:23 | call to params | semmle.label | call to params |
|
||||
| test.rb:53:18:53:35 | call to to_unsafe_h | semmle.label | call to to_unsafe_h |
|
||||
subpaths
|
||||
#select
|
||||
| test.rb:8:18:8:28 | call to user_params | test.rb:43:9:43:14 | call to params | test.rb:8:18:8:28 | call to user_params | This mass assignment operation can assign user-controlled attributes from $@. | test.rb:43:9:43:14 | call to params | this remote flow source |
|
||||
| test.rb:18:20:18:30 | call to user_params | test.rb:43:9:43:14 | call to params | test.rb:18:20:18:30 | call to user_params | This mass assignment operation can assign user-controlled attributes from $@. | test.rb:43:9:43:14 | call to params | this remote flow source |
|
||||
| test.rb:19:21:19:31 | call to user_params | test.rb:43:9:43:14 | call to params | test.rb:19:21:19:31 | call to user_params | This mass assignment operation can assign user-controlled attributes from $@. | test.rb:43:9:43:14 | call to params | this remote flow source |
|
||||
| test.rb:20:22:20:32 | call to user_params | test.rb:43:9:43:14 | call to params | test.rb:20:22:20:32 | call to user_params | This mass assignment operation can assign user-controlled attributes from $@. | test.rb:43:9:43:14 | call to params | this remote flow source |
|
||||
| test.rb:21:21:21:31 | call to user_params | test.rb:43:9:43:14 | call to params | test.rb:21:21:21:31 | call to user_params | This mass assignment operation can assign user-controlled attributes from $@. | test.rb:43:9:43:14 | call to params | this remote flow source |
|
||||
| test.rb:22:22:22:32 | call to user_params | test.rb:43:9:43:14 | call to params | test.rb:22:22:22:32 | call to user_params | This mass assignment operation can assign user-controlled attributes from $@. | test.rb:43:9:43:14 | call to params | this remote flow source |
|
||||
| test.rb:25:21:25:31 | call to user_params | test.rb:43:9:43:14 | call to params | test.rb:25:21:25:31 | call to user_params | This mass assignment operation can assign user-controlled attributes from $@. | test.rb:43:9:43:14 | call to params | this remote flow source |
|
||||
| test.rb:26:24:26:34 | call to user_params | test.rb:43:9:43:14 | call to params | test.rb:26:24:26:34 | call to user_params | This mass assignment operation can assign user-controlled attributes from $@. | test.rb:43:9:43:14 | call to params | this remote flow source |
|
||||
| test.rb:27:22:27:32 | call to user_params | test.rb:43:9:43:14 | call to params | test.rb:27:22:27:32 | call to user_params | This mass assignment operation can assign user-controlled attributes from $@. | test.rb:43:9:43:14 | call to params | this remote flow source |
|
||||
| test.rb:28:25:28:35 | call to user_params | test.rb:43:9:43:14 | call to params | test.rb:28:25:28:35 | call to user_params | This mass assignment operation can assign user-controlled attributes from $@. | test.rb:43:9:43:14 | call to params | this remote flow source |
|
||||
| test.rb:29:21:29:31 | call to user_params | test.rb:43:9:43:14 | call to params | test.rb:29:21:29:31 | call to user_params | This mass assignment operation can assign user-controlled attributes from $@. | test.rb:43:9:43:14 | call to params | this remote flow source |
|
||||
| test.rb:31:32:31:42 | call to user_params | test.rb:43:9:43:14 | call to params | test.rb:31:32:31:42 | call to user_params | This mass assignment operation can assign user-controlled attributes from $@. | test.rb:43:9:43:14 | call to params | this remote flow source |
|
||||
| test.rb:32:33:32:43 | call to user_params | test.rb:43:9:43:14 | call to params | test.rb:32:33:32:43 | call to user_params | This mass assignment operation can assign user-controlled attributes from $@. | test.rb:43:9:43:14 | call to params | this remote flow source |
|
||||
| test.rb:33:36:33:46 | call to user_params | test.rb:43:9:43:14 | call to params | test.rb:33:36:33:46 | call to user_params | This mass assignment operation can assign user-controlled attributes from $@. | test.rb:43:9:43:14 | call to params | this remote flow source |
|
||||
| test.rb:34:32:34:42 | call to user_params | test.rb:43:9:43:14 | call to params | test.rb:34:32:34:42 | call to user_params | This mass assignment operation can assign user-controlled attributes from $@. | test.rb:43:9:43:14 | call to params | this remote flow source |
|
||||
| test.rb:35:33:35:43 | call to user_params | test.rb:43:9:43:14 | call to params | test.rb:35:33:35:43 | call to user_params | This mass assignment operation can assign user-controlled attributes from $@. | test.rb:43:9:43:14 | call to params | this remote flow source |
|
||||
| test.rb:36:26:36:36 | call to user_params | test.rb:43:9:43:14 | call to params | test.rb:36:26:36:36 | call to user_params | This mass assignment operation can assign user-controlled attributes from $@. | test.rb:43:9:43:14 | call to params | this remote flow source |
|
||||
| test.rb:49:18:49:18 | x | test.rb:47:13:47:18 | call to params | test.rb:49:18:49:18 | x | This mass assignment operation can assign user-controlled attributes from $@. | test.rb:47:13:47:18 | call to params | this remote flow source |
|
||||
| test.rb:51:18:51:40 | call to permit | test.rb:51:18:51:23 | call to params | test.rb:51:18:51:40 | call to permit | This mass assignment operation can assign user-controlled attributes from $@. | test.rb:51:18:51:23 | call to params | this remote flow source |
|
||||
| test.rb:52:18:52:69 | call to permit | test.rb:52:18:52:23 | call to params | test.rb:52:18:52:69 | call to permit | This mass assignment operation can assign user-controlled attributes from $@. | test.rb:52:18:52:23 | call to params | this remote flow source |
|
||||
| test.rb:53:18:53:35 | call to to_unsafe_h | test.rb:53:18:53:23 | call to params | test.rb:53:18:53:35 | call to to_unsafe_h | This mass assignment operation can assign user-controlled attributes from $@. | test.rb:53:18:53:23 | call to params | this remote flow source |
|
||||
@@ -0,0 +1 @@
|
||||
queries/security/cwe-915/MassAssignment.ql
|
||||
56
ruby/ql/test/query-tests/security/cwe-915/test.rb
Normal file
56
ruby/ql/test/query-tests/security/cwe-915/test.rb
Normal file
@@ -0,0 +1,56 @@
|
||||
class User < ApplicationRecord
|
||||
|
||||
end
|
||||
|
||||
class UserController < ActionController::Base
|
||||
def create
|
||||
# BAD: arbitrary params are permitted to be used for this assignment
|
||||
User.new(user_params).save!
|
||||
end
|
||||
|
||||
def create2
|
||||
# GOOD: the permitted parameters are explicitly specified
|
||||
User.new(params[:user].permit(:name,:address))
|
||||
end
|
||||
|
||||
def create3
|
||||
# each BAD
|
||||
User.build(user_params)
|
||||
User.create(user_params)
|
||||
User.create!(user_params)
|
||||
User.insert(user_params)
|
||||
User.insert!(user_params)
|
||||
User.insert_all([user_params])
|
||||
User.insert_all!([user_params])
|
||||
User.update(user_params)
|
||||
User.update(7, user_params)
|
||||
User.update!(user_params)
|
||||
User.update!(7, user_params)
|
||||
User.upsert(user_params)
|
||||
User.upsert([user_params])
|
||||
User.find_or_create_by(user_params)
|
||||
User.find_or_create_by!(user_params)
|
||||
User.find_or_initialize_by(user_params)
|
||||
User.create_or_find_by(user_params)
|
||||
User.create_or_find_by!(user_params)
|
||||
User.create_with(user_params)
|
||||
|
||||
user = User.where(name:"abc")
|
||||
user.update(user_params)
|
||||
end
|
||||
|
||||
def user_params
|
||||
params.require(:user).permit!
|
||||
end
|
||||
|
||||
def create4
|
||||
x = params[:user]
|
||||
x.permit!
|
||||
User.new(x) # BAD
|
||||
User.new(x.permit(:name,:address)) # GOOD
|
||||
User.new(params.permit(user: {})) # BAD
|
||||
User.new(params.permit(user: [:name, :address, {friends:{}}])) # BAD
|
||||
User.new(params.to_unsafe_h) # BAD
|
||||
User.new(params.permit(user: [:name, :address]).to_unsafe_h) # GOOD
|
||||
end
|
||||
end
|
||||
@@ -1,5 +1,5 @@
|
||||
edges
|
||||
| ServerSideRequestForgery.rb:10:9:10:28 | users_service_domain | ServerSideRequestForgery.rb:11:31:11:62 | "#{...}/logins" | provenance | |
|
||||
| ServerSideRequestForgery.rb:10:9:10:28 | users_service_domain | ServerSideRequestForgery.rb:11:31:11:62 | "#{...}/logins" | provenance | AdditionalTaintStep |
|
||||
| ServerSideRequestForgery.rb:10:32:10:37 | call to params | ServerSideRequestForgery.rb:10:32:10:60 | ...[...] | provenance | |
|
||||
| ServerSideRequestForgery.rb:10:32:10:60 | ...[...] | ServerSideRequestForgery.rb:10:9:10:28 | users_service_domain | provenance | |
|
||||
| ServerSideRequestForgery.rb:15:33:15:38 | call to params | ServerSideRequestForgery.rb:15:33:15:44 | ...[...] | provenance | |
|
||||
|
||||
Reference in New Issue
Block a user