Skip to content

Commit 8e98dce

Browse files
committed
add clipboard data as a RemoteFlowSource
1 parent 3983ace commit 8e98dce

File tree

2 files changed

+64
-0
lines changed

2 files changed

+64
-0
lines changed

javascript/ql/lib/javascript.qll

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,7 @@ import semmle.javascript.frameworks.ComposedFunctions
7878
import semmle.javascript.frameworks.Classnames
7979
import semmle.javascript.frameworks.ClassValidator
8080
import semmle.javascript.frameworks.ClientRequests
81+
import semmle.javascript.frameworks.Clipboard
8182
import semmle.javascript.frameworks.ClosureLibrary
8283
import semmle.javascript.frameworks.CookieLibraries
8384
import semmle.javascript.frameworks.Credentials
Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
/**
2+
* Provides predicates for reasoning about clipboard data.
3+
*/
4+
5+
import javascript
6+
7+
/**
8+
* Gets a jQuery "paste" event.
9+
* E.g. `e` in `$("#foo").on("paste", function(e) { ... })`.
10+
*/
11+
private DataFlow::SourceNode jQueryPasteEvent(DataFlow::TypeTracker t) {
12+
t.start() and
13+
exists(DataFlow::CallNode call |
14+
call = JQuery::objectRef().getAMethodCall(["bind", "on", "live", "one", "delegate"]) and
15+
call.getArgument(0).mayHaveStringValue("paste")
16+
|
17+
result = call.getCallback(call.getNumArgument() - 1).getParameter(0)
18+
)
19+
or
20+
exists(DataFlow::TypeTracker t2 | result = jQueryPasteEvent(t2).track(t2, t))
21+
}
22+
23+
/**
24+
* Gets a DOM "paste" event.
25+
* E.g. `e` in `document.addEventListener("paste", e => { ... })`.
26+
*/
27+
private DataFlow::SourceNode pasteEvent(DataFlow::TypeTracker t) {
28+
t.start() and
29+
exists(DataFlow::CallNode call | call = DOM::domValueRef().getAMemberCall("addEventListener") |
30+
call.getArgument(0).mayHaveStringValue("paste") and
31+
result = call.getCallback(1).getParameter(0)
32+
)
33+
or
34+
t.start() and
35+
result = jQueryPasteEvent(DataFlow::TypeTracker::end()).getAPropertyRead("originalEvent")
36+
or
37+
exists(DataFlow::TypeTracker t2 | result = pasteEvent(t2).track(t2, t))
38+
}
39+
40+
/**
41+
* Gets a reference to the clipboardData DataTransfer object.
42+
* https://developer.mozilla.org/en-US/docs/Web/API/ClipboardEvent/clipboardData
43+
*/
44+
private DataFlow::SourceNode clipboardDataTransferSource(DataFlow::TypeTracker t) {
45+
t.start() and
46+
exists(DataFlow::PropRead read | read = result |
47+
read.getPropertyName() = "clipboardData" and
48+
read.getBase().getALocalSource() = pasteEvent(DataFlow::TypeTracker::end())
49+
)
50+
or
51+
exists(DataFlow::TypeTracker t2 | result = clipboardDataTransferSource(t2).track(t2, t))
52+
}
53+
54+
/**
55+
* A reference to data from the clipboard. Seen as a source for DOM-based XSS.
56+
*/
57+
private class ClipboardSource extends RemoteFlowSource {
58+
ClipboardSource() {
59+
this = clipboardDataTransferSource(DataFlow::TypeTracker::end()).getAMethodCall("getData")
60+
}
61+
62+
override string getSourceType() { result = "Clipboard data" }
63+
}

0 commit comments

Comments
 (0)