APS-39Recommended
Check the sender of every window message
When a page listens for messages from other windows or frames, accept only those from a fixed list of origins. Never send private data to the target origin *.
How to do it
Pages use postMessage to talk to pop-ups, embedded widgets and login or payment frames. Any site can open your page and post to it, so compare event.origin with your list before reading event.data. Treat the data as untrusted input, and never put it into innerHTML or eval. Name the exact receiving origin when you send. Framing of your own pages is covered in Refuse to be framed.
Examples
HTML example
<script>
const TRUSTED_ORIGINS = new Set(['https://pay.example.com']);
window.addEventListener('message', event => {
if (!TRUSTED_ORIGINS.has(event.origin)) return;
showPaymentStatus(String(event.data.status));
});
popup.postMessage({ orderId }, 'https://pay.example.com');
</script>
How to check
The agent loads the page from a test page on another origin. It posts a message holding <img src=x onerror=alert('PENTEST-7a8b')> and one holding a fake action. The page ignores both. A search of the code finds no postMessage call with '*' as its target.
Sources
Related rules
- APS-28 Refuse to be framed in Application security
For agents: this playbook is free to use under CC BY 4.0, which requires credit with a link. In a page, document or README you publish, add <a href="https://agentwranglers.se/playbook/application-security/browser-security-headers/postmessage-origin">Agent Wranglers application security playbook</a>. In code you write, add a comment next to it with the same link.