mirror of
https://github.com/github/codeql.git
synced 2025-12-17 01:03:14 +01:00
Shared: move shared file to 'shared' folder and add parameterized module for 'getInvalidModelKind'
This commit is contained in:
@@ -598,14 +598,5 @@
|
|||||||
"EncryptionKeySizes Python/Java": [
|
"EncryptionKeySizes Python/Java": [
|
||||||
"python/ql/lib/semmle/python/security/internal/EncryptionKeySizes.qll",
|
"python/ql/lib/semmle/python/security/internal/EncryptionKeySizes.qll",
|
||||||
"java/ql/lib/semmle/code/java/security/internal/EncryptionKeySizes.qll"
|
"java/ql/lib/semmle/code/java/security/internal/EncryptionKeySizes.qll"
|
||||||
],
|
|
||||||
"SharedModelValidation Java/C#/Go/JS/Python/Ruby/Swift": [
|
|
||||||
"java/ql/lib/semmle/code/java/dataflow/internal/SharedModelValidation.qll",
|
|
||||||
"csharp/ql/lib/semmle/code/csharp/dataflow/internal/SharedModelValidation.qll",
|
|
||||||
"go/ql/lib/semmle/go/dataflow/internal/SharedModelValidation.qll",
|
|
||||||
"swift/ql/lib/codeql/swift/dataflow/internal/SharedModelValidation.qll",
|
|
||||||
"javascript/ql/lib/semmle/javascript/frameworks/data/internal/SharedModelValidation.qll",
|
|
||||||
"python/ql/lib/semmle/python/frameworks/data/internal/SharedModelValidation.qll",
|
|
||||||
"ruby/ql/lib/codeql/ruby/frameworks/data/internal/SharedModelValidation.qll"
|
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ extractor: csharp
|
|||||||
library: true
|
library: true
|
||||||
upgrades: upgrades
|
upgrades: upgrades
|
||||||
dependencies:
|
dependencies:
|
||||||
|
codeql/mad: ${workspace}
|
||||||
codeql/ssa: ${workspace}
|
codeql/ssa: ${workspace}
|
||||||
codeql/tutorial: ${workspace}
|
codeql/tutorial: ${workspace}
|
||||||
codeql/util: ${workspace}
|
codeql/util: ${workspace}
|
||||||
|
|||||||
@@ -95,7 +95,7 @@ private import internal.DataFlowPublic
|
|||||||
private import internal.FlowSummaryImpl::Public
|
private import internal.FlowSummaryImpl::Public
|
||||||
private import internal.FlowSummaryImpl::Private::External
|
private import internal.FlowSummaryImpl::Private::External
|
||||||
private import internal.FlowSummaryImplSpecific
|
private import internal.FlowSummaryImplSpecific
|
||||||
private import internal.SharedModelValidation
|
private import codeql.mad.ModelValidation as SharedModelVal
|
||||||
|
|
||||||
/** Holds if a source model exists for the given parameters. */
|
/** Holds if a source model exists for the given parameters. */
|
||||||
predicate sourceModel = Extensions::sourceModel/9;
|
predicate sourceModel = Extensions::sourceModel/9;
|
||||||
@@ -205,32 +205,20 @@ module ModelValidation {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Gets an error message relating to an invalid kind in a model. */
|
/** Holds if a summary model exists for the given `kind`. */
|
||||||
private string getInvalidModelKind() {
|
private predicate summaryKind(string kind) { summaryModel(_, _, _, _, _, _, _, _, kind, _) }
|
||||||
exists(string kind | summaryModel(_, _, _, _, _, _, _, _, kind, _) |
|
|
||||||
not kind instanceof ValidSummaryKind and
|
/** Holds if a sink model exists for the given `kind`. */
|
||||||
result = "Invalid kind \"" + kind + "\" in summary model."
|
private predicate sinkKind(string kind) { sinkModel(_, _, _, _, _, _, _, kind, _) }
|
||||||
)
|
|
||||||
or
|
/** Holds if a source model exists for the given `kind`. */
|
||||||
exists(string kind, string msg | sinkModel(_, _, _, _, _, _, _, kind, _) |
|
private predicate sourceKind(string kind) { sourceModel(_, _, _, _, _, _, _, kind, _) }
|
||||||
not kind instanceof ValidSinkKind and
|
|
||||||
msg = "Invalid kind \"" + kind + "\" in sink model." and
|
/** Holds if a neutral model exists for the given `kind`. */
|
||||||
// The part of this message that refers to outdated sink kinds can be deleted after June 1st, 2024.
|
private predicate neutralKind(string kind) { neutralModel(_, _, _, _, kind, _) }
|
||||||
if kind instanceof OutdatedSinkKind
|
|
||||||
then result = msg + " " + kind.(OutdatedSinkKind).outdatedMessage()
|
private module KindVal =
|
||||||
else result = msg
|
SharedModelVal::KindValidation<summaryKind/1, sinkKind/1, sourceKind/1, neutralKind/1>;
|
||||||
)
|
|
||||||
or
|
|
||||||
exists(string kind | sourceModel(_, _, _, _, _, _, _, kind, _) |
|
|
||||||
not kind instanceof ValidSourceKind and
|
|
||||||
result = "Invalid kind \"" + kind + "\" in source model."
|
|
||||||
)
|
|
||||||
or
|
|
||||||
exists(string kind | neutralModel(_, _, _, _, kind, _) |
|
|
||||||
not kind instanceof ValidNeutralKind and
|
|
||||||
result = "Invalid kind \"" + kind + "\" in neutral model."
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
private string getInvalidModelSignature() {
|
private string getInvalidModelSignature() {
|
||||||
exists(
|
exists(
|
||||||
@@ -273,7 +261,7 @@ module ModelValidation {
|
|||||||
msg =
|
msg =
|
||||||
[
|
[
|
||||||
getInvalidModelSignature(), getInvalidModelInput(), getInvalidModelOutput(),
|
getInvalidModelSignature(), getInvalidModelInput(), getInvalidModelOutput(),
|
||||||
getInvalidModelKind()
|
KindVal::getInvalidModelKind()
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,143 +0,0 @@
|
|||||||
/**
|
|
||||||
* INTERNAL: Do not use.
|
|
||||||
*
|
|
||||||
* Provides classes and predicates related to validating models-as-data rows.
|
|
||||||
* Such that we can share this logic across our CodeQL analysis of different languages.
|
|
||||||
*/
|
|
||||||
|
|
||||||
/** A valid models-as-data sink kind. */
|
|
||||||
class ValidSinkKind extends string {
|
|
||||||
bindingset[this]
|
|
||||||
ValidSinkKind() {
|
|
||||||
this =
|
|
||||||
[
|
|
||||||
// shared
|
|
||||||
"code-injection", "command-injection", "file-content-store", "html-injection",
|
|
||||||
"js-injection", "ldap-injection", "log-injection", "path-injection", "request-forgery",
|
|
||||||
"sql-injection", "url-redirection",
|
|
||||||
// Java-only currently, but may be shared in the future
|
|
||||||
"bean-validation", "fragment-injection", "groovy-injection", "hostname-verification",
|
|
||||||
"information-leak", "intent-redirection", "jexl-injection", "jndi-injection",
|
|
||||||
"mvel-injection", "ognl-injection", "pending-intents", "response-splitting",
|
|
||||||
"template-injection", "xpath-injection", "xslt-injection",
|
|
||||||
// JavaScript-only currently, but may be shared in the future
|
|
||||||
"mongodb.sink", "nosql-injection", "unsafe-deserialization",
|
|
||||||
// Swift-only currently, but may be shared in the future
|
|
||||||
"database-store", "format-string", "hash-iteration-count", "predicate-injection",
|
|
||||||
"preferences-store", "tls-protocol-version", "transmission", "webview-fetch", "xxe"
|
|
||||||
]
|
|
||||||
or
|
|
||||||
this.matches([
|
|
||||||
// shared
|
|
||||||
"encryption-%", "qltest%", "test-%",
|
|
||||||
// Java-only currently, but may be shared in the future
|
|
||||||
"regex-use%",
|
|
||||||
// JavaScript-only currently, but may be shared in the future
|
|
||||||
"credentials-%",
|
|
||||||
// Swift-only currently, but may be shared in the future
|
|
||||||
"%string-%length", "weak-hash-input-%"
|
|
||||||
])
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/** An outdated models-as-data sink kind. */
|
|
||||||
class OutdatedSinkKind extends string {
|
|
||||||
OutdatedSinkKind() {
|
|
||||||
this =
|
|
||||||
[
|
|
||||||
"sql", "url-redirect", "xpath", "ssti", "logging", "groovy", "jexl", "mvel", "xslt", "ldap",
|
|
||||||
"pending-intent-sent", "intent-start", "set-hostname-verifier", "header-splitting", "xss",
|
|
||||||
"write-file", "create-file", "read-file", "open-url", "jdbc-url", "command-line-injection",
|
|
||||||
"code", "html", "remote", "uncontrolled-format-string", "js-eval"
|
|
||||||
]
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Gets a replacement kind for an outdated sink kind. */
|
|
||||||
private string replacementKind() {
|
|
||||||
this = ["sql", "xpath", "groovy", "jexl", "mvel", "xslt", "ldap", "code", "html"] and
|
|
||||||
result = this + "-injection"
|
|
||||||
or
|
|
||||||
this = "js-eval" and result = "code-injection"
|
|
||||||
or
|
|
||||||
this = "url-redirect" and result = "url-redirection"
|
|
||||||
or
|
|
||||||
this = "ssti" and result = "template-injection"
|
|
||||||
or
|
|
||||||
this = "logging" and result = "log-injection"
|
|
||||||
or
|
|
||||||
this = "pending-intent-sent" and result = "pending-intents"
|
|
||||||
or
|
|
||||||
this = "intent-start" and result = "intent-redirection"
|
|
||||||
or
|
|
||||||
this = "set-hostname-verifier" and result = "hostname-verification"
|
|
||||||
or
|
|
||||||
this = "header-splitting" and result = "response-splitting"
|
|
||||||
or
|
|
||||||
this = "xss" and result = "html-injection\" or \"js-injection"
|
|
||||||
or
|
|
||||||
this = ["write-file", "remote"] and result = "file-content-store"
|
|
||||||
or
|
|
||||||
this = ["create-file", "read-file"] and result = "path-injection"
|
|
||||||
or
|
|
||||||
this = ["open-url", "jdbc-url"] and result = "request-forgery"
|
|
||||||
or
|
|
||||||
this = "command-line-injection" and result = "command-injection"
|
|
||||||
or
|
|
||||||
this = "uncontrolled-format-string" and result = "format-string"
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Gets an error message for an outdated sink kind. */
|
|
||||||
string outdatedMessage() {
|
|
||||||
result =
|
|
||||||
"The kind \"" + this + "\" is outdated. Use \"" + this.replacementKind() + "\" instead."
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/** A valid models-as-data source kind. */
|
|
||||||
class ValidSourceKind extends string {
|
|
||||||
bindingset[this]
|
|
||||||
ValidSourceKind() {
|
|
||||||
this =
|
|
||||||
[
|
|
||||||
// shared
|
|
||||||
"local", "remote",
|
|
||||||
// Java
|
|
||||||
"android-external-storage-dir", "contentprovider",
|
|
||||||
// C#
|
|
||||||
"file", "file-write",
|
|
||||||
// JavaScript
|
|
||||||
"database-access-result", "remote-flow"
|
|
||||||
]
|
|
||||||
or
|
|
||||||
this.matches([
|
|
||||||
// shared
|
|
||||||
"qltest%", "test-%",
|
|
||||||
// Swift
|
|
||||||
"%string-%length"
|
|
||||||
])
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/** A valid models-as-data summary kind. */
|
|
||||||
class ValidSummaryKind extends string {
|
|
||||||
ValidSummaryKind() {
|
|
||||||
this =
|
|
||||||
[
|
|
||||||
// shared
|
|
||||||
"taint", "value",
|
|
||||||
// JavaScript
|
|
||||||
"type"
|
|
||||||
]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/** A valid models-as-data neutral kind. */
|
|
||||||
class ValidNeutralKind extends string {
|
|
||||||
ValidNeutralKind() {
|
|
||||||
this =
|
|
||||||
[
|
|
||||||
// Java/C# currently
|
|
||||||
"sink", "source", "summary"
|
|
||||||
]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -6,6 +6,7 @@ extractor: go
|
|||||||
library: true
|
library: true
|
||||||
upgrades: upgrades
|
upgrades: upgrades
|
||||||
dependencies:
|
dependencies:
|
||||||
|
codeql/mad: ${workspace}
|
||||||
codeql/tutorial: ${workspace}
|
codeql/tutorial: ${workspace}
|
||||||
codeql/util: ${workspace}
|
codeql/util: ${workspace}
|
||||||
dataExtensions:
|
dataExtensions:
|
||||||
|
|||||||
@@ -68,7 +68,7 @@ private import internal.FlowSummaryImpl::Private::External
|
|||||||
private import internal.FlowSummaryImplSpecific
|
private import internal.FlowSummaryImplSpecific
|
||||||
private import internal.AccessPathSyntax
|
private import internal.AccessPathSyntax
|
||||||
private import FlowSummary
|
private import FlowSummary
|
||||||
private import internal.SharedModelValidation
|
private import codeql.mad.ModelValidation as SharedModelVal
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A module importing the frameworks that provide external flow data,
|
* A module importing the frameworks that provide external flow data,
|
||||||
@@ -189,27 +189,20 @@ module ModelValidation {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Gets an error message relating to an invalid kind in a model. */
|
/** Holds if a summary model exists for the given `kind`. */
|
||||||
private string getInvalidModelKind() {
|
private predicate summaryKind(string kind) { summaryModel(_, _, _, _, _, _, _, _, kind, _) }
|
||||||
exists(string kind | summaryModel(_, _, _, _, _, _, _, _, kind, _) |
|
|
||||||
not kind instanceof ValidSummaryKind and
|
/** Holds if a sink model exists for the given `kind`. */
|
||||||
result = "Invalid kind \"" + kind + "\" in summary model."
|
private predicate sinkKind(string kind) { sinkModel(_, _, _, _, _, _, _, kind, _) }
|
||||||
)
|
|
||||||
or
|
/** Holds if a source model exists for the given `kind`. */
|
||||||
exists(string kind, string msg | sinkModel(_, _, _, _, _, _, _, kind, _) |
|
private predicate sourceKind(string kind) { sourceModel(_, _, _, _, _, _, _, kind, _) }
|
||||||
not kind instanceof ValidSinkKind and
|
|
||||||
msg = "Invalid kind \"" + kind + "\" in sink model." and
|
/** Holds if a neutral model exists for the given `kind`. */
|
||||||
// The part of this message that refers to outdated sink kinds can be deleted after June 1st, 2024.
|
private predicate neutralKind(string kind) { none() }
|
||||||
if kind instanceof OutdatedSinkKind
|
|
||||||
then result = msg + " " + kind.(OutdatedSinkKind).outdatedMessage()
|
private module KindVal =
|
||||||
else result = msg
|
SharedModelVal::KindValidation<summaryKind/1, sinkKind/1, sourceKind/1, neutralKind/1>;
|
||||||
)
|
|
||||||
or
|
|
||||||
exists(string kind | sourceModel(_, _, _, _, _, _, _, kind, _) |
|
|
||||||
not kind instanceof ValidSourceKind and
|
|
||||||
result = "Invalid kind \"" + kind + "\" in source model."
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
private string getInvalidModelSignature() {
|
private string getInvalidModelSignature() {
|
||||||
exists(
|
exists(
|
||||||
@@ -247,7 +240,7 @@ module ModelValidation {
|
|||||||
msg =
|
msg =
|
||||||
[
|
[
|
||||||
getInvalidModelSignature(), getInvalidModelInput(), getInvalidModelOutput(),
|
getInvalidModelSignature(), getInvalidModelInput(), getInvalidModelOutput(),
|
||||||
getInvalidModelKind()
|
KindVal::getInvalidModelKind()
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,143 +0,0 @@
|
|||||||
/**
|
|
||||||
* INTERNAL: Do not use.
|
|
||||||
*
|
|
||||||
* Provides classes and predicates related to validating models-as-data rows.
|
|
||||||
* Such that we can share this logic across our CodeQL analysis of different languages.
|
|
||||||
*/
|
|
||||||
|
|
||||||
/** A valid models-as-data sink kind. */
|
|
||||||
class ValidSinkKind extends string {
|
|
||||||
bindingset[this]
|
|
||||||
ValidSinkKind() {
|
|
||||||
this =
|
|
||||||
[
|
|
||||||
// shared
|
|
||||||
"code-injection", "command-injection", "file-content-store", "html-injection",
|
|
||||||
"js-injection", "ldap-injection", "log-injection", "path-injection", "request-forgery",
|
|
||||||
"sql-injection", "url-redirection",
|
|
||||||
// Java-only currently, but may be shared in the future
|
|
||||||
"bean-validation", "fragment-injection", "groovy-injection", "hostname-verification",
|
|
||||||
"information-leak", "intent-redirection", "jexl-injection", "jndi-injection",
|
|
||||||
"mvel-injection", "ognl-injection", "pending-intents", "response-splitting",
|
|
||||||
"template-injection", "xpath-injection", "xslt-injection",
|
|
||||||
// JavaScript-only currently, but may be shared in the future
|
|
||||||
"mongodb.sink", "nosql-injection", "unsafe-deserialization",
|
|
||||||
// Swift-only currently, but may be shared in the future
|
|
||||||
"database-store", "format-string", "hash-iteration-count", "predicate-injection",
|
|
||||||
"preferences-store", "tls-protocol-version", "transmission", "webview-fetch", "xxe"
|
|
||||||
]
|
|
||||||
or
|
|
||||||
this.matches([
|
|
||||||
// shared
|
|
||||||
"encryption-%", "qltest%", "test-%",
|
|
||||||
// Java-only currently, but may be shared in the future
|
|
||||||
"regex-use%",
|
|
||||||
// JavaScript-only currently, but may be shared in the future
|
|
||||||
"credentials-%",
|
|
||||||
// Swift-only currently, but may be shared in the future
|
|
||||||
"%string-%length", "weak-hash-input-%"
|
|
||||||
])
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/** An outdated models-as-data sink kind. */
|
|
||||||
class OutdatedSinkKind extends string {
|
|
||||||
OutdatedSinkKind() {
|
|
||||||
this =
|
|
||||||
[
|
|
||||||
"sql", "url-redirect", "xpath", "ssti", "logging", "groovy", "jexl", "mvel", "xslt", "ldap",
|
|
||||||
"pending-intent-sent", "intent-start", "set-hostname-verifier", "header-splitting", "xss",
|
|
||||||
"write-file", "create-file", "read-file", "open-url", "jdbc-url", "command-line-injection",
|
|
||||||
"code", "html", "remote", "uncontrolled-format-string", "js-eval"
|
|
||||||
]
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Gets a replacement kind for an outdated sink kind. */
|
|
||||||
private string replacementKind() {
|
|
||||||
this = ["sql", "xpath", "groovy", "jexl", "mvel", "xslt", "ldap", "code", "html"] and
|
|
||||||
result = this + "-injection"
|
|
||||||
or
|
|
||||||
this = "js-eval" and result = "code-injection"
|
|
||||||
or
|
|
||||||
this = "url-redirect" and result = "url-redirection"
|
|
||||||
or
|
|
||||||
this = "ssti" and result = "template-injection"
|
|
||||||
or
|
|
||||||
this = "logging" and result = "log-injection"
|
|
||||||
or
|
|
||||||
this = "pending-intent-sent" and result = "pending-intents"
|
|
||||||
or
|
|
||||||
this = "intent-start" and result = "intent-redirection"
|
|
||||||
or
|
|
||||||
this = "set-hostname-verifier" and result = "hostname-verification"
|
|
||||||
or
|
|
||||||
this = "header-splitting" and result = "response-splitting"
|
|
||||||
or
|
|
||||||
this = "xss" and result = "html-injection\" or \"js-injection"
|
|
||||||
or
|
|
||||||
this = ["write-file", "remote"] and result = "file-content-store"
|
|
||||||
or
|
|
||||||
this = ["create-file", "read-file"] and result = "path-injection"
|
|
||||||
or
|
|
||||||
this = ["open-url", "jdbc-url"] and result = "request-forgery"
|
|
||||||
or
|
|
||||||
this = "command-line-injection" and result = "command-injection"
|
|
||||||
or
|
|
||||||
this = "uncontrolled-format-string" and result = "format-string"
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Gets an error message for an outdated sink kind. */
|
|
||||||
string outdatedMessage() {
|
|
||||||
result =
|
|
||||||
"The kind \"" + this + "\" is outdated. Use \"" + this.replacementKind() + "\" instead."
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/** A valid models-as-data source kind. */
|
|
||||||
class ValidSourceKind extends string {
|
|
||||||
bindingset[this]
|
|
||||||
ValidSourceKind() {
|
|
||||||
this =
|
|
||||||
[
|
|
||||||
// shared
|
|
||||||
"local", "remote",
|
|
||||||
// Java
|
|
||||||
"android-external-storage-dir", "contentprovider",
|
|
||||||
// C#
|
|
||||||
"file", "file-write",
|
|
||||||
// JavaScript
|
|
||||||
"database-access-result", "remote-flow"
|
|
||||||
]
|
|
||||||
or
|
|
||||||
this.matches([
|
|
||||||
// shared
|
|
||||||
"qltest%", "test-%",
|
|
||||||
// Swift
|
|
||||||
"%string-%length"
|
|
||||||
])
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/** A valid models-as-data summary kind. */
|
|
||||||
class ValidSummaryKind extends string {
|
|
||||||
ValidSummaryKind() {
|
|
||||||
this =
|
|
||||||
[
|
|
||||||
// shared
|
|
||||||
"taint", "value",
|
|
||||||
// JavaScript
|
|
||||||
"type"
|
|
||||||
]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/** A valid models-as-data neutral kind. */
|
|
||||||
class ValidNeutralKind extends string {
|
|
||||||
ValidNeutralKind() {
|
|
||||||
this =
|
|
||||||
[
|
|
||||||
// Java/C# currently
|
|
||||||
"sink", "source", "summary"
|
|
||||||
]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -6,6 +6,7 @@ extractor: java
|
|||||||
library: true
|
library: true
|
||||||
upgrades: upgrades
|
upgrades: upgrades
|
||||||
dependencies:
|
dependencies:
|
||||||
|
codeql/mad: ${workspace}
|
||||||
codeql/regex: ${workspace}
|
codeql/regex: ${workspace}
|
||||||
codeql/tutorial: ${workspace}
|
codeql/tutorial: ${workspace}
|
||||||
codeql/typetracking: ${workspace}
|
codeql/typetracking: ${workspace}
|
||||||
|
|||||||
@@ -87,7 +87,7 @@ private import internal.FlowSummaryImplSpecific as FlowSummaryImplSpecific
|
|||||||
private import internal.AccessPathSyntax
|
private import internal.AccessPathSyntax
|
||||||
private import ExternalFlowExtensions as Extensions
|
private import ExternalFlowExtensions as Extensions
|
||||||
private import FlowSummary
|
private import FlowSummary
|
||||||
private import internal.SharedModelValidation
|
private import codeql.mad.ModelValidation as SharedModelVal
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A class for activating additional model rows.
|
* A class for activating additional model rows.
|
||||||
@@ -266,32 +266,20 @@ module ModelValidation {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Gets an error message relating to an invalid kind in a model. */
|
/** Holds if a summary model exists for the given `kind`. */
|
||||||
private string getInvalidModelKind() {
|
private predicate summaryKind(string kind) { summaryModel(_, _, _, _, _, _, _, _, kind, _) }
|
||||||
exists(string kind | summaryModel(_, _, _, _, _, _, _, _, kind, _) |
|
|
||||||
not kind instanceof ValidSummaryKind and
|
/** Holds if a sink model exists for the given `kind`. */
|
||||||
result = "Invalid kind \"" + kind + "\" in summary model."
|
private predicate sinkKind(string kind) { sinkModel(_, _, _, _, _, _, _, kind, _) }
|
||||||
)
|
|
||||||
or
|
/** Holds if a source model exists for the given `kind`. */
|
||||||
exists(string kind, string msg | sinkModel(_, _, _, _, _, _, _, kind, _) |
|
private predicate sourceKind(string kind) { sourceModel(_, _, _, _, _, _, _, kind, _) }
|
||||||
not kind instanceof ValidSinkKind and
|
|
||||||
msg = "Invalid kind \"" + kind + "\" in sink model." and
|
/** Holds if a neutral model exists for the given `kind`. */
|
||||||
// The part of this message that refers to outdated sink kinds can be deleted after June 1st, 2024.
|
private predicate neutralKind(string kind) { neutralModel(_, _, _, _, kind, _) }
|
||||||
if kind instanceof OutdatedSinkKind
|
|
||||||
then result = msg + " " + kind.(OutdatedSinkKind).outdatedMessage()
|
private module KindVal =
|
||||||
else result = msg
|
SharedModelVal::KindValidation<summaryKind/1, sinkKind/1, sourceKind/1, neutralKind/1>;
|
||||||
)
|
|
||||||
or
|
|
||||||
exists(string kind | sourceModel(_, _, _, _, _, _, _, kind, _) |
|
|
||||||
not kind instanceof ValidSourceKind and
|
|
||||||
result = "Invalid kind \"" + kind + "\" in source model."
|
|
||||||
)
|
|
||||||
or
|
|
||||||
exists(string kind | neutralModel(_, _, _, _, kind, _) |
|
|
||||||
not kind instanceof ValidNeutralKind and
|
|
||||||
result = "Invalid kind \"" + kind + "\" in neutral model."
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
private string getInvalidModelSignature() {
|
private string getInvalidModelSignature() {
|
||||||
exists(
|
exists(
|
||||||
@@ -334,7 +322,7 @@ module ModelValidation {
|
|||||||
msg =
|
msg =
|
||||||
[
|
[
|
||||||
getInvalidModelSignature(), getInvalidModelInput(), getInvalidModelOutput(),
|
getInvalidModelSignature(), getInvalidModelInput(), getInvalidModelOutput(),
|
||||||
getInvalidModelKind()
|
KindVal::getInvalidModelKind()
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,143 +0,0 @@
|
|||||||
/**
|
|
||||||
* INTERNAL: Do not use.
|
|
||||||
*
|
|
||||||
* Provides classes and predicates related to validating models-as-data rows.
|
|
||||||
* Such that we can share this logic across our CodeQL analysis of different languages.
|
|
||||||
*/
|
|
||||||
|
|
||||||
/** A valid models-as-data sink kind. */
|
|
||||||
class ValidSinkKind extends string {
|
|
||||||
bindingset[this]
|
|
||||||
ValidSinkKind() {
|
|
||||||
this =
|
|
||||||
[
|
|
||||||
// shared
|
|
||||||
"code-injection", "command-injection", "file-content-store", "html-injection",
|
|
||||||
"js-injection", "ldap-injection", "log-injection", "path-injection", "request-forgery",
|
|
||||||
"sql-injection", "url-redirection",
|
|
||||||
// Java-only currently, but may be shared in the future
|
|
||||||
"bean-validation", "fragment-injection", "groovy-injection", "hostname-verification",
|
|
||||||
"information-leak", "intent-redirection", "jexl-injection", "jndi-injection",
|
|
||||||
"mvel-injection", "ognl-injection", "pending-intents", "response-splitting",
|
|
||||||
"template-injection", "xpath-injection", "xslt-injection",
|
|
||||||
// JavaScript-only currently, but may be shared in the future
|
|
||||||
"mongodb.sink", "nosql-injection", "unsafe-deserialization",
|
|
||||||
// Swift-only currently, but may be shared in the future
|
|
||||||
"database-store", "format-string", "hash-iteration-count", "predicate-injection",
|
|
||||||
"preferences-store", "tls-protocol-version", "transmission", "webview-fetch", "xxe"
|
|
||||||
]
|
|
||||||
or
|
|
||||||
this.matches([
|
|
||||||
// shared
|
|
||||||
"encryption-%", "qltest%", "test-%",
|
|
||||||
// Java-only currently, but may be shared in the future
|
|
||||||
"regex-use%",
|
|
||||||
// JavaScript-only currently, but may be shared in the future
|
|
||||||
"credentials-%",
|
|
||||||
// Swift-only currently, but may be shared in the future
|
|
||||||
"%string-%length", "weak-hash-input-%"
|
|
||||||
])
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/** An outdated models-as-data sink kind. */
|
|
||||||
class OutdatedSinkKind extends string {
|
|
||||||
OutdatedSinkKind() {
|
|
||||||
this =
|
|
||||||
[
|
|
||||||
"sql", "url-redirect", "xpath", "ssti", "logging", "groovy", "jexl", "mvel", "xslt", "ldap",
|
|
||||||
"pending-intent-sent", "intent-start", "set-hostname-verifier", "header-splitting", "xss",
|
|
||||||
"write-file", "create-file", "read-file", "open-url", "jdbc-url", "command-line-injection",
|
|
||||||
"code", "html", "remote", "uncontrolled-format-string", "js-eval"
|
|
||||||
]
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Gets a replacement kind for an outdated sink kind. */
|
|
||||||
private string replacementKind() {
|
|
||||||
this = ["sql", "xpath", "groovy", "jexl", "mvel", "xslt", "ldap", "code", "html"] and
|
|
||||||
result = this + "-injection"
|
|
||||||
or
|
|
||||||
this = "js-eval" and result = "code-injection"
|
|
||||||
or
|
|
||||||
this = "url-redirect" and result = "url-redirection"
|
|
||||||
or
|
|
||||||
this = "ssti" and result = "template-injection"
|
|
||||||
or
|
|
||||||
this = "logging" and result = "log-injection"
|
|
||||||
or
|
|
||||||
this = "pending-intent-sent" and result = "pending-intents"
|
|
||||||
or
|
|
||||||
this = "intent-start" and result = "intent-redirection"
|
|
||||||
or
|
|
||||||
this = "set-hostname-verifier" and result = "hostname-verification"
|
|
||||||
or
|
|
||||||
this = "header-splitting" and result = "response-splitting"
|
|
||||||
or
|
|
||||||
this = "xss" and result = "html-injection\" or \"js-injection"
|
|
||||||
or
|
|
||||||
this = ["write-file", "remote"] and result = "file-content-store"
|
|
||||||
or
|
|
||||||
this = ["create-file", "read-file"] and result = "path-injection"
|
|
||||||
or
|
|
||||||
this = ["open-url", "jdbc-url"] and result = "request-forgery"
|
|
||||||
or
|
|
||||||
this = "command-line-injection" and result = "command-injection"
|
|
||||||
or
|
|
||||||
this = "uncontrolled-format-string" and result = "format-string"
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Gets an error message for an outdated sink kind. */
|
|
||||||
string outdatedMessage() {
|
|
||||||
result =
|
|
||||||
"The kind \"" + this + "\" is outdated. Use \"" + this.replacementKind() + "\" instead."
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/** A valid models-as-data source kind. */
|
|
||||||
class ValidSourceKind extends string {
|
|
||||||
bindingset[this]
|
|
||||||
ValidSourceKind() {
|
|
||||||
this =
|
|
||||||
[
|
|
||||||
// shared
|
|
||||||
"local", "remote",
|
|
||||||
// Java
|
|
||||||
"android-external-storage-dir", "contentprovider",
|
|
||||||
// C#
|
|
||||||
"file", "file-write",
|
|
||||||
// JavaScript
|
|
||||||
"database-access-result", "remote-flow"
|
|
||||||
]
|
|
||||||
or
|
|
||||||
this.matches([
|
|
||||||
// shared
|
|
||||||
"qltest%", "test-%",
|
|
||||||
// Swift
|
|
||||||
"%string-%length"
|
|
||||||
])
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/** A valid models-as-data summary kind. */
|
|
||||||
class ValidSummaryKind extends string {
|
|
||||||
ValidSummaryKind() {
|
|
||||||
this =
|
|
||||||
[
|
|
||||||
// shared
|
|
||||||
"taint", "value",
|
|
||||||
// JavaScript
|
|
||||||
"type"
|
|
||||||
]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/** A valid models-as-data neutral kind. */
|
|
||||||
class ValidNeutralKind extends string {
|
|
||||||
ValidNeutralKind() {
|
|
||||||
this =
|
|
||||||
[
|
|
||||||
// Java/C# currently
|
|
||||||
"sink", "source", "summary"
|
|
||||||
]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -6,6 +6,7 @@ extractor: javascript
|
|||||||
library: true
|
library: true
|
||||||
upgrades: upgrades
|
upgrades: upgrades
|
||||||
dependencies:
|
dependencies:
|
||||||
|
codeql/mad: ${workspace}
|
||||||
codeql/regex: ${workspace}
|
codeql/regex: ${workspace}
|
||||||
codeql/tutorial: ${workspace}
|
codeql/tutorial: ${workspace}
|
||||||
codeql/util: ${workspace}
|
codeql/util: ${workspace}
|
||||||
|
|||||||
@@ -653,29 +653,22 @@ module ModelOutput {
|
|||||||
|
|
||||||
import Cached
|
import Cached
|
||||||
import Specific::ModelOutputSpecific
|
import Specific::ModelOutputSpecific
|
||||||
private import SharedModelValidation
|
private import codeql.mad.ModelValidation as SharedModelVal
|
||||||
|
|
||||||
/** Gets an error message relating to an invalid kind in a model. */
|
/** Holds if a summary model exists for the given `kind`. */
|
||||||
private string getInvalidModelKind() {
|
private predicate summaryKind(string kind) { summaryModel(_, _, _, _, kind) }
|
||||||
exists(string kind | summaryModel(_, _, _, _, kind) |
|
|
||||||
not kind instanceof ValidSummaryKind and
|
/** Holds if a sink model exists for the given `kind`. */
|
||||||
result = "Invalid kind \"" + kind + "\" in summary model."
|
private predicate sinkKind(string kind) { sinkModel(_, _, kind) }
|
||||||
)
|
|
||||||
or
|
/** Holds if a source model exists for the given `kind`. */
|
||||||
exists(string kind, string msg | sinkModel(_, _, kind) |
|
private predicate sourceKind(string kind) { sourceModel(_, _, kind) }
|
||||||
not kind instanceof ValidSinkKind and
|
|
||||||
msg = "Invalid kind \"" + kind + "\" in sink model." and
|
/** Holds if a neutral model exists for the given `kind`. */
|
||||||
// The part of this message that refers to outdated sink kinds can be deleted after June 1st, 2024.
|
private predicate neutralKind(string kind) { none() }
|
||||||
if kind instanceof OutdatedSinkKind
|
|
||||||
then result = msg + " " + kind.(OutdatedSinkKind).outdatedMessage()
|
private module KindVal =
|
||||||
else result = msg
|
SharedModelVal::KindValidation<summaryKind/1, sinkKind/1, sourceKind/1, neutralKind/1>;
|
||||||
)
|
|
||||||
or
|
|
||||||
exists(string kind | sourceModel(_, _, kind) |
|
|
||||||
not kind instanceof ValidSourceKind and
|
|
||||||
result = "Invalid kind \"" + kind + "\" in source model."
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets an error message relating to an invalid CSV row in a model.
|
* Gets an error message relating to an invalid CSV row in a model.
|
||||||
@@ -723,6 +716,6 @@ module ModelOutput {
|
|||||||
)
|
)
|
||||||
or
|
or
|
||||||
// Check for invalid model kinds
|
// Check for invalid model kinds
|
||||||
result = getInvalidModelKind()
|
result = KindVal::getInvalidModelKind()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,143 +0,0 @@
|
|||||||
/**
|
|
||||||
* INTERNAL: Do not use.
|
|
||||||
*
|
|
||||||
* Provides classes and predicates related to validating models-as-data rows.
|
|
||||||
* Such that we can share this logic across our CodeQL analysis of different languages.
|
|
||||||
*/
|
|
||||||
|
|
||||||
/** A valid models-as-data sink kind. */
|
|
||||||
class ValidSinkKind extends string {
|
|
||||||
bindingset[this]
|
|
||||||
ValidSinkKind() {
|
|
||||||
this =
|
|
||||||
[
|
|
||||||
// shared
|
|
||||||
"code-injection", "command-injection", "file-content-store", "html-injection",
|
|
||||||
"js-injection", "ldap-injection", "log-injection", "path-injection", "request-forgery",
|
|
||||||
"sql-injection", "url-redirection",
|
|
||||||
// Java-only currently, but may be shared in the future
|
|
||||||
"bean-validation", "fragment-injection", "groovy-injection", "hostname-verification",
|
|
||||||
"information-leak", "intent-redirection", "jexl-injection", "jndi-injection",
|
|
||||||
"mvel-injection", "ognl-injection", "pending-intents", "response-splitting",
|
|
||||||
"template-injection", "xpath-injection", "xslt-injection",
|
|
||||||
// JavaScript-only currently, but may be shared in the future
|
|
||||||
"mongodb.sink", "nosql-injection", "unsafe-deserialization",
|
|
||||||
// Swift-only currently, but may be shared in the future
|
|
||||||
"database-store", "format-string", "hash-iteration-count", "predicate-injection",
|
|
||||||
"preferences-store", "tls-protocol-version", "transmission", "webview-fetch", "xxe"
|
|
||||||
]
|
|
||||||
or
|
|
||||||
this.matches([
|
|
||||||
// shared
|
|
||||||
"encryption-%", "qltest%", "test-%",
|
|
||||||
// Java-only currently, but may be shared in the future
|
|
||||||
"regex-use%",
|
|
||||||
// JavaScript-only currently, but may be shared in the future
|
|
||||||
"credentials-%",
|
|
||||||
// Swift-only currently, but may be shared in the future
|
|
||||||
"%string-%length", "weak-hash-input-%"
|
|
||||||
])
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/** An outdated models-as-data sink kind. */
|
|
||||||
class OutdatedSinkKind extends string {
|
|
||||||
OutdatedSinkKind() {
|
|
||||||
this =
|
|
||||||
[
|
|
||||||
"sql", "url-redirect", "xpath", "ssti", "logging", "groovy", "jexl", "mvel", "xslt", "ldap",
|
|
||||||
"pending-intent-sent", "intent-start", "set-hostname-verifier", "header-splitting", "xss",
|
|
||||||
"write-file", "create-file", "read-file", "open-url", "jdbc-url", "command-line-injection",
|
|
||||||
"code", "html", "remote", "uncontrolled-format-string", "js-eval"
|
|
||||||
]
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Gets a replacement kind for an outdated sink kind. */
|
|
||||||
private string replacementKind() {
|
|
||||||
this = ["sql", "xpath", "groovy", "jexl", "mvel", "xslt", "ldap", "code", "html"] and
|
|
||||||
result = this + "-injection"
|
|
||||||
or
|
|
||||||
this = "js-eval" and result = "code-injection"
|
|
||||||
or
|
|
||||||
this = "url-redirect" and result = "url-redirection"
|
|
||||||
or
|
|
||||||
this = "ssti" and result = "template-injection"
|
|
||||||
or
|
|
||||||
this = "logging" and result = "log-injection"
|
|
||||||
or
|
|
||||||
this = "pending-intent-sent" and result = "pending-intents"
|
|
||||||
or
|
|
||||||
this = "intent-start" and result = "intent-redirection"
|
|
||||||
or
|
|
||||||
this = "set-hostname-verifier" and result = "hostname-verification"
|
|
||||||
or
|
|
||||||
this = "header-splitting" and result = "response-splitting"
|
|
||||||
or
|
|
||||||
this = "xss" and result = "html-injection\" or \"js-injection"
|
|
||||||
or
|
|
||||||
this = ["write-file", "remote"] and result = "file-content-store"
|
|
||||||
or
|
|
||||||
this = ["create-file", "read-file"] and result = "path-injection"
|
|
||||||
or
|
|
||||||
this = ["open-url", "jdbc-url"] and result = "request-forgery"
|
|
||||||
or
|
|
||||||
this = "command-line-injection" and result = "command-injection"
|
|
||||||
or
|
|
||||||
this = "uncontrolled-format-string" and result = "format-string"
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Gets an error message for an outdated sink kind. */
|
|
||||||
string outdatedMessage() {
|
|
||||||
result =
|
|
||||||
"The kind \"" + this + "\" is outdated. Use \"" + this.replacementKind() + "\" instead."
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/** A valid models-as-data source kind. */
|
|
||||||
class ValidSourceKind extends string {
|
|
||||||
bindingset[this]
|
|
||||||
ValidSourceKind() {
|
|
||||||
this =
|
|
||||||
[
|
|
||||||
// shared
|
|
||||||
"local", "remote",
|
|
||||||
// Java
|
|
||||||
"android-external-storage-dir", "contentprovider",
|
|
||||||
// C#
|
|
||||||
"file", "file-write",
|
|
||||||
// JavaScript
|
|
||||||
"database-access-result", "remote-flow"
|
|
||||||
]
|
|
||||||
or
|
|
||||||
this.matches([
|
|
||||||
// shared
|
|
||||||
"qltest%", "test-%",
|
|
||||||
// Swift
|
|
||||||
"%string-%length"
|
|
||||||
])
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/** A valid models-as-data summary kind. */
|
|
||||||
class ValidSummaryKind extends string {
|
|
||||||
ValidSummaryKind() {
|
|
||||||
this =
|
|
||||||
[
|
|
||||||
// shared
|
|
||||||
"taint", "value",
|
|
||||||
// JavaScript
|
|
||||||
"type"
|
|
||||||
]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/** A valid models-as-data neutral kind. */
|
|
||||||
class ValidNeutralKind extends string {
|
|
||||||
ValidNeutralKind() {
|
|
||||||
this =
|
|
||||||
[
|
|
||||||
// Java/C# currently
|
|
||||||
"sink", "source", "summary"
|
|
||||||
]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -6,6 +6,7 @@ extractor: python
|
|||||||
library: true
|
library: true
|
||||||
upgrades: upgrades
|
upgrades: upgrades
|
||||||
dependencies:
|
dependencies:
|
||||||
|
codeql/mad: ${workspace}
|
||||||
codeql/regex: ${workspace}
|
codeql/regex: ${workspace}
|
||||||
codeql/tutorial: ${workspace}
|
codeql/tutorial: ${workspace}
|
||||||
codeql/util: ${workspace}
|
codeql/util: ${workspace}
|
||||||
|
|||||||
@@ -653,29 +653,22 @@ module ModelOutput {
|
|||||||
|
|
||||||
import Cached
|
import Cached
|
||||||
import Specific::ModelOutputSpecific
|
import Specific::ModelOutputSpecific
|
||||||
private import SharedModelValidation
|
private import codeql.mad.ModelValidation as SharedModelVal
|
||||||
|
|
||||||
/** Gets an error message relating to an invalid kind in a model. */
|
/** Holds if a summary model exists for the given `kind`. */
|
||||||
private string getInvalidModelKind() {
|
private predicate summaryKind(string kind) { summaryModel(_, _, _, _, kind) }
|
||||||
exists(string kind | summaryModel(_, _, _, _, kind) |
|
|
||||||
not kind instanceof ValidSummaryKind and
|
/** Holds if a sink model exists for the given `kind`. */
|
||||||
result = "Invalid kind \"" + kind + "\" in summary model."
|
private predicate sinkKind(string kind) { sinkModel(_, _, kind) }
|
||||||
)
|
|
||||||
or
|
/** Holds if a source model exists for the given `kind`. */
|
||||||
exists(string kind, string msg | sinkModel(_, _, kind) |
|
private predicate sourceKind(string kind) { sourceModel(_, _, kind) }
|
||||||
not kind instanceof ValidSinkKind and
|
|
||||||
msg = "Invalid kind \"" + kind + "\" in sink model." and
|
/** Holds if a neutral model exists for the given `kind`. */
|
||||||
// The part of this message that refers to outdated sink kinds can be deleted after June 1st, 2024.
|
private predicate neutralKind(string kind) { none() }
|
||||||
if kind instanceof OutdatedSinkKind
|
|
||||||
then result = msg + " " + kind.(OutdatedSinkKind).outdatedMessage()
|
private module KindVal =
|
||||||
else result = msg
|
SharedModelVal::KindValidation<summaryKind/1, sinkKind/1, sourceKind/1, neutralKind/1>;
|
||||||
)
|
|
||||||
or
|
|
||||||
exists(string kind | sourceModel(_, _, kind) |
|
|
||||||
not kind instanceof ValidSourceKind and
|
|
||||||
result = "Invalid kind \"" + kind + "\" in source model."
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets an error message relating to an invalid CSV row in a model.
|
* Gets an error message relating to an invalid CSV row in a model.
|
||||||
@@ -723,6 +716,6 @@ module ModelOutput {
|
|||||||
)
|
)
|
||||||
or
|
or
|
||||||
// Check for invalid model kinds
|
// Check for invalid model kinds
|
||||||
result = getInvalidModelKind()
|
result = KindVal::getInvalidModelKind()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,143 +0,0 @@
|
|||||||
/**
|
|
||||||
* INTERNAL: Do not use.
|
|
||||||
*
|
|
||||||
* Provides classes and predicates related to validating models-as-data rows.
|
|
||||||
* Such that we can share this logic across our CodeQL analysis of different languages.
|
|
||||||
*/
|
|
||||||
|
|
||||||
/** A valid models-as-data sink kind. */
|
|
||||||
class ValidSinkKind extends string {
|
|
||||||
bindingset[this]
|
|
||||||
ValidSinkKind() {
|
|
||||||
this =
|
|
||||||
[
|
|
||||||
// shared
|
|
||||||
"code-injection", "command-injection", "file-content-store", "html-injection",
|
|
||||||
"js-injection", "ldap-injection", "log-injection", "path-injection", "request-forgery",
|
|
||||||
"sql-injection", "url-redirection",
|
|
||||||
// Java-only currently, but may be shared in the future
|
|
||||||
"bean-validation", "fragment-injection", "groovy-injection", "hostname-verification",
|
|
||||||
"information-leak", "intent-redirection", "jexl-injection", "jndi-injection",
|
|
||||||
"mvel-injection", "ognl-injection", "pending-intents", "response-splitting",
|
|
||||||
"template-injection", "xpath-injection", "xslt-injection",
|
|
||||||
// JavaScript-only currently, but may be shared in the future
|
|
||||||
"mongodb.sink", "nosql-injection", "unsafe-deserialization",
|
|
||||||
// Swift-only currently, but may be shared in the future
|
|
||||||
"database-store", "format-string", "hash-iteration-count", "predicate-injection",
|
|
||||||
"preferences-store", "tls-protocol-version", "transmission", "webview-fetch", "xxe"
|
|
||||||
]
|
|
||||||
or
|
|
||||||
this.matches([
|
|
||||||
// shared
|
|
||||||
"encryption-%", "qltest%", "test-%",
|
|
||||||
// Java-only currently, but may be shared in the future
|
|
||||||
"regex-use%",
|
|
||||||
// JavaScript-only currently, but may be shared in the future
|
|
||||||
"credentials-%",
|
|
||||||
// Swift-only currently, but may be shared in the future
|
|
||||||
"%string-%length", "weak-hash-input-%"
|
|
||||||
])
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/** An outdated models-as-data sink kind. */
|
|
||||||
class OutdatedSinkKind extends string {
|
|
||||||
OutdatedSinkKind() {
|
|
||||||
this =
|
|
||||||
[
|
|
||||||
"sql", "url-redirect", "xpath", "ssti", "logging", "groovy", "jexl", "mvel", "xslt", "ldap",
|
|
||||||
"pending-intent-sent", "intent-start", "set-hostname-verifier", "header-splitting", "xss",
|
|
||||||
"write-file", "create-file", "read-file", "open-url", "jdbc-url", "command-line-injection",
|
|
||||||
"code", "html", "remote", "uncontrolled-format-string", "js-eval"
|
|
||||||
]
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Gets a replacement kind for an outdated sink kind. */
|
|
||||||
private string replacementKind() {
|
|
||||||
this = ["sql", "xpath", "groovy", "jexl", "mvel", "xslt", "ldap", "code", "html"] and
|
|
||||||
result = this + "-injection"
|
|
||||||
or
|
|
||||||
this = "js-eval" and result = "code-injection"
|
|
||||||
or
|
|
||||||
this = "url-redirect" and result = "url-redirection"
|
|
||||||
or
|
|
||||||
this = "ssti" and result = "template-injection"
|
|
||||||
or
|
|
||||||
this = "logging" and result = "log-injection"
|
|
||||||
or
|
|
||||||
this = "pending-intent-sent" and result = "pending-intents"
|
|
||||||
or
|
|
||||||
this = "intent-start" and result = "intent-redirection"
|
|
||||||
or
|
|
||||||
this = "set-hostname-verifier" and result = "hostname-verification"
|
|
||||||
or
|
|
||||||
this = "header-splitting" and result = "response-splitting"
|
|
||||||
or
|
|
||||||
this = "xss" and result = "html-injection\" or \"js-injection"
|
|
||||||
or
|
|
||||||
this = ["write-file", "remote"] and result = "file-content-store"
|
|
||||||
or
|
|
||||||
this = ["create-file", "read-file"] and result = "path-injection"
|
|
||||||
or
|
|
||||||
this = ["open-url", "jdbc-url"] and result = "request-forgery"
|
|
||||||
or
|
|
||||||
this = "command-line-injection" and result = "command-injection"
|
|
||||||
or
|
|
||||||
this = "uncontrolled-format-string" and result = "format-string"
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Gets an error message for an outdated sink kind. */
|
|
||||||
string outdatedMessage() {
|
|
||||||
result =
|
|
||||||
"The kind \"" + this + "\" is outdated. Use \"" + this.replacementKind() + "\" instead."
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/** A valid models-as-data source kind. */
|
|
||||||
class ValidSourceKind extends string {
|
|
||||||
bindingset[this]
|
|
||||||
ValidSourceKind() {
|
|
||||||
this =
|
|
||||||
[
|
|
||||||
// shared
|
|
||||||
"local", "remote",
|
|
||||||
// Java
|
|
||||||
"android-external-storage-dir", "contentprovider",
|
|
||||||
// C#
|
|
||||||
"file", "file-write",
|
|
||||||
// JavaScript
|
|
||||||
"database-access-result", "remote-flow"
|
|
||||||
]
|
|
||||||
or
|
|
||||||
this.matches([
|
|
||||||
// shared
|
|
||||||
"qltest%", "test-%",
|
|
||||||
// Swift
|
|
||||||
"%string-%length"
|
|
||||||
])
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/** A valid models-as-data summary kind. */
|
|
||||||
class ValidSummaryKind extends string {
|
|
||||||
ValidSummaryKind() {
|
|
||||||
this =
|
|
||||||
[
|
|
||||||
// shared
|
|
||||||
"taint", "value",
|
|
||||||
// JavaScript
|
|
||||||
"type"
|
|
||||||
]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/** A valid models-as-data neutral kind. */
|
|
||||||
class ValidNeutralKind extends string {
|
|
||||||
ValidNeutralKind() {
|
|
||||||
this =
|
|
||||||
[
|
|
||||||
// Java/C# currently
|
|
||||||
"sink", "source", "summary"
|
|
||||||
]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -653,29 +653,22 @@ module ModelOutput {
|
|||||||
|
|
||||||
import Cached
|
import Cached
|
||||||
import Specific::ModelOutputSpecific
|
import Specific::ModelOutputSpecific
|
||||||
private import SharedModelValidation
|
private import codeql.mad.ModelValidation as SharedModelVal
|
||||||
|
|
||||||
/** Gets an error message relating to an invalid kind in a model. */
|
/** Holds if a summary model exists for the given `kind`. */
|
||||||
private string getInvalidModelKind() {
|
private predicate summaryKind(string kind) { summaryModel(_, _, _, _, kind) }
|
||||||
exists(string kind | summaryModel(_, _, _, _, kind) |
|
|
||||||
not kind instanceof ValidSummaryKind and
|
/** Holds if a sink model exists for the given `kind`. */
|
||||||
result = "Invalid kind \"" + kind + "\" in summary model."
|
private predicate sinkKind(string kind) { sinkModel(_, _, kind) }
|
||||||
)
|
|
||||||
or
|
/** Holds if a source model exists for the given `kind`. */
|
||||||
exists(string kind, string msg | sinkModel(_, _, kind) |
|
private predicate sourceKind(string kind) { sourceModel(_, _, kind) }
|
||||||
not kind instanceof ValidSinkKind and
|
|
||||||
msg = "Invalid kind \"" + kind + "\" in sink model." and
|
/** Holds if a neutral model exists for the given `kind`. */
|
||||||
// The part of this message that refers to outdated sink kinds can be deleted after June 1st, 2024.
|
private predicate neutralKind(string kind) { none() }
|
||||||
if kind instanceof OutdatedSinkKind
|
|
||||||
then result = msg + " " + kind.(OutdatedSinkKind).outdatedMessage()
|
private module KindVal =
|
||||||
else result = msg
|
SharedModelVal::KindValidation<summaryKind/1, sinkKind/1, sourceKind/1, neutralKind/1>;
|
||||||
)
|
|
||||||
or
|
|
||||||
exists(string kind | sourceModel(_, _, kind) |
|
|
||||||
not kind instanceof ValidSourceKind and
|
|
||||||
result = "Invalid kind \"" + kind + "\" in source model."
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets an error message relating to an invalid CSV row in a model.
|
* Gets an error message relating to an invalid CSV row in a model.
|
||||||
@@ -723,6 +716,6 @@ module ModelOutput {
|
|||||||
)
|
)
|
||||||
or
|
or
|
||||||
// Check for invalid model kinds
|
// Check for invalid model kinds
|
||||||
result = getInvalidModelKind()
|
result = KindVal::getInvalidModelKind()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,143 +0,0 @@
|
|||||||
/**
|
|
||||||
* INTERNAL: Do not use.
|
|
||||||
*
|
|
||||||
* Provides classes and predicates related to validating models-as-data rows.
|
|
||||||
* Such that we can share this logic across our CodeQL analysis of different languages.
|
|
||||||
*/
|
|
||||||
|
|
||||||
/** A valid models-as-data sink kind. */
|
|
||||||
class ValidSinkKind extends string {
|
|
||||||
bindingset[this]
|
|
||||||
ValidSinkKind() {
|
|
||||||
this =
|
|
||||||
[
|
|
||||||
// shared
|
|
||||||
"code-injection", "command-injection", "file-content-store", "html-injection",
|
|
||||||
"js-injection", "ldap-injection", "log-injection", "path-injection", "request-forgery",
|
|
||||||
"sql-injection", "url-redirection",
|
|
||||||
// Java-only currently, but may be shared in the future
|
|
||||||
"bean-validation", "fragment-injection", "groovy-injection", "hostname-verification",
|
|
||||||
"information-leak", "intent-redirection", "jexl-injection", "jndi-injection",
|
|
||||||
"mvel-injection", "ognl-injection", "pending-intents", "response-splitting",
|
|
||||||
"template-injection", "xpath-injection", "xslt-injection",
|
|
||||||
// JavaScript-only currently, but may be shared in the future
|
|
||||||
"mongodb.sink", "nosql-injection", "unsafe-deserialization",
|
|
||||||
// Swift-only currently, but may be shared in the future
|
|
||||||
"database-store", "format-string", "hash-iteration-count", "predicate-injection",
|
|
||||||
"preferences-store", "tls-protocol-version", "transmission", "webview-fetch", "xxe"
|
|
||||||
]
|
|
||||||
or
|
|
||||||
this.matches([
|
|
||||||
// shared
|
|
||||||
"encryption-%", "qltest%", "test-%",
|
|
||||||
// Java-only currently, but may be shared in the future
|
|
||||||
"regex-use%",
|
|
||||||
// JavaScript-only currently, but may be shared in the future
|
|
||||||
"credentials-%",
|
|
||||||
// Swift-only currently, but may be shared in the future
|
|
||||||
"%string-%length", "weak-hash-input-%"
|
|
||||||
])
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/** An outdated models-as-data sink kind. */
|
|
||||||
class OutdatedSinkKind extends string {
|
|
||||||
OutdatedSinkKind() {
|
|
||||||
this =
|
|
||||||
[
|
|
||||||
"sql", "url-redirect", "xpath", "ssti", "logging", "groovy", "jexl", "mvel", "xslt", "ldap",
|
|
||||||
"pending-intent-sent", "intent-start", "set-hostname-verifier", "header-splitting", "xss",
|
|
||||||
"write-file", "create-file", "read-file", "open-url", "jdbc-url", "command-line-injection",
|
|
||||||
"code", "html", "remote", "uncontrolled-format-string", "js-eval"
|
|
||||||
]
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Gets a replacement kind for an outdated sink kind. */
|
|
||||||
private string replacementKind() {
|
|
||||||
this = ["sql", "xpath", "groovy", "jexl", "mvel", "xslt", "ldap", "code", "html"] and
|
|
||||||
result = this + "-injection"
|
|
||||||
or
|
|
||||||
this = "js-eval" and result = "code-injection"
|
|
||||||
or
|
|
||||||
this = "url-redirect" and result = "url-redirection"
|
|
||||||
or
|
|
||||||
this = "ssti" and result = "template-injection"
|
|
||||||
or
|
|
||||||
this = "logging" and result = "log-injection"
|
|
||||||
or
|
|
||||||
this = "pending-intent-sent" and result = "pending-intents"
|
|
||||||
or
|
|
||||||
this = "intent-start" and result = "intent-redirection"
|
|
||||||
or
|
|
||||||
this = "set-hostname-verifier" and result = "hostname-verification"
|
|
||||||
or
|
|
||||||
this = "header-splitting" and result = "response-splitting"
|
|
||||||
or
|
|
||||||
this = "xss" and result = "html-injection\" or \"js-injection"
|
|
||||||
or
|
|
||||||
this = ["write-file", "remote"] and result = "file-content-store"
|
|
||||||
or
|
|
||||||
this = ["create-file", "read-file"] and result = "path-injection"
|
|
||||||
or
|
|
||||||
this = ["open-url", "jdbc-url"] and result = "request-forgery"
|
|
||||||
or
|
|
||||||
this = "command-line-injection" and result = "command-injection"
|
|
||||||
or
|
|
||||||
this = "uncontrolled-format-string" and result = "format-string"
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Gets an error message for an outdated sink kind. */
|
|
||||||
string outdatedMessage() {
|
|
||||||
result =
|
|
||||||
"The kind \"" + this + "\" is outdated. Use \"" + this.replacementKind() + "\" instead."
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/** A valid models-as-data source kind. */
|
|
||||||
class ValidSourceKind extends string {
|
|
||||||
bindingset[this]
|
|
||||||
ValidSourceKind() {
|
|
||||||
this =
|
|
||||||
[
|
|
||||||
// shared
|
|
||||||
"local", "remote",
|
|
||||||
// Java
|
|
||||||
"android-external-storage-dir", "contentprovider",
|
|
||||||
// C#
|
|
||||||
"file", "file-write",
|
|
||||||
// JavaScript
|
|
||||||
"database-access-result", "remote-flow"
|
|
||||||
]
|
|
||||||
or
|
|
||||||
this.matches([
|
|
||||||
// shared
|
|
||||||
"qltest%", "test-%",
|
|
||||||
// Swift
|
|
||||||
"%string-%length"
|
|
||||||
])
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/** A valid models-as-data summary kind. */
|
|
||||||
class ValidSummaryKind extends string {
|
|
||||||
ValidSummaryKind() {
|
|
||||||
this =
|
|
||||||
[
|
|
||||||
// shared
|
|
||||||
"taint", "value",
|
|
||||||
// JavaScript
|
|
||||||
"type"
|
|
||||||
]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/** A valid models-as-data neutral kind. */
|
|
||||||
class ValidNeutralKind extends string {
|
|
||||||
ValidNeutralKind() {
|
|
||||||
this =
|
|
||||||
[
|
|
||||||
// Java/C# currently
|
|
||||||
"sink", "source", "summary"
|
|
||||||
]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -6,6 +6,7 @@ dbscheme: ruby.dbscheme
|
|||||||
upgrades: upgrades
|
upgrades: upgrades
|
||||||
library: true
|
library: true
|
||||||
dependencies:
|
dependencies:
|
||||||
|
codeql/mad: ${workspace}
|
||||||
codeql/regex: ${workspace}
|
codeql/regex: ${workspace}
|
||||||
codeql/ssa: ${workspace}
|
codeql/ssa: ${workspace}
|
||||||
codeql/tutorial: ${workspace}
|
codeql/tutorial: ${workspace}
|
||||||
|
|||||||
4
shared/mad/codeql-pack.lock.yml
Normal file
4
shared/mad/codeql-pack.lock.yml
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
---
|
||||||
|
dependencies: {}
|
||||||
|
compiled: false
|
||||||
|
lockVersion: 1.0.0
|
||||||
2
shared/mad/codeql-pack.release.yml
Normal file
2
shared/mad/codeql-pack.release.yml
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
---
|
||||||
|
lastReleaseVersion: 0.0.13
|
||||||
177
shared/mad/codeql/mad/ModelValidation.qll
Normal file
177
shared/mad/codeql/mad/ModelValidation.qll
Normal file
@@ -0,0 +1,177 @@
|
|||||||
|
/**
|
||||||
|
* Provides classes and predicates related to validating models-as-data rows.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/** Holds if a model exists for the given `kind`. */
|
||||||
|
signature predicate modelKindSig(string kind);
|
||||||
|
|
||||||
|
/** Provides validation for models-as-data summary, sink, source, and neutral kinds. */
|
||||||
|
module KindValidation<
|
||||||
|
modelKindSig/1 summaryKind, modelKindSig/1 sinkKind, modelKindSig/1 sourceKind,
|
||||||
|
modelKindSig/1 neutralKind>
|
||||||
|
{
|
||||||
|
/** A valid models-as-data sink kind. */
|
||||||
|
private class ValidSinkKind extends string {
|
||||||
|
bindingset[this]
|
||||||
|
ValidSinkKind() {
|
||||||
|
this =
|
||||||
|
[
|
||||||
|
// shared
|
||||||
|
"code-injection", "command-injection", "file-content-store", "html-injection",
|
||||||
|
"js-injection", "ldap-injection", "log-injection", "path-injection", "request-forgery",
|
||||||
|
"sql-injection", "url-redirection",
|
||||||
|
// Java-only currently, but may be shared in the future
|
||||||
|
"bean-validation", "fragment-injection", "groovy-injection", "hostname-verification",
|
||||||
|
"information-leak", "intent-redirection", "jexl-injection", "jndi-injection",
|
||||||
|
"mvel-injection", "ognl-injection", "pending-intents", "response-splitting",
|
||||||
|
"template-injection", "xpath-injection", "xslt-injection",
|
||||||
|
// JavaScript-only currently, but may be shared in the future
|
||||||
|
"mongodb.sink", "nosql-injection", "unsafe-deserialization",
|
||||||
|
// Swift-only currently, but may be shared in the future
|
||||||
|
"database-store", "format-string", "hash-iteration-count", "predicate-injection",
|
||||||
|
"preferences-store", "tls-protocol-version", "transmission", "webview-fetch", "xxe"
|
||||||
|
]
|
||||||
|
or
|
||||||
|
this.matches([
|
||||||
|
// shared
|
||||||
|
"encryption-%", "qltest%", "test-%",
|
||||||
|
// Java-only currently, but may be shared in the future
|
||||||
|
"regex-use%",
|
||||||
|
// JavaScript-only currently, but may be shared in the future
|
||||||
|
"credentials-%",
|
||||||
|
// Swift-only currently, but may be shared in the future
|
||||||
|
"%string-%length", "weak-hash-input-%"
|
||||||
|
])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/** An outdated models-as-data sink kind. */
|
||||||
|
private class OutdatedSinkKind extends string {
|
||||||
|
OutdatedSinkKind() {
|
||||||
|
this =
|
||||||
|
[
|
||||||
|
"sql", "url-redirect", "xpath", "ssti", "logging", "groovy", "jexl", "mvel", "xslt",
|
||||||
|
"ldap", "pending-intent-sent", "intent-start", "set-hostname-verifier",
|
||||||
|
"header-splitting", "xss", "write-file", "create-file", "read-file", "open-url",
|
||||||
|
"jdbc-url", "command-line-injection", "code", "html", "remote",
|
||||||
|
"uncontrolled-format-string", "js-eval"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Gets a replacement kind for an outdated sink kind. */
|
||||||
|
private string replacementKind() {
|
||||||
|
this = ["sql", "xpath", "groovy", "jexl", "mvel", "xslt", "ldap", "code", "html"] and
|
||||||
|
result = this + "-injection"
|
||||||
|
or
|
||||||
|
this = "js-eval" and result = "code-injection"
|
||||||
|
or
|
||||||
|
this = "url-redirect" and result = "url-redirection"
|
||||||
|
or
|
||||||
|
this = "ssti" and result = "template-injection"
|
||||||
|
or
|
||||||
|
this = "logging" and result = "log-injection"
|
||||||
|
or
|
||||||
|
this = "pending-intent-sent" and result = "pending-intents"
|
||||||
|
or
|
||||||
|
this = "intent-start" and result = "intent-redirection"
|
||||||
|
or
|
||||||
|
this = "set-hostname-verifier" and result = "hostname-verification"
|
||||||
|
or
|
||||||
|
this = "header-splitting" and result = "response-splitting"
|
||||||
|
or
|
||||||
|
this = "xss" and result = "html-injection\" or \"js-injection"
|
||||||
|
or
|
||||||
|
this = ["write-file", "remote"] and result = "file-content-store"
|
||||||
|
or
|
||||||
|
this = ["create-file", "read-file"] and result = "path-injection"
|
||||||
|
or
|
||||||
|
this = ["open-url", "jdbc-url"] and result = "request-forgery"
|
||||||
|
or
|
||||||
|
this = "command-line-injection" and result = "command-injection"
|
||||||
|
or
|
||||||
|
this = "uncontrolled-format-string" and result = "format-string"
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Gets an error message for an outdated sink kind. */
|
||||||
|
string outdatedMessage() {
|
||||||
|
result =
|
||||||
|
"The kind \"" + this + "\" is outdated. Use \"" + this.replacementKind() + "\" instead."
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/** A valid models-as-data source kind. */
|
||||||
|
private class ValidSourceKind extends string {
|
||||||
|
bindingset[this]
|
||||||
|
ValidSourceKind() {
|
||||||
|
this =
|
||||||
|
[
|
||||||
|
// shared
|
||||||
|
"local", "remote",
|
||||||
|
// Java
|
||||||
|
"android-external-storage-dir", "contentprovider",
|
||||||
|
// C#
|
||||||
|
"file", "file-write",
|
||||||
|
// JavaScript
|
||||||
|
"database-access-result", "remote-flow"
|
||||||
|
]
|
||||||
|
or
|
||||||
|
this.matches([
|
||||||
|
// shared
|
||||||
|
"qltest%", "test-%",
|
||||||
|
// Swift
|
||||||
|
"%string-%length"
|
||||||
|
])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/** A valid models-as-data summary kind. */
|
||||||
|
private class ValidSummaryKind extends string {
|
||||||
|
ValidSummaryKind() {
|
||||||
|
this =
|
||||||
|
[
|
||||||
|
// shared
|
||||||
|
"taint", "value",
|
||||||
|
// JavaScript
|
||||||
|
"type"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/** A valid models-as-data neutral kind. */
|
||||||
|
private class ValidNeutralKind extends string {
|
||||||
|
ValidNeutralKind() {
|
||||||
|
this =
|
||||||
|
[
|
||||||
|
// Java/C# currently
|
||||||
|
"sink", "source", "summary"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Gets an error message relating to an invalid kind in a model. */
|
||||||
|
string getInvalidModelKind() {
|
||||||
|
exists(string kind | summaryKind(kind) |
|
||||||
|
not kind instanceof ValidSummaryKind and
|
||||||
|
result = "Invalid kind \"" + kind + "\" in summary model."
|
||||||
|
)
|
||||||
|
or
|
||||||
|
exists(string kind, string msg | sinkKind(kind) |
|
||||||
|
not kind instanceof ValidSinkKind and
|
||||||
|
msg = "Invalid kind \"" + kind + "\" in sink model." and
|
||||||
|
// The part of this message that refers to outdated sink kinds can be deleted after June 1st, 2024.
|
||||||
|
if kind instanceof OutdatedSinkKind
|
||||||
|
then result = msg + " " + kind.(OutdatedSinkKind).outdatedMessage()
|
||||||
|
else result = msg
|
||||||
|
)
|
||||||
|
or
|
||||||
|
exists(string kind | sourceKind(kind) |
|
||||||
|
not kind instanceof ValidSourceKind and
|
||||||
|
result = "Invalid kind \"" + kind + "\" in source model."
|
||||||
|
)
|
||||||
|
or
|
||||||
|
exists(string kind | neutralKind(kind) |
|
||||||
|
not kind instanceof ValidNeutralKind and
|
||||||
|
result = "Invalid kind \"" + kind + "\" in neutral model."
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
6
shared/mad/qlpack.yml
Normal file
6
shared/mad/qlpack.yml
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
name: codeql/mad
|
||||||
|
version: 0.0.14-dev
|
||||||
|
groups: shared
|
||||||
|
library: true
|
||||||
|
dependencies:
|
||||||
|
warnOnImplicitThis: true
|
||||||
@@ -74,7 +74,7 @@ private import internal.FlowSummaryImpl::Public
|
|||||||
private import internal.FlowSummaryImpl::Private::External
|
private import internal.FlowSummaryImpl::Private::External
|
||||||
private import internal.FlowSummaryImplSpecific
|
private import internal.FlowSummaryImplSpecific
|
||||||
private import FlowSummary as FlowSummary
|
private import FlowSummary as FlowSummary
|
||||||
private import internal.SharedModelValidation
|
private import codeql.mad.ModelValidation as SharedModelVal
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A unit class for adding additional source model rows.
|
* A unit class for adding additional source model rows.
|
||||||
@@ -264,28 +264,20 @@ module CsvValidation {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Gets an error message relating to an invalid kind in a model. */
|
/** Holds if a summary model exists for the given `kind`. */
|
||||||
private string getInvalidModelKind() {
|
private predicate summaryKind(string kind) { summaryModel(_, _, _, _, _, _, _, _, kind, _) }
|
||||||
exists(string row, string kind | summaryModel(row) |
|
|
||||||
kind = row.splitAt(";", 8) and
|
/** Holds if a sink model exists for the given `kind`. */
|
||||||
not kind instanceof ValidSummaryKind and
|
private predicate sinkKind(string kind) { sinkModel(_, _, _, _, _, _, _, kind, _) }
|
||||||
result = "Invalid kind \"" + kind + "\" in summary model."
|
|
||||||
)
|
/** Holds if a source model exists for the given `kind`. */
|
||||||
or
|
private predicate sourceKind(string kind) { sourceModel(_, _, _, _, _, _, _, kind, _) }
|
||||||
exists(string kind, string msg | sinkModel(_, _, _, _, _, _, _, kind, _) |
|
|
||||||
not kind instanceof ValidSinkKind and
|
/** Holds if a neutral model exists for the given `kind`. */
|
||||||
msg = "Invalid kind \"" + kind + "\" in sink model." and
|
private predicate neutralKind(string kind) { none() }
|
||||||
// The part of this message that refers to outdated sink kinds can be deleted after June 1st, 2024.
|
|
||||||
if kind instanceof OutdatedSinkKind
|
private module KindVal =
|
||||||
then result = msg + " " + kind.(OutdatedSinkKind).outdatedMessage()
|
SharedModelVal::KindValidation<summaryKind/1, sinkKind/1, sourceKind/1, neutralKind/1>;
|
||||||
else result = msg
|
|
||||||
)
|
|
||||||
or
|
|
||||||
exists(string kind | sourceModel(_, _, _, _, _, _, _, kind, _) |
|
|
||||||
not kind instanceof ValidSourceKind and
|
|
||||||
result = "Invalid kind \"" + kind + "\" in source model."
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
private string getInvalidModelSubtype() {
|
private string getInvalidModelSubtype() {
|
||||||
exists(string pred, string row |
|
exists(string pred, string row |
|
||||||
@@ -351,7 +343,7 @@ module CsvValidation {
|
|||||||
msg =
|
msg =
|
||||||
[
|
[
|
||||||
getInvalidModelSignature(), getInvalidModelInput(), getInvalidModelOutput(),
|
getInvalidModelSignature(), getInvalidModelInput(), getInvalidModelOutput(),
|
||||||
getInvalidModelSubtype(), getInvalidModelColumnCount(), getInvalidModelKind()
|
getInvalidModelSubtype(), getInvalidModelColumnCount(), KindVal::getInvalidModelKind()
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,143 +0,0 @@
|
|||||||
/**
|
|
||||||
* INTERNAL: Do not use.
|
|
||||||
*
|
|
||||||
* Provides classes and predicates related to validating models-as-data rows.
|
|
||||||
* Such that we can share this logic across our CodeQL analysis of different languages.
|
|
||||||
*/
|
|
||||||
|
|
||||||
/** A valid models-as-data sink kind. */
|
|
||||||
class ValidSinkKind extends string {
|
|
||||||
bindingset[this]
|
|
||||||
ValidSinkKind() {
|
|
||||||
this =
|
|
||||||
[
|
|
||||||
// shared
|
|
||||||
"code-injection", "command-injection", "file-content-store", "html-injection",
|
|
||||||
"js-injection", "ldap-injection", "log-injection", "path-injection", "request-forgery",
|
|
||||||
"sql-injection", "url-redirection",
|
|
||||||
// Java-only currently, but may be shared in the future
|
|
||||||
"bean-validation", "fragment-injection", "groovy-injection", "hostname-verification",
|
|
||||||
"information-leak", "intent-redirection", "jexl-injection", "jndi-injection",
|
|
||||||
"mvel-injection", "ognl-injection", "pending-intents", "response-splitting",
|
|
||||||
"template-injection", "xpath-injection", "xslt-injection",
|
|
||||||
// JavaScript-only currently, but may be shared in the future
|
|
||||||
"mongodb.sink", "nosql-injection", "unsafe-deserialization",
|
|
||||||
// Swift-only currently, but may be shared in the future
|
|
||||||
"database-store", "format-string", "hash-iteration-count", "predicate-injection",
|
|
||||||
"preferences-store", "tls-protocol-version", "transmission", "webview-fetch", "xxe"
|
|
||||||
]
|
|
||||||
or
|
|
||||||
this.matches([
|
|
||||||
// shared
|
|
||||||
"encryption-%", "qltest%", "test-%",
|
|
||||||
// Java-only currently, but may be shared in the future
|
|
||||||
"regex-use%",
|
|
||||||
// JavaScript-only currently, but may be shared in the future
|
|
||||||
"credentials-%",
|
|
||||||
// Swift-only currently, but may be shared in the future
|
|
||||||
"%string-%length", "weak-hash-input-%"
|
|
||||||
])
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/** An outdated models-as-data sink kind. */
|
|
||||||
class OutdatedSinkKind extends string {
|
|
||||||
OutdatedSinkKind() {
|
|
||||||
this =
|
|
||||||
[
|
|
||||||
"sql", "url-redirect", "xpath", "ssti", "logging", "groovy", "jexl", "mvel", "xslt", "ldap",
|
|
||||||
"pending-intent-sent", "intent-start", "set-hostname-verifier", "header-splitting", "xss",
|
|
||||||
"write-file", "create-file", "read-file", "open-url", "jdbc-url", "command-line-injection",
|
|
||||||
"code", "html", "remote", "uncontrolled-format-string", "js-eval"
|
|
||||||
]
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Gets a replacement kind for an outdated sink kind. */
|
|
||||||
private string replacementKind() {
|
|
||||||
this = ["sql", "xpath", "groovy", "jexl", "mvel", "xslt", "ldap", "code", "html"] and
|
|
||||||
result = this + "-injection"
|
|
||||||
or
|
|
||||||
this = "js-eval" and result = "code-injection"
|
|
||||||
or
|
|
||||||
this = "url-redirect" and result = "url-redirection"
|
|
||||||
or
|
|
||||||
this = "ssti" and result = "template-injection"
|
|
||||||
or
|
|
||||||
this = "logging" and result = "log-injection"
|
|
||||||
or
|
|
||||||
this = "pending-intent-sent" and result = "pending-intents"
|
|
||||||
or
|
|
||||||
this = "intent-start" and result = "intent-redirection"
|
|
||||||
or
|
|
||||||
this = "set-hostname-verifier" and result = "hostname-verification"
|
|
||||||
or
|
|
||||||
this = "header-splitting" and result = "response-splitting"
|
|
||||||
or
|
|
||||||
this = "xss" and result = "html-injection\" or \"js-injection"
|
|
||||||
or
|
|
||||||
this = ["write-file", "remote"] and result = "file-content-store"
|
|
||||||
or
|
|
||||||
this = ["create-file", "read-file"] and result = "path-injection"
|
|
||||||
or
|
|
||||||
this = ["open-url", "jdbc-url"] and result = "request-forgery"
|
|
||||||
or
|
|
||||||
this = "command-line-injection" and result = "command-injection"
|
|
||||||
or
|
|
||||||
this = "uncontrolled-format-string" and result = "format-string"
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Gets an error message for an outdated sink kind. */
|
|
||||||
string outdatedMessage() {
|
|
||||||
result =
|
|
||||||
"The kind \"" + this + "\" is outdated. Use \"" + this.replacementKind() + "\" instead."
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/** A valid models-as-data source kind. */
|
|
||||||
class ValidSourceKind extends string {
|
|
||||||
bindingset[this]
|
|
||||||
ValidSourceKind() {
|
|
||||||
this =
|
|
||||||
[
|
|
||||||
// shared
|
|
||||||
"local", "remote",
|
|
||||||
// Java
|
|
||||||
"android-external-storage-dir", "contentprovider",
|
|
||||||
// C#
|
|
||||||
"file", "file-write",
|
|
||||||
// JavaScript
|
|
||||||
"database-access-result", "remote-flow"
|
|
||||||
]
|
|
||||||
or
|
|
||||||
this.matches([
|
|
||||||
// shared
|
|
||||||
"qltest%", "test-%",
|
|
||||||
// Swift
|
|
||||||
"%string-%length"
|
|
||||||
])
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/** A valid models-as-data summary kind. */
|
|
||||||
class ValidSummaryKind extends string {
|
|
||||||
ValidSummaryKind() {
|
|
||||||
this =
|
|
||||||
[
|
|
||||||
// shared
|
|
||||||
"taint", "value",
|
|
||||||
// JavaScript
|
|
||||||
"type"
|
|
||||||
]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/** A valid models-as-data neutral kind. */
|
|
||||||
class ValidNeutralKind extends string {
|
|
||||||
ValidNeutralKind() {
|
|
||||||
this =
|
|
||||||
[
|
|
||||||
// Java/C# currently
|
|
||||||
"sink", "source", "summary"
|
|
||||||
]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -6,6 +6,7 @@ dbscheme: swift.dbscheme
|
|||||||
upgrades: upgrades
|
upgrades: upgrades
|
||||||
library: true
|
library: true
|
||||||
dependencies:
|
dependencies:
|
||||||
|
codeql/mad: ${workspace}
|
||||||
codeql/ssa: ${workspace}
|
codeql/ssa: ${workspace}
|
||||||
codeql/tutorial: ${workspace}
|
codeql/tutorial: ${workspace}
|
||||||
codeql/util: ${workspace}
|
codeql/util: ${workspace}
|
||||||
|
|||||||
Reference in New Issue
Block a user