Skip to content

Commit e124ba6

Browse files
committed
moving jsdom sink to js/xss
1 parent 120faf9 commit e124ba6

File tree

8 files changed

+28
-33
lines changed

8 files changed

+28
-33
lines changed

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

Lines changed: 0 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -138,17 +138,4 @@ module CodeInjection {
138138
API::moduleImport("module").getInstance().getMember("_compile").getACall().getArgument(0)
139139
}
140140
}
141-
142-
/**
143-
* A construction of a JSDOM object (server side DOM), where scripts are allowed.
144-
*/
145-
class JSDomWithRunScripts extends Sink {
146-
JSDomWithRunScripts() {
147-
exists(DataFlow::NewNode instance |
148-
instance = API::moduleImport("jsdom").getMember("JSDOM").getInstance().getAnImmediateUse() and
149-
this = instance.getArgument(0) and
150-
instance.getOptionArgument(1, "runScripts").mayHaveStringValue("dangerously")
151-
)
152-
}
153-
}
154141
}

javascript/ql/src/semmle/javascript/security/dataflow/Xss.qll

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -151,7 +151,7 @@ module DomBasedXss {
151151
* An expression whose value is interpreted as HTML
152152
* and may be inserted into the DOM through a library.
153153
*/
154-
class LibrarySink extends Sink, DataFlow::ValueNode {
154+
class LibrarySink extends Sink {
155155
LibrarySink() {
156156
// call to a jQuery method that interprets its argument as HTML
157157
exists(JQuery::MethodCall call |
@@ -175,6 +175,13 @@ module DomBasedXss {
175175
this = any(Handlebars::SafeString s).getAnArgument()
176176
or
177177
this = any(JQuery::MethodCall call | call.getMethodName() = "jGrowl").getArgument(0)
178+
or
179+
// A construction of a JSDOM object (server side DOM), where scripts are allowed.
180+
exists(DataFlow::NewNode instance |
181+
instance = API::moduleImport("jsdom").getMember("JSDOM").getInstance().getAnImmediateUse() and
182+
this = instance.getArgument(0) and
183+
instance.getOptionArgument(1, "runScripts").mayHaveStringValue("dangerously")
184+
)
178185
}
179186
}
180187

javascript/ql/test/query-tests/Security/CWE-079/DomBasedXss/Xss.expected

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,9 @@ nodes
8989
| classnames.js:15:47:15:63 | clsx(window.name) |
9090
| classnames.js:15:52:15:62 | window.name |
9191
| classnames.js:15:52:15:62 | window.name |
92+
| express.js:7:15:7:33 | req.param("wobble") |
93+
| express.js:7:15:7:33 | req.param("wobble") |
94+
| express.js:7:15:7:33 | req.param("wobble") |
9295
| jquery.js:2:7:2:40 | tainted |
9396
| jquery.js:2:7:2:40 | tainted |
9497
| jquery.js:2:17:2:33 | document.location |
@@ -685,6 +688,7 @@ edges
685688
| classnames.js:15:47:15:63 | clsx(window.name) | classnames.js:15:31:15:78 | `<span ... <span>` |
686689
| classnames.js:15:52:15:62 | window.name | classnames.js:15:47:15:63 | clsx(window.name) |
687690
| classnames.js:15:52:15:62 | window.name | classnames.js:15:47:15:63 | clsx(window.name) |
691+
| express.js:7:15:7:33 | req.param("wobble") | express.js:7:15:7:33 | req.param("wobble") |
688692
| jquery.js:2:7:2:40 | tainted | jquery.js:7:20:7:26 | tainted |
689693
| jquery.js:2:7:2:40 | tainted | jquery.js:8:28:8:34 | tainted |
690694
| jquery.js:2:17:2:33 | document.location | jquery.js:2:17:2:40 | documen ... .search |
@@ -1175,6 +1179,7 @@ edges
11751179
| classnames.js:11:31:11:79 | `<span ... <span>` | classnames.js:10:45:10:55 | window.name | classnames.js:11:31:11:79 | `<span ... <span>` | Cross-site scripting vulnerability due to $@. | classnames.js:10:45:10:55 | window.name | user-provided value |
11761180
| classnames.js:13:31:13:83 | `<span ... <span>` | classnames.js:13:57:13:67 | window.name | classnames.js:13:31:13:83 | `<span ... <span>` | Cross-site scripting vulnerability due to $@. | classnames.js:13:57:13:67 | window.name | user-provided value |
11771181
| classnames.js:15:31:15:78 | `<span ... <span>` | classnames.js:15:52:15:62 | window.name | classnames.js:15:31:15:78 | `<span ... <span>` | Cross-site scripting vulnerability due to $@. | classnames.js:15:52:15:62 | window.name | user-provided value |
1182+
| express.js:7:15:7:33 | req.param("wobble") | express.js:7:15:7:33 | req.param("wobble") | express.js:7:15:7:33 | req.param("wobble") | Cross-site scripting vulnerability due to $@. | express.js:7:15:7:33 | req.param("wobble") | user-provided value |
11781183
| jquery.js:7:5:7:34 | "<div i ... + "\\">" | jquery.js:2:17:2:40 | documen ... .search | jquery.js:7:5:7:34 | "<div i ... + "\\">" | Cross-site scripting vulnerability due to $@. | jquery.js:2:17:2:40 | documen ... .search | user-provided value |
11791184
| jquery.js:8:18:8:34 | "XSS: " + tainted | jquery.js:2:17:2:33 | document.location | jquery.js:8:18:8:34 | "XSS: " + tainted | Cross-site scripting vulnerability due to $@. | jquery.js:2:17:2:33 | document.location | user-provided value |
11801185
| jquery.js:10:5:10:40 | "<b>" + ... "</b>" | jquery.js:10:13:10:20 | location | jquery.js:10:5:10:40 | "<b>" + ... "</b>" | Cross-site scripting vulnerability due to $@. | jquery.js:10:13:10:20 | location | user-provided value |

javascript/ql/test/query-tests/Security/CWE-079/DomBasedXss/XssWithAdditionalSources.expected

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,9 @@ nodes
8989
| classnames.js:15:47:15:63 | clsx(window.name) |
9090
| classnames.js:15:52:15:62 | window.name |
9191
| classnames.js:15:52:15:62 | window.name |
92+
| express.js:7:15:7:33 | req.param("wobble") |
93+
| express.js:7:15:7:33 | req.param("wobble") |
94+
| express.js:7:15:7:33 | req.param("wobble") |
9295
| jquery.js:2:7:2:40 | tainted |
9396
| jquery.js:2:7:2:40 | tainted |
9497
| jquery.js:2:17:2:33 | document.location |
@@ -689,6 +692,7 @@ edges
689692
| classnames.js:15:47:15:63 | clsx(window.name) | classnames.js:15:31:15:78 | `<span ... <span>` |
690693
| classnames.js:15:52:15:62 | window.name | classnames.js:15:47:15:63 | clsx(window.name) |
691694
| classnames.js:15:52:15:62 | window.name | classnames.js:15:47:15:63 | clsx(window.name) |
695+
| express.js:7:15:7:33 | req.param("wobble") | express.js:7:15:7:33 | req.param("wobble") |
692696
| jquery.js:2:7:2:40 | tainted | jquery.js:7:20:7:26 | tainted |
693697
| jquery.js:2:7:2:40 | tainted | jquery.js:8:28:8:34 | tainted |
694698
| jquery.js:2:17:2:33 | document.location | jquery.js:2:17:2:40 | documen ... .search |
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
var express = require('express');
2+
var app = express();
3+
4+
import { JSDOM } from "jsdom";
5+
app.get('/some/path', function (req, res) {
6+
// NOT OK
7+
new JSDOM(req.param("wobble"), { runScripts: "dangerously" });
8+
9+
// OK
10+
new JSDOM(req.param("wobble"), { runScripts: "outside-only" });
11+
});

javascript/ql/test/query-tests/Security/CWE-094/CodeInjection/CodeInjection.expected

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -108,9 +108,6 @@ nodes
108108
| express.js:21:19:21:48 | req.par ... ntext") |
109109
| express.js:21:19:21:48 | req.par ... ntext") |
110110
| express.js:21:19:21:48 | req.par ... ntext") |
111-
| express.js:28:13:28:31 | req.param("wobble") |
112-
| express.js:28:13:28:31 | req.param("wobble") |
113-
| express.js:28:13:28:31 | req.param("wobble") |
114111
| module.js:9:16:9:29 | req.query.code |
115112
| module.js:9:16:9:29 | req.query.code |
116113
| module.js:9:16:9:29 | req.query.code |
@@ -252,7 +249,6 @@ edges
252249
| express.js:17:30:17:53 | req.par ... cript") | express.js:17:30:17:53 | req.par ... cript") |
253250
| express.js:19:37:19:70 | req.par ... odule") | express.js:19:37:19:70 | req.par ... odule") |
254251
| express.js:21:19:21:48 | req.par ... ntext") | express.js:21:19:21:48 | req.par ... ntext") |
255-
| express.js:28:13:28:31 | req.param("wobble") | express.js:28:13:28:31 | req.param("wobble") |
256252
| module.js:9:16:9:29 | req.query.code | module.js:9:16:9:29 | req.query.code |
257253
| react-native.js:7:7:7:33 | tainted | react-native.js:8:32:8:38 | tainted |
258254
| react-native.js:7:7:7:33 | tainted | react-native.js:8:32:8:38 | tainted |
@@ -316,7 +312,6 @@ edges
316312
| express.js:17:30:17:53 | req.par ... cript") | express.js:17:30:17:53 | req.par ... cript") | express.js:17:30:17:53 | req.par ... cript") | $@ flows to here and is interpreted as code. | express.js:17:30:17:53 | req.par ... cript") | User-provided value |
317313
| express.js:19:37:19:70 | req.par ... odule") | express.js:19:37:19:70 | req.par ... odule") | express.js:19:37:19:70 | req.par ... odule") | $@ flows to here and is interpreted as code. | express.js:19:37:19:70 | req.par ... odule") | User-provided value |
318314
| express.js:21:19:21:48 | req.par ... ntext") | express.js:21:19:21:48 | req.par ... ntext") | express.js:21:19:21:48 | req.par ... ntext") | $@ flows to here and is interpreted as code. | express.js:21:19:21:48 | req.par ... ntext") | User-provided value |
319-
| express.js:28:13:28:31 | req.param("wobble") | express.js:28:13:28:31 | req.param("wobble") | express.js:28:13:28:31 | req.param("wobble") | $@ flows to here and is interpreted as code. | express.js:28:13:28:31 | req.param("wobble") | User-provided value |
320315
| module.js:9:16:9:29 | req.query.code | module.js:9:16:9:29 | req.query.code | module.js:9:16:9:29 | req.query.code | $@ flows to here and is interpreted as code. | module.js:9:16:9:29 | req.query.code | User-provided value |
321316
| react-native.js:8:32:8:38 | tainted | react-native.js:7:17:7:33 | req.param("code") | react-native.js:8:32:8:38 | tainted | $@ flows to here and is interpreted as code. | react-native.js:7:17:7:33 | req.param("code") | User-provided value |
322317
| react-native.js:10:23:10:29 | tainted | react-native.js:7:17:7:33 | req.param("code") | react-native.js:10:23:10:29 | tainted | $@ flows to here and is interpreted as code. | react-native.js:7:17:7:33 | req.param("code") | User-provided value |

javascript/ql/test/query-tests/Security/CWE-094/CodeInjection/HeuristicSourceCodeInjection.expected

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -112,9 +112,6 @@ nodes
112112
| express.js:21:19:21:48 | req.par ... ntext") |
113113
| express.js:21:19:21:48 | req.par ... ntext") |
114114
| express.js:21:19:21:48 | req.par ... ntext") |
115-
| express.js:28:13:28:31 | req.param("wobble") |
116-
| express.js:28:13:28:31 | req.param("wobble") |
117-
| express.js:28:13:28:31 | req.param("wobble") |
118115
| module.js:9:16:9:29 | req.query.code |
119116
| module.js:9:16:9:29 | req.query.code |
120117
| module.js:9:16:9:29 | req.query.code |
@@ -260,7 +257,6 @@ edges
260257
| express.js:17:30:17:53 | req.par ... cript") | express.js:17:30:17:53 | req.par ... cript") |
261258
| express.js:19:37:19:70 | req.par ... odule") | express.js:19:37:19:70 | req.par ... odule") |
262259
| express.js:21:19:21:48 | req.par ... ntext") | express.js:21:19:21:48 | req.par ... ntext") |
263-
| express.js:28:13:28:31 | req.param("wobble") | express.js:28:13:28:31 | req.param("wobble") |
264260
| module.js:9:16:9:29 | req.query.code | module.js:9:16:9:29 | req.query.code |
265261
| react-native.js:7:7:7:33 | tainted | react-native.js:8:32:8:38 | tainted |
266262
| react-native.js:7:7:7:33 | tainted | react-native.js:8:32:8:38 | tainted |

javascript/ql/test/query-tests/Security/CWE-094/CodeInjection/express.js

Lines changed: 0 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -20,13 +20,3 @@ app.get('/some/path', function(req, res) {
2020
// NOT OK
2121
vm.runInContext(req.param("code_runInContext"), vm.createContext());
2222
});
23-
24-
import {JSDOM} from "jsdom";
25-
26-
app.get('/some/path', function(req, res) {
27-
// NOT OK
28-
new JSDOM(req.param("wobble"), {runScripts: "dangerously"});
29-
30-
// OK
31-
new JSDOM(req.param("wobble"), {runScripts: "outside-only"});
32-
});

0 commit comments

Comments
 (0)