CWE-346 (Origin Validation Error) describes exactly this failure: a message listener that does not check sender.id will execute privileged extension logic when called by any other extension or web page that can reach the runtime. If externally_connectable is open, a malicious website can send crafted messages to trigger background actions — deleting data, making API calls, or exfiltrating stored tokens. CWE-20 (Improper Input Validation) compounds this when the message payload itself is trusted without validation. OWASP A01 (Broken Access Control) applies: the background script is a privileged context and its listeners are the access-control boundary.
High because an unvalidated message listener in the background script can be triggered by any extension or external web page, turning privileged background logic into a remotely callable attack surface.
Check sender.id against chrome.runtime.id in every onMessage and onConnect handler in your background script before processing the payload.
// src/background.js
chrome.runtime.onMessage.addListener((message, sender, sendResponse) => {
if (sender.id !== chrome.runtime.id) return; // reject foreign senders
// safe to process message
});
For pages listed in externally_connectable, additionally validate sender.url against an allowlist of your own domains.
ID: extension-permissions-security.permission-scope-validation.message-sender-validation
Severity: high
What to look for: Enumerate all chrome.runtime.onMessage.addListener and onConnect handlers in background scripts and content scripts. For each listener, quote the sender validation logic found (e.g., sender.id check). Count how many listeners validate the sender vs total listeners.
Pass criteria: At least 100% of message listeners check sender.id (to ensure it comes from your own extension) or sender.url (if expecting messages from specific pages) before processing the message. Every listener validates the sender before performing any action.
Fail criteria: Messages are processed blindly without verifying the sender, especially if externally_connectable is used or if message handling performs sensitive actions. Must not pass when only some listeners validate while others do not.
Skip (N/A) when: No message passing is used.
Detail on fail: "runtime.onMessage listener does not verify 'sender.id' or 'sender.url' before processing payload."
Remediation: Always verify where a message came from in your background script to prevent other extensions or compromised web pages from triggering your background logic.
// src/background.js
chrome.runtime.onMessage.addListener((message, sender, sendResponse) => {
if (sender.id !== chrome.runtime.id) return;
// ... process message
});
Cross-reference: For external connection restrictions, see the externally-connectable-restricted check in the Host Permissions Minimization category.