postMessage Origin Checking
postMessage crosses frame boundaries with an explicit target origin and a sender identity that must be verified on receive, or any embedding page can inject commands into your widget.
Definition
postMessage is the cross-window messaging channel between frames, workers, and popups. The sender must specify a targetOrigin so secrets are not delivered to a hostile embedder, and the receiver must check event.origin against an allowlist before trusting message content. Omitting either check is a common and exploitable bug.
Context and scope
Every iframe integration: payment widgets, embedded players, SSO flows, cross-window callbacks from popups, and the internal messaging of embedded SDKs.
Common misconceptions
- Browsers validate the sender for you — event.origin is attacker-controlled input that you must verify yourself
- Wildcard targetOrigin is just permissive — it leaks message content to whatever page happens to embed the frame
- Same-looking origins are the same origin — scheme, host, and exact port must all match the allowlist entry
Anti-patterns
- Sending tokens with targetOrigin set to the wildcard and trusting luck for delivery
- Accepting messages after checking anything other than a strict, exact-match origin allowlist
- Parsing message payloads with implicit structure assumptions and crashing or misbehaving on hostile input
Related concepts
Related examples
Authoritative source
https://developer.mozilla.org/en-US/docs/Web/API/Window/postMessage
What it is
A frame cannot call into another origin directly, so integrations speak over postMessage. The protocol has two trust decisions: where the sender aims the message, and who the receiver believes. Both are explicit; the browser enforces neither beyond delivery.
How it works
The sender passes targetOrigin; the browser delivers only if the recipient window matches, otherwise the message is dropped. On receipt, event.origin states the true sender origin. Robust handlers compare it exactly against expected origins, then validate the payload shape and a channel nonce before acting.
When to use it
Widget embeds, popup OAuth callback relays, and any cross-origin coordination. Define the message schema as a discriminated union, version it, and reject unknown types loudly to surface version skew between embedder and embed.
Pitfalls
Origins with trailing paths or wildcard subdomains in the allowlist silently never match. Message races between multiple embedders require channel identifiers. Secrets in messages should still be scoped and short-lived, since a compromised embedder within your allowlist is inside the trust boundary you drew.