Engineering Journal
Schema Editor
Schema Editor

The postMessage '*' Vulnerability Is Not an Advanced Security Topic. Every Codebase That Uses postMessage Has It.

2026-06-04

TLDR

Every team building webviews, iframes, and extension-hosted tools ships postMessage('*') at some point because every tutorial uses it. The fix is one character. The fact that this vulnerability is common enough to have its own OWASP entry is a documentation problem, not an engineering problem.


What the Industry Does

Search "postMessage tutorial" and the first page of results contains multiple examples of postMessage(data, '') used without qualification. MDN's documentation on postMessage explains what '' means (deliver to any origin) but does not prominently warn about the security implication in the syntax examples.

Stack Overflow answers recommending '*' for "when you don't know the parent's origin" have hundreds of upvotes. The answer is technically correct and practically wrong.

The result: most production codebases that use postMessage for cross-frame communication have at least one '*' call. OWASP lists it under A07:2021 Security Misconfiguration as one of the most common cross-document messaging vulnerabilities.

Why It Fails for This Problem Class

The '*' origin is not a failing-safe default. It is a disabling-safe default. It disables the browser's same-origin enforcement for your message, making your communication visible to any embedding page.

For VS Code extensions and Electron apps, the practical attack surface is constrained because the embedding context is controlled. But "the attack surface is constrained in our use case" is a situational argument, not a correctness argument. The code is wrong. It happens not to matter in this context. It will matter in the next context where someone reuses the pattern.

The deeper problem: '' as a default normalizes the unsafe pattern. Every developer who writes their second postMessage call copies the '' from the first one. The vulnerability propagates through copy-paste before anyone questions it.

The Better Approach

window.location.origin is the correct default for any postMessage call where the parent is on the same origin. It is not harder to type than '*'. It is more explicit (it names the intended audience) and more correct (it enforces the same-origin policy the developer almost certainly intended).

For the cases where the parent is on a different origin: specify the exact target origin string. Never use '*' as a fallback for "I don't know the parent's origin." Not knowing the parent's origin means the communication design needs more thought, not less origin checking.

The fix for any codebase is three minutes of work:

# Find all instances
grep -rn "postMessage(" src/ | grep "'\*'"

Replace each with window.location.origin

What You Give Up

window.location.origin breaks postMessage in certain development environments: file:// pages have a null origin, localhost port mismatches cause failures, and some browser extension environments use non-standard origins. These are legitimate development friction points.

The solution is explicit environment configuration (a dev-only override for the target origin), not defaulting back to '*'. The production code should always use a specific origin.

When the Common Pattern Is Right

Use '*' when: you are writing a tutorial and simplicity is more important than security modeling, the message contains no user data and the message type itself reveals nothing sensitive, or you are explicitly building a broadcast mechanism where any receiver is intended. None of these apply to most production postMessage usage.

Read this post in the full Engineering Journal →