postMessage XSS: How to Find Cross-Window Script Bugs
window.postMessage lets pages talk across origins. When a listener trusts the message without verifying event.origin — or uses the data in a sink like innerHTML — an attacker origin can inject script or steal data.
These bugs hide in OAuth popups, embedded widgets, mobile WebViews, and “universal” helper frames.
What to search for
In JavaScript:
addEventListener("message", ...)window.onmessage- Missing
event.origin === "https://trusted.example"checks event.dataflowing intoinnerHTML,eval, jQuery HTML, or navigation
Also note senders that use targetOrigin: "*" — it broadens who can receive sensitive payloads.
Safe proof workflow
- Find a listener on the target origin.
- From an origin you control,
postMessagea crafted payload to the target window/iframe. - If the target executes script or returns sensitive data to you, capture that with your own account context.
- Always verify origin filtering — try a wrong origin to show the check is absent.
Do not phish real users. Host the PoC yourself and demonstrate in your browsers.
Impact
- DOM XSS in the target origin
- Token or PII leakage to the attacker origin
- UI redress / state change in a privileged window
Report structure
Include the listener code path, the missing origin check, your sender origin, and the sink. Suggest allowlisting origins and validating message schema before use.
Defensive checklist
- Check
event.originagainst an allowlist on every handler. - Validate message shape with a schema.
- Never pass
event.datato HTML sinks without encoding. - Prefer
targetOriginset to an exact origin, never*for sensitive data. - Add regression tests that send cross-origin messages in CI.
postMessage bugs are DOM XSS with an origin twist. Find the listener, fail the origin check, then watch the sink.
Original Bugflare guide informed by PortSwigger web message / DOM XSS material.