Skip to content

Commit cc2a267

Browse files
committed
recognize array elements from JQuery objects as DOM values
1 parent 221a259 commit cc2a267

File tree

3 files changed

+23
-0
lines changed

3 files changed

+23
-0
lines changed

javascript/ql/src/semmle/javascript/DOM.qll

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -384,6 +384,13 @@ module DOM {
384384
this = eachCall.getABoundCallbackParameter(0, 1)
385385
)
386386
or
387+
// A read of an array-element from a JQuery object. E.g. `$("#foo")[0]`
388+
exists(DataFlow::PropRead read |
389+
read = this and read = JQuery::objectRef().getAPropertyRead()
390+
|
391+
unique(InferredType t | t = read.getPropertyNameExpr().analyze().getAType()) = TTNumber()
392+
)
393+
or
387394
// A receiver node of an event handler on a DOM node
388395
exists(DataFlow::SourceNode domNode, DataFlow::FunctionNode eventHandler |
389396
// NOTE: we do not use `getABoundFunctionValue()`, since bound functions tend to have

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

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -112,6 +112,12 @@ nodes
112112
| xss-through-dom.js:87:16:87:40 | new ans ... s(text) |
113113
| xss-through-dom.js:87:16:87:40 | new ans ... s(text) |
114114
| xss-through-dom.js:87:36:87:39 | text |
115+
| xss-through-dom.js:93:16:93:46 | $("#foo ... ].value |
116+
| xss-through-dom.js:93:16:93:46 | $("#foo ... ].value |
117+
| xss-through-dom.js:93:16:93:46 | $("#foo ... ].value |
118+
| xss-through-dom.js:96:17:96:47 | $("#foo ... ].value |
119+
| xss-through-dom.js:96:17:96:47 | $("#foo ... ].value |
120+
| xss-through-dom.js:96:17:96:47 | $("#foo ... ].value |
115121
edges
116122
| forms.js:8:23:8:28 | values | forms.js:9:31:9:36 | values |
117123
| forms.js:8:23:8:28 | values | forms.js:9:31:9:36 | values |
@@ -178,6 +184,8 @@ edges
178184
| xss-through-dom.js:86:33:86:36 | text | xss-through-dom.js:86:16:86:37 | anser.a ... l(text) |
179185
| xss-through-dom.js:87:36:87:39 | text | xss-through-dom.js:87:16:87:40 | new ans ... s(text) |
180186
| xss-through-dom.js:87:36:87:39 | text | xss-through-dom.js:87:16:87:40 | new ans ... s(text) |
187+
| xss-through-dom.js:93:16:93:46 | $("#foo ... ].value | xss-through-dom.js:93:16:93:46 | $("#foo ... ].value |
188+
| xss-through-dom.js:96:17:96:47 | $("#foo ... ].value | xss-through-dom.js:96:17:96:47 | $("#foo ... ].value |
181189
#select
182190
| forms.js:9:31:9:40 | values.foo | forms.js:8:23:8:28 | values | forms.js:9:31:9:40 | values.foo | $@ is reinterpreted as HTML without escaping meta-characters. | forms.js:8:23:8:28 | values | DOM text |
183191
| forms.js:12:31:12:40 | values.bar | forms.js:11:24:11:29 | values | forms.js:12:31:12:40 | values.bar | $@ is reinterpreted as HTML without escaping meta-characters. | forms.js:11:24:11:29 | values | DOM text |
@@ -209,3 +217,5 @@ edges
209217
| xss-through-dom.js:81:17:81:43 | $('#foo ... rText') | xss-through-dom.js:81:17:81:43 | $('#foo ... rText') | xss-through-dom.js:81:17:81:43 | $('#foo ... rText') | $@ is reinterpreted as HTML without escaping meta-characters. | xss-through-dom.js:81:17:81:43 | $('#foo ... rText') | DOM text |
210218
| xss-through-dom.js:86:16:86:37 | anser.a ... l(text) | xss-through-dom.js:84:15:84:30 | $("text").text() | xss-through-dom.js:86:16:86:37 | anser.a ... l(text) | $@ is reinterpreted as HTML without escaping meta-characters. | xss-through-dom.js:84:15:84:30 | $("text").text() | DOM text |
211219
| xss-through-dom.js:87:16:87:40 | new ans ... s(text) | xss-through-dom.js:84:15:84:30 | $("text").text() | xss-through-dom.js:87:16:87:40 | new ans ... s(text) | $@ is reinterpreted as HTML without escaping meta-characters. | xss-through-dom.js:84:15:84:30 | $("text").text() | DOM text |
220+
| xss-through-dom.js:93:16:93:46 | $("#foo ... ].value | xss-through-dom.js:93:16:93:46 | $("#foo ... ].value | xss-through-dom.js:93:16:93:46 | $("#foo ... ].value | $@ is reinterpreted as HTML without escaping meta-characters. | xss-through-dom.js:93:16:93:46 | $("#foo ... ].value | DOM text |
221+
| xss-through-dom.js:96:17:96:47 | $("#foo ... ].value | xss-through-dom.js:96:17:96:47 | $("#foo ... ].value | xss-through-dom.js:96:17:96:47 | $("#foo ... ].value | $@ is reinterpreted as HTML without escaping meta-characters. | xss-through-dom.js:96:17:96:47 | $("#foo ... ].value | DOM text |

javascript/ql/test/query-tests/Security/CWE-079/XssThroughDom/xss-through-dom.js

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -89,4 +89,10 @@
8989
$("section h1").each(function(){
9090
$("nav ul").append("<a href='#" + $(this).text().toLowerCase().replace(/ /g, '-').replace(/[^\w-]+/g,'') + "'>Section</a>"); // OK
9191
});
92+
93+
$("#id").html($("#foo").find(".bla")[0].value); // NOT OK.
94+
95+
for (var i = 0; i < foo.length; i++) {
96+
$("#id").html($("#foo").find(".bla")[i].value); // NOT OK.
97+
}
9298
})();

0 commit comments

Comments
 (0)