postMessage Receiver Without Origin Validation
A cross-document message listener trusts event.data without checking event.origin, so any page that can get a handle on the window can post into it. If the data reaches a DOM sink, it becomes DOM XSS or an open-navigation primitive.
What Vulkro detects
POSTMSG-001 (Medium) fires on a window.addEventListener('message', ...) or window.onmessage = ... handler whose body does no origin validation. Confidence rises to High when the body also writes the data into a DOM sink. Severity stays Medium because the trusted origin is application-specific and this is a shape heuristic, not a taint proof.
- Receiver side only; a send-side
postMessage(data, '*')is covered by other detectors. - Only JS/TS-family files (
.js,.jsx,.ts,.tsx,.mjs,.cjs,.vue,.svelte) that contain amessagelistener are parsed. - Inline handlers that reference an
origincomparison are skipped. Named-function and single-expression handlers are flagged only when the whole file has no origin validation.
Non-compliant code
window.addEventListener('message', (event) => {
document.getElementById('panel').innerHTML = event.data.html; // any origin can post
});
Compliant code
const TRUSTED_ORIGIN = 'https://widget.example.com';
window.addEventListener('message', (event) => {
if (event.origin !== TRUSTED_ORIGIN) return;
if (typeof event.data?.text !== 'string') return;
document.getElementById('panel').textContent = event.data.text;
});
How to fix
- Compare
event.originwith an exact expected origin before touchingevent.data, and return early on a mismatch. - Validate the payload shape too.
- Keep the origin allowlist in a constant, not a wildcard-built regular expression.
References
See also: Confidence model.
This page is generated by vulkro rules export <out-dir> from Vulkro's built-in detector catalogue. Edits made by hand are overwritten on the next regeneration.