Get the FREE Ultimate OpenClaw Setup Guide →

Postmessage Xss

npx machina-cli add skill allsmog/vuln-scout/postmessage-xss --openclaw
Files (1)
SKILL.md
3.5 KB

DOM XSS via postMessage

This skill covers detecting and exploiting Cross-Origin Messaging (postMessage) vulnerabilities that lead to DOM-based XSS.


Overview

postMessage is a browser API that allows cross-origin communication between windows/iframes. When message handlers don't validate event.origin, any website can send malicious data that may execute as XSS.

Why This Is Critical:

  • Often overlooked by security scanners (server-focused)
  • Enables XSS from any origin without user interaction
  • Commonly chained with SSRF/bot scenarios to bypass localhost restrictions

Vulnerability Pattern

Vulnerable Code

A handler that accepts messages from ANY origin and writes to DOM:

window.addEventListener("message", (event) => {
    const data = event.data;
    document.getElementById("output")[".inner" + "HTML"] = data.html;  // XSS!
});

Secure Code

window.addEventListener("message", (event) => {
    if (event.origin !== "https://trusted-domain.com") {
        return; // Reject untrusted origins
    }
    document.getElementById("output").textContent = data.text; // Safe
});

Detection Patterns

Step 1: Find Message Handlers

# Find all postMessage event listeners
grep -rniE "addEventListener\s*\(\s*['\"]message['\"]" --include="*.js" --include="*.ts" --include="*.html"

# Find direct onmessage assignments
grep -rniE "\.onmessage\s*=" --include="*.js" --include="*.ts"

Step 2: Check for Missing Origin Validation

# Find handlers and check next 10 lines for origin check
grep -rniE "addEventListener\s*\(\s*['\"]message['\"]" --include="*.js" --include="*.ts" -A 10 | grep -v "origin"

Step 3: Trace to Dangerous Sinks

# event.data to DOM write sinks
grep -rniE "event\.data.*(inner|outer)HTML" --include="*.js" --include="*.ts"

# event.data to location (open redirect)
grep -rniE "event\.data.*location|location.*event\.data" --include="*.js" --include="*.ts"

# event.data assigned to variable (trace further)
grep -rniE "=\s*event\.data" --include="*.js" --include="*.ts"

Common Vulnerable Patterns

PatternRiskDetection
No origin check + DOM sinkCriticalMissing event.origin validation
Weak origin check (regex)Highorigin.includes() or origin.match()
Variable assignment then sinkHighconst data = event.data then later to sink
jQuery .html() methodCritical$(elem).html(event.data)

Exploitation via SSRF + iframe

When combined with SSRF (bot visits attacker URL):

  1. Bot visits attacker page
  2. Attacker page creates iframe to http://localhost:1337/
  3. postMessage sends XSS payload to iframe
  4. XSS executes in localhost context (bypasses network restrictions)

This chain bypasses Chrome's Private Network Access restrictions.


Remediation

1. Always Validate Origin

const ALLOWED_ORIGINS = ["https://trusted.com"];

window.addEventListener("message", (event) => {
    if (!ALLOWED_ORIGINS.includes(event.origin)) {
        return; // Reject
    }
    // Process message safely...
});

2. Use Safe Sinks

  • Use textContent instead of HTML sinks
  • Use DOMPurify to sanitize HTML content
  • Validate message structure before processing

3. Add Frame Protection

X-Frame-Options: SAMEORIGIN
Content-Security-Policy: frame-ancestors 'self'

References

  • OWASP: DOM-based XSS
  • CWE-79: Improper Neutralization of Input
  • PortSwigger: DOM-based XSS via postMessage

Source

git clone https://github.com/allsmog/vuln-scout/blob/main/whitebox-pentest/skills/postmessage-xss/SKILL.mdView on GitHub

Overview

This skill covers detecting and exploiting Cross-Origin Messaging (postMessage) vulnerabilities that lead to DOM-based XSS. It explains how handlers that don’t validate event.origin can be abused to inject malicious data into the DOM from any origin, enabling XSS without user interaction.

How This Skill Works

postMessage enables cross-origin communication between windows and iframes. If a message handler accepts event.data from any origin and writes it directly to DOM sinks (for example via innerHTML), an attacker can inject and execute malicious HTML. Secure handling requires validating event.origin against a whitelist and using safe sinks such as textContent or HTML sanitization before insertion.

When to Use It

  • Auditing web apps that embed third-party widgets or iframes and rely on postMessage
  • Testing for XSS when messages may originate from untrusted sources
  • Reviewing code paths that use insecure origin checks (e.g., weak or regex-based checks)
  • Investigating SSRF/bot chains that leverage postMessage to reach localhost or internal frames
  • During secure code reviews for cross-origin messaging implementations

Quick Start

  1. Step 1: Find all postMessage listeners (addEventListener('message') and onmessage handlers)
  2. Step 2: Check for origin validation; flag missing or weak checks and dangerous sinks (innerHTML, location)
  3. Step 3: Replace with safe patterns (validate origin, use textContent or sanitize HTML) and add frame protections

Best Practices

  • Validate event.origin against an explicit whitelist on every message
  • Use safe DOM insertion: prefer textContent over innerHTML, or sanitize HTML with DOMPurify
  • Validate the message structure and type before processing (not just data length)
  • Avoid assigning event.data directly to DOM sinks; implement strict processing routines
  • Apply frame protections and origin enforcement: X-Frame-Options and frame-ancestors CSP; restrict origins and targets

Example Use Cases

  • Handler accepts any origin and writes data.html to innerHTML (XSS risk)
  • Weak origin check implemented with origin.includes() bypassed by crafted origins
  • event.data directly assigned to DOM (innerHTML or outerHTML) without sanitization
  • Using jQuery .html(event.data) as a sink for untrusted data
  • SSRF/bot-driven iframe chain reaching localhost, using postMessage to inject XSS payload

Frequently Asked Questions

Add this skill to your agents
Sponsor this space

Reach thousands of developers