Home / Knowledge hub / postMessage security
Knowledge hub
postMessage security
Checking who sent a message between windows before you act on its contents.
What it means
The postMessage method lets one browser window, tab or frame send a message to another, even across different origins. It is how embedded widgets, payment pop-ups and sign-in windows talk to the page that opened them.
The browser delivers the message, but it does not decide whether to trust it. The receiving code must check where the message came from and treat its contents as untrusted input, however friendly the sender looks.
Why it matters
A handler that trusts any message lets any page that can reach the window send commands. Depending on what the handler does, that can mean changed settings, a stolen token, a forged payment result, or script running in your page.
The flaw hides well. Nothing looks wrong in normal use, because normal senders behave. It tends to surface in an assessment of a widget or sign-in flow, or after someone finds that a single missing check opened the page to outside control.
How it shows up
You see it in single sign-in pop-ups, payment frames, chat widgets, embedded editors and any page that is framed by another. On the receiving side, look for message event listeners. On the sending side, look at the target origin argument.
The mistakes repeat. The handler never checks event.origin, or checks it with a loose match such as a substring. The sender uses a wildcard target for sensitive data. The message is passed straight into innerHTML, eval or a URL. Check the origin exactly, and validate the data like any other input.
Questions people ask
postMessage security, answered
How do I check the sender of a message?
Compare event.origin with an exact, expected origin string before doing anything. Reject everything else. Do not use a substring or a regular expression that can be satisfied by an attacker's domain.
Checking event.source can add a second confirmation that the message came from the window you expect.
Is a wildcard target origin always bad?
It is risky when the message contains anything private. A wildcard lets whichever page currently sits in that window receive the message, even if it was navigated elsewhere.
Name the exact origin you intend to send to.
Is it the same as cross-origin resource sharing?
No. CORS governs whether a page may read responses from another origin over HTTP requests. postMessage is a separate channel between windows.
Each needs its own checks.
Can postMessage lead to XSS?
Yes. If a handler writes message data into the page without encoding, a sender can inject script. This is a form of DOM-based XSS where the source is the message rather than the URL.
Use textContent or safe templating, not innerHTML.
How do we test for it?
Search the code for message listeners, then try sending messages from a page on another origin and see what the handler accepts. Look for state changes, data returned and anything written into the page.
Testing the running app plus reading the handler code finds more than either alone.
Sources
Where this comes from
Related
Terms that sit next to this one
DOM-based XSS
Script injection that happens in the browser's own code, not in the server's response.
Same-origin policy
The browser rule that stops one site's scripts reading another site's data.
CORS
The browser rule for which sites may read responses from your API.
Untrusted input
Anything that arrived from outside your own code, and is therefore suspect.
Input validation
Checking that what arrives is the shape and range you expected.
Does the handler check the sender?
In white-box mode we read your code while testing the running app, so a missing origin check can be shown with the file and line. We only report what we exploited. Book a pilot on one app.
Or start with a $199 pilot on one application: thirty days, success criteria agreed before day one, credited against the annual if you convert.