Fix guide · high · postmessage_wildcard_target
window.postMessage() called with target origin '*'
Code in your bundle calls postMessage(data, '*'). The wildcard target means the browser will deliver the message to whatever origin currently owns the receiving window — including attacker-controlled origins if the receiver navigated away mid-flow.
Why it matters
postMessage's second argument is the *target origin* — the browser uses it to decide whether to deliver the message. Passing '*' means "deliver to whoever owns this window right now, regardless of origin."
The common scenario that turns this into a real bug:
- Your page opens a popup or iframe to start a flow (OAuth, payment, SSO).
- The flow finishes; the child window calls
window.opener.postMessage(authResult, '*')to hand the result back. - Between steps 1 and 2, the child window navigated somewhere else — to an attacker's site (via open-redirect chain), or to a buggy intermediate page that ended up under attacker control, or to a slow-loading provider page where the user got bored and typed a new URL.
- The message is delivered to the new origin. The attacker harvests the auth token, payment confirmation, or session ID.
Because '*' accepts any receiver, the bug surface includes any code-path that lets an attacker influence which document loads in the target window. Even seemingly-innocent navigation patterns (Sign in → email confirmation → back to app) can introduce a window where the wrong origin owns the receiving frame.
Real-world precedent: the 2017 Facebook OAuth issue, multiple disclosed wallet/extension bugs in 2021–2024, and most of the "OAuth flow harvested my token" disclosure pattern reduce to wildcard-target postMessage calls in the popup-completion handler.
How to fix it
Replace '*' with the specific expected origin string.
// BAD
window.opener.postMessage(authResult, '*');
// GOOD
window.opener.postMessage(authResult, 'https://app.example.com');
If you don't know the exact origin at message-send time, you have a deeper structural problem — your flow shouldn't be sending tokens to unknown origins.
For popup-based OAuth flows specifically:
- The opener page should pass its origin to the popup via the URL:
/auth/start?return_origin=${encodeURIComponent(window.location.origin)}. - The popup's completion handler validates that the returned origin is on an allowlist (NEVER just trusts the parameter).
- The popup posts back with the validated specific origin:
window.opener.postMessage(authResult, validatedOrigin).
On the receiver side, ALWAYS check event.origin (see /fix/postmessage_listener_no_origin_check). Receiver-side validation is the defense-in-depth check that catches even sender-side bugs.
Did vibecheck flag this on your app?
If you reached this page from a vibecheck inspection report, the redacted match in your scan output is the exact string we found in your bundle. After applying the fix above, run the inspection again — the finding should clear.
Run another inspection