diff --git a/javascript/ql/lib/change-notes/2025-11-19-default-view.md b/javascript/ql/lib/change-notes/2025-11-19-default-view.md new file mode 100644 index 000000000000..1dd42c2697e1 --- /dev/null +++ b/javascript/ql/lib/change-notes/2025-11-19-default-view.md @@ -0,0 +1,5 @@ +--- +category: minorAnalysis +--- + +- JavaScript `DataFlow::globalVarRef` now recognizes `document.defaultView` as an alias of `window`, allowing flows such as `document.defaultView.history.pushState(...)` to be modeled and found by queries relying on `globalVarRef("history")`. diff --git a/javascript/ql/lib/semmle/javascript/dataflow/Nodes.qll b/javascript/ql/lib/semmle/javascript/dataflow/Nodes.qll index d4244ec3cbc6..aa12cfe18648 100644 --- a/javascript/ql/lib/semmle/javascript/dataflow/Nodes.qll +++ b/javascript/ql/lib/semmle/javascript/dataflow/Nodes.qll @@ -393,6 +393,9 @@ DataFlow::SourceNode globalObjectRef() { // DOM result = globalVariable("window") or + // DOM alias via `document.defaultView` + result = globalVariable("document").getAPropertyRead("defaultView") + or // Node.js result = globalVariable("global") or diff --git a/javascript/ql/test/library-tests/Nodes/globalObjectRef.expected b/javascript/ql/test/library-tests/Nodes/globalObjectRef.expected index 0c35fe87b268..d3a779eb5970 100644 --- a/javascript/ql/test/library-tests/Nodes/globalObjectRef.expected +++ b/javascript/ql/test/library-tests/Nodes/globalObjectRef.expected @@ -5,9 +5,12 @@ | tst2.js:8:1:8:6 | global | | tst3.js:1:1:1:0 | this | | tst3.js:3:9:3:19 | goog.global | +| tst4.js:1:1:1:0 | this | +| tst4.js:1:1:1:38 | require ... ultView | | tst.js:1:1:1:0 | this | | tst.js:1:1:1:6 | window | | tst.js:3:1:3:6 | window | | tst.js:4:1:4:6 | window | | tst.js:5:1:5:4 | self | | tst.js:6:1:6:10 | globalThis | +| tst.js:7:1:7:20 | document.defaultView | diff --git a/javascript/ql/test/library-tests/Nodes/globalVarRef.expected b/javascript/ql/test/library-tests/Nodes/globalVarRef.expected index 507e099b80ae..48d912d3aa72 100644 --- a/javascript/ql/test/library-tests/Nodes/globalVarRef.expected +++ b/javascript/ql/test/library-tests/Nodes/globalVarRef.expected @@ -1,15 +1,19 @@ | Object | tst2.js:8:1:8:13 | global.Object | | String | tst2.js:9:1:9:11 | this.String | | document | tst2.js:2:1:2:26 | require ... ument") | +| document | tst4.js:1:1:1:26 | require ... ument") | | document | tst.js:3:1:3:15 | window.document | | document | tst.js:5:1:5:13 | self.document | | document | tst.js:6:1:6:19 | globalThis.document | +| document | tst.js:7:1:7:8 | document | | foo | tst3.js:4:1:4:5 | w.foo | | global | tst2.js:7:1:7:6 | global | | global | tst2.js:8:1:8:6 | global | | globalThis | tst.js:6:1:6:10 | globalThis | | goog | tst3.js:1:1:1:4 | goog | | goog | tst3.js:3:9:3:12 | goog | +| history | tst4.js:1:1:1:46 | require ... history | +| history | tst.js:7:1:7:28 | documen ... history | | self | tst.js:5:1:5:4 | self | | setTimeout | tst2.js:5:1:5:12 | g.setTimeout | | window | tst2.js:3:1:3:24 | require ... indow") | diff --git a/javascript/ql/test/library-tests/Nodes/tst.js b/javascript/ql/test/library-tests/Nodes/tst.js index ec660b25580f..395309672d31 100644 --- a/javascript/ql/test/library-tests/Nodes/tst.js +++ b/javascript/ql/test/library-tests/Nodes/tst.js @@ -4,3 +4,4 @@ window.document; window.window.document; self.document; globalThis.document; +document.defaultView.history; diff --git a/javascript/ql/test/library-tests/Nodes/tst4.js b/javascript/ql/test/library-tests/Nodes/tst4.js new file mode 100644 index 000000000000..087a780629e9 --- /dev/null +++ b/javascript/ql/test/library-tests/Nodes/tst4.js @@ -0,0 +1 @@ +require("global/document").defaultView.history;