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 = ["//javascript:__pkg__"])

View File

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

View File

@@ -0,0 +1,13 @@
extensions:
- addsTo:
pack: codeql/javascript-all
extensible: typeModel
data:
# In Mongo version 2.x, a client and a database handle were the same concept, but in 3.x
# they were separated. To handle everything with a single model, we treat them as the same here.
- ['mongodb.Db', 'mongodb.MongoClient', '']
# 'marsdb' has no typings and is archived.
# We just model is as a variant of 'mongoose'.
- ['mongoose.Model', 'marsdb', 'Member[Collection].Instance']
- ['mongoose.Query', 'marsdb', 'Member[Collection].Instance']
- ['mongoose.Query', 'mongoose.Query', 'Member[sortFunc].ReturnValue']

View File

@@ -21,14 +21,6 @@ module NoSql {
* Provides classes modeling the `mongodb` and `mongoose` libraries.
*/
private module MongoDB {
private class OldMongoDbAdapter extends ModelInput::TypeModelCsv {
override predicate row(string row) {
// In Mongo version 2.x, a client and a database handle were the same concept, but in 3.x
// they were separated. To handle everything with a single model, we treat them as the same here.
row = "mongodb.Db;mongodb.MongoClient;"
}
}
/**
* An expression that is interpreted as a MongoDB query.
*/
@@ -169,24 +161,6 @@ private module Mongoose {
}
}
/**
* Provides classes modeling the MarsDB library.
*/
private module MarsDB {
// 'marsdb' has no typings and is archived.
// We just model is as a variant of 'mongoose'.
private class MongooseExtension extends ModelInput::TypeModelCsv {
override predicate row(string row) {
row =
[
"mongoose.Query;marsdb;Member[Collection].Instance",
"mongoose.Model;marsdb;Member[Collection].Instance",
"mongoose.Query;mongoose.Query;Member[sortFunc].ReturnValue",
]
}
}
}
/**
* Provides classes modeling the `Node Redis` library.
*

View File

@@ -0,0 +1,19 @@
extensions:
- addsTo:
pack: codeql/javascript-all
extensible: sourceModel
data:
- ['@google-cloud/spanner.~SpannerObject', 'Member[executeSql].Argument[0..].Parameter[1]', 'database-access-result']
- ['@google-cloud/spanner.~SpannerObject', 'Member[executeSql].ReturnValue.Awaited.Member[0]', 'database-access-result']
- ['@google-cloud/spanner.~SpannerObject', 'Member[run].Argument[0..].Parameter[1]', 'database-access-result']
- ['@google-cloud/spanner.~SpannerObject', 'Member[run].ReturnValue.Awaited', 'database-access-result']
- ['sequelize.Sequelize', 'Member[query].ReturnValue.Awaited', 'database-access-result']
- addsTo:
pack: codeql/javascript-all
extensible: sinkModel
data:
- ['@google-cloud/spanner.Transaction', 'Member[batchUpdate].Argument[0]', 'sql-injection']
- ['@google-cloud/spanner.Transaction', 'Member[batchUpdate].Argument[0].ArrayElement.Member[sql]', 'sql-injection']
- ['@google-cloud/spanner.~SqlExecutorDirect', 'Argument[0]', 'sql-injection']
- ['@google-cloud/spanner.~SqlExecutorDirect', 'Argument[0].Member[sql]', 'sql-injection']

View File

@@ -415,42 +415,3 @@ private module MsSql {
override string getCredentialsKind() { result = kind }
}
}
/**
* Provides classes modeling the `sequelize` package.
*/
private module Sequelize {
// Note: the sinks are specified directly in the MaD model
class SequelizeSource extends ModelInput::SourceModelCsv {
override predicate row(string row) {
row = "sequelize.Sequelize;Member[query].ReturnValue.Awaited;database-access-result"
}
}
}
private module SpannerCsv {
class SpannerSinks extends ModelInput::SinkModelCsv {
override predicate row(string row) {
// type; path; kind
row =
[
"@google-cloud/spanner.~SqlExecutorDirect;Argument[0];sql-injection",
"@google-cloud/spanner.~SqlExecutorDirect;Argument[0].Member[sql];sql-injection",
"@google-cloud/spanner.Transaction;Member[batchUpdate].Argument[0];sql-injection",
"@google-cloud/spanner.Transaction;Member[batchUpdate].Argument[0].ArrayElement.Member[sql];sql-injection",
]
}
}
class SpannerSources extends ModelInput::SourceModelCsv {
override predicate row(string row) {
row =
[
"@google-cloud/spanner.~SpannerObject;Member[executeSql].Argument[0..].Parameter[1];database-access-result",
"@google-cloud/spanner.~SpannerObject;Member[executeSql].ReturnValue.Awaited.Member[0];database-access-result",
"@google-cloud/spanner.~SpannerObject;Member[run].ReturnValue.Awaited;database-access-result",
"@google-cloud/spanner.~SpannerObject;Member[run].Argument[0..].Parameter[1];database-access-result",
]
}
}
}

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,87 +227,141 @@ 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. */
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
)
any(DeprecationAdapter a).typeModel(type1, type2, path)
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 +378,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 +608,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 +683,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 +720,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 +729,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 +745,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 +769,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

@@ -259,7 +259,7 @@ predicate invocationMatchesExtraCallSiteFilter(API::InvokeNode invoke, AccessPat
pragma[nomagic]
private predicate relevantInputOutputPath(API::InvokeNode base, AccessPath inputOrOutput) {
exists(string type, string input, string output, string path |
ModelOutput::relevantSummaryModel(type, path, input, output, _) and
ModelOutput::relevantSummaryModel(type, path, input, output, _, _) and
ModelOutput::resolvedSummaryBase(type, path, base) and
inputOrOutput = [input, output]
)
@@ -291,7 +291,7 @@ private API::Node getNodeFromInputOutputPath(API::InvokeNode baseNode, AccessPat
*/
predicate summaryStep(API::Node pred, API::Node succ, string kind) {
exists(string type, string path, API::InvokeNode base, AccessPath input, AccessPath output |
ModelOutput::relevantSummaryModel(type, path, input, output, kind) and
ModelOutput::relevantSummaryModel(type, path, input, output, kind, _) and
ModelOutput::resolvedSummaryBase(type, path, base) and
pred = getNodeFromInputOutputPath(base, input) and
succ = getNodeFromInputOutputPath(base, output)

View File

@@ -0,0 +1,76 @@
extensions:
- addsTo:
pack: codeql/javascript-all
extensible: sourceModel
data:
- ['testlib', 'Member[BaseClass].Instance.Member[baseclassSource].ReturnValue', 'test-source']
- ['testlib', 'Member[ClassDecorator].DecoratedClass.Instance.Member[inputIsSource].Parameter[0]', 'test-source']
- ['testlib', 'Member[FieldDecoratorSource].DecoratedMember', 'test-source']
- ['testlib', 'Member[MethodDecoratorWithArgs].ReturnValue.DecoratedMember.Parameter[0]', 'test-source']
- ['testlib', 'Member[MethodDecorator].DecoratedMember.Parameter[0]', 'test-source']
- ['testlib', 'Member[ParamDecoratorSource].DecoratedParameter', 'test-source']
- ['testlib', 'Member[getSource].ReturnValue', 'test-source']
- addsTo:
pack: codeql/javascript-all
extensible: sinkModel
data:
- ['testlib', 'AnyMember.Member[memberSink].Argument[0]', 'test-sink']
- ['testlib', 'Fuzzy.Member[fuzzyCall].Argument[0]', 'test-sink']
- ['testlib', 'Member[ClassDecorator].DecoratedClass.Instance.Member[returnValueIsSink].ReturnValue', 'test-sink']
- ['testlib', 'Member[FieldDecoratorSink].DecoratedMember', 'test-sink']
- ['testlib', 'Member[MethodDecoratorWithArgs].ReturnValue.DecoratedMember.ReturnValue', 'test-sink']
- ['testlib', 'Member[MethodDecorator].DecoratedMember.ReturnValue', 'test-sink']
- ['testlib', 'Member[ParamDecoratorSink].DecoratedParameter', 'test-sink']
- ['testlib', 'Member[foo', 'test-sink']
- ['testlib', 'Member[foo] .Member[bar]', 'test-sink']
- ['testlib', 'Member[foo] Member[bar]', 'test-sink']
- ['testlib', 'Member[foo], Member[bar]', 'test-sink']
- ['testlib', 'Member[foo],Member[bar]', 'test-sink']
- ['testlib', 'Member[foo]. Member[bar]', 'test-sink']
- ['testlib', 'Member[foo]..Member[bar]', 'test-sink']
- ['testlib', 'Member[foo]Member[bar]', 'test-sink']
- ['testlib', 'Member[foo]]', 'test-sink']
- ['testlib', 'Member[foo]].Member[bar]', 'test-sink']
- ['testlib', 'Member[mySinkExceptLast].Argument[0..N-2]', 'test-sink']
- ['testlib', 'Member[mySinkIfArityTwo].WithArity[2].Argument[0]', 'test-sink']
- ['testlib', 'Member[mySinkIfCall].Call.Argument[0]', 'test-sink']
- ['testlib', 'Member[mySinkIfNew].NewCall.Argument[0]', 'test-sink']
- ['testlib', 'Member[mySinkLast].Argument[N-1]', 'test-sink']
- ['testlib', 'Member[mySinkSecondLast].Argument[N-2]', 'test-sink']
- ['testlib', 'Member[mySinkTwoLastRange].Argument[N-2..N-1]', 'test-sink']
- ['testlib', 'Member[mySinkTwoLast].Argument[N-1,N-2]', 'test-sink']
- ['testlib', 'Member[mySink].Argument[0]', 'test-sink']
- ['testlib', 'Member[overloadedSink].WithStringArgument[0=danger].Argument[1]', 'test-sink']
- ['testlib', 'Member[sink1, sink2, sink3 ].Argument[0]', 'test-sink']
- ['testlib', 'Member[typevar].TypeVar[ABC].Member[mySink].Argument[0]', 'test-sink']
- ['testlib', 'Member[typevar].TypeVar[ABC].TypeVar[ABC].Member[mySink].Argument[1]', 'test-sink']
- ['testlib', 'Member[typevar].TypeVar[LeftRight].Member[mySink].Argument[0]', 'test-sink']
- addsTo:
pack: codeql/javascript-all
extensible: summaryModel
data:
- ['testlib', 'Member[getSource].ReturnValue.Member[continue]', 'Argument[this]', 'ReturnValue', 'taint']
- ['testlib', 'Member[preserveAllButFirstArgument]', 'Argument[1..]', 'ReturnValue', 'taint']
- ['testlib', 'Member[preserveAllIfCall].Call', 'Argument[0..]', 'ReturnValue', 'taint']
- ['testlib', 'Member[preserveArgZeroAndTwo]', 'Argument[0,2]', 'ReturnValue', 'taint']
- ['testlib', 'Member[preserveTaint]', 'Argument[0]', 'ReturnValue', 'taint']
- ['testlib', 'Member[taintIntoCallbackThis]', 'Argument[0]', 'Argument[1..2].Parameter[this]', 'taint']
- ['testlib', 'Member[taintIntoCallback]', 'Argument[0]', 'Argument[1..2].Parameter[0]', 'taint']
- ['testlib.~HasThisFlow', '', '', 'Member[getThis].ReturnValue', 'type']
- addsTo:
pack: codeql/javascript-all
extensible: typeModel
data:
- ['testlib.~HasThisFlow', 'testlib', 'Member[typevar]']
- ['testlib.~HasThisFlow', 'testlib.~HasThisFlow', 'Member[left,right,x]']
- addsTo:
pack: codeql/javascript-all
extensible: typeVariableModel
data:
- ['ABC', 'Member[a].Member[b].WithArity[0].ReturnValue.Member[c]']
- ['LeftRight', 'Member[left].TypeVar[LeftRight].Member[right]']
- ['LeftRight', 'Member[x]']

View File

@@ -2,89 +2,6 @@ import javascript
import testUtilities.ConsistencyChecking
import semmle.javascript.frameworks.data.internal.ApiGraphModels as ApiGraphModels
class Steps extends ModelInput::SummaryModelCsv {
override predicate row(string row) {
// type;path;input;output;kind
row =
[
"testlib;Member[preserveTaint];Argument[0];ReturnValue;taint",
"testlib;Member[taintIntoCallback];Argument[0];Argument[1..2].Parameter[0];taint",
"testlib;Member[taintIntoCallbackThis];Argument[0];Argument[1..2].Parameter[this];taint",
"testlib;Member[preserveArgZeroAndTwo];Argument[0,2];ReturnValue;taint",
"testlib;Member[preserveAllButFirstArgument];Argument[1..];ReturnValue;taint",
"testlib;Member[preserveAllIfCall].Call;Argument[0..];ReturnValue;taint",
"testlib;Member[getSource].ReturnValue.Member[continue];Argument[this];ReturnValue;taint",
"testlib.~HasThisFlow;;;Member[getThis].ReturnValue;type",
]
}
}
class TypeDefs extends ModelInput::TypeModelCsv {
override predicate row(string row) {
row =
[
"testlib.~HasThisFlow;testlib;Member[typevar]",
"testlib.~HasThisFlow;testlib.~HasThisFlow;Member[left,right,x]",
]
}
}
class Sinks extends ModelInput::SinkModelCsv {
override predicate row(string row) {
// type;path;kind
row =
[
"testlib;Member[mySink].Argument[0];test-sink",
"testlib;Member[mySinkIfCall].Call.Argument[0];test-sink",
"testlib;Member[mySinkIfNew].NewCall.Argument[0];test-sink",
"testlib;Member[mySinkLast].Argument[N-1];test-sink",
"testlib;Member[mySinkSecondLast].Argument[N-2];test-sink",
"testlib;Member[mySinkTwoLast].Argument[N-1,N-2];test-sink",
"testlib;Member[mySinkTwoLastRange].Argument[N-2..N-1];test-sink",
"testlib;Member[mySinkExceptLast].Argument[0..N-2];test-sink",
"testlib;Member[mySinkIfArityTwo].WithArity[2].Argument[0];test-sink",
"testlib;Member[sink1, sink2, sink3 ].Argument[0];test-sink",
"testlib;Member[ClassDecorator].DecoratedClass.Instance.Member[returnValueIsSink].ReturnValue;test-sink",
"testlib;Member[FieldDecoratorSink].DecoratedMember;test-sink",
"testlib;Member[MethodDecorator].DecoratedMember.ReturnValue;test-sink",
"testlib;Member[MethodDecoratorWithArgs].ReturnValue.DecoratedMember.ReturnValue;test-sink",
"testlib;Member[ParamDecoratorSink].DecoratedParameter;test-sink",
"testlib;AnyMember.Member[memberSink].Argument[0];test-sink",
"testlib;Member[overloadedSink].WithStringArgument[0=danger].Argument[1];test-sink",
"testlib;Member[typevar].TypeVar[ABC].Member[mySink].Argument[0];test-sink",
"testlib;Member[typevar].TypeVar[ABC].TypeVar[ABC].Member[mySink].Argument[1];test-sink",
"testlib;Member[typevar].TypeVar[LeftRight].Member[mySink].Argument[0];test-sink",
"testlib;Fuzzy.Member[fuzzyCall].Argument[0];test-sink"
]
}
}
class TypeVars extends ModelInput::TypeVariableModelCsv {
override predicate row(string row) {
row =
[
"ABC;Member[a].Member[b].WithArity[0].ReturnValue.Member[c]", //
"LeftRight;Member[left].TypeVar[LeftRight].Member[right]", //
"LeftRight;Member[x]",
]
}
}
class Sources extends ModelInput::SourceModelCsv {
override predicate row(string row) {
row =
[
"testlib;Member[getSource].ReturnValue;test-source",
"testlib;Member[ClassDecorator].DecoratedClass.Instance.Member[inputIsSource].Parameter[0];test-source",
"testlib;Member[FieldDecoratorSource].DecoratedMember;test-source",
"testlib;Member[ParamDecoratorSource].DecoratedParameter;test-source",
"testlib;Member[MethodDecorator].DecoratedMember.Parameter[0];test-source",
"testlib;Member[MethodDecoratorWithArgs].ReturnValue.DecoratedMember.Parameter[0];test-source",
"testlib;Member[BaseClass].Instance.Member[baseclassSource].ReturnValue;test-source",
]
}
}
class BasicTaintTracking extends TaintTracking::Configuration {
BasicTaintTracking() { this = "BasicTaintTracking" }
@@ -109,24 +26,6 @@ query predicate isSink(DataFlow::Node node, string kind) {
node = ModelOutput::getASinkNode(kind).asSink()
}
class SyntaxErrorTest extends ModelInput::SinkModelCsv {
override predicate row(string row) {
row =
[
"testlib;Member[foo],Member[bar];test-sink", //
"testlib;Member[foo] Member[bar];test-sink", //
"testlib;Member[foo]. Member[bar];test-sink", //
"testlib;Member[foo], Member[bar];test-sink", //
"testlib;Member[foo]..Member[bar];test-sink", //
"testlib;Member[foo] .Member[bar];test-sink", //
"testlib;Member[foo]Member[bar];test-sink", //
"testlib;Member[foo;test-sink", //
"testlib;Member[foo]];test-sink", //
"testlib;Member[foo]].Member[bar];test-sink"
]
}
}
query predicate syntaxErrors(ApiGraphModels::AccessPath path) { path.hasSyntaxError() }
query predicate warning = ModelOutput::getAWarning/0;

View File

@@ -1,5 +1,3 @@
| CSV type row should have 3 columns but has 1: test.TooFewColumns |
| CSV type row should have 3 columns but has 6: test.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 |

View File

@@ -0,0 +1,10 @@
extensions:
- addsTo:
pack: codeql/javascript-all
extensible: typeModel
data:
- ['test.X', 'test.Y', 'Method[foo].Arg[0]']
- ['test.X', 'test.Y', 'Method[foo].Argument[0-1]']
- ['test.X', 'test.Y', 'Method[foo].Argument[*]']
- ['test.X', 'test.Y', 'Method[foo].Argument']
- ['test.X', 'test.Y', 'Method[foo].Member']

View File

@@ -1,21 +1,6 @@
import javascript
import semmle.javascript.frameworks.data.internal.ApiGraphModels as ApiGraphModels
private class InvalidTypeModel extends ModelInput::TypeModelCsv {
override predicate row(string row) {
row =
[
"test.TooManyColumns;;Member[Foo].Instance;too;many;columns", //
"test.TooFewColumns", //
"test.X;test.Y;Method[foo].Arg[0]", //
"test.X;test.Y;Method[foo].Argument[0-1]", //
"test.X;test.Y;Method[foo].Argument[*]", //
"test.X;test.Y;Method[foo].Argument", //
"test.X;test.Y;Method[foo].Member", //
]
}
}
class IsTesting extends ApiGraphModels::TestAllModels {
IsTesting() { this = this }
}