Too Broad Message Posting
ID |
javascript.too_broad_message_posting |
Severity |
high |
Resource |
Information Leak |
Language |
JavaScript |
Tags |
CWE:346, CWE:940, NIST.SP.800-53, OWASP:2021:A4, PCI-DSS:6.5.3 |
Description
HTML5 provides the functionality of post cross-document messages (Web Messaging), allowing message posting between windows. window.postMessage()
safely enables cross-origin communication between Window objects; e.g., between a page and a pop-up that it spawned, or between a page and an iframe embedded within it.
This targetWindow.postMessage(msg, targetOrigin)
method can lift the same-origin restriction, by providing a way to securely pass messages across domains, with an option to specify the allowed origin for the target.
Always provide a specific targetOrigin, not '*', if you know where the other window’s document should be located. Failing to provide a specific target could disclose data to a malicious site. |
This detector registers a vulnerability when the target origin is overly permissive (using '*' for the targetOrigin) in a postMessage()
call, or when the origin is not checked in the event handler registered by the addEventListener()
on the target window.
Rationale
Normally, scripts on different pages are allowed to access each other if and only if the pages that executed them came from same origins (protocol, host and port).
The Window.postMessage()
method safely enables cross-origin communication, and provides a controlled mechanism to send data cross-origin, in a secure way when properly used.
For sending messages, syntax is: otherWindow.postMessage(message, targetOrigin, [transfer])
, where otherWindow
is the window that will receive the message, and targetOrigin
may contain the URL of the window that the message is being sent to, or either "*" (any domain, no restriction) or "/" (same domain as sender).
The receiver then registers a message
event handler, where the sender origin could be checked using the MessageEvent.origin
property. The MessageEvent.source
contains the sender’s window, for two-way communications. The message itself is provided in the MessageEvent.data
property (and should be considered by the receiver as untrusted input, unless the origin is checked and it is trusted). It is important to check the origin to ensure the message is intended for the intended receiver.
An overly permissive target origin can provide a malicious script to communicate with the window in an inappropriate way. Attackers can:
-
Intercept sensitive data: If postMessage() is used to send authentication tokens, user data, or API keys, an attacker-controlled site in an iframe could read and steal this information.
-
Trigger actions in the receiving context: If the receiving window executes actions based on the received messages, an attacker could perform unauthorized transactions, change security settings, or exfiltrate user data.
On the sender side, any target origin is allowed, which means that the message can be sent to an iframe on a different domain.
var o = window.frames[0];
// Vulnerable - too broad origin.
o.contentWindow.postMessage(message, '*');
On the receiver side, the message event handler should check the origin:
const TRUSTED_ORIGIN = 'https://trusted.com';
// Vulnerable - not checking the event origin
window.addEventListener('message', function(event) {
// ... process the message
})
Remediation
To address this vulnerability:
-
On the sender side, never use a wildcard origin ('*') with postMessage. Specify the exact target origin you intend to communicate with.
var o = window.frames[0];
// Vulnerable - too broad origin.
o.contentWindow.postMessage(message, 'https://trusted.com');
-
On the receiver side, always check the
event.origin
in your message event handler to ensure the data is coming from a trusted source.
const TRUSTED_ORIGIN = 'https://trusted.com';
window.addEventListener('message', function(event) {
if (event.origin !== TRUSTED_ORIGIN) {
// Reject messages from unknown sources
console.warn('Message from untrusted source:', event.origin);
return;
}
// ... process the message
})
There are more secure and structured alternatives to the native cross-origin message API, such as Postmate or Comlink. For messaging across different browser tabs or iframes in the same domain, the built-in BroadcastChannel API can be more convenient.
References
-
CWE-346 : Origin Validation Error.
-
CWE-940 : Improper Verification of Source of a Communication Channel.
-
OWASP - Top 10 2021 Category A04 : Insecure Design.
-
Understanding postMessage for Secure Cross-Origin Communication, post by Diego Caceres.