mirror of
https://github.com/github/codeql.git
synced 2026-06-29 00:27:05 +02:00
JavaScript: Recognize Angular @HostListener('window:message') as a postMessage handler
Angular registers window message handlers via the
@HostListener('window:message', ['\']) decorator rather than
window.addEventListener('message', ...). The PostMessageEventHandler class
only modeled the addEventListener and window.onmessage forms, so the decorated
handler's event parameter was never treated as a message source. As a result,
js/missing-origin-check produced no alert and the event was not a client-side
remote flow source for downstream queries (e.g. client-side URL redirection).
Extend PostMessageEventHandler to also recognize methods decorated with
@HostListener for 'window:message', 'document:message', or 'message'.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
This commit is contained in:
@@ -0,0 +1,4 @@
|
||||
---
|
||||
category: minorAnalysis
|
||||
---
|
||||
* Added support for Angular's `@HostListener('window:message', ...)` and `@HostListener('document:message', ...)` decorators as `postMessage` event handlers. The decorated method's event parameter is now recognized as a client-side remote flow source, and is considered by the `js/missing-origin-check` query.
|
||||
@@ -195,6 +195,18 @@ class PostMessageEventHandler extends Function {
|
||||
rhs = DataFlow::globalObjectRef().getAPropertyWrite("onmessage").getRhs() and
|
||||
rhs.getABoundFunctionValue(paramIndex).getFunction() = this
|
||||
)
|
||||
or
|
||||
// Angular's `@HostListener('window:message', ['$event'])` decorator registers
|
||||
// a method as a `message` event handler on the global `window`/`document`
|
||||
// target. The decorated method receives the `MessageEvent` as its first
|
||||
// parameter, so it is equivalent to `window.addEventListener('message', ...)`.
|
||||
exists(MethodDefinition method, DataFlow::CallNode decorator |
|
||||
decorator = DataFlow::moduleMember("@angular/core", "HostListener").getACall() and
|
||||
decorator = method.getADecorator().getExpression().flow() and
|
||||
decorator.getArgument(0).mayHaveStringValue(["window:message", "document:message", "message"]) and
|
||||
method.getBody() = this and
|
||||
paramIndex = 0
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -0,0 +1,29 @@
|
||||
import { Component, HostListener } from '@angular/core';
|
||||
|
||||
@Component({ selector: 'app-root' })
|
||||
class AngularComponent {
|
||||
// Angular registers this as a `window` message handler via the decorator,
|
||||
// equivalent to `window.addEventListener('message', ...)`.
|
||||
@HostListener('window:message', ['$event'])
|
||||
onWindowMessage(event: MessageEvent): void { // $ Alert - no origin check
|
||||
eval(event.data);
|
||||
}
|
||||
|
||||
@HostListener('document:message', ['$event'])
|
||||
onDocumentMessage(event: MessageEvent): void { // $ Alert - no origin check
|
||||
eval(event.data);
|
||||
}
|
||||
|
||||
@HostListener('window:message', ['$event'])
|
||||
onCheckedMessage(event: MessageEvent): void { // OK - has an origin check
|
||||
if (event.origin === 'https://www.example.com') {
|
||||
eval(event.data);
|
||||
}
|
||||
}
|
||||
|
||||
// Not a message event, so it is not a postMessage handler.
|
||||
@HostListener('window:resize', ['$event'])
|
||||
onResize(event: MessageEvent): void { // OK - not a message handler
|
||||
eval(event.data);
|
||||
}
|
||||
}
|
||||
@@ -1,3 +1,5 @@
|
||||
| Angular.ts:8:19:8:23 | event | Postmessage handler has no origin check. |
|
||||
| Angular.ts:13:21:13:25 | event | Postmessage handler has no origin check. |
|
||||
| tst.js:11:20:11:24 | event | Postmessage handler has no origin check. |
|
||||
| tst.js:24:27:24:27 | e | Postmessage handler has no origin check. |
|
||||
| tst.js:40:27:40:27 | e | Postmessage handler has no origin check. |
|
||||
|
||||
Reference in New Issue
Block a user