Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
41 changes: 41 additions & 0 deletions cheatsheets/Browser_Extension_Vulnerabilities_Cheat_Sheet.md
Original file line number Diff line number Diff line change
Expand Up @@ -285,6 +285,47 @@ Please note that it's not recommended to try to get native (not-overwritten) pro

Also, please don't assume your extension's script can use native prototypes even if it's executed at `document_start` timing. At least, in the case of Chromium browser extension, it's known that the context of a newly created iframe can be tweaked by a web page's script BEFORE the extension's script starts in the iframe event at `document_start` ([official bug issue](https://issues.chromium.org/issues/40202434)).

## 13. Insecure Message Passing

### Vulnerability: Insecure Message Passing

Browser extensions often rely on message passing (`chrome.runtime.sendMessage/onMessage`) between low-privilege contexts (Content Scripts, Popup) and the high-privilege Service Worker (Background). If the Service Worker fails to validate the sender's origin or URL, a compromised webpage can send malicious messages, tricking the extension into performing privileged actions (e.g., retrieving sensitive data or API keys).

### Example: Insecure Message Passing

```javascript
// In Service Worker (Background)
chrome.runtime.onMessage.addListener((request, sender, sendResponse) => {
if (request.action === 'fetchSecret') { // No validation of sender
// A malicious content script/webpage could trigger this.
fetch(SECRET_API_URL);
}
});
```

### Mitigation: Insecure Message Passing

Treat all incoming messages as untrusted input.
In Service Workers, always:

- Validate `sender.id` to ensure the message originates from your own extension.
- Validate `sender.url` or `sender.origin` to restrict which extension pages or content scripts may communicate.
- Avoid allowing webpages to indirectly influence privileged logic through content scripts.
- Perform strict validation and allow-listing of `request.action` and all request parameters.

Chrome explicitly states that content scripts are less trustworthy than extension pages and must be treated accordingly. Secure example:

```javascript
chrome.runtime.onMessage.addListener((request, sender, sendResponse) => {
if (sender.id !== chrome.runtime.id) return;
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should this id be the extension's id?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes. sender.id is the ID of the extension that sent the message.
Comparing it to chrome.runtime.id ensures the message originated from this same extension.

if (!sender.url?.startsWith('chrome-extension://')) return;
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Once we're checking if it comes from an extension, why not also check the extension ID, like if (!sender.url?.startsWith('chrome-extension://<my-extension-id>'))

Copy link
Contributor Author

@KadirArslan KadirArslan Dec 10, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

sender.id already uniquely identifies the extension; checking the ID again in the URL would be redundant. URL validation can still be used optionally to restrict specific extension contexts.


if (request.action === 'fetchSecret') {
fetch(SECRET_API_URL);
}
});
```

## Conclusion

By following these security best practices, developers can build safer browser extensions and protect users from privacy and security threats. Always prioritize least privilege, encryption, and secure coding principles when developing extensions.
Expand Down