Merge branch 'main' into js/graph-export

This commit is contained in:
Asger F
2024-04-16 20:23:33 +02:00
1236 changed files with 37405 additions and 42510 deletions

View File

@@ -1,4 +1,4 @@
load("@rules_pkg//:mappings.bzl", "pkg_files")
load("@rules_pkg//pkg:mappings.bzl", "pkg_files")
package(default_visibility = ["//ruby:__pkg__"])

View File

@@ -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

View File

@@ -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 {

View File

@@ -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"
}
}
}

View File

@@ -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) {

View File

@@ -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) {

View File

@@ -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.

View File

@@ -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, _)

View File

@@ -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, _)
}
/**

View File

@@ -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)
)
}
}
}

View 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]']

View File

@@ -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()

View 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']

View File

@@ -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",
]
}
}
}
}

View File

@@ -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

View 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']

View File

@@ -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",
]
}
}
}

View File

@@ -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']

View File

@@ -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`.

View File

@@ -0,0 +1,7 @@
extensions:
- addsTo:
pack: codeql/ruby-all
extensible: summaryModel
data:
- ['Regexp!', 'Method[escape,quote]', 'Argument[0]', 'ReturnValue', 'taint']

View File

@@ -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"
}
}
}

View File

@@ -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

View File

@@ -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

View File

@@ -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`.

View 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']

View File

@@ -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",
]
}
}
}

View File

@@ -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" }

View File

@@ -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()

View File

@@ -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 }
}
}

View 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>;

View File

@@ -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")
}
}
/**

View File

@@ -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")
}
}
/**

View File

@@ -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`.

View File

@@ -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) {

View File

@@ -15,4 +15,5 @@ dependencies:
codeql/util: ${workspace}
dataExtensions:
- codeql/ruby/frameworks/**/model.yml
- codeql/ruby/frameworks/**/*.model.yml
warnOnImplicitThis: true

View 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.

View File

@@ -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

View File

@@ -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

View File

@@ -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>

View File

@@ -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

View File

@@ -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

View File

@@ -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

View 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>

View 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"

View File

@@ -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

View File

@@ -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

View File

@@ -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, _, _, _, _)
)
}
}

View File

@@ -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 | |

View File

@@ -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 | |

View File

@@ -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] |

View File

@@ -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']

View File

@@ -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) }

View File

@@ -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 |

View File

@@ -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 | |

View File

@@ -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 |

View File

@@ -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

View File

@@ -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

View File

@@ -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 | ...[...] |

View File

@@ -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 |

View File

@@ -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 |

View File

@@ -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 | |

View File

@@ -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 | |

View File

@@ -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 | |

View File

@@ -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 | |

View File

@@ -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 | ...[...] |

View File

@@ -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 | |

View File

@@ -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 | |

View File

@@ -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 | |

View File

@@ -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 | |

View File

@@ -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

View File

@@ -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 |

View File

@@ -0,0 +1 @@
queries/security/cwe-915/MassAssignment.ql

View 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

View File

@@ -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 | |