Files
codeql/java/ql/lib/semmle/code/java/frameworks/SnakeYaml.qll
Chris Smowton 90505949c7 Generally define lower-numbered data-flow configs in terms of higher-numbered ones
Since usually we have DataFlow3::Configurations that stand alone, DataFlow2::Configurations that depend on them, and finally DataFlow::Configurations that produce a top-level query result (for example), qll files where the reverse pattern holds will usually not be concurrently importable due to dataflow configuration recursion prevention.
2022-04-15 09:25:40 +01:00

88 lines
2.8 KiB
Plaintext

/**
* Provides classes and predicates for working with the SnakeYaml serialization framework.
*/
import java
import semmle.code.java.dataflow.DataFlow
import semmle.code.java.dataflow.DataFlow2
import semmle.code.java.dataflow.DataFlow3
/**
* The class `org.yaml.snakeyaml.constructor.SafeConstructor`.
*/
class SnakeYamlSafeConstructor extends RefType {
SnakeYamlSafeConstructor() {
this.hasQualifiedName("org.yaml.snakeyaml.constructor", "SafeConstructor")
}
}
/**
* An instance of `SafeConstructor`.
*/
class SafeSnakeYamlConstruction extends ClassInstanceExpr {
SafeSnakeYamlConstruction() { this.getConstructedType() instanceof SnakeYamlSafeConstructor }
}
/**
* The class `org.yaml.snakeyaml.Yaml`.
*/
class Yaml extends RefType {
Yaml() { this.getAnAncestor().hasQualifiedName("org.yaml.snakeyaml", "Yaml") }
}
private class SafeYamlConstructionFlowConfig extends DataFlow3::Configuration {
SafeYamlConstructionFlowConfig() { this = "SnakeYaml::SafeYamlConstructionFlowConfig" }
override predicate isSource(DataFlow::Node src) {
src.asExpr() instanceof SafeSnakeYamlConstruction
}
override predicate isSink(DataFlow::Node sink) { sink = this.yamlClassInstanceExprArgument(_) }
private DataFlow::ExprNode yamlClassInstanceExprArgument(ClassInstanceExpr cie) {
cie.getConstructedType() instanceof Yaml and
result.getExpr() = cie.getArgument(0)
}
ClassInstanceExpr getSafeYaml() { this.hasFlowTo(this.yamlClassInstanceExprArgument(result)) }
}
/**
* An instance of `Yaml` that does not allow arbitrary constructor to be called.
*/
private class SafeYaml extends ClassInstanceExpr {
SafeYaml() { exists(SafeYamlConstructionFlowConfig conf | conf.getSafeYaml() = this) }
}
/** A call to a parse method of `Yaml`. */
private class SnakeYamlParse extends MethodAccess {
SnakeYamlParse() {
exists(Method m |
m.getDeclaringType() instanceof Yaml and
m.hasName(["compose", "composeAll", "load", "loadAll", "loadAs", "parse"]) and
m = this.getMethod()
)
}
}
private class SafeYamlFlowConfig extends DataFlow2::Configuration {
SafeYamlFlowConfig() { this = "SnakeYaml::SafeYamlFlowConfig" }
override predicate isSource(DataFlow::Node src) { src.asExpr() instanceof SafeYaml }
override predicate isSink(DataFlow::Node sink) { sink = this.yamlParseQualifier(_) }
private DataFlow::ExprNode yamlParseQualifier(SnakeYamlParse syp) {
result.getExpr() = syp.getQualifier()
}
SnakeYamlParse getASafeSnakeYamlParse() { this.hasFlowTo(this.yamlParseQualifier(result)) }
}
/**
* A call to a parse method of `Yaml` that allows arbitrary constructor to be called.
*/
class UnsafeSnakeYamlParse extends SnakeYamlParse {
UnsafeSnakeYamlParse() { not exists(SafeYamlFlowConfig sy | sy.getASafeSnakeYamlParse() = this) }
}