Skip to content

Commit 6b19e69

Browse files
committed
JS: Fix some join orders
1 parent 42e6c7e commit 6b19e69

File tree

5 files changed

+64
-45
lines changed

5 files changed

+64
-45
lines changed

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

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -315,6 +315,11 @@ module DOM {
315315
)
316316
}
317317

318+
private InferredType getArgumentTypeFromJQueryMethodGet(JQuery::MethodCall call) {
319+
call.getMethodName() = "get" and
320+
result = call.getArgument(0).analyze().getAType()
321+
}
322+
318323
private class DefaultRange extends Range {
319324
DefaultRange() {
320325
this.asExpr().(VarAccess).getVariable() instanceof DOMGlobalVariable
@@ -344,7 +349,7 @@ module DOM {
344349
or
345350
exists(JQuery::MethodCall call | this = call and call.getMethodName() = "get" |
346351
call.getNumArgument() = 1 and
347-
unique(InferredType t | t = call.getArgument(0).analyze().getAType()) = TTNumber()
352+
unique(InferredType t | t = getArgumentTypeFromJQueryMethodGet(call)) = TTNumber()
348353
)
349354
or
350355
// A `this` node from a callback given to a `$().each(callback)` call.

javascript/ql/src/semmle/javascript/HtmlSanitizers.qll

Lines changed: 43 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -16,51 +16,54 @@ abstract class HtmlSanitizerCall extends DataFlow::CallNode {
1616
abstract DataFlow::Node getInput();
1717
}
1818

19+
pragma[noinline]
20+
private DataFlow::SourceNode htmlSanitizerFunction() {
21+
result = DataFlow::moduleMember("ent", "encode")
22+
or
23+
result = DataFlow::moduleMember("entities", "encodeHTML")
24+
or
25+
result = DataFlow::moduleMember("entities", "encodeXML")
26+
or
27+
result = DataFlow::moduleMember("escape-goat", "escape")
28+
or
29+
result = DataFlow::moduleMember("he", "encode")
30+
or
31+
result = DataFlow::moduleMember("he", "escape")
32+
or
33+
result = DataFlow::moduleImport("sanitize-html")
34+
or
35+
result = DataFlow::moduleMember("sanitizer", "escape")
36+
or
37+
result = DataFlow::moduleMember("sanitizer", "sanitize")
38+
or
39+
result = DataFlow::moduleMember("validator", "escape")
40+
or
41+
result = DataFlow::moduleImport("xss")
42+
or
43+
result = DataFlow::moduleMember("xss-filters", _)
44+
or
45+
result = LodashUnderscore::member("escape")
46+
or
47+
exists(DataFlow::PropRead read | read = result |
48+
read.getPropertyName() = "sanitize" and
49+
read.getBase().asExpr().(VarAccess).getName() = "DOMPurify"
50+
)
51+
or
52+
exists(string name | name = "encode" or name = "encodeNonUTF" |
53+
result =
54+
DataFlow::moduleMember("html-entities", _).getAnInstantiation().getAPropertyRead(name) or
55+
result = DataFlow::moduleMember("html-entities", _).getAPropertyRead(name)
56+
)
57+
or
58+
result = Closure::moduleImport("goog.string.htmlEscape")
59+
}
60+
1961
/**
2062
* Matches HTML sanitizers from known NPM packages as well as home-made sanitizers (matched by name).
2163
*/
2264
private class DefaultHtmlSanitizerCall extends HtmlSanitizerCall {
2365
DefaultHtmlSanitizerCall() {
24-
exists(DataFlow::SourceNode callee | this = callee.getACall() |
25-
callee = DataFlow::moduleMember("ent", "encode")
26-
or
27-
callee = DataFlow::moduleMember("entities", "encodeHTML")
28-
or
29-
callee = DataFlow::moduleMember("entities", "encodeXML")
30-
or
31-
callee = DataFlow::moduleMember("escape-goat", "escape")
32-
or
33-
callee = DataFlow::moduleMember("he", "encode")
34-
or
35-
callee = DataFlow::moduleMember("he", "escape")
36-
or
37-
callee = DataFlow::moduleImport("sanitize-html")
38-
or
39-
callee = DataFlow::moduleMember("sanitizer", "escape")
40-
or
41-
callee = DataFlow::moduleMember("sanitizer", "sanitize")
42-
or
43-
callee = DataFlow::moduleMember("validator", "escape")
44-
or
45-
callee = DataFlow::moduleImport("xss")
46-
or
47-
callee = DataFlow::moduleMember("xss-filters", _)
48-
or
49-
callee = LodashUnderscore::member("escape")
50-
or
51-
exists(DataFlow::PropRead read | read = callee |
52-
read.getPropertyName() = "sanitize" and
53-
read.getBase().asExpr().(VarAccess).getName() = "DOMPurify"
54-
)
55-
or
56-
exists(string name | name = "encode" or name = "encodeNonUTF" |
57-
callee =
58-
DataFlow::moduleMember("html-entities", _).getAnInstantiation().getAPropertyRead(name) or
59-
callee = DataFlow::moduleMember("html-entities", _).getAPropertyRead(name)
60-
)
61-
or
62-
callee = Closure::moduleImport("goog.string.htmlEscape")
63-
)
66+
this = htmlSanitizerFunction().getACall()
6467
or
6568
// Match home-made sanitizers by name.
6669
exists(string calleeName | calleeName = getCalleeName() |

javascript/ql/src/semmle/javascript/Promises.qll

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -596,6 +596,7 @@ private module ClosurePromise {
596596
* A promise created by a call `goog.Promise.resolve(value)`.
597597
*/
598598
private class ResolvedClosurePromiseDefinition extends ResolvedPromiseDefinition {
599+
pragma[noinline]
599600
ResolvedClosurePromiseDefinition() {
600601
this = Closure::moduleImport("goog.Promise.resolve").getACall()
601602
}

javascript/ql/src/semmle/javascript/frameworks/SocketIO.qll

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -268,9 +268,11 @@ module SocketIO {
268268

269269
/** Gets the `i`th parameter through which data is received from a client. */
270270
override DataFlow::SourceNode getReceivedItem(int i) {
271-
exists(DataFlow::FunctionNode cb | cb = getListener() and result = cb.getParameter(i) |
271+
exists(DataFlow::FunctionNode cb |
272+
cb = getListener() and
273+
result = cb.getParameter(i) and
272274
// exclude last parameter if it looks like a callback
273-
result != cb.getLastParameter() or not exists(result.getAnInvocation())
275+
not (result = cb.getLastParameter() and exists(result.getAnInvocation()))
274276
)
275277
}
276278

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

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -156,6 +156,12 @@ private module PersistentWebStorage {
156156
result = DataFlow::globalVarRef(kind)
157157
}
158158

159+
pragma[noinline]
160+
WriteAccess getAWriteByName(string name, string kind) {
161+
result.getKey() = name and
162+
result.getKind() = kind
163+
}
164+
159165
/**
160166
* A read access.
161167
*/
@@ -165,8 +171,10 @@ private module PersistentWebStorage {
165171
ReadAccess() { this = webStorage(kind).getAMethodCall("getItem") }
166172

167173
override PersistentWriteAccess getAWrite() {
168-
getArgument(0).mayHaveStringValue(result.(WriteAccess).getKey()) and
169-
result.(WriteAccess).getKind() = kind
174+
exists(string name |
175+
getArgument(0).mayHaveStringValue(name) and
176+
result = getAWriteByName(name, kind)
177+
)
170178
}
171179
}
172180

0 commit comments

Comments
 (0)