JS: Handle split() with '#' or '?' separator in a separate summary

This summary uses the notion of optional steps/barriers so it becomes configurable whether there is flow into the zero'th array element.

Also makes sure we handle the second-argument version of split().
This commit is contained in:
Asger F
2024-09-10 15:01:51 +02:00
parent 24983a5836
commit 3b34cd72f2

View File

@@ -55,7 +55,9 @@ class StringSplit extends SummarizedCallable {
StringSplit() { this = "String#split" }
override DataFlow::MethodCallNode getACallSimple() {
result.getMethodName() = "split" and result.getNumArgument() = 1
result.getMethodName() = "split" and
result.getNumArgument() = [1, 2] and
not result.getArgument(0).getStringValue() = ["#", "?"]
}
override predicate propagatesFlowExt(string input, string output, boolean preservesValue) {
@@ -64,3 +66,33 @@ class StringSplit extends SummarizedCallable {
output = "ReturnValue.ArrayElement"
}
}
/**
* A call of form `x.split("#")` or `x.split("?")`.
*
* These are of special significance when tracking a tainted URL suffix, such as `window.location.href`,
* because the first element of the resulting array should not be considered tainted.
*
* This summary defaults to the same behaviour as the general `.split()` case, but it contains optional steps
* and barriers named `tainted-url-suffix` that should be activated when tracking a tainted URL suffix.
*/
class StringSplitHashOrQuestionMark extends SummarizedCallable {
StringSplitHashOrQuestionMark() { this = "String#split with '#' or '?'" }
override DataFlow::MethodCallNode getACallSimple() {
result.getMethodName() = "split" and
result.getNumArgument() = [1, 2] and
result.getArgument(0).getStringValue() = ["#", "?"]
}
override predicate propagatesFlowExt(string input, string output, boolean preservesValue) {
preservesValue = false and
(
input = "Argument[this].OptionalBarrier[tainted-url-suffix]" and
output = "ReturnValue.ArrayElement"
or
input = "Argument[this].OptionalStep[tainted-url-suffix]" and
output = "ReturnValue.ArrayElement[1]" // TODO: support ArrayElement[1..]
)
}
}