Skip to content

Commit 5f53820

Browse files
committed
Exlucde environmental variables from default detection in regexp injection
1 parent 16e9e8e commit 5f53820

File tree

3 files changed

+21
-11
lines changed

3 files changed

+21
-11
lines changed

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

Lines changed: 20 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
*/
66

77
import javascript
8+
private import codeql.threatmodels.ThreatModels
89

910
module RegExpInjection {
1011
/**
@@ -32,19 +33,32 @@ module RegExpInjection {
3233

3334
/**
3435
* An active threat-model source, considered as a flow source.
36+
* Excludes environment variables by default - they require the "environment" threat model.
3537
*/
3638
private class ActiveThreatModelSourceAsSource extends Source instanceof ActiveThreatModelSource {
37-
ActiveThreatModelSourceAsSource() { not this.isClientSideSource() }
39+
ActiveThreatModelSourceAsSource() {
40+
not this.isClientSideSource() and
41+
not this.(ThreatModelSource).getThreatModel() = "environment"
42+
}
3843
}
3944

40-
private import IndirectCommandInjectionCustomizations
45+
/**
46+
* Environment variables as a source when the "environment" threat model is active.
47+
*/
48+
private class EnvironmentVariableAsSource extends Source instanceof ThreatModelSource {
49+
EnvironmentVariableAsSource() {
50+
this.getThreatModel() = "environment" and
51+
currentThreatModel("environment")
52+
}
53+
54+
override string describe() { result = "environment variable" }
55+
}
4156

4257
/**
43-
* A read of `process.env`, `process.argv`, and similar, considered as a flow source for regular
44-
* expression injection.
58+
* Command line arguments as a source for regular expression injection.
4559
*/
46-
class ArgvAsSource extends Source instanceof IndirectCommandInjection::Source {
47-
override string describe() { result = IndirectCommandInjection::Source.super.describe() }
60+
private class CommandLineArgumentAsSource extends Source instanceof CommandLineArguments {
61+
override string describe() { result = "command-line argument" }
4862
}
4963

5064
/**

javascript/ql/test/query-tests/Security/CWE-730/RegExpInjection.expected

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,6 @@
1414
| RegExpInjection.js:49:14:49:52 | key.spl ... in("-") | RegExpInjection.js:5:13:5:28 | req.param("key") | RegExpInjection.js:49:14:49:52 | key.spl ... in("-") | This regular expression is constructed from a $@. | RegExpInjection.js:5:13:5:28 | req.param("key") | user-provided value |
1515
| RegExpInjection.js:59:14:59:18 | input | RegExpInjection.js:55:39:55:56 | req.param("input") | RegExpInjection.js:59:14:59:18 | input | This regular expression is constructed from a $@. | RegExpInjection.js:55:39:55:56 | req.param("input") | user-provided value |
1616
| RegExpInjection.js:82:14:82:55 | "^.*\\.( ... + ")$" | RegExpInjection.js:77:15:77:32 | req.param("input") | RegExpInjection.js:82:14:82:55 | "^.*\\.( ... + ")$" | This regular expression is constructed from a $@. | RegExpInjection.js:77:15:77:32 | req.param("input") | user-provided value |
17-
| RegExpInjection.js:86:16:86:50 | `^${pro ... r.app$` | RegExpInjection.js:86:20:86:30 | process.env | RegExpInjection.js:86:16:86:50 | `^${pro ... r.app$` | This regular expression is constructed from a $@. | RegExpInjection.js:86:20:86:30 | process.env | environment variable |
1817
| RegExpInjection.js:88:16:88:49 | `^${pro ... r.app$` | RegExpInjection.js:88:20:88:31 | process.argv | RegExpInjection.js:88:16:88:49 | `^${pro ... r.app$` | This regular expression is constructed from a $@. | RegExpInjection.js:88:20:88:31 | process.argv | command-line argument |
1918
| RegExpInjection.js:95:14:95:22 | sanitized | RegExpInjection.js:92:15:92:32 | req.param("input") | RegExpInjection.js:95:14:95:22 | sanitized | This regular expression is constructed from a $@. | RegExpInjection.js:92:15:92:32 | req.param("input") | user-provided value |
2019
| tst.js:6:16:6:35 | "^"+ data.name + "$" | tst.js:5:16:5:29 | req.query.data | tst.js:6:16:6:35 | "^"+ data.name + "$" | This regular expression is constructed from a $@. | tst.js:5:16:5:29 | req.query.data | user-provided value |
@@ -57,7 +56,6 @@ edges
5756
| RegExpInjection.js:77:15:77:32 | req.param("input") | RegExpInjection.js:77:7:77:32 | input | provenance | |
5857
| RegExpInjection.js:82:25:82:29 | input | RegExpInjection.js:82:25:82:48 | input.r ... g, "\|") | provenance | |
5958
| RegExpInjection.js:82:25:82:48 | input.r ... g, "\|") | RegExpInjection.js:82:14:82:55 | "^.*\\.( ... + ")$" | provenance | |
60-
| RegExpInjection.js:86:20:86:30 | process.env | RegExpInjection.js:86:16:86:50 | `^${pro ... r.app$` | provenance | |
6159
| RegExpInjection.js:88:20:88:31 | process.argv | RegExpInjection.js:88:16:88:49 | `^${pro ... r.app$` | provenance | |
6260
| RegExpInjection.js:92:7:92:32 | input | RegExpInjection.js:94:19:94:23 | input | provenance | |
6361
| RegExpInjection.js:92:15:92:32 | req.param("input") | RegExpInjection.js:92:7:92:32 | input | provenance | |
@@ -109,8 +107,6 @@ nodes
109107
| RegExpInjection.js:82:14:82:55 | "^.*\\.( ... + ")$" | semmle.label | "^.*\\.( ... + ")$" |
110108
| RegExpInjection.js:82:25:82:29 | input | semmle.label | input |
111109
| RegExpInjection.js:82:25:82:48 | input.r ... g, "\|") | semmle.label | input.r ... g, "\|") |
112-
| RegExpInjection.js:86:16:86:50 | `^${pro ... r.app$` | semmle.label | `^${pro ... r.app$` |
113-
| RegExpInjection.js:86:20:86:30 | process.env | semmle.label | process.env |
114110
| RegExpInjection.js:88:16:88:49 | `^${pro ... r.app$` | semmle.label | `^${pro ... r.app$` |
115111
| RegExpInjection.js:88:20:88:31 | process.argv | semmle.label | process.argv |
116112
| RegExpInjection.js:92:7:92:32 | input | semmle.label | input |

javascript/ql/test/query-tests/Security/CWE-730/RegExpInjection.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -83,7 +83,7 @@ app.get('/has-sanitizer', function(req, res) {
8383
});
8484

8585
app.get("argv", function(req, res) {
86-
new RegExp(`^${process.env.HOME}/Foo/bar.app$`); // $ Alert[js/regex-injection]
86+
new RegExp(`^${process.env.HOME}/Foo/bar.app$`); // environment variable, should be detected only with threat model enabled.
8787

8888
new RegExp(`^${process.argv[1]}/Foo/bar.app$`); // $ Alert[js/regex-injection]
8989
});

0 commit comments

Comments
 (0)