postMessage Wildcard Origin Bugs Worth Reporting
postMessage is how windows talk across origins without exploding the same-origin policy. The API is fine. The * target origin and missing event.origin checks are not.
If a page listens for messages and acts on event.data without verifying who sent it, any iframe or popup you can point at that page becomes a remote control.
Chat widgets, SSO popups, payment iframes, and mobile-to-web bridges all lean on this channel. One careless listener in a shared layout bundle can expose every route that loads it—not only the feature that "owns" messaging.
Read the listener before you send noise
In DevTools, dig for addEventListener("message" and onmessage. Ask three questions:
- Is
event.origincompared to a concrete allowlist? - Is
event.sourcechecked when a reply matters? - Does the handler pass
event.dataintoinnerHTML,eval,Function, store APIs, or navigation?
A wildcard send looks like frames[0].postMessage(payload, "*"). That does not by itself mean the receiver is broken—it means anyone can deliver a message if they get a reference to the window. The bug lives in the receiver.
I've lost time chasing handlers that only accept structured clones with a type field, then found the real issue in a second listener registered by an analytics SDK. Enumerate every listener, including those added after hydration.
Proof without stealing real sessions
Embed or open the target, then from your origin:
targetWindow.postMessage(
{ cmd: "setTitle", html: "<img src=x onerror=..." },
"https://target.example"
);
Prefer sending to the explicit origin in your PoC even if the app uses * when talking back. Your report should show the target accepted hostile data from https://attacker.example.
If the handler expects a string, try JSON, then a stringified HTML blob, then prototype-looking keys. Some code does data.action === "navigate" and assigns data.url to location—that is XSS-adjacent phishing with origin trust confusion.
Wildcards in the send direction
Sending with * leaks the payload to any embedder that wins the race. For secrets—tokens, PII, postMessage-based auth handshakes—that is a separate finding from XSS. Show a malicious parent capturing the message. Keep secrets out of * sends; name the intended origin.
Sandboxed iframes with allow-scripts but without allow-same-origin still complicate theft; your PoC should match how the product actually embeds widgets. If the target only listens while a checkout iframe is open, say how long the window stays vulnerable.
Reporting that survives review
Include the listener location (file + line or pretty-printed snippet), the exact message shape, and a parent page PoC. Clarify whether the victim must visit an attacker page that iframes the target, or whether an open redirect into a named window is enough.
Call out weak origin checks such as event.origin.endsWith("example.com") or substring matches on event.origin. Those fail against lookalike hosts more often than teams expect, and they are easy for triage to verify.
Recommend allowlisting origins, validating message schemas, using event.source.postMessage(..., event.origin) for replies, and avoiding HTML sinks for message data. Removing one console.log is not a fix. Checking event.origin against https://target.example is.