mirror of
https://github.com/github/codeql.git
synced 2026-05-05 21:55:19 +02:00
merge Clipboard.qll and DragAndDrop.qll, and support InputEvent
This commit is contained in:
@@ -79,7 +79,6 @@ import semmle.javascript.frameworks.ComposedFunctions
|
||||
import semmle.javascript.frameworks.Classnames
|
||||
import semmle.javascript.frameworks.ClassValidator
|
||||
import semmle.javascript.frameworks.ClientRequests
|
||||
import semmle.javascript.frameworks.Clipboard
|
||||
import semmle.javascript.frameworks.ClosureLibrary
|
||||
import semmle.javascript.frameworks.CookieLibraries
|
||||
import semmle.javascript.frameworks.Credentials
|
||||
@@ -88,7 +87,7 @@ import semmle.javascript.frameworks.D3
|
||||
import semmle.javascript.frameworks.data.ModelsAsData
|
||||
import semmle.javascript.frameworks.DateFunctions
|
||||
import semmle.javascript.frameworks.DigitalOcean
|
||||
import semmle.javascript.frameworks.DragAndDrop
|
||||
import semmle.javascript.frameworks.DomEvents
|
||||
import semmle.javascript.frameworks.Electron
|
||||
import semmle.javascript.frameworks.EventEmitter
|
||||
import semmle.javascript.frameworks.Files
|
||||
|
||||
@@ -1,75 +0,0 @@
|
||||
/**
|
||||
* Provides predicates for reasoning about clipboard data.
|
||||
*/
|
||||
|
||||
import javascript
|
||||
|
||||
/**
|
||||
* Gets a jQuery "paste" event.
|
||||
* E.g. `e` in `$("#foo").on("paste", function(e) { ... })`.
|
||||
*/
|
||||
private DataFlow::SourceNode jQueryPasteEvent(DataFlow::TypeTracker t) {
|
||||
t.start() and
|
||||
exists(DataFlow::CallNode call |
|
||||
call = JQuery::objectRef().getAMethodCall(["bind", "on", "live", "one", "delegate"]) and
|
||||
call.getArgument(0).mayHaveStringValue("paste")
|
||||
|
|
||||
result = call.getCallback(call.getNumArgument() - 1).getParameter(0)
|
||||
)
|
||||
or
|
||||
exists(DataFlow::TypeTracker t2 | result = jQueryPasteEvent(t2).track(t2, t))
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a DOM "paste" event.
|
||||
* E.g. `e` in `document.addEventListener("paste", e => { ... })`.
|
||||
*/
|
||||
private DataFlow::SourceNode pasteEvent(DataFlow::TypeTracker t) {
|
||||
t.start() and
|
||||
exists(DataFlow::CallNode call | call = DOM::domValueRef().getAMemberCall("addEventListener") |
|
||||
call.getArgument(0).mayHaveStringValue("paste") and
|
||||
result = call.getCallback(1).getParameter(0)
|
||||
)
|
||||
or
|
||||
t.start() and
|
||||
exists(DataFlow::ParameterNode pn |
|
||||
// https://developer.mozilla.org/en-US/docs/Web/API/ClipboardEvent
|
||||
pn.hasUnderlyingType("ClipboardEvent") and result = pn
|
||||
)
|
||||
or
|
||||
t.start() and
|
||||
exists(DataFlow::PropWrite pw | pw = DOM::domValueRef().getAPropertyWrite() |
|
||||
pw.getPropertyName() = "onpaste" and
|
||||
result = pw.getRhs().getABoundFunctionValue(0).getParameter(0)
|
||||
)
|
||||
or
|
||||
t.start() and
|
||||
result = jQueryPasteEvent(DataFlow::TypeTracker::end()).getAPropertyRead("originalEvent")
|
||||
or
|
||||
exists(DataFlow::TypeTracker t2 | result = pasteEvent(t2).track(t2, t))
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a reference to the clipboardData DataTransfer object.
|
||||
* https://developer.mozilla.org/en-US/docs/Web/API/ClipboardEvent/clipboardData
|
||||
*/
|
||||
private DataFlow::SourceNode clipboardDataTransferSource(DataFlow::TypeTracker t) {
|
||||
t.start() and
|
||||
exists(DataFlow::PropRead read | read = result |
|
||||
read.getPropertyName() = "clipboardData" and
|
||||
read.getBase().getALocalSource() = pasteEvent(DataFlow::TypeTracker::end())
|
||||
)
|
||||
or
|
||||
exists(DataFlow::TypeTracker t2 | result = clipboardDataTransferSource(t2).track(t2, t))
|
||||
}
|
||||
|
||||
/**
|
||||
* A reference to data from the clipboard. Seen as a source for DOM-based XSS.
|
||||
*/
|
||||
private class ClipboardSource extends RemoteFlowSource {
|
||||
ClipboardSource() {
|
||||
this = clipboardDataTransferSource(DataFlow::TypeTracker::end()).getAMethodCall("getData")
|
||||
}
|
||||
|
||||
override string getSourceType() { result = "Clipboard data" }
|
||||
}
|
||||
96
javascript/ql/lib/semmle/javascript/frameworks/DomEvents.qll
Normal file
96
javascript/ql/lib/semmle/javascript/frameworks/DomEvents.qll
Normal file
@@ -0,0 +1,96 @@
|
||||
/**
|
||||
* Provides predicates for reasoning about events from the DOM that introduce tainted data.
|
||||
*/
|
||||
|
||||
import javascript
|
||||
|
||||
/** Gets the name of a DOM event that might introduce tainted data. */
|
||||
private string getATaintedDomEvent() { result = ["paste", "drop", "beforeinput"] }
|
||||
|
||||
/**
|
||||
* Gets a jQuery event that might introduce tainted data.
|
||||
* E.g. `e` in `$("#foo").on("paste", function(e) { ... })`.
|
||||
*/
|
||||
private DataFlow::SourceNode taintedJQueryEvent(DataFlow::TypeTracker t, string event) {
|
||||
t.start() and
|
||||
exists(DataFlow::CallNode call |
|
||||
call = JQuery::objectRef().getAMethodCall(["bind", "on", "live", "one", "delegate"]) and
|
||||
call.getArgument(0).mayHaveStringValue(event) and
|
||||
event = getATaintedDomEvent()
|
||||
|
|
||||
result = call.getCallback(call.getNumArgument() - 1).getParameter(0)
|
||||
)
|
||||
or
|
||||
exists(DataFlow::TypeTracker t2 | result = taintedJQueryEvent(t2, event).track(t2, t))
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a DOM event that might introduce tainted data.
|
||||
* E.g. `e` in `document.addEventListener("paste", e => { ... })`.
|
||||
*/
|
||||
private DataFlow::SourceNode taintedEvent(DataFlow::TypeTracker t, string event) {
|
||||
t.start() and
|
||||
exists(DataFlow::CallNode call | call = DOM::domValueRef().getAMemberCall("addEventListener") |
|
||||
call.getArgument(0).mayHaveStringValue(event) and
|
||||
event = getATaintedDomEvent() and
|
||||
result = call.getCallback(1).getParameter(0)
|
||||
)
|
||||
or
|
||||
t.start() and
|
||||
exists(DataFlow::ParameterNode pn |
|
||||
// https://developer.mozilla.org/en-US/docs/Web/API/ClipboardEvent
|
||||
pn.hasUnderlyingType("ClipboardEvent") and
|
||||
result = pn and
|
||||
event = "paste"
|
||||
or
|
||||
// https://developer.mozilla.org/en-US/docs/Web/API/DragEvent
|
||||
pn.hasUnderlyingType("DragEvent") and
|
||||
result = pn and
|
||||
event = "drop"
|
||||
or
|
||||
// https://developer.mozilla.org/en-US/docs/Web/API/InputEvent
|
||||
pn.hasUnderlyingType("InputEvent") and
|
||||
result = pn and
|
||||
event = "beforeinput"
|
||||
)
|
||||
or
|
||||
t.start() and
|
||||
exists(DataFlow::PropWrite pw | pw = DOM::domValueRef().getAPropertyWrite() |
|
||||
pw.getPropertyName() = "on" + event and
|
||||
event = ["paste", "drop"] and // doesn't work for beforeinput, it's just not part of the API
|
||||
result = pw.getRhs().getABoundFunctionValue(0).getParameter(0)
|
||||
)
|
||||
or
|
||||
t.start() and
|
||||
result = taintedJQueryEvent(DataFlow::TypeTracker::end(), event).getAPropertyRead("originalEvent")
|
||||
or
|
||||
exists(DataFlow::TypeTracker t2 | result = taintedEvent(t2, event).track(t2, t))
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a reference to a DataTransfer object.
|
||||
* https://developer.mozilla.org/en-US/docs/Web/API/ClipboardEvent/clipboardData
|
||||
*/
|
||||
private DataFlow::SourceNode taintedDataTransfer(DataFlow::TypeTracker t) {
|
||||
t.start() and
|
||||
result = taintedEvent(DataFlow::TypeTracker::end(), "paste").getAPropertyRead("clipboardData")
|
||||
or
|
||||
t.start() and
|
||||
result =
|
||||
taintedEvent(DataFlow::TypeTracker::end(), ["drop", "beforeinput"])
|
||||
.getAPropertyRead("dataTransfer")
|
||||
or
|
||||
exists(DataFlow::TypeTracker t2 | result = taintedDataTransfer(t2).track(t2, t))
|
||||
}
|
||||
|
||||
/**
|
||||
* A reference to data from a DataTransfer object, which might originate from e.g. the clipboard.
|
||||
* Seen as a source for DOM-based XSS.
|
||||
*/
|
||||
private class TaintedDataTransfer extends RemoteFlowSource {
|
||||
TaintedDataTransfer() {
|
||||
this = taintedDataTransfer(DataFlow::TypeTracker::end()).getAMethodCall("getData")
|
||||
}
|
||||
|
||||
override string getSourceType() { result = "Clipboard data" }
|
||||
}
|
||||
@@ -1,75 +0,0 @@
|
||||
/**
|
||||
* Provides predicates for reasoning about dragAndDrop data.
|
||||
*/
|
||||
|
||||
import javascript
|
||||
|
||||
/**
|
||||
* Gets a jQuery "drop" event.
|
||||
* E.g. `e` in `$("#foo").on("drop", function(e) { ... })`.
|
||||
*/
|
||||
private DataFlow::SourceNode jQueryDropEvent(DataFlow::TypeTracker t) {
|
||||
t.start() and
|
||||
exists(DataFlow::CallNode call |
|
||||
call = JQuery::objectRef().getAMethodCall(["bind", "on", "live", "one", "delegate"]) and
|
||||
call.getArgument(0).mayHaveStringValue("drop")
|
||||
|
|
||||
result = call.getCallback(call.getNumArgument() - 1).getParameter(0)
|
||||
)
|
||||
or
|
||||
exists(DataFlow::TypeTracker t2 | result = jQueryDropEvent(t2).track(t2, t))
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a DOM "drop" event.
|
||||
* E.g. `e` in `document.addEventListener("drop", e => { ... })`.
|
||||
*/
|
||||
private DataFlow::SourceNode dropEvent(DataFlow::TypeTracker t) {
|
||||
t.start() and
|
||||
exists(DataFlow::CallNode call | call = DOM::domValueRef().getAMemberCall("addEventListener") |
|
||||
call.getArgument(0).mayHaveStringValue("drop") and
|
||||
result = call.getCallback(1).getParameter(0)
|
||||
)
|
||||
or
|
||||
t.start() and
|
||||
exists(DataFlow::ParameterNode pn |
|
||||
// https://developer.mozilla.org/en-US/docs/Web/API/DragEvent
|
||||
pn.hasUnderlyingType("DragEvent") and result = pn
|
||||
)
|
||||
or
|
||||
t.start() and
|
||||
exists(DataFlow::PropWrite pw | pw = DOM::domValueRef().getAPropertyWrite() |
|
||||
pw.getPropertyName() = "ondrop" and
|
||||
result = pw.getRhs().getABoundFunctionValue(0).getParameter(0)
|
||||
)
|
||||
or
|
||||
t.start() and
|
||||
result = jQueryDropEvent(DataFlow::TypeTracker::end()).getAPropertyRead("originalEvent")
|
||||
or
|
||||
exists(DataFlow::TypeTracker t2 | result = dropEvent(t2).track(t2, t))
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a reference to the dragAndDropData DataTransfer object.
|
||||
* https://developer.mozilla.org/docs/Web/API/HTML_Drag_and_Drop_API
|
||||
*/
|
||||
private DataFlow::SourceNode dragAndDropDataTransferSource(DataFlow::TypeTracker t) {
|
||||
t.start() and
|
||||
exists(DataFlow::PropRead read | read = result |
|
||||
read.getPropertyName() = "dataTransfer" and
|
||||
read.getBase().getALocalSource() = dropEvent(DataFlow::TypeTracker::end())
|
||||
)
|
||||
or
|
||||
exists(DataFlow::TypeTracker t2 | result = dragAndDropDataTransferSource(t2).track(t2, t))
|
||||
}
|
||||
|
||||
/**
|
||||
* A reference to data from the dragAndDrop. Seen as a source for DOM-based XSS.
|
||||
*/
|
||||
private class DragAndDropSource extends RemoteFlowSource {
|
||||
DragAndDropSource() {
|
||||
this = dragAndDropDataTransferSource(DataFlow::TypeTracker::end()).getAMethodCall("getData")
|
||||
}
|
||||
|
||||
override string getSourceType() { result = "DragAndDrop data" }
|
||||
}
|
||||
Reference in New Issue
Block a user