mirror of
https://github.com/github/codeql.git
synced 2025-12-17 01:03:14 +01:00
Merge branch 'main' into redsun82/cmake-generator-prototype
This commit is contained in:
@@ -885,7 +885,7 @@ module TestOutput {
|
||||
/**
|
||||
* Gets a string used to resolve ties in node and edge ordering.
|
||||
*/
|
||||
string getOrderDisambuigation() { result = "" }
|
||||
string getOrderDisambiguation() { result = "" }
|
||||
}
|
||||
|
||||
query predicate nodes(RelevantNode n, string attr, string val) {
|
||||
@@ -900,7 +900,7 @@ module TestOutput {
|
||||
order by
|
||||
l.getFile().getBaseName(), l.getFile().getAbsolutePath(), l.getStartLine(),
|
||||
l.getStartColumn(), l.getEndLine(), l.getEndColumn(), p.toString(),
|
||||
p.getOrderDisambuigation()
|
||||
p.getOrderDisambiguation()
|
||||
)
|
||||
).toString()
|
||||
}
|
||||
@@ -923,7 +923,7 @@ module TestOutput {
|
||||
order by
|
||||
l.getFile().getBaseName(), l.getFile().getAbsolutePath(), l.getStartLine(),
|
||||
l.getStartColumn(), l.getEndLine(), l.getEndColumn(), t.toString(), s.toString(),
|
||||
s.getOrderDisambuigation()
|
||||
s.getOrderDisambiguation()
|
||||
)
|
||||
).toString()
|
||||
}
|
||||
|
||||
@@ -202,7 +202,7 @@ private predicate isFork(State q, InputSymbol s1, InputSymbol s2, State r1, Stat
|
||||
//
|
||||
// We additionally require that the there exists another InfiniteRepetitionQuantifier `mid` on the path from `q` to itself.
|
||||
// This is done to avoid flagging regular expressions such as `/(a?)*b/` - that only has polynomial runtime, and is detected by `js/polynomial-redos`.
|
||||
// The below code is therefore a heuritic, that only flags regular expressions such as `/(a*)*b/`,
|
||||
// The below code is therefore a heuristic, that only flags regular expressions such as `/(a*)*b/`,
|
||||
// and does not flag regular expressions such as `/(a?b?)c/`, but the latter pattern is not used frequently.
|
||||
r1 = r2 and
|
||||
q1 = q2 and
|
||||
|
||||
@@ -76,7 +76,7 @@ class StateTuple extends TStateTuple {
|
||||
StateTuple() { this = MkStateTuple(q1, q2, q3) }
|
||||
|
||||
/**
|
||||
* Gest a string repesentation of this tuple.
|
||||
* Gest a string representation of this tuple.
|
||||
*/
|
||||
string toString() { result = "(" + q1 + ", " + q2 + ", " + q3 + ")" }
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/**
|
||||
* Provides precicates for reasoning about bad tag filter vulnerabilities.
|
||||
* Provides predicates for reasoning about bad tag filter vulnerabilities.
|
||||
*/
|
||||
|
||||
import regexp.RegexpMatching
|
||||
@@ -65,7 +65,7 @@ predicate isBadRegexpFilter(HtmlMatchingRegExp regexp, string msg) {
|
||||
regexp.matches("<!-- foo --!>") and
|
||||
exists(int a, int b | a != b |
|
||||
regexp.fillsCaptureGroup("<!-- foo -->", a) and
|
||||
// <!-- foo --> might be ambigously parsed (matching both capture groups), and that is ok here.
|
||||
// <!-- foo --> might be ambiguously parsed (matching both capture groups), and that is ok here.
|
||||
regexp.fillsCaptureGroup("<!-- foo --!>", b) and
|
||||
not regexp.fillsCaptureGroup("<!-- foo --!>", a) and
|
||||
msg =
|
||||
|
||||
@@ -202,7 +202,7 @@ private predicate isFork(State q, InputSymbol s1, InputSymbol s2, State r1, Stat
|
||||
//
|
||||
// We additionally require that the there exists another InfiniteRepetitionQuantifier `mid` on the path from `q` to itself.
|
||||
// This is done to avoid flagging regular expressions such as `/(a?)*b/` - that only has polynomial runtime, and is detected by `js/polynomial-redos`.
|
||||
// The below code is therefore a heuritic, that only flags regular expressions such as `/(a*)*b/`,
|
||||
// The below code is therefore a heuristic, that only flags regular expressions such as `/(a*)*b/`,
|
||||
// and does not flag regular expressions such as `/(a?b?)c/`, but the latter pattern is not used frequently.
|
||||
r1 = r2 and
|
||||
q1 = q2 and
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/**
|
||||
* Provides precicates for reasoning about which strings are matched by a regular expression,
|
||||
* Provides predicates for reasoning about which strings are matched by a regular expression,
|
||||
* and for testing which capture groups are filled when a particular regexp matches a string.
|
||||
*/
|
||||
|
||||
|
||||
@@ -76,7 +76,7 @@ class StateTuple extends TStateTuple {
|
||||
StateTuple() { this = MkStateTuple(q1, q2, q3) }
|
||||
|
||||
/**
|
||||
* Gest a string repesentation of this tuple.
|
||||
* Gest a string representation of this tuple.
|
||||
*/
|
||||
string toString() { result = "(" + q1 + ", " + q2 + ", " + q3 + ")" }
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/**
|
||||
* Provides precicates for reasoning about bad tag filter vulnerabilities.
|
||||
* Provides predicates for reasoning about bad tag filter vulnerabilities.
|
||||
*/
|
||||
|
||||
import regexp.RegexpMatching
|
||||
@@ -65,7 +65,7 @@ predicate isBadRegexpFilter(HtmlMatchingRegExp regexp, string msg) {
|
||||
regexp.matches("<!-- foo --!>") and
|
||||
exists(int a, int b | a != b |
|
||||
regexp.fillsCaptureGroup("<!-- foo -->", a) and
|
||||
// <!-- foo --> might be ambigously parsed (matching both capture groups), and that is ok here.
|
||||
// <!-- foo --> might be ambiguously parsed (matching both capture groups), and that is ok here.
|
||||
regexp.fillsCaptureGroup("<!-- foo --!>", b) and
|
||||
not regexp.fillsCaptureGroup("<!-- foo --!>", a) and
|
||||
msg =
|
||||
|
||||
@@ -202,7 +202,7 @@ private predicate isFork(State q, InputSymbol s1, InputSymbol s2, State r1, Stat
|
||||
//
|
||||
// We additionally require that the there exists another InfiniteRepetitionQuantifier `mid` on the path from `q` to itself.
|
||||
// This is done to avoid flagging regular expressions such as `/(a?)*b/` - that only has polynomial runtime, and is detected by `js/polynomial-redos`.
|
||||
// The below code is therefore a heuritic, that only flags regular expressions such as `/(a*)*b/`,
|
||||
// The below code is therefore a heuristic, that only flags regular expressions such as `/(a*)*b/`,
|
||||
// and does not flag regular expressions such as `/(a?b?)c/`, but the latter pattern is not used frequently.
|
||||
r1 = r2 and
|
||||
q1 = q2 and
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/**
|
||||
* Provides precicates for reasoning about which strings are matched by a regular expression,
|
||||
* Provides predicates for reasoning about which strings are matched by a regular expression,
|
||||
* and for testing which capture groups are filled when a particular regexp matches a string.
|
||||
*/
|
||||
|
||||
|
||||
@@ -76,7 +76,7 @@ class StateTuple extends TStateTuple {
|
||||
StateTuple() { this = MkStateTuple(q1, q2, q3) }
|
||||
|
||||
/**
|
||||
* Gest a string repesentation of this tuple.
|
||||
* Gest a string representation of this tuple.
|
||||
*/
|
||||
string toString() { result = "(" + q1 + ", " + q2 + ", " + q3 + ")" }
|
||||
|
||||
|
||||
@@ -216,7 +216,7 @@ struct Visitor<'a> {
|
||||
schema: &'a NodeTypeMap,
|
||||
/// A stack for gathering information from child nodes. Whenever a node is
|
||||
/// entered the parent's [Label], child counter, and an empty list is pushed.
|
||||
/// All children append their data to the the list. When the visitor leaves a
|
||||
/// All children append their data to the list. When the visitor leaves a
|
||||
/// node the list containing the child data is popped from the stack and
|
||||
/// matched against the dbscheme for the node. If the expectations are met
|
||||
/// the corresponding row definitions are added to the trap_output.
|
||||
|
||||
@@ -43,7 +43,7 @@ pub enum FieldTypeInfo {
|
||||
},
|
||||
|
||||
/// The field can be one of several tokens, so the db type will be an `int`
|
||||
/// with a `case @foo.kind` for each possiblity.
|
||||
/// with a `case @foo.kind` for each possibility.
|
||||
ReservedWordInt(BTreeMap<String, (usize, String)>),
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,4 @@
|
||||
---
|
||||
category: minorAnalysis
|
||||
---
|
||||
* `ActiveJob::Serializers.deserialize` is considered to be a code execution sink.
|
||||
@@ -898,7 +898,7 @@ module API {
|
||||
/** Gets the `subclass` edge label. */
|
||||
LabelSubclass subclass() { any() }
|
||||
|
||||
/** Gets the label representing the given keword argument/parameter. */
|
||||
/** Gets the label representing the given keyword argument/parameter. */
|
||||
LabelKeywordParameter keywordParameter(string name) { result.getName() = name }
|
||||
|
||||
/** Gets the label representing the `n`th positional argument/parameter. */
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
private import codeql.ruby.frameworks.Core
|
||||
private import codeql.ruby.frameworks.ActionCable
|
||||
private import codeql.ruby.frameworks.ActionController
|
||||
private import codeql.ruby.frameworks.ActiveJob
|
||||
private import codeql.ruby.frameworks.ActionMailer
|
||||
private import codeql.ruby.frameworks.ActiveRecord
|
||||
private import codeql.ruby.frameworks.ActiveResource
|
||||
|
||||
@@ -106,7 +106,7 @@ class MethodCall extends Call instanceof MethodCallImpl {
|
||||
final Block getBlock() { result = super.getBlockImpl() }
|
||||
|
||||
/**
|
||||
* Holds if the safe nagivation operator (`&.`) is used in this call.
|
||||
* Holds if the safe navigation operator (`&.`) is used in this call.
|
||||
* ```rb
|
||||
* foo&.empty?
|
||||
* ```
|
||||
|
||||
@@ -65,7 +65,7 @@ class ConstantValue extends TConstantValue {
|
||||
/** Holds if this is the string value `s`. */
|
||||
predicate isString(string s) { s = this.getString() }
|
||||
|
||||
/** Gets the symbol value (exluding the `:` prefix), if this is a symbol. */
|
||||
/** Gets the symbol value (excluding the `:` prefix), if this is a symbol. */
|
||||
string getSymbol() { this = TSymbol(result) }
|
||||
|
||||
/** Holds if this is the symbol value `:s`. */
|
||||
|
||||
@@ -394,7 +394,7 @@ private module ResolveImpl {
|
||||
|
||||
/**
|
||||
* The qualified names of the ancestors of a class/module. The ancestors should be an ordered list
|
||||
* of the ancestores of `prepend`ed modules, the module itself , the ancestors or `include`d modules
|
||||
* of the ancestors of `prepend`ed modules, the module itself , the ancestors or `include`d modules
|
||||
* and the ancestors of the super class. The priority value only distinguishes the kind of ancestor,
|
||||
* it does not order the ancestors within a group of the same kind. This is an over-approximation, however,
|
||||
* computing the precise order is tricky because it depends on the evaluation/file loading order.
|
||||
|
||||
@@ -885,7 +885,7 @@ module TestOutput {
|
||||
/**
|
||||
* Gets a string used to resolve ties in node and edge ordering.
|
||||
*/
|
||||
string getOrderDisambuigation() { result = "" }
|
||||
string getOrderDisambiguation() { result = "" }
|
||||
}
|
||||
|
||||
query predicate nodes(RelevantNode n, string attr, string val) {
|
||||
@@ -900,7 +900,7 @@ module TestOutput {
|
||||
order by
|
||||
l.getFile().getBaseName(), l.getFile().getAbsolutePath(), l.getStartLine(),
|
||||
l.getStartColumn(), l.getEndLine(), l.getEndColumn(), p.toString(),
|
||||
p.getOrderDisambuigation()
|
||||
p.getOrderDisambiguation()
|
||||
)
|
||||
).toString()
|
||||
}
|
||||
@@ -923,7 +923,7 @@ module TestOutput {
|
||||
order by
|
||||
l.getFile().getBaseName(), l.getFile().getAbsolutePath(), l.getStartLine(),
|
||||
l.getStartColumn(), l.getEndLine(), l.getEndColumn(), t.toString(), s.toString(),
|
||||
s.getOrderDisambuigation()
|
||||
s.getOrderDisambiguation()
|
||||
)
|
||||
).toString()
|
||||
}
|
||||
|
||||
@@ -46,7 +46,7 @@ module SummaryComponent {
|
||||
|
||||
/**
|
||||
* Gets a summary component that represents an element in a collection at a specific
|
||||
* known index `cv`, or an uknown index.
|
||||
* known index `cv`, or an unknown index.
|
||||
*/
|
||||
SummaryComponent elementKnownOrUnknown(ConstantValue cv) {
|
||||
result = SC::content(TKnownOrUnknownElementContent(TKnownElementContent(cv)))
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/**
|
||||
* Provides an extension point for for modeling user-controlled data.
|
||||
* Provides an extension point for modeling user-controlled data.
|
||||
* Such data is often used as data-flow sources in security queries.
|
||||
*/
|
||||
|
||||
|
||||
@@ -1165,8 +1165,8 @@ private module PostUpdateNodes {
|
||||
ExprPostUpdateNode() { this = TExprPostUpdateNode(e) }
|
||||
|
||||
override ExprNode getPreUpdateNode() {
|
||||
// For compund arguments, such as `m(if b then x else y)`, we want the leaf nodes
|
||||
// `[post] x` and `[post] y` to have two pre-update nodes: (1) the compund argument,
|
||||
// For compound arguments, such as `m(if b then x else y)`, we want the leaf nodes
|
||||
// `[post] x` and `[post] y` to have two pre-update nodes: (1) the compound argument,
|
||||
// `if b then x else y`; and the (2) the underlying expressions; `x` and `y`,
|
||||
// respectively.
|
||||
//
|
||||
|
||||
@@ -64,7 +64,7 @@ predicate uninitializedWrite(Cfg::EntryBasicBlock bb, int i, LocalVariable v) {
|
||||
i = -1
|
||||
}
|
||||
|
||||
/** Holds if `bb` contains a caputured read of variable `v`. */
|
||||
/** Holds if `bb` contains a captured read of variable `v`. */
|
||||
pragma[noinline]
|
||||
private predicate hasCapturedVariableRead(Cfg::BasicBlock bb, LocalVariable v) {
|
||||
exists(LocalVariableReadAccess read |
|
||||
@@ -74,7 +74,7 @@ private predicate hasCapturedVariableRead(Cfg::BasicBlock bb, LocalVariable v) {
|
||||
)
|
||||
}
|
||||
|
||||
/** Holds if `bb` contains a caputured write to variable `v`. */
|
||||
/** Holds if `bb` contains a captured write to variable `v`. */
|
||||
pragma[noinline]
|
||||
private predicate writesCapturedVariable(Cfg::BasicBlock bb, LocalVariable v) {
|
||||
exists(LocalVariableWriteAccess write |
|
||||
|
||||
@@ -417,7 +417,7 @@ module Rbi {
|
||||
override ReturnType getReturnType() { result = ReturnsCall.super.getReturnType() }
|
||||
}
|
||||
|
||||
/** A call to `void` that spcifies that a given method does not return a useful value. */
|
||||
/** A call to `void` that specifies that a given method does not return a useful value. */
|
||||
class MethodVoidCall extends MethodReturnsTypeCall instanceof VoidCall {
|
||||
override ReturnType getReturnType() { result = VoidCall.super.getReturnType() }
|
||||
}
|
||||
@@ -448,7 +448,7 @@ module Rbi {
|
||||
}
|
||||
|
||||
/**
|
||||
* A call to `void` that spcifies that a given proc or block does not return
|
||||
* A call to `void` that specifies that a given proc or block does not return
|
||||
* a useful value.
|
||||
*/
|
||||
class ProcVoidCall extends ProcReturnsTypeCall instanceof VoidCall {
|
||||
|
||||
@@ -6,7 +6,7 @@ private import codeql.ruby.ast.internal.TreeSitter
|
||||
/** A source file that contains generated code. */
|
||||
abstract class GeneratedCodeFile extends RubyFile { }
|
||||
|
||||
/** A file contining comments suggesting it contains generated code. */
|
||||
/** A file continuing comments suggesting it contains generated code. */
|
||||
class GeneratedCommentFile extends GeneratedCodeFile {
|
||||
GeneratedCommentFile() { this = any(GeneratedCodeComment c).getLocation().getFile() }
|
||||
}
|
||||
|
||||
30
ruby/ql/lib/codeql/ruby/frameworks/ActiveJob.qll
Normal file
30
ruby/ql/lib/codeql/ruby/frameworks/ActiveJob.qll
Normal file
@@ -0,0 +1,30 @@
|
||||
/**
|
||||
* Modeling for `ActiveJob`, a framweork for declaring and enqueueing jobs that
|
||||
* ships with Rails.
|
||||
* https://rubygems.org/gems/activejob
|
||||
*/
|
||||
|
||||
private import codeql.ruby.ApiGraphs
|
||||
private import codeql.ruby.Concepts
|
||||
private import codeql.ruby.DataFlow
|
||||
|
||||
/** Modeling for `ActiveJob`. */
|
||||
module ActiveJob {
|
||||
/**
|
||||
* `ActiveJob::Serializers`
|
||||
*/
|
||||
module Serializers {
|
||||
/**
|
||||
* A call to `ActiveJob::Serializers.deserialize`, which interprets part of
|
||||
* its argument as a Ruby constant.
|
||||
*/
|
||||
class DeserializeCall extends DataFlow::CallNode, CodeExecution::Range {
|
||||
DeserializeCall() {
|
||||
this =
|
||||
API::getTopLevelMember("ActiveJob").getMember("Serializers").getAMethodCall("deserialize")
|
||||
}
|
||||
|
||||
override DataFlow::Node getCode() { result = this.getArgument(0) }
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -120,7 +120,7 @@ class GraphqlSchemaObjectClass extends ClassDeclaration {
|
||||
* `GraphQL::Schema::RelayClassicMutation` or
|
||||
* `GraphQL::Schema::Resolver`.
|
||||
*
|
||||
* Both of these classes have an overrideable `resolve` instance
|
||||
* Both of these classes have an overridable `resolve` instance
|
||||
* method which can receive user input in order to resolve a query or mutation.
|
||||
*/
|
||||
private class GraphqlResolvableClass extends ClassDeclaration {
|
||||
@@ -144,7 +144,7 @@ private class GraphqlResolvableClass extends ClassDeclaration {
|
||||
*
|
||||
* ```rb
|
||||
* module Mutation
|
||||
* class NameAnInstrument < BaseMutationn
|
||||
* class NameAnInstrument < BaseMutation
|
||||
* argument :instrument_uuid, Types::Uuid,
|
||||
* required: true,
|
||||
* loads: ::Instrument,
|
||||
@@ -188,7 +188,7 @@ class GraphqlResolveMethod extends Method, Http::Server::RequestHandler::Range {
|
||||
*
|
||||
* ```rb
|
||||
* module Mutation
|
||||
* class NameAnInstrument < BaseMutationn
|
||||
* class NameAnInstrument < BaseMutation
|
||||
* argument :instrument_uuid, Types::Uuid,
|
||||
* required: true,
|
||||
* loads: ::Instrument,
|
||||
|
||||
@@ -95,7 +95,7 @@ module IO {
|
||||
* popen([env,] cmd, mode="r" [, opt]) -> io
|
||||
* popen([env,] cmd, mode="r" [, opt]) {|io| block } -> obj
|
||||
* ```
|
||||
* `IO.popen` does different things based on the the value of `cmd`:
|
||||
* `IO.popen` does different things based on the value of `cmd`:
|
||||
* ```
|
||||
* "-" : fork
|
||||
* commandline : command line string which is passed to a shell
|
||||
|
||||
@@ -25,7 +25,7 @@ class HttpClientRequest extends Http::Client::Request::Range, DataFlow::CallNode
|
||||
[
|
||||
// One-off requests
|
||||
API::getTopLevelMember("HTTPClient"),
|
||||
// Conncection re-use
|
||||
// Connection re-use
|
||||
API::getTopLevelMember("HTTPClient").getInstance()
|
||||
] and
|
||||
requestNode = connectionNode.getReturn(method) and
|
||||
|
||||
@@ -241,7 +241,7 @@ abstract class RegExp extends Ast::StringlikeLiteral {
|
||||
|
||||
/**
|
||||
* Helper predicate for `escapingChar`.
|
||||
* In order to avoid negative recusrion, we return a boolean.
|
||||
* In order to avoid negative recursion, we return a boolean.
|
||||
* This way, we can refer to `escaping(pos - 1).booleanNot()`
|
||||
* rather than to a negated version of `escaping(pos)`.
|
||||
*/
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/**
|
||||
* Provides precicates for reasoning about bad tag filter vulnerabilities.
|
||||
* Provides predicates for reasoning about bad tag filter vulnerabilities.
|
||||
*/
|
||||
|
||||
import regexp.RegexpMatching
|
||||
@@ -65,7 +65,7 @@ predicate isBadRegexpFilter(HtmlMatchingRegExp regexp, string msg) {
|
||||
regexp.matches("<!-- foo --!>") and
|
||||
exists(int a, int b | a != b |
|
||||
regexp.fillsCaptureGroup("<!-- foo -->", a) and
|
||||
// <!-- foo --> might be ambigously parsed (matching both capture groups), and that is ok here.
|
||||
// <!-- foo --> might be ambiguously parsed (matching both capture groups), and that is ok here.
|
||||
regexp.fillsCaptureGroup("<!-- foo --!>", b) and
|
||||
not regexp.fillsCaptureGroup("<!-- foo --!>", a) and
|
||||
msg =
|
||||
|
||||
36
ruby/ql/lib/codeql/ruby/security/KernelOpenQuery.qll
Normal file
36
ruby/ql/lib/codeql/ruby/security/KernelOpenQuery.qll
Normal file
@@ -0,0 +1,36 @@
|
||||
/**
|
||||
* Provides utility classes and predicates for reasoning about `Kernel.open` and related methods.
|
||||
*/
|
||||
|
||||
private import codeql.ruby.AST
|
||||
private import codeql.ruby.DataFlow
|
||||
private import codeql.ruby.AST
|
||||
private import codeql.ruby.ApiGraphs
|
||||
private import codeql.ruby.frameworks.core.Kernel::Kernel
|
||||
|
||||
/** A call to a method that might access a file or start a process. */
|
||||
class AmbiguousPathCall extends DataFlow::CallNode {
|
||||
string name;
|
||||
|
||||
AmbiguousPathCall() {
|
||||
this.(KernelMethodCall).getMethodName() = "open" and
|
||||
name = "Kernel.open"
|
||||
or
|
||||
this = API::getTopLevelMember("IO").getAMethodCall("read") and
|
||||
not this = API::getTopLevelMember("File").getAMethodCall("read") and // needed in e.g. opal/opal, where some calls have both paths, but I'm not sure why
|
||||
name = "IO.read"
|
||||
}
|
||||
|
||||
/** Gets the name for the method being called. */
|
||||
string getName() { result = name }
|
||||
|
||||
/** Gets the name for a safer method that can be used instead. */
|
||||
string getReplacement() {
|
||||
result = "File.read" and name = "IO.read"
|
||||
or
|
||||
result = "File.open" and name = "Kernel.open"
|
||||
}
|
||||
|
||||
/** Gets the argument that specifies the path to be accessed. */
|
||||
DataFlow::Node getPathArgument() { result = this.getArgument(0) }
|
||||
}
|
||||
@@ -8,6 +8,8 @@ private import codeql.ruby.ApiGraphs
|
||||
private import codeql.ruby.CFG
|
||||
private import codeql.ruby.DataFlow
|
||||
private import codeql.ruby.dataflow.RemoteFlowSources
|
||||
private import codeql.ruby.frameworks.ActiveJob
|
||||
private import codeql.ruby.frameworks.core.Module
|
||||
|
||||
module UnsafeDeserialization {
|
||||
/**
|
||||
@@ -199,4 +201,27 @@ module UnsafeDeserialization {
|
||||
toNode = callNode
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* A argument in a call to `Module.const_get`, considered as a sink for unsafe
|
||||
* deserialization.
|
||||
*
|
||||
* Calls to `Module.const_get` can return arbitrary classes which can then be
|
||||
* instantiated.
|
||||
*/
|
||||
class ConstGetCallArgument extends Sink {
|
||||
ConstGetCallArgument() { this = any(Module::ModuleConstGetCallCodeExecution c).getCode() }
|
||||
}
|
||||
|
||||
/**
|
||||
* A argument in a call to `ActiveJob::Serializers.deserialize`, considered as
|
||||
* a sink for unsafe deserialization.
|
||||
*
|
||||
* This is roughly equivalent to a call to `Module.const_get`.
|
||||
*/
|
||||
class ActiveJobSerializersDeserializeArgument extends Sink {
|
||||
ActiveJobSerializersDeserializeArgument() {
|
||||
this = any(ActiveJob::Serializers::DeserializeCall c).getCode()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -202,7 +202,7 @@ private predicate isFork(State q, InputSymbol s1, InputSymbol s2, State r1, Stat
|
||||
//
|
||||
// We additionally require that the there exists another InfiniteRepetitionQuantifier `mid` on the path from `q` to itself.
|
||||
// This is done to avoid flagging regular expressions such as `/(a?)*b/` - that only has polynomial runtime, and is detected by `js/polynomial-redos`.
|
||||
// The below code is therefore a heuritic, that only flags regular expressions such as `/(a*)*b/`,
|
||||
// The below code is therefore a heuristic, that only flags regular expressions such as `/(a*)*b/`,
|
||||
// and does not flag regular expressions such as `/(a?b?)c/`, but the latter pattern is not used frequently.
|
||||
r1 = r2 and
|
||||
q1 = q2 and
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/**
|
||||
* Provides precicates for reasoning about which strings are matched by a regular expression,
|
||||
* Provides predicates for reasoning about which strings are matched by a regular expression,
|
||||
* and for testing which capture groups are filled when a particular regexp matches a string.
|
||||
*/
|
||||
|
||||
|
||||
@@ -76,7 +76,7 @@ class StateTuple extends TStateTuple {
|
||||
StateTuple() { this = MkStateTuple(q1, q2, q3) }
|
||||
|
||||
/**
|
||||
* Gest a string repesentation of this tuple.
|
||||
* Gest a string representation of this tuple.
|
||||
*/
|
||||
string toString() { result = "(" + q1 + ", " + q2 + ", " + q3 + ")" }
|
||||
|
||||
|
||||
@@ -23,7 +23,7 @@
|
||||
|
||||
### New Queries
|
||||
|
||||
* Added a new query, `rb/log-inection`, to detect cases where a malicious user may be able to forge log entries.
|
||||
* Added a new query, `rb/log-injection`, to detect cases where a malicious user may be able to forge log entries.
|
||||
* Added a new query, `rb/incomplete-multi-character-sanitization`. The query
|
||||
finds string transformations that do not replace all occurrences of a
|
||||
multi-character substring.
|
||||
|
||||
@@ -0,0 +1,4 @@
|
||||
---
|
||||
category: newQuery
|
||||
---
|
||||
* Added a new query, `rb/non-constant-kernel-open`, to detect uses of Kernel.open and related methods with non-constant values.
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
### New Queries
|
||||
|
||||
* Added a new query, `rb/log-inection`, to detect cases where a malicious user may be able to forge log entries.
|
||||
* Added a new query, `rb/log-injection`, to detect cases where a malicious user may be able to forge log entries.
|
||||
* Added a new query, `rb/incomplete-multi-character-sanitization`. The query
|
||||
finds string transformations that do not replace all occurrences of a
|
||||
multi-character substring.
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/**
|
||||
* @name Manually checking http verb instead of using built in rails routes and protections
|
||||
* @description Manually checking HTTP verbs is an indication that multiple requests are routed to the same controller action. This could lead to bypassing necessary authorization methods and other protections, like CSRF protection. Prefer using different controller actions for each HTTP method and relying Rails routing to handle mappting resources and verbs to specific methods.
|
||||
* @description Manually checking HTTP verbs is an indication that multiple requests are routed to the same controller action. This could lead to bypassing necessary authorization methods and other protections, like CSRF protection. Prefer using different controller actions for each HTTP method and relying Rails routing to handle mapping resources and verbs to specific methods.
|
||||
* @kind path-problem
|
||||
* @problem.severity error
|
||||
* @security-severity 5.0
|
||||
@@ -93,4 +93,4 @@ class HttpVerbConfig extends TaintTracking::Configuration {
|
||||
from HttpVerbConfig config, DataFlow::PathNode source, DataFlow::PathNode sink
|
||||
where config.hasFlowPath(source, sink)
|
||||
select sink.getNode(), source, sink,
|
||||
"Manually checking HTTP verbs is an indication that multiple requests are routed to the same controller action. This could lead to bypassing necessary authorization methods and other protections, like CSRF protection. Prefer using different controller actions for each HTTP method and relying Rails routing to handle mappting resources and verbs to specific methods."
|
||||
"Manually checking HTTP verbs is an indication that multiple requests are routed to the same controller action. This could lead to bypassing necessary authorization methods and other protections, like CSRF protection. Prefer using different controller actions for each HTTP method and relying Rails routing to handle mapping resources and verbs to specific methods."
|
||||
|
||||
46
ruby/ql/src/queries/security/cwe-078/KernelOpen.inc.qhelp
Normal file
46
ruby/ql/src/queries/security/cwe-078/KernelOpen.inc.qhelp
Normal file
@@ -0,0 +1,46 @@
|
||||
<!DOCTYPE qhelp PUBLIC
|
||||
"-//Semmle//qhelp//EN"
|
||||
"qhelp.dtd">
|
||||
<qhelp>
|
||||
<overview>
|
||||
<p>If <code>Kernel.open</code> is given a file name that starts with a <code>|</code>
|
||||
character, it will execute the remaining string as a shell command. If a
|
||||
malicious user can control the file name, they can execute arbitrary code.
|
||||
The same vulnerability applies to <code>IO.read</code>.
|
||||
</p>
|
||||
|
||||
</overview>
|
||||
<recommendation>
|
||||
|
||||
<p>Use <code>File.open</code> instead of <code>Kernel.open</code>, as the former
|
||||
does not have this vulnerability. Similarly, use <code>File.read</code> instead
|
||||
of <code>IO.read</code>.</p>
|
||||
|
||||
</recommendation>
|
||||
<example>
|
||||
|
||||
<p>
|
||||
The following example shows code that calls <code>Kernel.open</code> on a
|
||||
user-supplied file path.
|
||||
</p>
|
||||
|
||||
<sample src="examples/kernel_open.rb" />
|
||||
|
||||
<p>Instead, <code>File.open</code> should be used, as in the following example.</p>
|
||||
|
||||
<sample src="examples/file_open.rb" />
|
||||
|
||||
</example>
|
||||
<references>
|
||||
|
||||
<li>
|
||||
OWASP:
|
||||
<a href="https://www.owasp.org/index.php/Command_Injection">Command Injection</a>.
|
||||
</li>
|
||||
|
||||
<li>
|
||||
Example CVE: <a href="https://www.ruby-lang.org/en/news/2021/05/02/os-command-injection-in-rdoc/">Command Injection in RDoc</a>.
|
||||
</li>
|
||||
|
||||
</references>
|
||||
</qhelp>
|
||||
@@ -1,46 +1,4 @@
|
||||
<!DOCTYPE qhelp PUBLIC
|
||||
"-//Semmle//qhelp//EN"
|
||||
"qhelp.dtd">
|
||||
<!DOCTYPE qhelp PUBLIC "-//Semmle//qhelp//EN" "qhelp.dtd">
|
||||
<qhelp>
|
||||
<overview>
|
||||
<p>If <code>Kernel.open</code> is given a file name that starts with a <code>|</code>
|
||||
character, it will execute the remaining string as a shell command. If a
|
||||
malicious user can control the file name, they can execute arbitrary code.
|
||||
The same vulnerability applies to <code>IO.read</code>.
|
||||
</p>
|
||||
|
||||
</overview>
|
||||
<recommendation>
|
||||
|
||||
<p>Use <code>File.open</code> instead of <code>Kernel.open</code>, as the former
|
||||
does not have this vulnerability. Similarly, use <code>File.read</code> instead
|
||||
of <code>IO.read</code>.</p>
|
||||
|
||||
</recommendation>
|
||||
<example>
|
||||
|
||||
<p>
|
||||
The following example shows code that calls <code>Kernel.open</code> on a
|
||||
user-supplied file path.
|
||||
</p>
|
||||
|
||||
<sample src="examples/kernel_open.rb" />
|
||||
|
||||
<p>Instead, <code>File.open</code> should be used, as in the following example.</p>
|
||||
|
||||
<sample src="examples/file_open.rb" />
|
||||
|
||||
</example>
|
||||
<references>
|
||||
|
||||
<li>
|
||||
OWASP:
|
||||
<a href="https://www.owasp.org/index.php/Command_Injection">Command Injection</a>.
|
||||
</li>
|
||||
|
||||
<li>
|
||||
Example CVE: <a href="https://www.ruby-lang.org/en/news/2021/05/02/os-command-injection-in-rdoc/">Command Injection in RDoc</a>.
|
||||
</li>
|
||||
|
||||
</references>
|
||||
</qhelp>
|
||||
<include src="KernelOpen.inc.qhelp" />
|
||||
</qhelp>
|
||||
@@ -1,5 +1,5 @@
|
||||
/**
|
||||
* @name Use of `Kernel.open` or `IO.read`
|
||||
* @name Use of `Kernel.open` or `IO.read` with user-controlled input
|
||||
* @description Using `Kernel.open` or `IO.read` may allow a malicious
|
||||
* user to execute arbitrary system commands.
|
||||
* @kind path-problem
|
||||
@@ -14,39 +14,12 @@
|
||||
* external/cwe/cwe-073
|
||||
*/
|
||||
|
||||
import codeql.ruby.AST
|
||||
import codeql.ruby.ApiGraphs
|
||||
import codeql.ruby.frameworks.core.Kernel::Kernel
|
||||
import codeql.ruby.TaintTracking
|
||||
import codeql.ruby.dataflow.BarrierGuards
|
||||
import codeql.ruby.dataflow.RemoteFlowSources
|
||||
import codeql.ruby.DataFlow
|
||||
import codeql.ruby.TaintTracking
|
||||
import codeql.ruby.dataflow.RemoteFlowSources
|
||||
import codeql.ruby.dataflow.BarrierGuards
|
||||
import DataFlow::PathGraph
|
||||
|
||||
/**
|
||||
* A method call that has a suggested replacement.
|
||||
*/
|
||||
abstract class Replacement extends DataFlow::CallNode {
|
||||
abstract string getFrom();
|
||||
|
||||
abstract string getTo();
|
||||
}
|
||||
|
||||
class KernelOpenCall extends KernelMethodCall, Replacement {
|
||||
KernelOpenCall() { this.getMethodName() = "open" }
|
||||
|
||||
override string getFrom() { result = "Kernel.open" }
|
||||
|
||||
override string getTo() { result = "File.open" }
|
||||
}
|
||||
|
||||
class IOReadCall extends DataFlow::CallNode, Replacement {
|
||||
IOReadCall() { this = API::getTopLevelMember("IO").getAMethodCall("read") }
|
||||
|
||||
override string getFrom() { result = "IO.read" }
|
||||
|
||||
override string getTo() { result = "File.read" }
|
||||
}
|
||||
import codeql.ruby.security.KernelOpenQuery
|
||||
|
||||
class Configuration extends TaintTracking::Configuration {
|
||||
Configuration() { this = "KernelOpen" }
|
||||
@@ -54,9 +27,7 @@ class Configuration extends TaintTracking::Configuration {
|
||||
override predicate isSource(DataFlow::Node source) { source instanceof RemoteFlowSource }
|
||||
|
||||
override predicate isSink(DataFlow::Node sink) {
|
||||
exists(KernelOpenCall c | c.getArgument(0) = sink)
|
||||
or
|
||||
exists(IOReadCall c | c.getArgument(0) = sink)
|
||||
sink = any(AmbiguousPathCall r).getPathArgument()
|
||||
}
|
||||
|
||||
override predicate isSanitizer(DataFlow::Node node) {
|
||||
@@ -73,5 +44,6 @@ where
|
||||
sourceNode = source.getNode() and
|
||||
call.getArgument(0) = sink.getNode()
|
||||
select sink.getNode(), source, sink,
|
||||
"This call to " + call.(Replacement).getFrom() + " depends on a $@. Replace it with " +
|
||||
call.(Replacement).getTo() + ".", source.getNode(), "user-provided value"
|
||||
"This call to " + call.(AmbiguousPathCall).getName() +
|
||||
" depends on a $@. Consider replacing it with " + call.(AmbiguousPathCall).getReplacement() +
|
||||
".", source.getNode(), "user-provided value"
|
||||
|
||||
@@ -0,0 +1,4 @@
|
||||
<!DOCTYPE qhelp PUBLIC "-//Semmle//qhelp//EN" "qhelp.dtd">
|
||||
<qhelp>
|
||||
<include src="KernelOpen.inc.qhelp" />
|
||||
</qhelp>
|
||||
@@ -0,0 +1,29 @@
|
||||
/**
|
||||
* @name Use of `Kernel.open` or `IO.read` with a non-constant value
|
||||
* @description Using `Kernel.open` or `IO.read` may allow a malicious
|
||||
* user to execute arbitrary system commands.
|
||||
* @kind problem
|
||||
* @problem.severity warning
|
||||
* @security-severity 6.5
|
||||
* @precision high
|
||||
* @id rb/non-constant-kernel-open
|
||||
* @tags correctness
|
||||
* security
|
||||
* external/cwe/cwe-078
|
||||
* external/cwe/cwe-088
|
||||
* external/cwe/cwe-073
|
||||
*/
|
||||
|
||||
import codeql.ruby.security.KernelOpenQuery
|
||||
import codeql.ruby.ast.Literal
|
||||
|
||||
from AmbiguousPathCall call
|
||||
where
|
||||
// there is not a constant string argument
|
||||
not exists(call.getPathArgument().asExpr().getExpr().getConstantValue()) and
|
||||
// if it's a format string, then the first argument is not a constant string
|
||||
not call.getPathArgument().getALocalSource().asExpr().getExpr().(StringLiteral).getComponent(0)
|
||||
instanceof StringTextComponent
|
||||
select call,
|
||||
"Call to " + call.getName() + " with a non-constant value. Consider replacing it with " +
|
||||
call.getReplacement() + "."
|
||||
@@ -23,10 +23,10 @@ nodes
|
||||
| ManuallyCheckHttpVerb.rb:59:10:59:38 | ...[...] | semmle.label | ...[...] |
|
||||
subpaths
|
||||
#select
|
||||
| ManuallyCheckHttpVerb.rb:4:8:4:19 | call to get? | ManuallyCheckHttpVerb.rb:4:8:4:19 | call to get? | ManuallyCheckHttpVerb.rb:4:8:4:19 | call to get? | Manually checking HTTP verbs is an indication that multiple requests are routed to the same controller action. This could lead to bypassing necessary authorization methods and other protections, like CSRF protection. Prefer using different controller actions for each HTTP method and relying Rails routing to handle mappting resources and verbs to specific methods. |
|
||||
| ManuallyCheckHttpVerb.rb:12:8:12:22 | ... == ... | ManuallyCheckHttpVerb.rb:11:14:11:24 | call to env : | ManuallyCheckHttpVerb.rb:12:8:12:22 | ... == ... | Manually checking HTTP verbs is an indication that multiple requests are routed to the same controller action. This could lead to bypassing necessary authorization methods and other protections, like CSRF protection. Prefer using different controller actions for each HTTP method and relying Rails routing to handle mappting resources and verbs to specific methods. |
|
||||
| ManuallyCheckHttpVerb.rb:20:8:20:22 | ... == ... | ManuallyCheckHttpVerb.rb:19:14:19:35 | call to request_method : | ManuallyCheckHttpVerb.rb:20:8:20:22 | ... == ... | Manually checking HTTP verbs is an indication that multiple requests are routed to the same controller action. This could lead to bypassing necessary authorization methods and other protections, like CSRF protection. Prefer using different controller actions for each HTTP method and relying Rails routing to handle mappting resources and verbs to specific methods. |
|
||||
| ManuallyCheckHttpVerb.rb:28:8:28:22 | ... == ... | ManuallyCheckHttpVerb.rb:27:14:27:27 | call to method : | ManuallyCheckHttpVerb.rb:28:8:28:22 | ... == ... | Manually checking HTTP verbs is an indication that multiple requests are routed to the same controller action. This could lead to bypassing necessary authorization methods and other protections, like CSRF protection. Prefer using different controller actions for each HTTP method and relying Rails routing to handle mappting resources and verbs to specific methods. |
|
||||
| ManuallyCheckHttpVerb.rb:36:8:36:22 | ... == ... | ManuallyCheckHttpVerb.rb:35:14:35:39 | call to raw_request_method : | ManuallyCheckHttpVerb.rb:36:8:36:22 | ... == ... | Manually checking HTTP verbs is an indication that multiple requests are routed to the same controller action. This could lead to bypassing necessary authorization methods and other protections, like CSRF protection. Prefer using different controller actions for each HTTP method and relying Rails routing to handle mappting resources and verbs to specific methods. |
|
||||
| ManuallyCheckHttpVerb.rb:52:10:52:23 | ... == ... | ManuallyCheckHttpVerb.rb:51:16:51:44 | call to request_method_symbol : | ManuallyCheckHttpVerb.rb:52:10:52:23 | ... == ... | Manually checking HTTP verbs is an indication that multiple requests are routed to the same controller action. This could lead to bypassing necessary authorization methods and other protections, like CSRF protection. Prefer using different controller actions for each HTTP method and relying Rails routing to handle mappting resources and verbs to specific methods. |
|
||||
| ManuallyCheckHttpVerb.rb:59:10:59:38 | ...[...] | ManuallyCheckHttpVerb.rb:59:10:59:20 | call to env : | ManuallyCheckHttpVerb.rb:59:10:59:38 | ...[...] | Manually checking HTTP verbs is an indication that multiple requests are routed to the same controller action. This could lead to bypassing necessary authorization methods and other protections, like CSRF protection. Prefer using different controller actions for each HTTP method and relying Rails routing to handle mappting resources and verbs to specific methods. |
|
||||
| ManuallyCheckHttpVerb.rb:4:8:4:19 | call to get? | ManuallyCheckHttpVerb.rb:4:8:4:19 | call to get? | ManuallyCheckHttpVerb.rb:4:8:4:19 | call to get? | Manually checking HTTP verbs is an indication that multiple requests are routed to the same controller action. This could lead to bypassing necessary authorization methods and other protections, like CSRF protection. Prefer using different controller actions for each HTTP method and relying Rails routing to handle mapping resources and verbs to specific methods. |
|
||||
| ManuallyCheckHttpVerb.rb:12:8:12:22 | ... == ... | ManuallyCheckHttpVerb.rb:11:14:11:24 | call to env : | ManuallyCheckHttpVerb.rb:12:8:12:22 | ... == ... | Manually checking HTTP verbs is an indication that multiple requests are routed to the same controller action. This could lead to bypassing necessary authorization methods and other protections, like CSRF protection. Prefer using different controller actions for each HTTP method and relying Rails routing to handle mapping resources and verbs to specific methods. |
|
||||
| ManuallyCheckHttpVerb.rb:20:8:20:22 | ... == ... | ManuallyCheckHttpVerb.rb:19:14:19:35 | call to request_method : | ManuallyCheckHttpVerb.rb:20:8:20:22 | ... == ... | Manually checking HTTP verbs is an indication that multiple requests are routed to the same controller action. This could lead to bypassing necessary authorization methods and other protections, like CSRF protection. Prefer using different controller actions for each HTTP method and relying Rails routing to handle mapping resources and verbs to specific methods. |
|
||||
| ManuallyCheckHttpVerb.rb:28:8:28:22 | ... == ... | ManuallyCheckHttpVerb.rb:27:14:27:27 | call to method : | ManuallyCheckHttpVerb.rb:28:8:28:22 | ... == ... | Manually checking HTTP verbs is an indication that multiple requests are routed to the same controller action. This could lead to bypassing necessary authorization methods and other protections, like CSRF protection. Prefer using different controller actions for each HTTP method and relying Rails routing to handle mapping resources and verbs to specific methods. |
|
||||
| ManuallyCheckHttpVerb.rb:36:8:36:22 | ... == ... | ManuallyCheckHttpVerb.rb:35:14:35:39 | call to raw_request_method : | ManuallyCheckHttpVerb.rb:36:8:36:22 | ... == ... | Manually checking HTTP verbs is an indication that multiple requests are routed to the same controller action. This could lead to bypassing necessary authorization methods and other protections, like CSRF protection. Prefer using different controller actions for each HTTP method and relying Rails routing to handle mapping resources and verbs to specific methods. |
|
||||
| ManuallyCheckHttpVerb.rb:52:10:52:23 | ... == ... | ManuallyCheckHttpVerb.rb:51:16:51:44 | call to request_method_symbol : | ManuallyCheckHttpVerb.rb:52:10:52:23 | ... == ... | Manually checking HTTP verbs is an indication that multiple requests are routed to the same controller action. This could lead to bypassing necessary authorization methods and other protections, like CSRF protection. Prefer using different controller actions for each HTTP method and relying Rails routing to handle mapping resources and verbs to specific methods. |
|
||||
| ManuallyCheckHttpVerb.rb:59:10:59:38 | ...[...] | ManuallyCheckHttpVerb.rb:59:10:59:20 | call to env : | ManuallyCheckHttpVerb.rb:59:10:59:38 | ...[...] | Manually checking HTTP verbs is an indication that multiple requests are routed to the same controller action. This could lead to bypassing necessary authorization methods and other protections, like CSRF protection. Prefer using different controller actions for each HTTP method and relying Rails routing to handle mapping resources and verbs to specific methods. |
|
||||
|
||||
@@ -9,5 +9,5 @@ nodes
|
||||
| KernelOpen.rb:5:13:5:16 | file | semmle.label | file |
|
||||
subpaths
|
||||
#select
|
||||
| KernelOpen.rb:4:10:4:13 | file | KernelOpen.rb:3:12:3:17 | call to params : | KernelOpen.rb:4:10:4:13 | file | This call to Kernel.open depends on a $@. Replace it with File.open. | KernelOpen.rb:3:12:3:17 | call to params | user-provided value |
|
||||
| KernelOpen.rb:5:13:5:16 | file | KernelOpen.rb:3:12:3:17 | call to params : | KernelOpen.rb:5:13:5:16 | file | This call to IO.read depends on a $@. Replace it with File.read. | KernelOpen.rb:3:12:3:17 | call to params | user-provided value |
|
||||
| KernelOpen.rb:4:10:4:13 | file | KernelOpen.rb:3:12:3:17 | call to params : | KernelOpen.rb:4:10:4:13 | file | This call to Kernel.open depends on a $@. Consider replacing it with File.open. | KernelOpen.rb:3:12:3:17 | call to params | user-provided value |
|
||||
| KernelOpen.rb:5:13:5:16 | file | KernelOpen.rb:3:12:3:17 | call to params : | KernelOpen.rb:5:13:5:16 | file | This call to IO.read depends on a $@. Consider replacing it with File.read. | KernelOpen.rb:3:12:3:17 | call to params | user-provided value |
|
||||
@@ -0,0 +1,4 @@
|
||||
| NonConstantKernelOpen.rb:4:5:4:14 | call to open | Call to Kernel.open with a non-constant value. Consider replacing it with File.open. |
|
||||
| NonConstantKernelOpen.rb:5:5:5:17 | call to read | Call to IO.read with a non-constant value. Consider replacing it with File.read. |
|
||||
| NonConstantKernelOpen.rb:9:5:9:21 | call to open | Call to Kernel.open with a non-constant value. Consider replacing it with File.open. |
|
||||
| NonConstantKernelOpen.rb:19:5:19:33 | call to open | Call to Kernel.open with a non-constant value. Consider replacing it with File.open. |
|
||||
@@ -0,0 +1 @@
|
||||
queries/security/cwe-078/NonConstantKernelOpen.ql
|
||||
@@ -0,0 +1,23 @@
|
||||
class UsersController < ActionController::Base
|
||||
def create
|
||||
file = params[:file]
|
||||
open(file) # BAD
|
||||
IO.read(file) # BAD
|
||||
|
||||
File.open(file).read # GOOD
|
||||
|
||||
Kernel.open(file) # BAD
|
||||
|
||||
File.open(file, "r") # GOOD
|
||||
|
||||
Kernel.open("constant") # GOOD
|
||||
|
||||
IO.read("constant") # GOOD
|
||||
|
||||
Kernel.open("this is #{fine}") # GOOD
|
||||
|
||||
Kernel.open("#{this_is} bad") # BAD
|
||||
|
||||
open("| #{this_is_an_explicit_command} foo bar") # GOOD
|
||||
end
|
||||
end
|
||||
@@ -1,29 +1,32 @@
|
||||
edges
|
||||
| CodeInjection.rb:3:12:3:17 | call to params : | CodeInjection.rb:3:12:3:24 | ...[...] : |
|
||||
| CodeInjection.rb:3:12:3:24 | ...[...] : | CodeInjection.rb:6:10:6:13 | code |
|
||||
| CodeInjection.rb:3:12:3:24 | ...[...] : | CodeInjection.rb:18:20:18:23 | code |
|
||||
| CodeInjection.rb:3:12:3:24 | ...[...] : | CodeInjection.rb:21:21:21:24 | code |
|
||||
| CodeInjection.rb:3:12:3:24 | ...[...] : | CodeInjection.rb:27:15:27:18 | code |
|
||||
| CodeInjection.rb:3:12:3:24 | ...[...] : | CodeInjection.rb:30:19:30:22 | code |
|
||||
| CodeInjection.rb:3:12:3:24 | ...[...] : | CodeInjection.rb:36:24:36:27 | code : |
|
||||
| CodeInjection.rb:36:24:36:27 | code : | CodeInjection.rb:36:10:36:28 | call to escape |
|
||||
| CodeInjection.rb:5:12:5:17 | call to params : | CodeInjection.rb:5:12:5:24 | ...[...] : |
|
||||
| CodeInjection.rb:5:12:5:24 | ...[...] : | CodeInjection.rb:8:10:8:13 | code |
|
||||
| CodeInjection.rb:5:12:5:24 | ...[...] : | CodeInjection.rb:20:20:20:23 | code |
|
||||
| CodeInjection.rb:5:12:5:24 | ...[...] : | CodeInjection.rb:23:21:23:24 | code |
|
||||
| CodeInjection.rb:5:12:5:24 | ...[...] : | CodeInjection.rb:29:15:29:18 | code |
|
||||
| CodeInjection.rb:5:12:5:24 | ...[...] : | CodeInjection.rb:32:19:32:22 | code |
|
||||
| CodeInjection.rb:5:12:5:24 | ...[...] : | CodeInjection.rb:38:24:38:27 | code : |
|
||||
| CodeInjection.rb:5:12:5:24 | ...[...] : | CodeInjection.rb:41:40:41:43 | code |
|
||||
| CodeInjection.rb:38:24:38:27 | code : | CodeInjection.rb:38:10:38:28 | call to escape |
|
||||
nodes
|
||||
| CodeInjection.rb:3:12:3:17 | call to params : | semmle.label | call to params : |
|
||||
| CodeInjection.rb:3:12:3:24 | ...[...] : | semmle.label | ...[...] : |
|
||||
| CodeInjection.rb:6:10:6:13 | code | semmle.label | code |
|
||||
| CodeInjection.rb:9:10:9:15 | call to params | semmle.label | call to params |
|
||||
| CodeInjection.rb:18:20:18:23 | code | semmle.label | code |
|
||||
| CodeInjection.rb:21:21:21:24 | code | semmle.label | code |
|
||||
| CodeInjection.rb:27:15:27:18 | code | semmle.label | code |
|
||||
| CodeInjection.rb:30:19:30:22 | code | semmle.label | code |
|
||||
| CodeInjection.rb:36:10:36:28 | call to escape | semmle.label | call to escape |
|
||||
| CodeInjection.rb:36:24:36:27 | code : | semmle.label | code : |
|
||||
| CodeInjection.rb:5:12:5:17 | call to params : | semmle.label | call to params : |
|
||||
| CodeInjection.rb:5:12:5:24 | ...[...] : | semmle.label | ...[...] : |
|
||||
| CodeInjection.rb:8:10:8:13 | code | semmle.label | code |
|
||||
| CodeInjection.rb:11:10:11:15 | call to params | semmle.label | call to params |
|
||||
| CodeInjection.rb:20:20:20:23 | code | semmle.label | code |
|
||||
| CodeInjection.rb:23:21:23:24 | code | semmle.label | code |
|
||||
| CodeInjection.rb:29:15:29:18 | code | semmle.label | code |
|
||||
| CodeInjection.rb:32:19:32:22 | code | semmle.label | code |
|
||||
| CodeInjection.rb:38:10:38:28 | call to escape | semmle.label | call to escape |
|
||||
| CodeInjection.rb:38:24:38:27 | code : | semmle.label | code : |
|
||||
| CodeInjection.rb:41:40:41:43 | code | semmle.label | code |
|
||||
subpaths
|
||||
#select
|
||||
| CodeInjection.rb:6:10:6:13 | code | CodeInjection.rb:3:12:3:17 | call to params : | CodeInjection.rb:6:10:6:13 | code | This code execution depends on a $@. | CodeInjection.rb:3:12:3:17 | call to params | user-provided value |
|
||||
| CodeInjection.rb:9:10:9:15 | call to params | CodeInjection.rb:9:10:9:15 | call to params | CodeInjection.rb:9:10:9:15 | call to params | This code execution depends on a $@. | CodeInjection.rb:9:10:9:15 | call to params | user-provided value |
|
||||
| CodeInjection.rb:18:20:18:23 | code | CodeInjection.rb:3:12:3:17 | call to params : | CodeInjection.rb:18:20:18:23 | code | This code execution depends on a $@. | CodeInjection.rb:3:12:3:17 | call to params | user-provided value |
|
||||
| CodeInjection.rb:21:21:21:24 | code | CodeInjection.rb:3:12:3:17 | call to params : | CodeInjection.rb:21:21:21:24 | code | This code execution depends on a $@. | CodeInjection.rb:3:12:3:17 | call to params | user-provided value |
|
||||
| CodeInjection.rb:27:15:27:18 | code | CodeInjection.rb:3:12:3:17 | call to params : | CodeInjection.rb:27:15:27:18 | code | This code execution depends on a $@. | CodeInjection.rb:3:12:3:17 | call to params | user-provided value |
|
||||
| CodeInjection.rb:30:19:30:22 | code | CodeInjection.rb:3:12:3:17 | call to params : | CodeInjection.rb:30:19:30:22 | code | This code execution depends on a $@. | CodeInjection.rb:3:12:3:17 | call to params | user-provided value |
|
||||
| CodeInjection.rb:36:10:36:28 | call to escape | CodeInjection.rb:3:12:3:17 | call to params : | CodeInjection.rb:36:10:36:28 | call to escape | This code execution depends on a $@. | CodeInjection.rb:3:12:3:17 | call to params | user-provided value |
|
||||
| CodeInjection.rb:8:10:8:13 | code | CodeInjection.rb:5:12:5:17 | call to params : | CodeInjection.rb:8:10:8:13 | code | This code execution depends on a $@. | CodeInjection.rb:5:12:5:17 | call to params | user-provided value |
|
||||
| CodeInjection.rb:11:10:11:15 | call to params | CodeInjection.rb:11:10:11:15 | call to params | CodeInjection.rb:11:10:11:15 | call to params | This code execution depends on a $@. | CodeInjection.rb:11:10:11:15 | call to params | user-provided value |
|
||||
| CodeInjection.rb:20:20:20:23 | code | CodeInjection.rb:5:12:5:17 | call to params : | CodeInjection.rb:20:20:20:23 | code | This code execution depends on a $@. | CodeInjection.rb:5:12:5:17 | call to params | user-provided value |
|
||||
| CodeInjection.rb:23:21:23:24 | code | CodeInjection.rb:5:12:5:17 | call to params : | CodeInjection.rb:23:21:23:24 | code | This code execution depends on a $@. | CodeInjection.rb:5:12:5:17 | call to params | user-provided value |
|
||||
| CodeInjection.rb:29:15:29:18 | code | CodeInjection.rb:5:12:5:17 | call to params : | CodeInjection.rb:29:15:29:18 | code | This code execution depends on a $@. | CodeInjection.rb:5:12:5:17 | call to params | user-provided value |
|
||||
| CodeInjection.rb:32:19:32:22 | code | CodeInjection.rb:5:12:5:17 | call to params : | CodeInjection.rb:32:19:32:22 | code | This code execution depends on a $@. | CodeInjection.rb:5:12:5:17 | call to params | user-provided value |
|
||||
| CodeInjection.rb:38:10:38:28 | call to escape | CodeInjection.rb:5:12:5:17 | call to params : | CodeInjection.rb:38:10:38:28 | call to escape | This code execution depends on a $@. | CodeInjection.rb:5:12:5:17 | call to params | user-provided value |
|
||||
| CodeInjection.rb:41:40:41:43 | code | CodeInjection.rb:5:12:5:17 | call to params : | CodeInjection.rb:41:40:41:43 | code | This code execution depends on a $@. | CodeInjection.rb:5:12:5:17 | call to params | user-provided value |
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
require 'active_job'
|
||||
|
||||
class UsersController < ActionController::Base
|
||||
def create
|
||||
code = params[:code]
|
||||
@@ -22,18 +24,21 @@ class UsersController < ActionController::Base
|
||||
|
||||
# GOOD
|
||||
Bar.class_eval(code)
|
||||
|
||||
|
||||
# BAD
|
||||
const_get(code)
|
||||
|
||||
|
||||
# BAD
|
||||
Foo.const_get(code)
|
||||
|
||||
|
||||
# GOOD
|
||||
Bar.const_get(code)
|
||||
|
||||
# BAD
|
||||
eval(Regexp.escape(code))
|
||||
|
||||
# BAD
|
||||
ActiveJob::Serializers.deserialize(code)
|
||||
end
|
||||
|
||||
def update
|
||||
@@ -62,8 +67,8 @@ class Bar
|
||||
def self.class_eval(x)
|
||||
true
|
||||
end
|
||||
|
||||
|
||||
def self.const_get(x)
|
||||
true
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -1,61 +1,69 @@
|
||||
edges
|
||||
| UnsafeDeserialization.rb:9:39:9:44 | call to params : | UnsafeDeserialization.rb:9:39:9:50 | ...[...] : |
|
||||
| UnsafeDeserialization.rb:9:39:9:50 | ...[...] : | UnsafeDeserialization.rb:10:27:10:41 | serialized_data |
|
||||
| UnsafeDeserialization.rb:15:39:15:44 | call to params : | UnsafeDeserialization.rb:15:39:15:50 | ...[...] : |
|
||||
| UnsafeDeserialization.rb:15:39:15:50 | ...[...] : | UnsafeDeserialization.rb:16:30:16:44 | serialized_data |
|
||||
| UnsafeDeserialization.rb:21:17:21:22 | call to params : | UnsafeDeserialization.rb:21:17:21:28 | ...[...] : |
|
||||
| UnsafeDeserialization.rb:21:17:21:28 | ...[...] : | UnsafeDeserialization.rb:22:24:22:32 | json_data |
|
||||
| UnsafeDeserialization.rb:27:17:27:22 | call to params : | UnsafeDeserialization.rb:27:17:27:28 | ...[...] : |
|
||||
| UnsafeDeserialization.rb:27:17:27:28 | ...[...] : | UnsafeDeserialization.rb:28:27:28:35 | json_data |
|
||||
| UnsafeDeserialization.rb:39:17:39:22 | call to params : | UnsafeDeserialization.rb:39:17:39:28 | ...[...] : |
|
||||
| UnsafeDeserialization.rb:39:17:39:28 | ...[...] : | UnsafeDeserialization.rb:40:24:40:32 | yaml_data |
|
||||
| UnsafeDeserialization.rb:51:17:51:22 | call to params : | UnsafeDeserialization.rb:51:17:51:28 | ...[...] : |
|
||||
| UnsafeDeserialization.rb:51:17:51:28 | ...[...] : | UnsafeDeserialization.rb:52:22:52:30 | json_data |
|
||||
| UnsafeDeserialization.rb:51:17:51:28 | ...[...] : | UnsafeDeserialization.rb:53:22:53:30 | json_data |
|
||||
| UnsafeDeserialization.rb:58:17:58:22 | call to params : | UnsafeDeserialization.rb:58:17:58:28 | ...[...] : |
|
||||
| UnsafeDeserialization.rb:58:17:58:28 | ...[...] : | UnsafeDeserialization.rb:68:23:68:31 | json_data |
|
||||
| UnsafeDeserialization.rb:80:11:80:16 | call to params : | UnsafeDeserialization.rb:80:11:80:22 | ...[...] : |
|
||||
| UnsafeDeserialization.rb:80:11:80:22 | ...[...] : | UnsafeDeserialization.rb:81:34:81:36 | xml |
|
||||
| UnsafeDeserialization.rb:86:17:86:22 | call to params : | UnsafeDeserialization.rb:86:17:86:28 | ...[...] : |
|
||||
| UnsafeDeserialization.rb:86:17:86:28 | ...[...] : | UnsafeDeserialization.rb:87:25:87:33 | yaml_data |
|
||||
| UnsafeDeserialization.rb:10:39:10:44 | call to params : | UnsafeDeserialization.rb:10:39:10:50 | ...[...] : |
|
||||
| UnsafeDeserialization.rb:10:39:10:50 | ...[...] : | UnsafeDeserialization.rb:11:27:11:41 | serialized_data |
|
||||
| UnsafeDeserialization.rb:16:39:16:44 | call to params : | UnsafeDeserialization.rb:16:39:16:50 | ...[...] : |
|
||||
| UnsafeDeserialization.rb:16:39:16:50 | ...[...] : | UnsafeDeserialization.rb:17:30:17:44 | serialized_data |
|
||||
| UnsafeDeserialization.rb:22:17:22:22 | call to params : | UnsafeDeserialization.rb:22:17:22:28 | ...[...] : |
|
||||
| UnsafeDeserialization.rb:22:17:22:28 | ...[...] : | UnsafeDeserialization.rb:23:24:23:32 | json_data |
|
||||
| UnsafeDeserialization.rb:28:17:28:22 | call to params : | UnsafeDeserialization.rb:28:17:28:28 | ...[...] : |
|
||||
| UnsafeDeserialization.rb:28:17:28:28 | ...[...] : | UnsafeDeserialization.rb:29:27:29:35 | json_data |
|
||||
| UnsafeDeserialization.rb:40:17:40:22 | call to params : | UnsafeDeserialization.rb:40:17:40:28 | ...[...] : |
|
||||
| UnsafeDeserialization.rb:40:17:40:28 | ...[...] : | UnsafeDeserialization.rb:41:24:41:32 | yaml_data |
|
||||
| UnsafeDeserialization.rb:52:17:52:22 | call to params : | UnsafeDeserialization.rb:52:17:52:28 | ...[...] : |
|
||||
| UnsafeDeserialization.rb:52:17:52:28 | ...[...] : | UnsafeDeserialization.rb:53:22:53:30 | json_data |
|
||||
| UnsafeDeserialization.rb:52:17:52:28 | ...[...] : | UnsafeDeserialization.rb:54:22:54:30 | json_data |
|
||||
| UnsafeDeserialization.rb:59:17:59:22 | call to params : | UnsafeDeserialization.rb:59:17:59:28 | ...[...] : |
|
||||
| UnsafeDeserialization.rb:59:17:59:28 | ...[...] : | UnsafeDeserialization.rb:69:23:69:31 | json_data |
|
||||
| UnsafeDeserialization.rb:81:11:81:16 | call to params : | UnsafeDeserialization.rb:81:11:81:22 | ...[...] : |
|
||||
| UnsafeDeserialization.rb:81:11:81:22 | ...[...] : | UnsafeDeserialization.rb:82:34:82:36 | xml |
|
||||
| UnsafeDeserialization.rb:87:17:87:22 | call to params : | UnsafeDeserialization.rb:87:17:87:28 | ...[...] : |
|
||||
| UnsafeDeserialization.rb:87:17:87:28 | ...[...] : | UnsafeDeserialization.rb:88:25:88:33 | yaml_data |
|
||||
| UnsafeDeserialization.rb:93:30:93:35 | call to params : | UnsafeDeserialization.rb:93:30:93:43 | ...[...] |
|
||||
| UnsafeDeserialization.rb:99:48:99:53 | call to params : | UnsafeDeserialization.rb:99:48:99:61 | ...[...] |
|
||||
nodes
|
||||
| UnsafeDeserialization.rb:9:39:9:44 | call to params : | semmle.label | call to params : |
|
||||
| UnsafeDeserialization.rb:9:39:9:50 | ...[...] : | semmle.label | ...[...] : |
|
||||
| UnsafeDeserialization.rb:10:27:10:41 | serialized_data | semmle.label | serialized_data |
|
||||
| UnsafeDeserialization.rb:15:39:15:44 | call to params : | semmle.label | call to params : |
|
||||
| UnsafeDeserialization.rb:15:39:15:50 | ...[...] : | semmle.label | ...[...] : |
|
||||
| UnsafeDeserialization.rb:16:30:16:44 | serialized_data | semmle.label | serialized_data |
|
||||
| UnsafeDeserialization.rb:21:17:21:22 | call to params : | semmle.label | call to params : |
|
||||
| UnsafeDeserialization.rb:21:17:21:28 | ...[...] : | semmle.label | ...[...] : |
|
||||
| UnsafeDeserialization.rb:22:24:22:32 | json_data | semmle.label | json_data |
|
||||
| UnsafeDeserialization.rb:27:17:27:22 | call to params : | semmle.label | call to params : |
|
||||
| UnsafeDeserialization.rb:27:17:27:28 | ...[...] : | semmle.label | ...[...] : |
|
||||
| UnsafeDeserialization.rb:28:27:28:35 | json_data | semmle.label | json_data |
|
||||
| UnsafeDeserialization.rb:39:17:39:22 | call to params : | semmle.label | call to params : |
|
||||
| UnsafeDeserialization.rb:39:17:39:28 | ...[...] : | semmle.label | ...[...] : |
|
||||
| UnsafeDeserialization.rb:40:24:40:32 | yaml_data | semmle.label | yaml_data |
|
||||
| UnsafeDeserialization.rb:51:17:51:22 | call to params : | semmle.label | call to params : |
|
||||
| UnsafeDeserialization.rb:51:17:51:28 | ...[...] : | semmle.label | ...[...] : |
|
||||
| UnsafeDeserialization.rb:52:22:52:30 | json_data | semmle.label | json_data |
|
||||
| UnsafeDeserialization.rb:10:39:10:44 | call to params : | semmle.label | call to params : |
|
||||
| UnsafeDeserialization.rb:10:39:10:50 | ...[...] : | semmle.label | ...[...] : |
|
||||
| UnsafeDeserialization.rb:11:27:11:41 | serialized_data | semmle.label | serialized_data |
|
||||
| UnsafeDeserialization.rb:16:39:16:44 | call to params : | semmle.label | call to params : |
|
||||
| UnsafeDeserialization.rb:16:39:16:50 | ...[...] : | semmle.label | ...[...] : |
|
||||
| UnsafeDeserialization.rb:17:30:17:44 | serialized_data | semmle.label | serialized_data |
|
||||
| UnsafeDeserialization.rb:22:17:22:22 | call to params : | semmle.label | call to params : |
|
||||
| UnsafeDeserialization.rb:22:17:22:28 | ...[...] : | semmle.label | ...[...] : |
|
||||
| UnsafeDeserialization.rb:23:24:23:32 | json_data | semmle.label | json_data |
|
||||
| UnsafeDeserialization.rb:28:17:28:22 | call to params : | semmle.label | call to params : |
|
||||
| UnsafeDeserialization.rb:28:17:28:28 | ...[...] : | semmle.label | ...[...] : |
|
||||
| UnsafeDeserialization.rb:29:27:29:35 | json_data | semmle.label | json_data |
|
||||
| UnsafeDeserialization.rb:40:17:40:22 | call to params : | semmle.label | call to params : |
|
||||
| UnsafeDeserialization.rb:40:17:40:28 | ...[...] : | semmle.label | ...[...] : |
|
||||
| UnsafeDeserialization.rb:41:24:41:32 | yaml_data | semmle.label | yaml_data |
|
||||
| UnsafeDeserialization.rb:52:17:52:22 | call to params : | semmle.label | call to params : |
|
||||
| UnsafeDeserialization.rb:52:17:52:28 | ...[...] : | semmle.label | ...[...] : |
|
||||
| UnsafeDeserialization.rb:53:22:53:30 | json_data | semmle.label | json_data |
|
||||
| UnsafeDeserialization.rb:58:17:58:22 | call to params : | semmle.label | call to params : |
|
||||
| UnsafeDeserialization.rb:58:17:58:28 | ...[...] : | semmle.label | ...[...] : |
|
||||
| UnsafeDeserialization.rb:68:23:68:31 | json_data | semmle.label | json_data |
|
||||
| UnsafeDeserialization.rb:80:11:80:16 | call to params : | semmle.label | call to params : |
|
||||
| UnsafeDeserialization.rb:80:11:80:22 | ...[...] : | semmle.label | ...[...] : |
|
||||
| UnsafeDeserialization.rb:81:34:81:36 | xml | semmle.label | xml |
|
||||
| UnsafeDeserialization.rb:86:17:86:22 | call to params : | semmle.label | call to params : |
|
||||
| UnsafeDeserialization.rb:86:17:86:28 | ...[...] : | semmle.label | ...[...] : |
|
||||
| UnsafeDeserialization.rb:87:25:87:33 | yaml_data | semmle.label | yaml_data |
|
||||
| UnsafeDeserialization.rb:54:22:54:30 | json_data | semmle.label | json_data |
|
||||
| UnsafeDeserialization.rb:59:17:59:22 | call to params : | semmle.label | call to params : |
|
||||
| UnsafeDeserialization.rb:59:17:59:28 | ...[...] : | semmle.label | ...[...] : |
|
||||
| UnsafeDeserialization.rb:69:23:69:31 | json_data | semmle.label | json_data |
|
||||
| UnsafeDeserialization.rb:81:11:81:16 | call to params : | semmle.label | call to params : |
|
||||
| UnsafeDeserialization.rb:81:11:81:22 | ...[...] : | semmle.label | ...[...] : |
|
||||
| UnsafeDeserialization.rb:82:34:82:36 | xml | semmle.label | xml |
|
||||
| UnsafeDeserialization.rb:87:17:87:22 | call to params : | semmle.label | call to params : |
|
||||
| UnsafeDeserialization.rb:87:17:87:28 | ...[...] : | semmle.label | ...[...] : |
|
||||
| UnsafeDeserialization.rb:88:25:88:33 | yaml_data | semmle.label | yaml_data |
|
||||
| UnsafeDeserialization.rb:93:30:93:35 | call to params : | semmle.label | call to params : |
|
||||
| UnsafeDeserialization.rb:93:30:93:43 | ...[...] | semmle.label | ...[...] |
|
||||
| UnsafeDeserialization.rb:99:48:99:53 | call to params : | semmle.label | call to params : |
|
||||
| UnsafeDeserialization.rb:99:48:99:61 | ...[...] | semmle.label | ...[...] |
|
||||
subpaths
|
||||
#select
|
||||
| UnsafeDeserialization.rb:10:27:10:41 | serialized_data | UnsafeDeserialization.rb:9:39:9:44 | call to params : | UnsafeDeserialization.rb:10:27:10:41 | serialized_data | Unsafe deserialization depends on a $@. | UnsafeDeserialization.rb:9:39:9:44 | call to params | user-provided value |
|
||||
| UnsafeDeserialization.rb:16:30:16:44 | serialized_data | UnsafeDeserialization.rb:15:39:15:44 | call to params : | UnsafeDeserialization.rb:16:30:16:44 | serialized_data | Unsafe deserialization depends on a $@. | UnsafeDeserialization.rb:15:39:15:44 | call to params | user-provided value |
|
||||
| UnsafeDeserialization.rb:22:24:22:32 | json_data | UnsafeDeserialization.rb:21:17:21:22 | call to params : | UnsafeDeserialization.rb:22:24:22:32 | json_data | Unsafe deserialization depends on a $@. | UnsafeDeserialization.rb:21:17:21:22 | call to params | user-provided value |
|
||||
| UnsafeDeserialization.rb:28:27:28:35 | json_data | UnsafeDeserialization.rb:27:17:27:22 | call to params : | UnsafeDeserialization.rb:28:27:28:35 | json_data | Unsafe deserialization depends on a $@. | UnsafeDeserialization.rb:27:17:27:22 | call to params | user-provided value |
|
||||
| UnsafeDeserialization.rb:40:24:40:32 | yaml_data | UnsafeDeserialization.rb:39:17:39:22 | call to params : | UnsafeDeserialization.rb:40:24:40:32 | yaml_data | Unsafe deserialization depends on a $@. | UnsafeDeserialization.rb:39:17:39:22 | call to params | user-provided value |
|
||||
| UnsafeDeserialization.rb:52:22:52:30 | json_data | UnsafeDeserialization.rb:51:17:51:22 | call to params : | UnsafeDeserialization.rb:52:22:52:30 | json_data | Unsafe deserialization depends on a $@. | UnsafeDeserialization.rb:51:17:51:22 | call to params | user-provided value |
|
||||
| UnsafeDeserialization.rb:53:22:53:30 | json_data | UnsafeDeserialization.rb:51:17:51:22 | call to params : | UnsafeDeserialization.rb:53:22:53:30 | json_data | Unsafe deserialization depends on a $@. | UnsafeDeserialization.rb:51:17:51:22 | call to params | user-provided value |
|
||||
| UnsafeDeserialization.rb:68:23:68:31 | json_data | UnsafeDeserialization.rb:58:17:58:22 | call to params : | UnsafeDeserialization.rb:68:23:68:31 | json_data | Unsafe deserialization depends on a $@. | UnsafeDeserialization.rb:58:17:58:22 | call to params | user-provided value |
|
||||
| UnsafeDeserialization.rb:81:34:81:36 | xml | UnsafeDeserialization.rb:80:11:80:16 | call to params : | UnsafeDeserialization.rb:81:34:81:36 | xml | Unsafe deserialization depends on a $@. | UnsafeDeserialization.rb:80:11:80:16 | call to params | user-provided value |
|
||||
| UnsafeDeserialization.rb:87:25:87:33 | yaml_data | UnsafeDeserialization.rb:86:17:86:22 | call to params : | UnsafeDeserialization.rb:87:25:87:33 | yaml_data | Unsafe deserialization depends on a $@. | UnsafeDeserialization.rb:86:17:86:22 | call to params | user-provided value |
|
||||
| UnsafeDeserialization.rb:11:27:11:41 | serialized_data | UnsafeDeserialization.rb:10:39:10:44 | call to params : | UnsafeDeserialization.rb:11:27:11:41 | serialized_data | Unsafe deserialization depends on a $@. | UnsafeDeserialization.rb:10:39:10:44 | call to params | user-provided value |
|
||||
| UnsafeDeserialization.rb:17:30:17:44 | serialized_data | UnsafeDeserialization.rb:16:39:16:44 | call to params : | UnsafeDeserialization.rb:17:30:17:44 | serialized_data | Unsafe deserialization depends on a $@. | UnsafeDeserialization.rb:16:39:16:44 | call to params | user-provided value |
|
||||
| UnsafeDeserialization.rb:23:24:23:32 | json_data | UnsafeDeserialization.rb:22:17:22:22 | call to params : | UnsafeDeserialization.rb:23:24:23:32 | json_data | Unsafe deserialization depends on a $@. | UnsafeDeserialization.rb:22:17:22:22 | call to params | user-provided value |
|
||||
| UnsafeDeserialization.rb:29:27:29:35 | json_data | UnsafeDeserialization.rb:28:17:28:22 | call to params : | UnsafeDeserialization.rb:29:27:29:35 | json_data | Unsafe deserialization depends on a $@. | UnsafeDeserialization.rb:28:17:28:22 | call to params | user-provided value |
|
||||
| UnsafeDeserialization.rb:41:24:41:32 | yaml_data | UnsafeDeserialization.rb:40:17:40:22 | call to params : | UnsafeDeserialization.rb:41:24:41:32 | yaml_data | Unsafe deserialization depends on a $@. | UnsafeDeserialization.rb:40:17:40:22 | call to params | user-provided value |
|
||||
| UnsafeDeserialization.rb:53:22:53:30 | json_data | UnsafeDeserialization.rb:52:17:52:22 | call to params : | UnsafeDeserialization.rb:53:22:53:30 | json_data | Unsafe deserialization depends on a $@. | UnsafeDeserialization.rb:52:17:52:22 | call to params | user-provided value |
|
||||
| UnsafeDeserialization.rb:54:22:54:30 | json_data | UnsafeDeserialization.rb:52:17:52:22 | call to params : | UnsafeDeserialization.rb:54:22:54:30 | json_data | Unsafe deserialization depends on a $@. | UnsafeDeserialization.rb:52:17:52:22 | call to params | user-provided value |
|
||||
| UnsafeDeserialization.rb:69:23:69:31 | json_data | UnsafeDeserialization.rb:59:17:59:22 | call to params : | UnsafeDeserialization.rb:69:23:69:31 | json_data | Unsafe deserialization depends on a $@. | UnsafeDeserialization.rb:59:17:59:22 | call to params | user-provided value |
|
||||
| UnsafeDeserialization.rb:82:34:82:36 | xml | UnsafeDeserialization.rb:81:11:81:16 | call to params : | UnsafeDeserialization.rb:82:34:82:36 | xml | Unsafe deserialization depends on a $@. | UnsafeDeserialization.rb:81:11:81:16 | call to params | user-provided value |
|
||||
| UnsafeDeserialization.rb:88:25:88:33 | yaml_data | UnsafeDeserialization.rb:87:17:87:22 | call to params : | UnsafeDeserialization.rb:88:25:88:33 | yaml_data | Unsafe deserialization depends on a $@. | UnsafeDeserialization.rb:87:17:87:22 | call to params | user-provided value |
|
||||
| UnsafeDeserialization.rb:93:30:93:43 | ...[...] | UnsafeDeserialization.rb:93:30:93:35 | call to params : | UnsafeDeserialization.rb:93:30:93:43 | ...[...] | Unsafe deserialization depends on a $@. | UnsafeDeserialization.rb:93:30:93:35 | call to params | user-provided value |
|
||||
| UnsafeDeserialization.rb:99:48:99:61 | ...[...] | UnsafeDeserialization.rb:99:48:99:53 | call to params : | UnsafeDeserialization.rb:99:48:99:61 | ...[...] | Unsafe deserialization depends on a $@. | UnsafeDeserialization.rb:99:48:99:53 | call to params | user-provided value |
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
require "active_job"
|
||||
require "base64"
|
||||
require "json"
|
||||
require "oj"
|
||||
@@ -86,4 +87,16 @@ class UsersController < ActionController::Base
|
||||
yaml_data = params[:key]
|
||||
object = Psych.load yaml_data
|
||||
end
|
||||
|
||||
# BAD - user input determines which class is instantiated
|
||||
def route12
|
||||
klass = Module.const_get(params[:class])
|
||||
object = klass.new
|
||||
end
|
||||
|
||||
# BAD - user input determines which class is instantiated
|
||||
def route13
|
||||
klass = ActiveJob::Serializers.deserialize(params[:class])
|
||||
object = klass.new
|
||||
end
|
||||
end
|
||||
|
||||
@@ -230,18 +230,18 @@ def _partition(l, pred):
|
||||
return map(list, _partition_iter(l, pred))
|
||||
|
||||
|
||||
def _is_in_qltest_collapsed_hierachy(cls: schema.Class, lookup: typing.Dict[str, schema.Class]):
|
||||
return "qltest_collapse_hierarchy" in cls.pragmas or _is_under_qltest_collapsed_hierachy(cls, lookup)
|
||||
def _is_in_qltest_collapsed_hierarchy(cls: schema.Class, lookup: typing.Dict[str, schema.Class]):
|
||||
return "qltest_collapse_hierarchy" in cls.pragmas or _is_under_qltest_collapsed_hierarchy(cls, lookup)
|
||||
|
||||
|
||||
def _is_under_qltest_collapsed_hierachy(cls: schema.Class, lookup: typing.Dict[str, schema.Class]):
|
||||
def _is_under_qltest_collapsed_hierarchy(cls: schema.Class, lookup: typing.Dict[str, schema.Class]):
|
||||
return "qltest_uncollapse_hierarchy" not in cls.pragmas and any(
|
||||
_is_in_qltest_collapsed_hierachy(lookup[b], lookup) for b in cls.bases)
|
||||
_is_in_qltest_collapsed_hierarchy(lookup[b], lookup) for b in cls.bases)
|
||||
|
||||
|
||||
def _should_skip_qltest(cls: schema.Class, lookup: typing.Dict[str, schema.Class]):
|
||||
return "qltest_skip" in cls.pragmas or not (
|
||||
cls.final or "qltest_collapse_hierarchy" in cls.pragmas) or _is_under_qltest_collapsed_hierachy(
|
||||
cls.final or "qltest_collapse_hierarchy" in cls.pragmas) or _is_under_qltest_collapsed_hierarchy(
|
||||
cls, lookup)
|
||||
|
||||
|
||||
|
||||
@@ -308,7 +308,7 @@ class SwiftDispatcher {
|
||||
|
||||
static FilePath getFilePath(llvm::StringRef path) {
|
||||
// TODO: this needs more testing
|
||||
// TODO: check canonicaliztion of names on a case insensitive filesystems
|
||||
// TODO: check canonicalization of names on a case insensitive filesystems
|
||||
// TODO: make symlink resolution conditional on CODEQL_PRESERVE_SYMLINKS=true
|
||||
llvm::SmallString<PATH_MAX> realPath;
|
||||
if (std::error_code ec = llvm::sys::fs::real_path(path, realPath)) {
|
||||
|
||||
@@ -94,7 +94,7 @@ private predicate isBooleanConstant(ControlFlowElement n, boolean value) {
|
||||
mustHaveBooleanCompletion(n) and
|
||||
value = n.asAstNode().(BooleanLiteralExpr).getValue()
|
||||
or
|
||||
// Boolean consants hidden inside conversions are also
|
||||
// Boolean constants hidden inside conversions are also
|
||||
// constants that resolve to the same value.
|
||||
exists(ControlFlowElement parent |
|
||||
parent.asAstNode() = n.asAstNode().getResolveStep() and
|
||||
|
||||
@@ -1074,7 +1074,7 @@ module Exprs {
|
||||
|
||||
/**
|
||||
* The control-flow for assignments where the left-hand side has
|
||||
* direct-to-implmentation-access semantics.
|
||||
* direct-to-implementation-access semantics.
|
||||
*/
|
||||
class PropertyAssignExpr extends AssignExprTree {
|
||||
AccessorDecl accessorDecl;
|
||||
|
||||
@@ -885,7 +885,7 @@ module TestOutput {
|
||||
/**
|
||||
* Gets a string used to resolve ties in node and edge ordering.
|
||||
*/
|
||||
string getOrderDisambuigation() { result = "" }
|
||||
string getOrderDisambiguation() { result = "" }
|
||||
}
|
||||
|
||||
query predicate nodes(RelevantNode n, string attr, string val) {
|
||||
@@ -900,7 +900,7 @@ module TestOutput {
|
||||
order by
|
||||
l.getFile().getBaseName(), l.getFile().getAbsolutePath(), l.getStartLine(),
|
||||
l.getStartColumn(), l.getEndLine(), l.getEndColumn(), p.toString(),
|
||||
p.getOrderDisambuigation()
|
||||
p.getOrderDisambiguation()
|
||||
)
|
||||
).toString()
|
||||
}
|
||||
@@ -923,7 +923,7 @@ module TestOutput {
|
||||
order by
|
||||
l.getFile().getBaseName(), l.getFile().getAbsolutePath(), l.getStartLine(),
|
||||
l.getStartColumn(), l.getEndLine(), l.getEndColumn(), t.toString(), s.toString(),
|
||||
s.getOrderDisambuigation()
|
||||
s.getOrderDisambiguation()
|
||||
)
|
||||
).toString()
|
||||
}
|
||||
|
||||
@@ -71,7 +71,7 @@ newtype TDataFlowCall =
|
||||
TNormalCall(ApplyExprCfgNode call) or
|
||||
TPropertyGetterCall(PropertyGetterCfgNode getter) or
|
||||
TPropertySetterCall(PropertySetterCfgNode setter) or
|
||||
TPropertyObserverCall(PropertyObserverCfgNode obserer) or
|
||||
TPropertyObserverCall(PropertyObserverCfgNode observer) or
|
||||
TSummaryCall(FlowSummaryImpl::Public::SummarizedCallable c, Node receiver) {
|
||||
FlowSummaryImpl::Private::summaryCallbackRange(c, receiver)
|
||||
}
|
||||
@@ -191,7 +191,7 @@ class PropertyObserverCall extends DataFlowCall, TPropertyObserverCall {
|
||||
result = observer.getBase()
|
||||
or
|
||||
// TODO: This is correct for `willSet` (which takes a `newValue` parameter),
|
||||
// but for `didSet` (which takes an `oldValue` paramter) we need an rvalue
|
||||
// but for `didSet` (which takes an `oldValue` parameter) we need an rvalue
|
||||
// for `getBase()`.
|
||||
i = 0 and
|
||||
result = observer.getSource()
|
||||
|
||||
@@ -11,7 +11,7 @@ class MyRelevantNode extends RelevantNode {
|
||||
|
||||
private AstNode asAstNode() { result = this.getNode().asAstNode() }
|
||||
|
||||
override string getOrderDisambuigation() {
|
||||
override string getOrderDisambiguation() {
|
||||
result = this.asAstNode().getPrimaryQlClasses()
|
||||
or
|
||||
not exists(this.asAstNode()) and result = ""
|
||||
|
||||
@@ -12,7 +12,7 @@ function RegisterExtractorPack(id)
|
||||
return nil
|
||||
end
|
||||
|
||||
-- removes upsupported CLI arg including the following how_many args
|
||||
-- removes unsupported CLI arg including the following how_many args
|
||||
function strip_unsupported_arg(args, arg, how_many)
|
||||
local index = indexOf(args, arg)
|
||||
if index then
|
||||
|
||||
Reference in New Issue
Block a user