Skip to content

Commit 8323a77

Browse files
authored
Merge pull request #56 from xiemaisi/js/import-globals
Approved by asger-semmle
2 parents da02c45 + 8863296 commit 8323a77

File tree

10 files changed

+80
-7
lines changed

10 files changed

+80
-7
lines changed

change-notes/1.18/analysis-javascript.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@
66

77
* Modelling of data flow through destructuring assignments has been improved. This may give additional results for the security queries and other queries that rely on data flow.
88

9+
* Modelling of global variables has been improved. This may give more true-positive results and fewer false-positive results for a variety of queries.
10+
911
* Modelling of taint flow through the array operations `map` and `join` has been improved. This may give additional results for the security queries.
1012

1113
* Support for popular libraries has been improved. Consequently, queries may produce more results on code bases that use the following libraries:
@@ -31,6 +33,7 @@
3133
- [extend2](https://github.com/eggjs/extend2)
3234
- [fast-json-parse](https://github.com/mcollina/fast-json-parse)
3335
- [forge](https://github.com/digitalbazaar/forge)
36+
- [global](https://www.npmjs.com/package/global)
3437
- [he](https://github.com/mathiasbynens/he)
3538
- [html-entities](https://github.com/mdevils/node-html-entities)
3639
- [jquery](https://jquery.com)

javascript/ql/src/semmle/javascript/dataflow/Nodes.qll

Lines changed: 27 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -219,17 +219,38 @@ class GlobalVarRefNode extends DataFlow::ValueNode, DataFlow::DefaultSourceNode
219219
string getName() { result = astNode.getName() }
220220
}
221221

222+
/**
223+
* Gets a data flow node corresponding to an access to the global object, including
224+
* `this` expressions outside functions, references to global variables `window`
225+
* and `global`, and uses of the `global` npm package.
226+
*/
227+
DataFlow::SourceNode globalObjectRef() {
228+
// top-level `this`
229+
exists (ThisNode globalThis | result = globalThis |
230+
not exists(globalThis.getBinder())
231+
)
232+
or
233+
// DOM
234+
result = globalVarRef("window") or
235+
// Node.js
236+
result = globalVarRef("global") or
237+
// `require("global")`
238+
result = moduleImport("global")
239+
}
240+
222241
/**
223242
* Gets a data flow node corresponding to an access to global variable `name`,
224-
* either directly or through `window` or `global`.
243+
* either directly, through `window` or `global`, or through the `global` npm package.
225244
*/
226245
pragma[nomagic]
227246
DataFlow::SourceNode globalVarRef(string name) {
228-
result.(GlobalVarRefNode).getName() = name or
229-
// DOM environment
230-
result = globalVarRef("window").getAPropertyReference(name) or
231-
// Node.js environment
232-
result = globalVarRef("global").getAPropertyReference(name)
247+
result.(GlobalVarRefNode).getName() = name
248+
or
249+
result = globalObjectRef().getAPropertyReference(name)
250+
or
251+
// `require("global/document")` or `require("global/window")`
252+
(name = "document" or name = "window") and
253+
result = moduleImport("global/" + name)
233254
}
234255

235256
/** A data flow node corresponding to a function definition. */
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
| tst2.js:1:9:1:25 | require("global") |
2+
| tst2.js:3:1:3:24 | require ... indow") |
3+
| tst2.js:7:1:7:6 | global |
4+
| tst2.js:8:1:8:6 | global |
5+
| tst2.js:9:1:9:4 | this |
6+
| tst.js:1:1:1:6 | window |
7+
| tst.js:2:1:2:4 | this |
8+
| tst.js:3:1:3:6 | window |
9+
| tst.js:4:1:4:6 | window |
10+
| tst.js:4:1:4:13 | window.window |
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
import javascript
2+
3+
select DataFlow::globalObjectRef()
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
| Object | tst2.js:8:1:8:13 | global.Object |
2+
| String | tst2.js:9:1:9:11 | this.String |
3+
| document | tst2.js:2:1:2:26 | require ... ument") |
4+
| document | tst.js:3:1:3:15 | window.document |
5+
| document | tst.js:4:1:4:22 | window. ... ocument |
6+
| global | tst2.js:7:1:7:6 | global |
7+
| global | tst2.js:8:1:8:6 | global |
8+
| setTimeout | tst2.js:5:1:5:12 | g.setTimeout |
9+
| window | tst2.js:3:1:3:24 | require ... indow") |
10+
| window | tst.js:1:1:1:6 | window |
11+
| window | tst.js:3:1:3:6 | window |
12+
| window | tst.js:4:1:4:6 | window |
13+
| window | tst.js:4:1:4:13 | window.window |
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
import javascript
2+
3+
from string n
4+
select n, DataFlow::globalVarRef(n)
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
window;
2+
this;
3+
window.document;
4+
window.window.document;
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
var g = require("global");
2+
require("global/document");
3+
require("global/window");
4+
5+
g.setTimeout;
6+
7+
global;
8+
global.Object;
9+
this.String;

javascript/ql/test/query-tests/DOM/PseudoEval/PseudoEval.expected

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,3 +2,4 @@
22
| tst.js:2:1:2:24 | setInte ... te();") | Avoid using functions that evaluate strings as code. |
33
| tst.js:4:1:4:31 | documen ... i!');") | Avoid using functions that evaluate strings as code. |
44
| tst.js:5:1:5:30 | window. ... gger;") | Avoid using functions that evaluate strings as code. |
5+
| tst.js:9:3:9:33 | documen ... d = 2") | Avoid using functions that evaluate strings as code. |

javascript/ql/test/query-tests/DOM/PseudoEval/tst.js

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,4 +2,9 @@ window.setTimeout(";");
22
setInterval("update();");
33
setInterval(update);
44
document.write("alert('Hi!');");
5-
window.execScript("debugger;");
5+
window.execScript("debugger;");
6+
7+
(function(global) {
8+
var document = global.document;
9+
document.write("undefined = 2");
10+
})(this);

0 commit comments

Comments
 (0)