JS: Update model of js-yaml

This commit is contained in:
Asger F
2023-04-20 12:47:13 +02:00
parent b6a7661c7e
commit 1acc0d2ddf
2 changed files with 26 additions and 14 deletions

View File

@@ -491,6 +491,7 @@ module API {
* In other words, the value of a use of `that` may flow into the right-hand side of a
* definition of this node.
*/
pragma[inline]
predicate refersTo(Node that) { this.asSink() = that.getAValueReachableFromSource() }
/**

View File

@@ -25,25 +25,36 @@ module UnsafeDeserialization {
/** A source of remote user input, considered as a flow source for unsafe deserialization. */
class RemoteFlowSourceAsSource extends Source instanceof RemoteFlowSource { }
private API::Node unsafeYamlSchema() {
result = API::moduleImport("js-yaml").getMember("DEFAULT_FULL_SCHEMA") // from older versions
or
result = API::moduleImport("js-yaml-js-types").getMember(["all", "function"])
or
result = unsafeYamlSchema().getMember("extend").getReceiver()
or
exists(API::CallNode call |
call.getAParameter().refersTo(unsafeYamlSchema()) and
call.getCalleeName() = "extend" and
result = call.getReturn()
)
}
/**
* An expression passed to one of the unsafe load functions of the `js-yaml` package.
*
* `js-yaml` since v4 defaults to being safe, but is unsafe when invoked with a schema
* that permits unsafe values.
*/
class JsYamlUnsafeLoad extends Sink {
JsYamlUnsafeLoad() {
exists(DataFlow::ModuleImportNode mi | mi.getPath() = "js-yaml" |
// the first argument to a call to `load` or `loadAll`
exists(string n | n = "load" or n = "loadAll" | this = mi.getAMemberCall(n).getArgument(0))
or
// the first argument to a call to `safeLoad` or `safeLoadAll` where
// the schema is specified to be `DEFAULT_FULL_SCHEMA`
exists(string n, DataFlow::CallNode c, DataFlow::Node fullSchema |
n = "safeLoad" or n = "safeLoadAll"
|
c = mi.getAMemberCall(n) and
this = c.getArgument(0) and
fullSchema = c.getOptionArgument(c.getNumArgument() - 1, "schema") and
mi.getAPropertyRead("DEFAULT_FULL_SCHEMA").flowsTo(fullSchema)
)
exists(API::CallNode call |
// Note: we include the old 'safeLoad' and 'safeLoadAll' functon because they were also unsafe when invoked with an unsafe schema.
call =
API::moduleImport("js-yaml")
.getMember(["load", "loadAll", "safeLoad", "safeLoadAll"])
.getACall() and
call.getAParameter().getMember("schema").refersTo(unsafeYamlSchema()) and
this = call.getArgument(0)
)
}
}