mirror of
https://github.com/github/codeql.git
synced 2025-12-17 01:03:14 +01:00
Merge pull request #20986 from aschackmull/java/mad-barriers
Java: Support for MaD barriers and barrier guards.
This commit is contained in:
@@ -148,6 +148,19 @@ module SourceSinkInterpretationInput implements
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
predicate barrierElement(
|
||||||
|
Element n, string output, string kind, Public::Provenance provenance, string model
|
||||||
|
) {
|
||||||
|
none()
|
||||||
|
}
|
||||||
|
|
||||||
|
predicate barrierGuardElement(
|
||||||
|
Element n, string input, Public::AcceptingValue acceptingvalue, string kind,
|
||||||
|
Public::Provenance provenance, string model
|
||||||
|
) {
|
||||||
|
none()
|
||||||
|
}
|
||||||
|
|
||||||
private newtype TInterpretNode =
|
private newtype TInterpretNode =
|
||||||
TElement_(Element n) or
|
TElement_(Element n) or
|
||||||
TNode_(Node n)
|
TNode_(Node n)
|
||||||
|
|||||||
@@ -235,6 +235,19 @@ module SourceSinkInterpretationInput implements
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
predicate barrierElement(
|
||||||
|
Element n, string output, string kind, Public::Provenance provenance, string model
|
||||||
|
) {
|
||||||
|
none()
|
||||||
|
}
|
||||||
|
|
||||||
|
predicate barrierGuardElement(
|
||||||
|
Element n, string input, Public::AcceptingValue acceptingvalue, string kind,
|
||||||
|
Public::Provenance provenance, string model
|
||||||
|
) {
|
||||||
|
none()
|
||||||
|
}
|
||||||
|
|
||||||
class SourceOrSinkElement = Element;
|
class SourceOrSinkElement = Element;
|
||||||
|
|
||||||
private newtype TInterpretNode =
|
private newtype TInterpretNode =
|
||||||
|
|||||||
@@ -163,6 +163,19 @@ module SourceSinkInterpretationInput implements
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
predicate barrierElement(
|
||||||
|
Element n, string output, string kind, Public::Provenance provenance, string model
|
||||||
|
) {
|
||||||
|
none()
|
||||||
|
}
|
||||||
|
|
||||||
|
predicate barrierGuardElement(
|
||||||
|
Element n, string input, Public::AcceptingValue acceptingvalue, string kind,
|
||||||
|
Public::Provenance provenance, string model
|
||||||
|
) {
|
||||||
|
none()
|
||||||
|
}
|
||||||
|
|
||||||
// Note that due to embedding, which is currently implemented via some
|
// Note that due to embedding, which is currently implemented via some
|
||||||
// Methods having multiple qualified names, a given Method is liable to have
|
// Methods having multiple qualified names, a given Method is liable to have
|
||||||
// more than one SourceOrSinkElement, one for each of the names it claims.
|
// more than one SourceOrSinkElement, one for each of the names it claims.
|
||||||
|
|||||||
@@ -13,6 +13,14 @@ extensions:
|
|||||||
pack: codeql/java-all
|
pack: codeql/java-all
|
||||||
extensible: summaryModel
|
extensible: summaryModel
|
||||||
data: []
|
data: []
|
||||||
|
- addsTo:
|
||||||
|
pack: codeql/java-all
|
||||||
|
extensible: barrierModel
|
||||||
|
data: []
|
||||||
|
- addsTo:
|
||||||
|
pack: codeql/java-all
|
||||||
|
extensible: barrierGuardModel
|
||||||
|
data: []
|
||||||
- addsTo:
|
- addsTo:
|
||||||
pack: codeql/java-all
|
pack: codeql/java-all
|
||||||
extensible: neutralModel
|
extensible: neutralModel
|
||||||
|
|||||||
@@ -50,6 +50,12 @@ extensions:
|
|||||||
- ["hudson", "FilePath", False, "readToString", "", "", "ReturnValue", "file", "manual"]
|
- ["hudson", "FilePath", False, "readToString", "", "", "ReturnValue", "file", "manual"]
|
||||||
- ["hudson", "Plugin", True, "configure", "", "", "Parameter", "remote", "manual"]
|
- ["hudson", "Plugin", True, "configure", "", "", "Parameter", "remote", "manual"]
|
||||||
- ["hudson", "Plugin", True, "newInstance", "", "", "Parameter", "remote", "manual"]
|
- ["hudson", "Plugin", True, "newInstance", "", "", "Parameter", "remote", "manual"]
|
||||||
|
- addsTo:
|
||||||
|
pack: codeql/java-all
|
||||||
|
extensible: barrierModel
|
||||||
|
data:
|
||||||
|
- ["hudson", "Util", True, "escape", "(String)", "", "ReturnValue", "html-injection", "manual"]
|
||||||
|
# Not including xmlEscape because it only accounts for >, <, and &. It does not account for ", or ', which makes it an incomplete XSS sanitizer.
|
||||||
- addsTo:
|
- addsTo:
|
||||||
pack: codeql/java-all
|
pack: codeql/java-all
|
||||||
extensible: summaryModel
|
extensible: summaryModel
|
||||||
|
|||||||
@@ -162,3 +162,8 @@ extensions:
|
|||||||
extensible: sourceModel
|
extensible: sourceModel
|
||||||
data:
|
data:
|
||||||
- ["java.io", "FileInputStream", True, "FileInputStream", "", "", "Argument[this]", "file", "manual"]
|
- ["java.io", "FileInputStream", True, "FileInputStream", "", "", "Argument[this]", "file", "manual"]
|
||||||
|
- addsTo:
|
||||||
|
pack: codeql/java-all
|
||||||
|
extensible: barrierModel
|
||||||
|
data:
|
||||||
|
- ["java.io", "File", True, "getName", "()", "", "ReturnValue", "path-injection", "manual"]
|
||||||
|
|||||||
@@ -34,6 +34,11 @@ extensions:
|
|||||||
- ["java.net", "URLClassLoader", False, "URLClassLoader", "(URL[],ClassLoader)", "", "Argument[0]", "request-forgery", "manual"]
|
- ["java.net", "URLClassLoader", False, "URLClassLoader", "(URL[],ClassLoader)", "", "Argument[0]", "request-forgery", "manual"]
|
||||||
- ["java.net", "URLClassLoader", False, "URLClassLoader", "(URL[])", "", "Argument[0]", "request-forgery", "manual"]
|
- ["java.net", "URLClassLoader", False, "URLClassLoader", "(URL[])", "", "Argument[0]", "request-forgery", "manual"]
|
||||||
- ["java.net", "PasswordAuthentication", False, "PasswordAuthentication", "(String,char[])", "", "Argument[0]", "credentials-username", "hq-generated"]
|
- ["java.net", "PasswordAuthentication", False, "PasswordAuthentication", "(String,char[])", "", "Argument[0]", "credentials-username", "hq-generated"]
|
||||||
|
- addsTo:
|
||||||
|
pack: codeql/java-all
|
||||||
|
extensible: barrierGuardModel
|
||||||
|
data:
|
||||||
|
- ["java.net", "URI", True, "isAbsolute", "()", "", "Argument[this]", "false", "request-forgery", "manual"]
|
||||||
- addsTo:
|
- addsTo:
|
||||||
pack: codeql/java-all
|
pack: codeql/java-all
|
||||||
extensible: summaryModel
|
extensible: summaryModel
|
||||||
|
|||||||
@@ -12,6 +12,11 @@ extensions:
|
|||||||
- ["java.util.regex", "Pattern", False, "split", "(CharSequence)", "", "Argument[this]", "regex-use[0]", "manual"]
|
- ["java.util.regex", "Pattern", False, "split", "(CharSequence)", "", "Argument[this]", "regex-use[0]", "manual"]
|
||||||
- ["java.util.regex", "Pattern", False, "split", "(CharSequence,int)", "", "Argument[this]", "regex-use[0]", "manual"]
|
- ["java.util.regex", "Pattern", False, "split", "(CharSequence,int)", "", "Argument[this]", "regex-use[0]", "manual"]
|
||||||
- ["java.util.regex", "Pattern", False, "splitAsStream", "(CharSequence)", "", "Argument[this]", "regex-use[0]", "manual"]
|
- ["java.util.regex", "Pattern", False, "splitAsStream", "(CharSequence)", "", "Argument[this]", "regex-use[0]", "manual"]
|
||||||
|
- addsTo:
|
||||||
|
pack: codeql/java-all
|
||||||
|
extensible: barrierModel
|
||||||
|
data:
|
||||||
|
- ["java.util.regex", "Pattern", False, "quote", "(String)", "", "ReturnValue", "regex-use", "manual"]
|
||||||
- addsTo:
|
- addsTo:
|
||||||
pack: codeql/java-all
|
pack: codeql/java-all
|
||||||
extensible: summaryModel
|
extensible: summaryModel
|
||||||
|
|||||||
@@ -1,6 +1,42 @@
|
|||||||
extensions:
|
extensions:
|
||||||
|
- addsTo:
|
||||||
|
pack: codeql/java-all
|
||||||
|
extensible: barrierGuardModel
|
||||||
|
data:
|
||||||
|
- ["org.owasp.esapi", "Validator", true, "isValidCreditCard", "", "", "Argument[1]", "true", "trust-boundary-violation", "manual"]
|
||||||
|
- ["org.owasp.esapi", "Validator", true, "isValidDate", "", "", "Argument[1]", "true", "trust-boundary-violation", "manual"]
|
||||||
|
- ["org.owasp.esapi", "Validator", true, "isValidDirectoryPath", "", "", "Argument[1]", "true", "trust-boundary-violation", "manual"]
|
||||||
|
- ["org.owasp.esapi", "Validator", true, "isValidDouble", "", "", "Argument[1]", "true", "trust-boundary-violation", "manual"]
|
||||||
|
- ["org.owasp.esapi", "Validator", true, "isValidFileContent", "", "", "Argument[1]", "true", "trust-boundary-violation", "manual"]
|
||||||
|
- ["org.owasp.esapi", "Validator", true, "isValidFileName", "", "", "Argument[1]", "true", "trust-boundary-violation", "manual"]
|
||||||
|
- ["org.owasp.esapi", "Validator", true, "isValidInput", "", "", "Argument[1]", "true", "trust-boundary-violation", "manual"]
|
||||||
|
- ["org.owasp.esapi", "Validator", true, "isValidInteger", "", "", "Argument[1]", "true", "trust-boundary-violation", "manual"]
|
||||||
|
- ["org.owasp.esapi", "Validator", true, "isValidListItem", "", "", "Argument[1]", "true", "trust-boundary-violation", "manual"]
|
||||||
|
- ["org.owasp.esapi", "Validator", true, "isValidNumber", "", "", "Argument[1]", "true", "trust-boundary-violation", "manual"]
|
||||||
|
- ["org.owasp.esapi", "Validator", true, "isValidPrintable", "", "", "Argument[1]", "true", "trust-boundary-violation", "manual"]
|
||||||
|
- ["org.owasp.esapi", "Validator", true, "isValidRedirectLocation", "", "", "Argument[1]", "true", "trust-boundary-violation", "manual"]
|
||||||
|
- ["org.owasp.esapi", "Validator", true, "isValidSafeHTML", "", "", "Argument[1]", "true", "trust-boundary-violation", "manual"]
|
||||||
|
- ["org.owasp.esapi", "Validator", true, "isValidURI", "", "", "Argument[1]", "true", "trust-boundary-violation", "manual"]
|
||||||
|
- addsTo:
|
||||||
|
pack: codeql/java-all
|
||||||
|
extensible: barrierModel
|
||||||
|
data:
|
||||||
|
- ["org.owasp.esapi", "Validator", true, "getValidCreditCard", "", "", "ReturnValue", "trust-boundary-violation", "manual"]
|
||||||
|
- ["org.owasp.esapi", "Validator", true, "getValidDate", "", "", "ReturnValue", "trust-boundary-violation", "manual"]
|
||||||
|
- ["org.owasp.esapi", "Validator", true, "getValidDirectoryPath", "", "", "ReturnValue", "trust-boundary-violation", "manual"]
|
||||||
|
- ["org.owasp.esapi", "Validator", true, "getValidDouble", "", "", "ReturnValue", "trust-boundary-violation", "manual"]
|
||||||
|
- ["org.owasp.esapi", "Validator", true, "getValidFileContent", "", "", "ReturnValue", "trust-boundary-violation", "manual"]
|
||||||
|
- ["org.owasp.esapi", "Validator", true, "getValidFileName", "", "", "ReturnValue", "trust-boundary-violation", "manual"]
|
||||||
|
- ["org.owasp.esapi", "Validator", true, "getValidInput", "", "", "ReturnValue", "trust-boundary-violation", "manual"]
|
||||||
|
- ["org.owasp.esapi", "Validator", true, "getValidInteger", "", "", "ReturnValue", "trust-boundary-violation", "manual"]
|
||||||
|
- ["org.owasp.esapi", "Validator", true, "getValidListItem", "", "", "ReturnValue", "trust-boundary-violation", "manual"]
|
||||||
|
- ["org.owasp.esapi", "Validator", true, "getValidNumber", "", "", "ReturnValue", "trust-boundary-violation", "manual"]
|
||||||
|
- ["org.owasp.esapi", "Validator", true, "getValidPrintable", "", "", "ReturnValue", "trust-boundary-violation", "manual"]
|
||||||
|
- ["org.owasp.esapi", "Validator", true, "getValidRedirectLocation", "", "", "ReturnValue", "trust-boundary-violation", "manual"]
|
||||||
|
- ["org.owasp.esapi", "Validator", true, "getValidSafeHTML", "", "", "ReturnValue", "trust-boundary-violation", "manual"]
|
||||||
|
- ["org.owasp.esapi", "Validator", true, "getValidURI", "", "", "ReturnValue", "trust-boundary-violation", "manual"]
|
||||||
- addsTo:
|
- addsTo:
|
||||||
pack: codeql/java-all
|
pack: codeql/java-all
|
||||||
extensible: summaryModel
|
extensible: summaryModel
|
||||||
data:
|
data:
|
||||||
- ["org.owasp.esapi", "Encoder", true, "encodeForHTML", "(String)", "", "Argument[0]", "ReturnValue", "taint", "manual"]
|
- ["org.owasp.esapi", "Encoder", true, "encodeForHTML", "(String)", "", "Argument[0]", "ReturnValue", "taint", "manual"]
|
||||||
|
|||||||
@@ -91,6 +91,7 @@ module;
|
|||||||
|
|
||||||
import java
|
import java
|
||||||
private import semmle.code.java.dataflow.DataFlow::DataFlow
|
private import semmle.code.java.dataflow.DataFlow::DataFlow
|
||||||
|
private import semmle.code.java.controlflow.Guards
|
||||||
private import FlowSummary as FlowSummary
|
private import FlowSummary as FlowSummary
|
||||||
private import internal.DataFlowPrivate
|
private import internal.DataFlowPrivate
|
||||||
private import internal.FlowSummaryImpl
|
private import internal.FlowSummaryImpl
|
||||||
@@ -174,6 +175,24 @@ predicate sinkModel(
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** Holds if a barrier model exists for the given parameters. */
|
||||||
|
predicate barrierModel(
|
||||||
|
string package, string type, boolean subtypes, string name, string signature, string ext,
|
||||||
|
string output, string kind, string provenance, QlBuiltins::ExtensionId madId
|
||||||
|
) {
|
||||||
|
Extensions::barrierModel(package, type, subtypes, name, signature, ext, output, kind, provenance,
|
||||||
|
madId)
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Holds if a barrier guard model exists for the given parameters. */
|
||||||
|
predicate barrierGuardModel(
|
||||||
|
string package, string type, boolean subtypes, string name, string signature, string ext,
|
||||||
|
string input, string acceptingvalue, string kind, string provenance, QlBuiltins::ExtensionId madId
|
||||||
|
) {
|
||||||
|
Extensions::barrierGuardModel(package, type, subtypes, name, signature, ext, input,
|
||||||
|
acceptingvalue, kind, provenance, madId)
|
||||||
|
}
|
||||||
|
|
||||||
/** Holds if a summary model exists for the given parameters. */
|
/** Holds if a summary model exists for the given parameters. */
|
||||||
predicate summaryModel(
|
predicate summaryModel(
|
||||||
string package, string type, boolean subtypes, string name, string signature, string ext,
|
string package, string type, boolean subtypes, string name, string signature, string ext,
|
||||||
@@ -234,6 +253,7 @@ predicate interpretModelForTest(QlBuiltins::ExtensionId madId, string model) {
|
|||||||
"Summary: " + package + "; " + type + "; " + subtypes + "; " + name + "; " + signature + "; " +
|
"Summary: " + package + "; " + type + "; " + subtypes + "; " + name + "; " + signature + "; " +
|
||||||
ext + "; " + input + "; " + output + "; " + kind + "; " + provenance
|
ext + "; " + input + "; " + output + "; " + kind + "; " + provenance
|
||||||
)
|
)
|
||||||
|
//TODO: possibly barrier models?
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Holds if a neutral model exists for the given parameters. */
|
/** Holds if a neutral model exists for the given parameters. */
|
||||||
@@ -292,6 +312,7 @@ predicate modelCoverage(string package, int pkgs, string kind, string part, int
|
|||||||
summaryModel(subpkg, type, subtypes, name, signature, ext, input, output, kind, provenance,
|
summaryModel(subpkg, type, subtypes, name, signature, ext, input, output, kind, provenance,
|
||||||
_)
|
_)
|
||||||
)
|
)
|
||||||
|
// TODO: possibly barrier models?
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -303,7 +324,9 @@ module ModelValidation {
|
|||||||
summaryModel(_, _, _, _, _, _, path, _, _, _, _) or
|
summaryModel(_, _, _, _, _, _, path, _, _, _, _) or
|
||||||
summaryModel(_, _, _, _, _, _, _, path, _, _, _) or
|
summaryModel(_, _, _, _, _, _, _, path, _, _, _) or
|
||||||
sinkModel(_, _, _, _, _, _, path, _, _, _) or
|
sinkModel(_, _, _, _, _, _, path, _, _, _) or
|
||||||
sourceModel(_, _, _, _, _, _, path, _, _, _)
|
sourceModel(_, _, _, _, _, _, path, _, _, _) or
|
||||||
|
barrierModel(_, _, _, _, _, _, path, _, _, _) or
|
||||||
|
barrierGuardModel(_, _, _, _, _, _, path, _, _, _, _)
|
||||||
}
|
}
|
||||||
|
|
||||||
private module MkAccessPath = AccessPathSyntax::AccessPath<getRelevantAccessPath/1>;
|
private module MkAccessPath = AccessPathSyntax::AccessPath<getRelevantAccessPath/1>;
|
||||||
@@ -316,6 +339,8 @@ module ModelValidation {
|
|||||||
exists(string pred, AccessPath input, AccessPathToken part |
|
exists(string pred, AccessPath input, AccessPathToken part |
|
||||||
sinkModel(_, _, _, _, _, _, input, _, _, _) and pred = "sink"
|
sinkModel(_, _, _, _, _, _, input, _, _, _) and pred = "sink"
|
||||||
or
|
or
|
||||||
|
barrierGuardModel(_, _, _, _, _, _, input, _, _, _, _) and pred = "barrier guard"
|
||||||
|
or
|
||||||
summaryModel(_, _, _, _, _, _, input, _, _, _, _) and pred = "summary"
|
summaryModel(_, _, _, _, _, _, input, _, _, _, _) and pred = "summary"
|
||||||
|
|
|
|
||||||
(
|
(
|
||||||
@@ -338,6 +363,8 @@ module ModelValidation {
|
|||||||
exists(string pred, AccessPath output, AccessPathToken part |
|
exists(string pred, AccessPath output, AccessPathToken part |
|
||||||
sourceModel(_, _, _, _, _, _, output, _, _, _) and pred = "source"
|
sourceModel(_, _, _, _, _, _, output, _, _, _) and pred = "source"
|
||||||
or
|
or
|
||||||
|
barrierModel(_, _, _, _, _, _, output, _, _, _) and pred = "barrier"
|
||||||
|
or
|
||||||
summaryModel(_, _, _, _, _, _, _, output, _, _, _) and pred = "summary"
|
summaryModel(_, _, _, _, _, _, _, output, _, _, _) and pred = "summary"
|
||||||
|
|
|
|
||||||
(
|
(
|
||||||
@@ -355,7 +382,13 @@ module ModelValidation {
|
|||||||
private module KindValConfig implements SharedModelVal::KindValidationConfigSig {
|
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, _, _)
|
||||||
|
or
|
||||||
|
barrierModel(_, _, _, _, _, _, _, kind, _, _)
|
||||||
|
or
|
||||||
|
barrierGuardModel(_, _, _, _, _, _, _, _, kind, _, _)
|
||||||
|
}
|
||||||
|
|
||||||
predicate sourceKind(string kind) { sourceModel(_, _, _, _, _, _, _, kind, _, _) }
|
predicate sourceKind(string kind) { sourceModel(_, _, _, _, _, _, _, kind, _, _) }
|
||||||
|
|
||||||
@@ -373,6 +406,11 @@ module ModelValidation {
|
|||||||
or
|
or
|
||||||
sinkModel(package, type, _, name, signature, ext, _, _, provenance, _) and pred = "sink"
|
sinkModel(package, type, _, name, signature, ext, _, _, provenance, _) and pred = "sink"
|
||||||
or
|
or
|
||||||
|
barrierModel(package, type, _, name, signature, ext, _, _, provenance, _) and pred = "barrier"
|
||||||
|
or
|
||||||
|
barrierGuardModel(package, type, _, name, signature, ext, _, _, _, provenance, _) and
|
||||||
|
pred = "barrier guard"
|
||||||
|
or
|
||||||
summaryModel(package, type, _, name, signature, ext, _, _, _, provenance, _) and
|
summaryModel(package, type, _, name, signature, ext, _, _, _, provenance, _) and
|
||||||
pred = "summary"
|
pred = "summary"
|
||||||
or
|
or
|
||||||
@@ -398,6 +436,14 @@ module ModelValidation {
|
|||||||
invalidProvenance(provenance) and
|
invalidProvenance(provenance) and
|
||||||
result = "Unrecognized provenance description \"" + provenance + "\" in " + pred + " model."
|
result = "Unrecognized provenance description \"" + provenance + "\" in " + pred + " model."
|
||||||
)
|
)
|
||||||
|
or
|
||||||
|
exists(string acceptingvalue |
|
||||||
|
barrierGuardModel(_, _, _, _, _, _, _, acceptingvalue, _, _, _) and
|
||||||
|
invalidAcceptingValue(acceptingvalue) and
|
||||||
|
result =
|
||||||
|
"Unrecognized accepting value description \"" + acceptingvalue +
|
||||||
|
"\" in barrier guard model."
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Holds if some row in a MaD flow model appears to contain typos. */
|
/** Holds if some row in a MaD flow model appears to contain typos. */
|
||||||
@@ -418,6 +464,10 @@ private predicate elementSpec(
|
|||||||
or
|
or
|
||||||
sinkModel(package, type, subtypes, name, signature, ext, _, _, _, _)
|
sinkModel(package, type, subtypes, name, signature, ext, _, _, _, _)
|
||||||
or
|
or
|
||||||
|
barrierModel(package, type, subtypes, name, signature, ext, _, _, _, _)
|
||||||
|
or
|
||||||
|
barrierGuardModel(package, type, subtypes, name, signature, ext, _, _, _, _, _)
|
||||||
|
or
|
||||||
summaryModel(package, type, subtypes, name, signature, ext, _, _, _, _, _)
|
summaryModel(package, type, subtypes, name, signature, ext, _, _, _, _, _)
|
||||||
or
|
or
|
||||||
neutralModel(package, type, name, signature, _, _) and ext = "" and subtypes = true
|
neutralModel(package, type, name, signature, _, _) and ext = "" and subtypes = true
|
||||||
@@ -578,6 +628,53 @@ private module Cached {
|
|||||||
isSinkNode(n, kind, model) and n.asNode() = node
|
isSinkNode(n, kind, model) and n.asNode() = node
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private newtype TKindModelPair =
|
||||||
|
TMkPair(string kind, string model) { isBarrierGuardNode(_, _, kind, model) }
|
||||||
|
|
||||||
|
private GuardValue convertAcceptingValue(AcceptingValue av) {
|
||||||
|
av.isTrue() and result.asBooleanValue() = true
|
||||||
|
or
|
||||||
|
av.isFalse() and result.asBooleanValue() = false
|
||||||
|
or
|
||||||
|
av.isNoException() and result.getDualValue().isThrowsException()
|
||||||
|
or
|
||||||
|
av.isZero() and result.asIntValue() = 0
|
||||||
|
or
|
||||||
|
av.isNotZero() and result.getDualValue().asIntValue() = 0
|
||||||
|
or
|
||||||
|
av.isNull() and result.isNullValue()
|
||||||
|
or
|
||||||
|
av.isNotNull() and result.isNonNullValue()
|
||||||
|
}
|
||||||
|
|
||||||
|
private predicate barrierGuardChecks(Guard g, Expr e, GuardValue gv, TKindModelPair kmp) {
|
||||||
|
exists(
|
||||||
|
SourceSinkInterpretationInput::InterpretNode n, AcceptingValue acceptingvalue, string kind,
|
||||||
|
string model
|
||||||
|
|
|
||||||
|
isBarrierGuardNode(n, acceptingvalue, kind, model) and
|
||||||
|
n.asNode().asExpr() = e and
|
||||||
|
kmp = TMkPair(kind, model) and
|
||||||
|
gv = convertAcceptingValue(acceptingvalue)
|
||||||
|
|
|
||||||
|
g.(Call).getAnArgument() = e or g.(MethodCall).getQualifier() = e
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Holds if `node` is specified as a barrier with the given kind in a MaD flow
|
||||||
|
* model.
|
||||||
|
*/
|
||||||
|
cached
|
||||||
|
predicate barrierNode(Node node, string kind, string model) {
|
||||||
|
exists(SourceSinkInterpretationInput::InterpretNode n |
|
||||||
|
isBarrierNode(n, kind, model) and n.asNode() = node
|
||||||
|
)
|
||||||
|
or
|
||||||
|
ParameterizedBarrierGuard<TKindModelPair, barrierGuardChecks/4>::getABarrierNode(TMkPair(kind,
|
||||||
|
model)) = node
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
import Cached
|
import Cached
|
||||||
@@ -594,6 +691,12 @@ predicate sourceNode(Node node, string kind) { sourceNode(node, kind, _) }
|
|||||||
*/
|
*/
|
||||||
predicate sinkNode(Node node, string kind) { sinkNode(node, kind, _) }
|
predicate sinkNode(Node node, string kind) { sinkNode(node, kind, _) }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Holds if `node` is specified as a barrier with the given kind in a MaD flow
|
||||||
|
* model.
|
||||||
|
*/
|
||||||
|
predicate barrierNode(Node node, string kind) { barrierNode(node, kind, _) }
|
||||||
|
|
||||||
// adapter class for converting Mad summaries to `SummarizedCallable`s
|
// adapter class for converting Mad summaries to `SummarizedCallable`s
|
||||||
private class SummarizedCallableAdapter extends SummarizedCallable {
|
private class SummarizedCallableAdapter extends SummarizedCallable {
|
||||||
SummarizedCallableAdapter() { summaryElement(this, _, _, _, _, _, _) }
|
SummarizedCallableAdapter() { summaryElement(this, _, _, _, _, _, _) }
|
||||||
|
|||||||
@@ -420,3 +420,31 @@ module BarrierGuard<guardChecksSig/3 guardChecks> {
|
|||||||
/** Gets a node that is safely guarded by the given guard check. */
|
/** Gets a node that is safely guarded by the given guard check. */
|
||||||
Node getABarrierNode() { result = BarrierGuardValue<guardChecks0/3>::getABarrierNode() }
|
Node getABarrierNode() { result = BarrierGuardValue<guardChecks0/3>::getABarrierNode() }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bindingset[this]
|
||||||
|
private signature class ParamSig;
|
||||||
|
|
||||||
|
private module WithParam<ParamSig P> {
|
||||||
|
/**
|
||||||
|
* Holds if the guard `g` validates the expression `e` upon evaluating to `gv`.
|
||||||
|
*
|
||||||
|
* The expression `e` is expected to be a syntactic part of the guard `g`.
|
||||||
|
* For example, the guard `g` might be a call `isSafe(x)` and the expression `e`
|
||||||
|
* the argument `x`.
|
||||||
|
*/
|
||||||
|
signature predicate guardChecksSig(Guard g, Expr e, GuardValue gv, P param);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Provides a set of barrier nodes for a guard that validates an expression.
|
||||||
|
*
|
||||||
|
* This is expected to be used in `isBarrier`/`isSanitizer` definitions
|
||||||
|
* in data flow and taint tracking.
|
||||||
|
*/
|
||||||
|
module ParameterizedBarrierGuard<ParamSig P, WithParam<P>::guardChecksSig/4 guardChecks> {
|
||||||
|
/** Gets a node that is safely guarded by the given guard check. */
|
||||||
|
Node getABarrierNode(P param) {
|
||||||
|
SsaFlow::asNode(result) =
|
||||||
|
SsaImpl::DataFlowIntegration::ParameterizedBarrierGuard<P, guardChecks/4>::getABarrierNode(param)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -20,6 +20,22 @@ extensible predicate sinkModel(
|
|||||||
string input, string kind, string provenance, QlBuiltins::ExtensionId madId
|
string input, string kind, string provenance, QlBuiltins::ExtensionId madId
|
||||||
);
|
);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Holds if a barrier model exists for the given parameters.
|
||||||
|
*/
|
||||||
|
extensible predicate barrierModel(
|
||||||
|
string package, string type, boolean subtypes, string name, string signature, string ext,
|
||||||
|
string output, string kind, string provenance, QlBuiltins::ExtensionId madId
|
||||||
|
);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Holds if a barrier guard model exists for the given parameters.
|
||||||
|
*/
|
||||||
|
extensible predicate barrierGuardModel(
|
||||||
|
string package, string type, boolean subtypes, string name, string signature, string ext,
|
||||||
|
string input, string acceptingvalue, string kind, string provenance, QlBuiltins::ExtensionId madId
|
||||||
|
);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Holds if a summary model exists for the given parameters.
|
* Holds if a summary model exists for the given parameters.
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -158,7 +158,9 @@ private predicate relatedArgSpec(Callable c, string spec) {
|
|||||||
summaryModel(namespace, type, subtypes, name, signature, ext, spec, _, _, _, _) or
|
summaryModel(namespace, type, subtypes, name, signature, ext, spec, _, _, _, _) or
|
||||||
summaryModel(namespace, type, subtypes, name, signature, ext, _, spec, _, _, _) or
|
summaryModel(namespace, type, subtypes, name, signature, ext, _, spec, _, _, _) or
|
||||||
sourceModel(namespace, type, subtypes, name, signature, ext, spec, _, _, _) or
|
sourceModel(namespace, type, subtypes, name, signature, ext, spec, _, _, _) or
|
||||||
sinkModel(namespace, type, subtypes, name, signature, ext, spec, _, _, _)
|
sinkModel(namespace, type, subtypes, name, signature, ext, spec, _, _, _) or
|
||||||
|
barrierModel(namespace, type, subtypes, name, signature, ext, spec, _, _, _) or
|
||||||
|
barrierGuardModel(namespace, type, subtypes, name, signature, ext, spec, _, _, _, _)
|
||||||
|
|
|
|
||||||
c = interpretElement(namespace, type, subtypes, name, signature, ext, _)
|
c = interpretElement(namespace, type, subtypes, name, signature, ext, _)
|
||||||
)
|
)
|
||||||
@@ -259,6 +261,45 @@ module SourceSinkInterpretationInput implements
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
predicate barrierElement(
|
||||||
|
Element e, string output, string kind, Public::Provenance provenance, string model
|
||||||
|
) {
|
||||||
|
exists(
|
||||||
|
string namespace, string type, boolean subtypes, string name, string signature, string ext,
|
||||||
|
SourceOrSinkElement baseBarrier, string originalOutput, QlBuiltins::ExtensionId madId
|
||||||
|
|
|
||||||
|
barrierModel(namespace, type, subtypes, name, signature, ext, originalOutput, kind,
|
||||||
|
provenance, madId) and
|
||||||
|
model = "MaD:" + madId.toString() and
|
||||||
|
baseBarrier = interpretElement(namespace, type, subtypes, name, signature, ext, _) and
|
||||||
|
(
|
||||||
|
e = baseBarrier and output = originalOutput
|
||||||
|
or
|
||||||
|
correspondingKotlinParameterDefaultsArgSpec(baseBarrier, e, originalOutput, output)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
predicate barrierGuardElement(
|
||||||
|
Element e, string input, Public::AcceptingValue acceptingvalue, string kind,
|
||||||
|
Public::Provenance provenance, string model
|
||||||
|
) {
|
||||||
|
exists(
|
||||||
|
string namespace, string type, boolean subtypes, string name, string signature, string ext,
|
||||||
|
SourceOrSinkElement baseBarrier, string originalInput, QlBuiltins::ExtensionId madId
|
||||||
|
|
|
||||||
|
barrierGuardModel(namespace, type, subtypes, name, signature, ext, originalInput,
|
||||||
|
acceptingvalue, kind, provenance, madId) and
|
||||||
|
model = "MaD:" + madId.toString() and
|
||||||
|
baseBarrier = interpretElement(namespace, type, subtypes, name, signature, ext, _) and
|
||||||
|
(
|
||||||
|
e = baseBarrier and input = originalInput
|
||||||
|
or
|
||||||
|
correspondingKotlinParameterDefaultsArgSpec(baseBarrier, e, originalInput, input)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
class SourceOrSinkElement = Element;
|
class SourceOrSinkElement = Element;
|
||||||
|
|
||||||
private newtype TInterpretNode =
|
private newtype TInterpretNode =
|
||||||
|
|||||||
@@ -588,6 +588,36 @@ private module Cached {
|
|||||||
|
|
||||||
predicate getABarrierNode = getABarrierNodeImpl/0;
|
predicate getABarrierNode = getABarrierNodeImpl/0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bindingset[this]
|
||||||
|
private signature class ParamSig;
|
||||||
|
|
||||||
|
private module WithParam<ParamSig P> {
|
||||||
|
signature predicate guardChecksSig(Guards::Guard g, Expr e, Guards::GuardValue gv, P param);
|
||||||
|
}
|
||||||
|
|
||||||
|
cached // nothing is actually cached
|
||||||
|
module ParameterizedBarrierGuard<ParamSig P, WithParam<P>::guardChecksSig/4 guardChecks> {
|
||||||
|
private predicate guardChecksAdjTypes(
|
||||||
|
Guards::Guards_v3::Guard g, Expr e, Guards::GuardValue gv, P param
|
||||||
|
) {
|
||||||
|
guardChecks(g, e, gv, param)
|
||||||
|
}
|
||||||
|
|
||||||
|
private predicate guardChecksWithWrappers(
|
||||||
|
DataFlowIntegrationInput::Guard g, Definition def, Guards::GuardValue val, P param
|
||||||
|
) {
|
||||||
|
Guards::Guards_v3::ParameterizedValidationWrapper<P, guardChecksAdjTypes/4>::guardChecksDef(g,
|
||||||
|
def, val, param)
|
||||||
|
}
|
||||||
|
|
||||||
|
private Node getABarrierNodeImpl(P param) {
|
||||||
|
result =
|
||||||
|
DataFlowIntegrationImpl::BarrierGuardDefWithState<P, guardChecksWithWrappers/4>::getABarrierNode(param)
|
||||||
|
}
|
||||||
|
|
||||||
|
predicate getABarrierNode = getABarrierNodeImpl/1;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
cached
|
cached
|
||||||
|
|||||||
@@ -14,14 +14,3 @@ class HudsonWebMethod extends Method {
|
|||||||
this.getDeclaringType().getASourceSupertype*().hasQualifiedName("hudson.model", "Descriptor")
|
this.getDeclaringType().getASourceSupertype*().hasQualifiedName("hudson.model", "Descriptor")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private class HudsonUtilXssSanitizer extends XssSanitizer {
|
|
||||||
HudsonUtilXssSanitizer() {
|
|
||||||
this.asExpr()
|
|
||||||
.(MethodCall)
|
|
||||||
.getMethod()
|
|
||||||
// Not including xmlEscape because it only accounts for >, <, and &.
|
|
||||||
// It does not account for ", or ', which makes it an incomplete XSS sanitizer.
|
|
||||||
.hasQualifiedName("hudson", "Util", "escape")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -1,42 +0,0 @@
|
|||||||
/** Classes and predicates for reasoning about the `owasp.easpi` package. */
|
|
||||||
overlay[local?]
|
|
||||||
module;
|
|
||||||
|
|
||||||
import java
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The `org.owasp.esapi.Validator` interface.
|
|
||||||
*/
|
|
||||||
class EsapiValidator extends RefType {
|
|
||||||
EsapiValidator() { this.hasQualifiedName("org.owasp.esapi", "Validator") }
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The methods of `org.owasp.esapi.Validator` which validate data.
|
|
||||||
*/
|
|
||||||
class EsapiIsValidMethod extends Method {
|
|
||||||
EsapiIsValidMethod() {
|
|
||||||
this.getDeclaringType() instanceof EsapiValidator and
|
|
||||||
this.hasName([
|
|
||||||
"isValidCreditCard", "isValidDate", "isValidDirectoryPath", "isValidDouble",
|
|
||||||
"isValidFileContent", "isValidFileName", "isValidInput", "isValidInteger",
|
|
||||||
"isValidListItem", "isValidNumber", "isValidPrintable", "isValidRedirectLocation",
|
|
||||||
"isValidSafeHTML", "isValidURI"
|
|
||||||
])
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The methods of `org.owasp.esapi.Validator` which return validated data.
|
|
||||||
*/
|
|
||||||
class EsapiGetValidMethod extends Method {
|
|
||||||
EsapiGetValidMethod() {
|
|
||||||
this.getDeclaringType() instanceof EsapiValidator and
|
|
||||||
this.hasName([
|
|
||||||
"getValidCreditCard", "getValidDate", "getValidDirectoryPath", "getValidDouble",
|
|
||||||
"getValidFileContent", "getValidFileName", "getValidInput", "getValidInteger",
|
|
||||||
"getValidListItem", "getValidNumber", "getValidPrintable", "getValidRedirectLocation",
|
|
||||||
"getValidSafeHTML", "getValidURI"
|
|
||||||
])
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -4,6 +4,7 @@ module;
|
|||||||
|
|
||||||
import java
|
import java
|
||||||
private import semmle.code.java.controlflow.Guards
|
private import semmle.code.java.controlflow.Guards
|
||||||
|
private import semmle.code.java.dataflow.ExternalFlow
|
||||||
private import semmle.code.java.dataflow.FlowSources
|
private import semmle.code.java.dataflow.FlowSources
|
||||||
private import semmle.code.java.dataflow.SSA
|
private import semmle.code.java.dataflow.SSA
|
||||||
private import semmle.code.java.frameworks.kotlin.IO
|
private import semmle.code.java.frameworks.kotlin.IO
|
||||||
@@ -288,19 +289,8 @@ private Method getSourceMethod(Method m) {
|
|||||||
result = m
|
result = m
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
private class DefaultPathInjectionSanitizer extends PathInjectionSanitizer {
|
||||||
* A sanitizer that protects against path injection vulnerabilities
|
DefaultPathInjectionSanitizer() { barrierNode(this, "path-injection") }
|
||||||
* by extracting the final component of the user provided path.
|
|
||||||
*
|
|
||||||
* TODO: convert this class to models-as-data if sanitizer support is added
|
|
||||||
*/
|
|
||||||
private class FileGetNameSanitizer extends PathInjectionSanitizer {
|
|
||||||
FileGetNameSanitizer() {
|
|
||||||
exists(MethodCall mc |
|
|
||||||
mc.getMethod().hasQualifiedName("java.io", "File", "getName") and
|
|
||||||
this.asExpr() = mc
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Holds if `g` is a guard that checks for `..` components. */
|
/** Holds if `g` is a guard that checks for `..` components. */
|
||||||
|
|||||||
@@ -118,25 +118,8 @@ private class ContainsUrlSanitizer extends RequestForgerySanitizer {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
private class DefaultRequestForgerySanitizer extends RequestForgerySanitizer {
|
||||||
* A check that the URL is relative, and therefore safe for URL redirects.
|
DefaultRequestForgerySanitizer() { barrierNode(this, "request-forgery") }
|
||||||
*/
|
|
||||||
private predicate isRelativeUrlSanitizer(Guard guard, Expr e, boolean branch) {
|
|
||||||
guard =
|
|
||||||
any(MethodCall call |
|
|
||||||
call.getMethod().hasQualifiedName("java.net", "URI", "isAbsolute") and
|
|
||||||
e = call.getQualifier() and
|
|
||||||
branch = false
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A check that the URL is relative, and therefore safe for URL redirects.
|
|
||||||
*/
|
|
||||||
private class RelativeUrlSanitizer extends RequestForgerySanitizer {
|
|
||||||
RelativeUrlSanitizer() {
|
|
||||||
this = DataFlow::BarrierGuard<isRelativeUrlSanitizer/3>::getABarrierNode()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -5,7 +5,6 @@ private import semmle.code.java.dataflow.DataFlow
|
|||||||
private import semmle.code.java.controlflow.Guards
|
private import semmle.code.java.controlflow.Guards
|
||||||
private import semmle.code.java.dataflow.ExternalFlow
|
private import semmle.code.java.dataflow.ExternalFlow
|
||||||
private import semmle.code.java.dataflow.FlowSources
|
private import semmle.code.java.dataflow.FlowSources
|
||||||
private import semmle.code.java.frameworks.owasp.Esapi
|
|
||||||
private import semmle.code.java.security.Sanitizers
|
private import semmle.code.java.security.Sanitizers
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -28,25 +27,8 @@ class TrustBoundaryViolationSink extends DataFlow::Node {
|
|||||||
*/
|
*/
|
||||||
abstract class TrustBoundaryValidationSanitizer extends DataFlow::Node { }
|
abstract class TrustBoundaryValidationSanitizer extends DataFlow::Node { }
|
||||||
|
|
||||||
/**
|
private class DefaultTrustBoundaryValidationSanitizer extends TrustBoundaryValidationSanitizer {
|
||||||
* A node validated by an OWASP ESAPI validation method.
|
DefaultTrustBoundaryValidationSanitizer() { barrierNode(this, "trust-boundary-violation") }
|
||||||
*/
|
|
||||||
private class EsapiValidatedInputSanitizer extends TrustBoundaryValidationSanitizer {
|
|
||||||
EsapiValidatedInputSanitizer() {
|
|
||||||
this = DataFlow::BarrierGuard<esapiIsValidData/3>::getABarrierNode() or
|
|
||||||
this.asExpr().(MethodCall).getMethod() instanceof EsapiGetValidMethod
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Holds if `g` is a guard that checks that `e` is valid data according to an OWASP ESAPI validation method.
|
|
||||||
*/
|
|
||||||
private predicate esapiIsValidData(Guard g, Expr e, boolean branch) {
|
|
||||||
branch = true and
|
|
||||||
exists(MethodCall ma | ma.getMethod() instanceof EsapiIsValidMethod |
|
|
||||||
g = ma and
|
|
||||||
e = ma.getArgument(1)
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -54,12 +54,24 @@ private class DefaultXssSink extends XssSink {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/** A default sanitizer that considers numeric and boolean typed data safe for writing to output. */
|
|
||||||
private class DefaultXssSanitizer extends XssSanitizer {
|
private class DefaultXssSanitizer extends XssSanitizer {
|
||||||
DefaultXssSanitizer() {
|
DefaultXssSanitizer() { barrierNode(this, ["html-injection", "js-injection"]) }
|
||||||
|
}
|
||||||
|
|
||||||
|
/** A sanitizer that considers numeric and boolean typed data safe for writing to output. */
|
||||||
|
private class PrimitiveSanitizer extends XssSanitizer {
|
||||||
|
PrimitiveSanitizer() {
|
||||||
this.getType() instanceof NumericType or
|
this.getType() instanceof NumericType or
|
||||||
this.getType() instanceof BooleanType or
|
this.getType() instanceof BooleanType
|
||||||
// Match `org.springframework.web.util.HtmlUtils.htmlEscape` and possibly other methods like it.
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A call to `org.springframework.web.util.HtmlUtils.htmlEscape`, or possibly
|
||||||
|
* other methods like it, considered as a sanitizer for XSS.
|
||||||
|
*/
|
||||||
|
private class HtmlEscapeXssSanitizer extends XssSanitizer {
|
||||||
|
HtmlEscapeXssSanitizer() {
|
||||||
this.asExpr().(MethodCall).getMethod().getName().regexpMatch("(?i)html_?escape.*")
|
this.asExpr().(MethodCall).getMethod().getName().regexpMatch("(?i)html_?escape.*")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -21,17 +21,8 @@ private class DefaultRegexInjectionSink extends RegexInjectionSink {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
private class DefaultRegexInjectionSanitizer extends RegexInjectionSanitizer {
|
||||||
* A call to the `Pattern.quote` method, which gives metacharacters or escape sequences
|
DefaultRegexInjectionSanitizer() { barrierNode(this, "regex-use") }
|
||||||
* no special meaning.
|
|
||||||
*/
|
|
||||||
private class PatternQuoteCall extends RegexInjectionSanitizer {
|
|
||||||
PatternQuoteCall() {
|
|
||||||
exists(MethodCall ma, Method m | m = ma.getMethod() |
|
|
||||||
ma.getArgument(0) = this.asExpr() and
|
|
||||||
m instanceof PatternQuoteMethod
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -215,6 +215,35 @@ module Make<
|
|||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class AcceptingValue extends string {
|
||||||
|
AcceptingValue() {
|
||||||
|
this =
|
||||||
|
[
|
||||||
|
"true",
|
||||||
|
"false",
|
||||||
|
"no-exception",
|
||||||
|
"zero",
|
||||||
|
"not-zero",
|
||||||
|
"null",
|
||||||
|
"not-null",
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
predicate isTrue() { this = "true" }
|
||||||
|
|
||||||
|
predicate isFalse() { this = "false" }
|
||||||
|
|
||||||
|
predicate isNoException() { this = "no-exception" }
|
||||||
|
|
||||||
|
predicate isZero() { this = "zero" }
|
||||||
|
|
||||||
|
predicate isNotZero() { this = "not-zero" }
|
||||||
|
|
||||||
|
predicate isNull() { this = "null" }
|
||||||
|
|
||||||
|
predicate isNotNull() { this = "not-null" }
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A class used to represent provenance values for MaD models.
|
* A class used to represent provenance values for MaD models.
|
||||||
*
|
*
|
||||||
@@ -2015,6 +2044,12 @@ module Make<
|
|||||||
not exists(interpretComponent(c))
|
not exists(interpretComponent(c))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** Holds if `acceptingvalue` is not a valid barrier guard accepting-value. */
|
||||||
|
bindingset[acceptingvalue]
|
||||||
|
predicate invalidAcceptingValue(string acceptingvalue) {
|
||||||
|
not acceptingvalue instanceof AcceptingValue
|
||||||
|
}
|
||||||
|
|
||||||
/** Holds if `provenance` is not a valid provenance value. */
|
/** Holds if `provenance` is not a valid provenance value. */
|
||||||
bindingset[provenance]
|
bindingset[provenance]
|
||||||
predicate invalidProvenance(string provenance) { not provenance instanceof Provenance }
|
predicate invalidProvenance(string provenance) { not provenance instanceof Provenance }
|
||||||
@@ -2052,6 +2087,23 @@ module Make<
|
|||||||
Element n, string input, string kind, Provenance provenance, string model
|
Element n, string input, string kind, Provenance provenance, string model
|
||||||
);
|
);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Holds if an external barrier specification exists for `n` with output specification
|
||||||
|
* `output` and kind `kind`.
|
||||||
|
*/
|
||||||
|
predicate barrierElement(
|
||||||
|
Element n, string output, string kind, Provenance provenance, string model
|
||||||
|
);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Holds if an external barrier guard specification exists for `n` with input
|
||||||
|
* specification `input`, accepting value `acceptingvalue`, and kind `kind`.
|
||||||
|
*/
|
||||||
|
predicate barrierGuardElement(
|
||||||
|
Element n, string input, AcceptingValue acceptingvalue, string kind,
|
||||||
|
Provenance provenance, string model
|
||||||
|
);
|
||||||
|
|
||||||
class SourceOrSinkElement extends Element;
|
class SourceOrSinkElement extends Element;
|
||||||
|
|
||||||
/** An entity used to interpret a source/sink specification. */
|
/** An entity used to interpret a source/sink specification. */
|
||||||
@@ -2105,7 +2157,9 @@ module Make<
|
|||||||
|
|
||||||
private predicate sourceSinkSpec(string spec) {
|
private predicate sourceSinkSpec(string spec) {
|
||||||
sourceElement(_, spec, _, _, _) or
|
sourceElement(_, spec, _, _, _) or
|
||||||
sinkElement(_, spec, _, _, _)
|
sinkElement(_, spec, _, _, _) or
|
||||||
|
barrierElement(_, spec, _, _, _) or
|
||||||
|
barrierGuardElement(_, spec, _, _, _, _)
|
||||||
}
|
}
|
||||||
|
|
||||||
private module AccessPath = AccessPathSyntax::AccessPath<sourceSinkSpec/1>;
|
private module AccessPath = AccessPathSyntax::AccessPath<sourceSinkSpec/1>;
|
||||||
@@ -2160,11 +2214,34 @@ module Make<
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private predicate barrierElementRef(
|
||||||
|
InterpretNode ref, SourceSinkAccessPath output, string kind, string model
|
||||||
|
) {
|
||||||
|
exists(SourceOrSinkElement e |
|
||||||
|
barrierElement(e, output, kind, _, model) and
|
||||||
|
if outputNeedsReferenceExt(output.getToken(0))
|
||||||
|
then e = ref.getCallTarget()
|
||||||
|
else e = ref.asElement()
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
private predicate barrierGuardElementRef(
|
||||||
|
InterpretNode ref, SourceSinkAccessPath input, AcceptingValue acceptingvalue, string kind,
|
||||||
|
string model
|
||||||
|
) {
|
||||||
|
exists(SourceOrSinkElement e |
|
||||||
|
barrierGuardElement(e, input, acceptingvalue, kind, _, model) and
|
||||||
|
if inputNeedsReferenceExt(input.getToken(0))
|
||||||
|
then e = ref.getCallTarget()
|
||||||
|
else e = ref.asElement()
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
/** Holds if the first `n` tokens of `output` resolve to the given interpretation. */
|
/** Holds if the first `n` tokens of `output` resolve to the given interpretation. */
|
||||||
private predicate interpretOutput(
|
private predicate interpretOutput(
|
||||||
SourceSinkAccessPath output, int n, InterpretNode ref, InterpretNode node
|
SourceSinkAccessPath output, int n, InterpretNode ref, InterpretNode node
|
||||||
) {
|
) {
|
||||||
sourceElementRef(ref, output, _, _) and
|
(sourceElementRef(ref, output, _, _) or barrierElementRef(ref, output, _, _)) and
|
||||||
n = 0 and
|
n = 0 and
|
||||||
(
|
(
|
||||||
if output = ""
|
if output = ""
|
||||||
@@ -2220,7 +2297,7 @@ module Make<
|
|||||||
private predicate interpretInput(
|
private predicate interpretInput(
|
||||||
SourceSinkAccessPath input, int n, InterpretNode ref, InterpretNode node
|
SourceSinkAccessPath input, int n, InterpretNode ref, InterpretNode node
|
||||||
) {
|
) {
|
||||||
sinkElementRef(ref, input, _, _) and
|
(sinkElementRef(ref, input, _, _) or barrierGuardElementRef(ref, input, _, _, _)) and
|
||||||
n = 0 and
|
n = 0 and
|
||||||
(
|
(
|
||||||
if input = ""
|
if input = ""
|
||||||
@@ -2280,6 +2357,30 @@ module Make<
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Holds if `node` is specified as a barrier with the given kind in a MaD flow
|
||||||
|
* model.
|
||||||
|
*/
|
||||||
|
predicate isBarrierNode(InterpretNode node, string kind, string model) {
|
||||||
|
exists(InterpretNode ref, SourceSinkAccessPath output |
|
||||||
|
barrierElementRef(ref, output, kind, model) and
|
||||||
|
interpretOutput(output, output.getNumToken(), ref, node)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Holds if `node` is specified as a barrier guard argument with the
|
||||||
|
* given kind in a MaD flow model.
|
||||||
|
*/
|
||||||
|
predicate isBarrierGuardNode(
|
||||||
|
InterpretNode node, AcceptingValue acceptingvalue, string kind, string model
|
||||||
|
) {
|
||||||
|
exists(InterpretNode ref, SourceSinkAccessPath input |
|
||||||
|
barrierGuardElementRef(ref, input, acceptingvalue, kind, model) and
|
||||||
|
interpretInput(input, input.getNumToken(), ref, node)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
final private class SourceOrSinkElementFinal = SourceOrSinkElement;
|
final private class SourceOrSinkElementFinal = SourceOrSinkElement;
|
||||||
|
|
||||||
signature predicate sourceOrSinkElementSig(
|
signature predicate sourceOrSinkElementSig(
|
||||||
|
|||||||
@@ -173,7 +173,7 @@ module KindValidation<KindValidationConfigSig Config> {
|
|||||||
or
|
or
|
||||||
exists(string kind, string msg | Config::sinkKind(kind) |
|
exists(string kind, string msg | Config::sinkKind(kind) |
|
||||||
not kind instanceof ValidSinkKind and
|
not kind instanceof ValidSinkKind and
|
||||||
msg = "Invalid kind \"" + kind + "\" in sink model." and
|
msg = "Invalid kind \"" + kind + "\" in sink or barrier model." and
|
||||||
// The part of this message that refers to outdated sink kinds can be deleted after June 1st, 2024.
|
// The part of this message that refers to outdated sink kinds can be deleted after June 1st, 2024.
|
||||||
if kind instanceof OutdatedSinkKind
|
if kind instanceof OutdatedSinkKind
|
||||||
then result = msg + " " + kind.(OutdatedSinkKind).outdatedMessage()
|
then result = msg + " " + kind.(OutdatedSinkKind).outdatedMessage()
|
||||||
|
|||||||
@@ -159,6 +159,19 @@ module SourceSinkInterpretationInput implements
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
predicate barrierElement(
|
||||||
|
Element n, string output, string kind, Public::Provenance provenance, string model
|
||||||
|
) {
|
||||||
|
none()
|
||||||
|
}
|
||||||
|
|
||||||
|
predicate barrierGuardElement(
|
||||||
|
Element n, string input, Public::AcceptingValue acceptingvalue, string kind,
|
||||||
|
Public::Provenance provenance, string model
|
||||||
|
) {
|
||||||
|
none()
|
||||||
|
}
|
||||||
|
|
||||||
private newtype TInterpretNode =
|
private newtype TInterpretNode =
|
||||||
TElement_(Element n) or
|
TElement_(Element n) or
|
||||||
TNode_(Node n) or
|
TNode_(Node n) or
|
||||||
|
|||||||
Reference in New Issue
Block a user