Skip to content

Commit 5259a6e

Browse files
authored
Merge pull request github#13324 from jcogs33/jcogs33/shared-sink-kind-validation
Shared: share MaD kind validation across languages
2 parents 865c050 + 3559111 commit 5259a6e

File tree

16 files changed

+283
-114
lines changed

16 files changed

+283
-114
lines changed

csharp/ql/lib/qlpack.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ extractor: csharp
66
library: true
77
upgrades: upgrades
88
dependencies:
9+
codeql/mad: ${workspace}
910
codeql/ssa: ${workspace}
1011
codeql/tutorial: ${workspace}
1112
codeql/util: ${workspace}

csharp/ql/lib/semmle/code/csharp/dataflow/ExternalFlow.qll

Lines changed: 12 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -95,6 +95,7 @@ private import internal.DataFlowPublic
9595
private import internal.FlowSummaryImpl::Public
9696
private import internal.FlowSummaryImpl::Private::External
9797
private import internal.FlowSummaryImplSpecific
98+
private import codeql.mad.ModelValidation as SharedModelVal
9899

99100
/** Holds if a source model exists for the given parameters. */
100101
predicate sourceModel = Extensions::sourceModel/9;
@@ -204,30 +205,18 @@ module ModelValidation {
204205
)
205206
}
206207

207-
private string getInvalidModelKind() {
208-
exists(string kind | summaryModel(_, _, _, _, _, _, _, _, kind, _) |
209-
not kind = ["taint", "value"] and
210-
result = "Invalid kind \"" + kind + "\" in summary model."
211-
)
212-
or
213-
exists(string kind | sinkModel(_, _, _, _, _, _, _, kind, _) |
214-
not kind =
215-
["code-injection", "sql-injection", "js-injection", "html-injection", "file-content-store"] and
216-
not kind.matches("encryption-%") and
217-
result = "Invalid kind \"" + kind + "\" in sink model."
218-
)
219-
or
220-
exists(string kind | sourceModel(_, _, _, _, _, _, _, kind, _) |
221-
not kind = ["local", "remote", "file", "file-write"] and
222-
result = "Invalid kind \"" + kind + "\" in source model."
223-
)
224-
or
225-
exists(string kind | neutralModel(_, _, _, _, kind, _) |
226-
not kind = ["summary", "source", "sink"] and
227-
result = "Invalid kind \"" + kind + "\" in neutral model."
228-
)
208+
private module KindValConfig implements SharedModelVal::KindValidationConfigSig {
209+
predicate summaryKind(string kind) { summaryModel(_, _, _, _, _, _, _, _, kind, _) }
210+
211+
predicate sinkKind(string kind) { sinkModel(_, _, _, _, _, _, _, kind, _) }
212+
213+
predicate sourceKind(string kind) { sourceModel(_, _, _, _, _, _, _, kind, _) }
214+
215+
predicate neutralKind(string kind) { neutralModel(_, _, _, _, kind, _) }
229216
}
230217

218+
private module KindVal = SharedModelVal::KindValidation<KindValConfig>;
219+
231220
private string getInvalidModelSignature() {
232221
exists(
233222
string pred, string namespace, string type, string name, string signature, string ext,
@@ -269,7 +258,7 @@ module ModelValidation {
269258
msg =
270259
[
271260
getInvalidModelSignature(), getInvalidModelInput(), getInvalidModelOutput(),
272-
getInvalidModelKind()
261+
KindVal::getInvalidModelKind()
273262
]
274263
}
275264
}

go/ql/lib/qlpack.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ extractor: go
66
library: true
77
upgrades: upgrades
88
dependencies:
9+
codeql/mad: ${workspace}
910
codeql/tutorial: ${workspace}
1011
codeql/util: ${workspace}
1112
dataExtensions:

go/ql/lib/semmle/go/dataflow/ExternalFlow.qll

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,7 @@ private import internal.FlowSummaryImpl::Private::External
8080
private import internal.FlowSummaryImplSpecific
8181
private import internal.AccessPathSyntax
8282
private import FlowSummary
83+
private import codeql.mad.ModelValidation as SharedModelVal
8384

8485
/**
8586
* A module importing the frameworks that provide external flow data,
@@ -200,13 +201,16 @@ module ModelValidation {
200201
)
201202
}
202203

203-
private string getInvalidModelKind() {
204-
exists(string kind | summaryModel(_, _, _, _, _, _, _, _, kind, _) |
205-
not kind = ["taint", "value"] and
206-
result = "Invalid kind \"" + kind + "\" in summary model."
207-
)
204+
private module KindValConfig implements SharedModelVal::KindValidationConfigSig {
205+
predicate summaryKind(string kind) { summaryModel(_, _, _, _, _, _, _, _, kind, _) }
206+
207+
predicate sinkKind(string kind) { sinkModel(_, _, _, _, _, _, _, kind, _) }
208+
209+
predicate sourceKind(string kind) { sourceModel(_, _, _, _, _, _, _, kind, _) }
208210
}
209211

212+
private module KindVal = SharedModelVal::KindValidation<KindValConfig>;
213+
210214
private string getInvalidModelSignature() {
211215
exists(
212216
string pred, string package, string type, string name, string signature, string ext,
@@ -243,7 +247,7 @@ module ModelValidation {
243247
msg =
244248
[
245249
getInvalidModelSignature(), getInvalidModelInput(), getInvalidModelOutput(),
246-
getInvalidModelKind()
250+
KindVal::getInvalidModelKind()
247251
]
248252
}
249253
}

java/ql/lib/qlpack.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ extractor: java
66
library: true
77
upgrades: upgrades
88
dependencies:
9+
codeql/mad: ${workspace}
910
codeql/regex: ${workspace}
1011
codeql/tutorial: ${workspace}
1112
codeql/typetracking: ${workspace}

java/ql/lib/semmle/code/java/dataflow/ExternalFlow.qll

Lines changed: 10 additions & 78 deletions
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,7 @@ private import internal.FlowSummaryImplSpecific as FlowSummaryImplSpecific
8787
private import internal.AccessPathSyntax
8888
private import ExternalFlowExtensions as Extensions
8989
private import FlowSummary
90+
private import codeql.mad.ModelValidation as SharedModelVal
9091

9192
/**
9293
* A class for activating additional model rows.
@@ -265,87 +266,18 @@ module ModelValidation {
265266
)
266267
}
267268

268-
private class OutdatedSinkKind extends string {
269-
OutdatedSinkKind() {
270-
this =
271-
[
272-
"sql", "url-redirect", "xpath", "ssti", "logging", "groovy", "jexl", "mvel", "xslt",
273-
"ldap", "pending-intent-sent", "intent-start", "set-hostname-verifier",
274-
"header-splitting", "xss", "write-file", "create-file", "read-file", "open-url",
275-
"jdbc-url"
276-
]
277-
}
278-
279-
private string replacementKind() {
280-
this = ["sql", "xpath", "groovy", "jexl", "mvel", "xslt", "ldap"] and
281-
result = this + "-injection"
282-
or
283-
this = "url-redirect" and result = "url-redirection"
284-
or
285-
this = "ssti" and result = "template-injection"
286-
or
287-
this = "logging" and result = "log-injection"
288-
or
289-
this = "pending-intent-sent" and result = "pending-intents"
290-
or
291-
this = "intent-start" and result = "intent-redirection"
292-
or
293-
this = "set-hostname-verifier" and result = "hostname-verification"
294-
or
295-
this = "header-splitting" and result = "response-splitting"
296-
or
297-
this = "xss" and result = "html-injection\" or \"js-injection"
298-
or
299-
this = "write-file" and result = "file-content-store"
300-
or
301-
this = ["create-file", "read-file"] and result = "path-injection"
302-
or
303-
this = ["open-url", "jdbc-url"] and result = "request-forgery"
304-
}
269+
private module KindValConfig implements SharedModelVal::KindValidationConfigSig {
270+
predicate summaryKind(string kind) { summaryModel(_, _, _, _, _, _, _, _, kind, _) }
305271

306-
string outdatedMessage() {
307-
result =
308-
"The kind \"" + this + "\" is outdated. Use \"" + this.replacementKind() + "\" instead."
309-
}
310-
}
272+
predicate sinkKind(string kind) { sinkModel(_, _, _, _, _, _, _, kind, _) }
311273

312-
private string getInvalidModelKind() {
313-
exists(string kind | summaryModel(_, _, _, _, _, _, _, _, kind, _) |
314-
not kind = ["taint", "value"] and
315-
result = "Invalid kind \"" + kind + "\" in summary model."
316-
)
317-
or
318-
exists(string kind, string msg | sinkModel(_, _, _, _, _, _, _, kind, _) |
319-
not kind =
320-
[
321-
"request-forgery", "jndi-injection", "ldap-injection", "sql-injection", "log-injection",
322-
"mvel-injection", "xpath-injection", "groovy-injection", "html-injection", "js-injection",
323-
"ognl-injection", "intent-redirection", "pending-intents", "url-redirection",
324-
"path-injection", "file-content-store", "hostname-verification", "response-splitting",
325-
"information-leak", "xslt-injection", "jexl-injection", "bean-validation",
326-
"template-injection", "fragment-injection", "command-injection"
327-
] and
328-
not kind.matches("regex-use%") and
329-
not kind.matches("qltest%") and
330-
msg = "Invalid kind \"" + kind + "\" in sink model." and
331-
// The part of this message that refers to outdated sink kinds can be deleted after June 1st, 2024.
332-
if kind instanceof OutdatedSinkKind
333-
then result = msg + " " + kind.(OutdatedSinkKind).outdatedMessage()
334-
else result = msg
335-
)
336-
or
337-
exists(string kind | sourceModel(_, _, _, _, _, _, _, kind, _) |
338-
not kind = ["remote", "contentprovider", "android-external-storage-dir"] and
339-
not kind.matches("qltest%") and
340-
result = "Invalid kind \"" + kind + "\" in source model."
341-
)
342-
or
343-
exists(string kind | neutralModel(_, _, _, _, kind, _) |
344-
not kind = ["summary", "source", "sink"] and
345-
result = "Invalid kind \"" + kind + "\" in neutral model."
346-
)
274+
predicate sourceKind(string kind) { sourceModel(_, _, _, _, _, _, _, kind, _) }
275+
276+
predicate neutralKind(string kind) { neutralModel(_, _, _, _, kind, _) }
347277
}
348278

279+
private module KindVal = SharedModelVal::KindValidation<KindValConfig>;
280+
349281
private string getInvalidModelSignature() {
350282
exists(
351283
string pred, string package, string type, string name, string signature, string ext,
@@ -387,7 +319,7 @@ module ModelValidation {
387319
msg =
388320
[
389321
getInvalidModelSignature(), getInvalidModelInput(), getInvalidModelOutput(),
390-
getInvalidModelKind()
322+
KindVal::getInvalidModelKind()
391323
]
392324
}
393325
}

javascript/ql/lib/qlpack.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ extractor: javascript
66
library: true
77
upgrades: upgrades
88
dependencies:
9+
codeql/mad: ${workspace}
910
codeql/regex: ${workspace}
1011
codeql/tutorial: ${workspace}
1112
codeql/util: ${workspace}

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

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -653,6 +653,17 @@ module ModelOutput {
653653

654654
import Cached
655655
import Specific::ModelOutputSpecific
656+
private import codeql.mad.ModelValidation as SharedModelVal
657+
658+
private module KindValConfig implements SharedModelVal::KindValidationConfigSig {
659+
predicate summaryKind(string kind) { summaryModel(_, _, _, _, kind) }
660+
661+
predicate sinkKind(string kind) { sinkModel(_, _, kind) }
662+
663+
predicate sourceKind(string kind) { sourceModel(_, _, kind) }
664+
}
665+
666+
private module KindVal = SharedModelVal::KindValidation<KindValConfig>;
656667

657668
/**
658669
* Gets an error message relating to an invalid CSV row in a model.
@@ -698,5 +709,8 @@ module ModelOutput {
698709
not isValidNoArgumentTokenInIdentifyingAccessPath(token.getName()) and
699710
result = "Invalid token '" + token + "' is missing its arguments, in access path: " + path
700711
)
712+
or
713+
// Check for invalid model kinds
714+
result = KindVal::getInvalidModelKind()
701715
}
702716
}

python/ql/lib/qlpack.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ extractor: python
66
library: true
77
upgrades: upgrades
88
dependencies:
9+
codeql/mad: ${workspace}
910
codeql/regex: ${workspace}
1011
codeql/tutorial: ${workspace}
1112
codeql/util: ${workspace}

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

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -653,6 +653,17 @@ module ModelOutput {
653653

654654
import Cached
655655
import Specific::ModelOutputSpecific
656+
private import codeql.mad.ModelValidation as SharedModelVal
657+
658+
private module KindValConfig implements SharedModelVal::KindValidationConfigSig {
659+
predicate summaryKind(string kind) { summaryModel(_, _, _, _, kind) }
660+
661+
predicate sinkKind(string kind) { sinkModel(_, _, kind) }
662+
663+
predicate sourceKind(string kind) { sourceModel(_, _, kind) }
664+
}
665+
666+
private module KindVal = SharedModelVal::KindValidation<KindValConfig>;
656667

657668
/**
658669
* Gets an error message relating to an invalid CSV row in a model.
@@ -698,5 +709,8 @@ module ModelOutput {
698709
not isValidNoArgumentTokenInIdentifyingAccessPath(token.getName()) and
699710
result = "Invalid token '" + token + "' is missing its arguments, in access path: " + path
700711
)
712+
or
713+
// Check for invalid model kinds
714+
result = KindVal::getInvalidModelKind()
701715
}
702716
}

0 commit comments

Comments
 (0)