Skip to content

Commit cacdc46

Browse files
authored
Merge pull request #22036 from forks-felickz/felickz/js-angular-hostlistener-postmessage
JavaScript: Recognize Angular @HostListener('window:message') as a postMessage handler
2 parents 7b800b1 + d1d9df7 commit cacdc46

4 files changed

Lines changed: 47 additions & 0 deletions

File tree

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
---
2+
category: minorAnalysis
3+
---
4+
* 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.

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

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -195,6 +195,18 @@ class PostMessageEventHandler extends Function {
195195
rhs = DataFlow::globalObjectRef().getAPropertyWrite("onmessage").getRhs() and
196196
rhs.getABoundFunctionValue(paramIndex).getFunction() = this
197197
)
198+
or
199+
// Angular's `@HostListener('window:message', ['$event'])` decorator registers
200+
// a method as a `message` event handler on the global `window` or `document`
201+
// target. The decorated method receives the `MessageEvent` as its first
202+
// parameter, so it is equivalent to `window.addEventListener('message', ...)`.
203+
exists(MethodDefinition method, DataFlow::CallNode decorator |
204+
decorator = DataFlow::moduleMember("@angular/core", "HostListener").getACall() and
205+
decorator = method.getADecorator().getExpression().flow() and
206+
decorator.getArgument(0).mayHaveStringValue(["window:message", "document:message"]) and
207+
method.getBody() = this and
208+
paramIndex = 0
209+
)
198210
}
199211

200212
/**
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
import { Component, HostListener } from '@angular/core';
2+
3+
@Component({ selector: 'app-root' })
4+
class AngularComponent {
5+
// Angular registers this as a `window` message handler via the decorator,
6+
// equivalent to `window.addEventListener('message', ...)`.
7+
@HostListener('window:message', ['$event'])
8+
onWindowMessage(event: MessageEvent): void { // $ Alert - no origin check
9+
eval(event.data);
10+
}
11+
12+
@HostListener('document:message', ['$event'])
13+
onDocumentMessage(event: MessageEvent): void { // $ Alert - no origin check
14+
eval(event.data);
15+
}
16+
17+
@HostListener('window:message', ['$event'])
18+
onCheckedMessage(event: MessageEvent): void { // OK - has an origin check
19+
if (event.origin === 'https://www.example.com') {
20+
eval(event.data);
21+
}
22+
}
23+
24+
// Not a message event, so it is not a postMessage handler.
25+
@HostListener('window:resize', ['$event'])
26+
onResize(event: MessageEvent): void { // OK - not a message handler
27+
eval(event.data);
28+
}
29+
}
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
| Angular.ts:8:19:8:23 | event | Postmessage handler has no origin check. |
2+
| Angular.ts:13:21:13:25 | event | Postmessage handler has no origin check. |
13
| tst.js:11:20:11:24 | event | Postmessage handler has no origin check. |
24
| tst.js:24:27:24:27 | e | Postmessage handler has no origin check. |
35
| tst.js:40:27:40:27 | e | Postmessage handler has no origin check. |

0 commit comments

Comments
 (0)