Skip to content

Commit 66eb458

Browse files
committed
JS: Handle match/matchAll and unknown regexps
1 parent 6e7c5a3 commit 66eb458

File tree

3 files changed

+59
-3
lines changed

3 files changed

+59
-3
lines changed

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

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -107,10 +107,21 @@ module TaintedUrlSuffix {
107107
)
108108
or
109109
exists(MethodCallNode call, DataFlow::RegExpCreationNode re |
110-
call = re.getAMethodCall("exec") and
111-
src = call.getArgument(0) and
112-
dst = call and
110+
(
111+
call = re.getAMethodCall("exec") and
112+
src = call.getArgument(0) and
113+
dst = call
114+
or
115+
call.getMethodName() = ["match", "matchAll"] and
116+
re.flowsTo(call.getArgument(0)) and
117+
src = call.getReceiver() and
118+
dst = call
119+
)
120+
|
113121
captureAfterSuffixIndicator(re.getRoot().getAChild*())
122+
or
123+
// If the regexp is unknown, assume it will extract the URL suffix
124+
not exists(re.getRoot())
114125
)
115126
)
116127
}

javascript/ql/test/query-tests/Security/CWE-601/ClientSideUrlRedirect/ClientSideUrlRedirect.expected

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,21 @@ nodes
2121
| regexp-exec.js:9:24:9:58 | /\\?(.*) ... n.href) | semmle.label | /\\?(.*) ... n.href) |
2222
| regexp-exec.js:9:38:9:57 | window.location.href | semmle.label | window.location.href |
2323
| regexp-exec.js:10:28:10:33 | group1 | semmle.label | group1 |
24+
| regexp-exec.js:29:11:29:20 | [, group1] | semmle.label | [, group1] |
25+
| regexp-exec.js:29:11:29:58 | group1 | semmle.label | group1 |
26+
| regexp-exec.js:29:24:29:43 | window.location.href | semmle.label | window.location.href |
27+
| regexp-exec.js:29:24:29:58 | window. ... #(.*)/) | semmle.label | window. ... #(.*)/) |
28+
| regexp-exec.js:30:28:30:33 | group1 | semmle.label | group1 |
29+
| regexp-exec.js:34:11:34:20 | [, group1] | semmle.label | [, group1] |
30+
| regexp-exec.js:34:11:34:64 | group1 | semmle.label | group1 |
31+
| regexp-exec.js:34:24:34:43 | window.location.href | semmle.label | window.location.href |
32+
| regexp-exec.js:34:24:34:61 | window. ... #(.*)/) | semmle.label | window. ... #(.*)/) |
33+
| regexp-exec.js:35:28:35:33 | group1 | semmle.label | group1 |
34+
| regexp-exec.js:39:11:39:20 | [, group1] | semmle.label | [, group1] |
35+
| regexp-exec.js:39:11:39:71 | group1 | semmle.label | group1 |
36+
| regexp-exec.js:39:24:39:71 | new Reg ... n.href) | semmle.label | new Reg ... n.href) |
37+
| regexp-exec.js:39:51:39:70 | window.location.href | semmle.label | window.location.href |
38+
| regexp-exec.js:40:28:40:33 | group1 | semmle.label | group1 |
2439
| sanitizer.js:2:9:2:25 | url | semmle.label | url |
2540
| sanitizer.js:2:15:2:25 | window.name | semmle.label | window.name |
2641
| sanitizer.js:4:27:4:29 | url | semmle.label | url |
@@ -186,6 +201,18 @@ edges
186201
| regexp-exec.js:9:11:9:58 | group1 | regexp-exec.js:10:28:10:33 | group1 | provenance | |
187202
| regexp-exec.js:9:24:9:58 | /\\?(.*) ... n.href) | regexp-exec.js:9:11:9:20 | [, group1] | provenance | |
188203
| regexp-exec.js:9:38:9:57 | window.location.href | regexp-exec.js:9:24:9:58 | /\\?(.*) ... n.href) | provenance | Config |
204+
| regexp-exec.js:29:11:29:20 | [, group1] | regexp-exec.js:29:11:29:58 | group1 | provenance | |
205+
| regexp-exec.js:29:11:29:58 | group1 | regexp-exec.js:30:28:30:33 | group1 | provenance | |
206+
| regexp-exec.js:29:24:29:43 | window.location.href | regexp-exec.js:29:24:29:58 | window. ... #(.*)/) | provenance | Config |
207+
| regexp-exec.js:29:24:29:58 | window. ... #(.*)/) | regexp-exec.js:29:11:29:20 | [, group1] | provenance | |
208+
| regexp-exec.js:34:11:34:20 | [, group1] | regexp-exec.js:34:11:34:64 | group1 | provenance | |
209+
| regexp-exec.js:34:11:34:64 | group1 | regexp-exec.js:35:28:35:33 | group1 | provenance | |
210+
| regexp-exec.js:34:24:34:43 | window.location.href | regexp-exec.js:34:24:34:61 | window. ... #(.*)/) | provenance | Config |
211+
| regexp-exec.js:34:24:34:61 | window. ... #(.*)/) | regexp-exec.js:34:11:34:20 | [, group1] | provenance | |
212+
| regexp-exec.js:39:11:39:20 | [, group1] | regexp-exec.js:39:11:39:71 | group1 | provenance | |
213+
| regexp-exec.js:39:11:39:71 | group1 | regexp-exec.js:40:28:40:33 | group1 | provenance | |
214+
| regexp-exec.js:39:24:39:71 | new Reg ... n.href) | regexp-exec.js:39:11:39:20 | [, group1] | provenance | |
215+
| regexp-exec.js:39:51:39:70 | window.location.href | regexp-exec.js:39:24:39:71 | new Reg ... n.href) | provenance | Config |
189216
| sanitizer.js:2:9:2:25 | url | sanitizer.js:4:27:4:29 | url | provenance | |
190217
| sanitizer.js:2:9:2:25 | url | sanitizer.js:16:27:16:29 | url | provenance | |
191218
| sanitizer.js:2:9:2:25 | url | sanitizer.js:19:27:19:29 | url | provenance | |
@@ -314,6 +341,9 @@ subpaths
314341
| react.js:43:19:43:50 | documen ... bstr(1) | react.js:43:19:43:40 | documen ... on.hash | react.js:43:19:43:50 | documen ... bstr(1) | Untrusted URL redirection depends on a $@. | react.js:43:19:43:40 | documen ... on.hash | user-provided value |
315342
| regexp-exec.js:5:28:5:33 | group1 | regexp-exec.js:4:37:4:56 | window.location.href | regexp-exec.js:5:28:5:33 | group1 | Untrusted URL redirection depends on a $@. | regexp-exec.js:4:37:4:56 | window.location.href | user-provided value |
316343
| regexp-exec.js:10:28:10:33 | group1 | regexp-exec.js:9:38:9:57 | window.location.href | regexp-exec.js:10:28:10:33 | group1 | Untrusted URL redirection depends on a $@. | regexp-exec.js:9:38:9:57 | window.location.href | user-provided value |
344+
| regexp-exec.js:30:28:30:33 | group1 | regexp-exec.js:29:24:29:43 | window.location.href | regexp-exec.js:30:28:30:33 | group1 | Untrusted URL redirection depends on a $@. | regexp-exec.js:29:24:29:43 | window.location.href | user-provided value |
345+
| regexp-exec.js:35:28:35:33 | group1 | regexp-exec.js:34:24:34:43 | window.location.href | regexp-exec.js:35:28:35:33 | group1 | Untrusted URL redirection depends on a $@. | regexp-exec.js:34:24:34:43 | window.location.href | user-provided value |
346+
| regexp-exec.js:40:28:40:33 | group1 | regexp-exec.js:39:51:39:70 | window.location.href | regexp-exec.js:40:28:40:33 | group1 | Untrusted URL redirection depends on a $@. | regexp-exec.js:39:51:39:70 | window.location.href | user-provided value |
317347
| sanitizer.js:4:27:4:29 | url | sanitizer.js:2:15:2:25 | window.name | sanitizer.js:4:27:4:29 | url | Untrusted URL redirection depends on a $@. | sanitizer.js:2:15:2:25 | window.name | user-provided value |
318348
| sanitizer.js:16:27:16:29 | url | sanitizer.js:2:15:2:25 | window.name | sanitizer.js:16:27:16:29 | url | Untrusted URL redirection depends on a $@. | sanitizer.js:2:15:2:25 | window.name | user-provided value |
319349
| sanitizer.js:19:27:19:29 | url | sanitizer.js:2:15:2:25 | window.name | sanitizer.js:19:27:19:29 | url | Untrusted URL redirection depends on a $@. | sanitizer.js:2:15:2:25 | window.name | user-provided value |

javascript/ql/test/query-tests/Security/CWE-601/ClientSideUrlRedirect/regexp-exec.js

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,3 +24,18 @@ function extractNothing() {
2424
const [, group1] = /blah#baz/.exec(window.location.href);
2525
window.location.href = group1; // OK
2626
}
27+
28+
function extractWithMatch() {
29+
const [, group1] = window.location.href.match(/#(.*)/);
30+
window.location.href = group1; // NOT OK
31+
}
32+
33+
function extractWithMatchAll() {
34+
const [, group1] = window.location.href.matchAll(/#(.*)/)[0];
35+
window.location.href = group1; // NOT OK
36+
}
37+
38+
function extractFromUnknownRegExp() {
39+
const [, group1] = new RegExp(unknown()).exec(window.location.href);
40+
window.location.href = group1; // NOT OK
41+
}

0 commit comments

Comments
 (0)