JS: Recognize RegExps in JSON schemas

This commit is contained in:
Asger Feldthaus
2021-02-26 15:25:52 +00:00
parent 7afa755597
commit 12079cd1e4
4 changed files with 71 additions and 0 deletions

View File

@@ -17,6 +17,34 @@ module JsonSchema {
boolean getPolarity() { result = true }
}
/** A data flow node that is used a JSON schema. */
abstract class SchemaRoot extends DataFlow::Node {
}
/** An object literal with a `$schema` property indicating it is the root of a JSON schema. */
private class SchemaNodeByTag extends SchemaRoot, DataFlow::ObjectLiteralNode {
SchemaNodeByTag() {
getAPropertyWrite("$schema").getRhs().getStringValue().matches("%//json-schema.org%")
}
}
/** Gets a data flow node that is part of a JSON schema. */
private DataFlow::SourceNode getAPartOfJsonSchema(DataFlow::TypeBackTracker t) {
t.start() and
result = any(SchemaRoot n).getALocalSource()
or
result = getAPartOfJsonSchema(t.continue()).getAPropertySource()
or
exists(DataFlow::TypeBackTracker t2 |
result = getAPartOfJsonSchema(t2).backtrack(t2, t)
)
}
/** Gets a data flow node that is part of a JSON schema. */
DataFlow::SourceNode getAPartOfJsonSchema() {
result = getAPartOfJsonSchema(DataFlow::TypeBackTracker::end())
}
/** Provides a model of the `ajv` library. */
module Ajv {
/** A method on `Ajv` that returns `this`. */
@@ -91,5 +119,11 @@ module JsonSchema {
/** Gets the ajv instance doing the validation. */
Instance getAjvInstance() { result = instance }
}
private class AjvSchemaNode extends SchemaRoot {
AjvSchemaNode() {
this = any(Instance i).ref().getMember(["addSchema", "validate", "compile", "compileAsync"]).getParameter(0).getARhs()
}
}
}
}

View File

@@ -865,6 +865,14 @@ predicate isInterpretedAsRegExp(DataFlow::Node source) {
// because `String.prototype.search` returns a number
not exists(PropAccess p | p.getBase() = mce.getEnclosingExpr())
)
or
exists(DataFlow::SourceNode schema |
schema = JsonSchema::getAPartOfJsonSchema()
|
source = schema.getAPropertyWrite("pattern").getRhs()
or
source = schema.getAPropertySource("patternProperties").getAPropertyWrite().getPropertyNameExpr().flow()
)
)
}