Skip to content

Commit 62b0c7a

Browse files
committed
python/ruby/javascript: add machinery for simple MaD sanitizers
- add `barrierNode` to ApiGraphModels which takes MaD barreirs into account - add `sourceNode` and `sinkNode` which operate on `DataFlow::Node`s for convenience - use the convenience predicates throughout - add support for parameterized barrier nodes where needed
1 parent 2e78b14 commit 62b0c7a

File tree

44 files changed

+237
-66
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

44 files changed

+237
-66
lines changed

javascript/ql/lib/semmle/javascript/dataflow/internal/BarrierGuards.qll

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,30 @@ module MakeBarrierGuard<BarrierGuardSig BaseGuard> {
3636
}
3737
}
3838

39+
module ExternalBarrierGuard {
40+
private predicate guardCheck(DataFlow::Node g, Expr e, boolean branch, string kind) {
41+
exists(API::CallNode call, API::Node parameter |
42+
parameter = call.getAParameter() and
43+
parameter = ModelOutput::getABarrierGuardNode(kind, branch)
44+
|
45+
g = call and
46+
e = parameter.asSink().asExpr()
47+
)
48+
}
49+
50+
class BarrierGuard extends DataFlow::Node {
51+
BarrierGuard() { guardCheck(this, _, _, _) }
52+
53+
predicate blocksExpr(boolean outcome, Expr e, string kind) {
54+
guardCheck(this, e, outcome, kind)
55+
}
56+
}
57+
58+
DataFlow::Node getAnExternalBarrierNode(string kind) {
59+
result = MakeStateBarrierGuard<string, BarrierGuard>::getABarrierNode(kind)
60+
}
61+
}
62+
3963
deprecated private module DeprecationWrapper {
4064
signature class LabeledBarrierGuardSig extends DataFlow::Node {
4165
/**

javascript/ql/lib/semmle/javascript/frameworks/Credentials.qll

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ module CredentialsExpr {
2929
private class CredentialsFromModel extends CredentialsNode {
3030
string kind;
3131

32-
CredentialsFromModel() { this = ModelOutput::getASinkNode("credentials-" + kind).asSink() }
32+
CredentialsFromModel() { ModelOutput::sinkNode(this, "credentials-" + kind) }
3333

3434
override string getCredentialsKind() { result = CredentialsExpr::normalizeKind(kind) }
3535
}

javascript/ql/lib/semmle/javascript/frameworks/NoSQL.qll

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ module NoSql {
1313
}
1414

1515
private class QueryFromModel extends Query {
16-
QueryFromModel() { this = ModelOutput::getASinkNode("nosql-injection").asSink() }
16+
QueryFromModel() { ModelOutput::sinkNode(this, "nosql-injection") }
1717
}
1818
}
1919

@@ -46,7 +46,7 @@ private module MongoDB {
4646

4747
override DataFlow::Node getAQueryArgument() {
4848
result = [this.getAnArgument(), this.getOptionArgument(_, _)] and
49-
result = ModelOutput::getASinkNode("mongodb.sink").asSink()
49+
ModelOutput::sinkNode(result, "mongodb.sink")
5050
}
5151

5252
override DataFlow::Node getAResult() {

javascript/ql/lib/semmle/javascript/frameworks/SQL.qll

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ module SQL {
99
abstract class SqlString extends DataFlow::Node { }
1010

1111
private class SqlStringFromModel extends SqlString {
12-
SqlStringFromModel() { this = ModelOutput::getASinkNode("sql-injection").asSink() }
12+
SqlStringFromModel() { ModelOutput::sinkNode(this, "sql-injection") }
1313
}
1414

1515
/**

javascript/ql/lib/semmle/javascript/frameworks/data/ModelsAsData.qll

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ import Shared::ModelOutput as ModelOutput
3030
* A remote flow source originating from a MaD source row.
3131
*/
3232
private class RemoteFlowSourceFromMaD extends RemoteFlowSource {
33-
RemoteFlowSourceFromMaD() { this = ModelOutput::getASourceNode("remote").asSource() }
33+
RemoteFlowSourceFromMaD() { ModelOutput::sourceNode(this, "remote") }
3434

3535
override string getSourceType() { result = "Remote flow" }
3636
}
@@ -39,9 +39,9 @@ private class RemoteFlowSourceFromMaD extends RemoteFlowSource {
3939
* A threat-model flow source originating from a data extension.
4040
*/
4141
private class ThreatModelSourceFromDataExtension extends ThreatModelSource::Range {
42-
ThreatModelSourceFromDataExtension() { this = ModelOutput::getASourceNode(_).asSource() }
42+
ThreatModelSourceFromDataExtension() { ModelOutput::sourceNode(this, _) }
4343

44-
override string getThreatModel() { this = ModelOutput::getASourceNode(result).asSource() }
44+
override string getThreatModel() { ModelOutput::sourceNode(this, result) }
4545

4646
override string getSourceType() {
4747
result = "Source node (" + this.getThreatModel() + ") [from data-extension]"

javascript/ql/lib/semmle/javascript/frameworks/data/internal/ApiGraphModels.qll

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -781,7 +781,7 @@ module ModelOutput {
781781
}
782782

783783
/**
784-
* Holds if a barrier model contributed `barrier` with the given `kind`.
784+
* Holds if a barrier model contributed `barrier` with the given `kind` for the given `branch`.
785785
*/
786786
cached
787787
API::Node getABarrierGuardNode(string kind, boolean branch, string model) {
@@ -858,6 +858,25 @@ module ModelOutput {
858858
result = getABarrierGuardNode(kind, branch, _)
859859
}
860860

861+
/**
862+
* Holds if `node` is specified as a source with the given kind in an external model.
863+
*/
864+
predicate sourceNode(DataFlow::Node node, string kind) { node = getASourceNode(kind).asSource() }
865+
866+
/**
867+
* Holds if `node` is specified as a sink with the given kind in an external model.
868+
*/
869+
predicate sinkNode(DataFlow::Node node, string kind) { node = getASinkNode(kind).asSink() }
870+
871+
/**
872+
* Holds if `node` is specified as a barrier with the given kind in an external model.
873+
*/
874+
predicate barrierNode(DataFlow::Node node, string kind) {
875+
node = getABarrierNode(kind).asSink()
876+
or
877+
node = DataFlow::ExternalBarrierGuard::getAnExternalBarrierNode(kind)
878+
}
879+
861880
private module KindValConfig implements SharedModelVal::KindValidationConfigSig {
862881
predicate summaryKind(string kind) { summaryModel(_, _, _, _, kind, _) }
863882

javascript/ql/lib/semmle/javascript/security/CorsPermissiveConfigurationCustomizations.qll

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,7 @@ module CorsPermissiveConfiguration {
6666
* The value of cors origin when initializing the application.
6767
*/
6868
class CorsOriginSink extends Sink, DataFlow::ValueNode {
69-
CorsOriginSink() { this = ModelOutput::getASinkNode("cors-origin").asSink() }
69+
CorsOriginSink() { ModelOutput::sinkNode(this, "cors-origin") }
7070
}
7171

7272
/**

javascript/ql/lib/semmle/javascript/security/dataflow/ClientSideUrlRedirectCustomizations.qll

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -268,6 +268,6 @@ module ClientSideUrlRedirect {
268268
}
269269

270270
private class SinkFromModel extends Sink {
271-
SinkFromModel() { this = ModelOutput::getASinkNode("url-redirection").asSink() }
271+
SinkFromModel() { ModelOutput::sinkNode(this, "url-redirection") }
272272
}
273273
}

javascript/ql/lib/semmle/javascript/security/dataflow/CodeInjectionCustomizations.qll

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -436,6 +436,6 @@ module CodeInjection {
436436
class JsonStringifySanitizer extends Sanitizer, JsonStringifyCall { }
437437

438438
private class SinkFromModel extends Sink {
439-
SinkFromModel() { this = ModelOutput::getASinkNode("code-injection").asSink() }
439+
SinkFromModel() { ModelOutput::sinkNode(this, "code-injection") }
440440
}
441441
}

javascript/ql/lib/semmle/javascript/security/dataflow/CommandInjectionCustomizations.qll

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,6 @@ module CommandInjection {
5656
}
5757

5858
private class SinkFromModel extends Sink {
59-
SinkFromModel() { this = ModelOutput::getASinkNode("command-injection").asSink() }
59+
SinkFromModel() { ModelOutput::sinkNode(this, "command-injection") }
6060
}
6161
}

0 commit comments

Comments
 (0)