# `socket` command allows sending data over WebSockets to arbitrary origins from Grammarly Extension

Grammarly extension's socket command let any page open WebSockets from the extension origin, sending credentialed data to arbitrary or Grammarly WS endpoints.

- Payout: hidden
- Severity: high
- Program: Superhuman (formerly Grammarly)
- Found by: metnew
- Disclosed: 2019-07-15
- Write-up quality: 7/10
- Original: https://hackerone.com/reports/395729
- Library page: https://bugbountylibrary.com/r/h1%3A395729
- Tags: area:os domain:browser impact:integrity impact:internal-access kind:bounty platform:hackerone sev:high tech:websocket technique:chained technique:source-review vuln:access-control vuln:csrf

**Target:** Browser extension background page / content script message bridge
**Root cause:** The content script forwards attacker-controlled `socket` actions from `window.postMessage` to the background page, which creates a BackgroundSocket with an attacker-supplied URL and connects without validating the requesting origin.
**Steps:**
1. Craft a page that posts a message with `action:"socket"`, a `socketId`, `method:"connect"`, and `arg.url` set to the target WS endpoint.
2. Content script handler `Z` sees `"socket" === n` and calls `p.emitBackground(b.MessageTypes.client, e)`.
3. Background `_onContentScriptSocketMessage` creates `new d.BackgroundSocket(e,...)` and calls `a.connect(e.arg)`, which does `new u(e.url)` with the attacker URL.
4. Send a second message with `method:"send"` and `arg` payload to transmit data over the established socket.
5. Observe server logs: 'Connection received' and 'Message event {"grammarly":"1"}'.
**How found:** Reading the extension's message-passing code, the researcher noticed the content script forwards any `socket` action from `window.postMessage` to the background page, then traced `connect` to `new u(e.url)` with no origin check, and reasoned that WebSockets bypass CORS so the extension origin would be trusted by Grammarly's WS servers.
**Exploitation:** Any web page visited by a Grammarly user can drive the extension background page to open a WebSocket to an arbitrary URL using the extension's origin and cookies, then send arbitrary data. Because Grammarly's own WS endpoints (capi.grammarly.com, dox.grammarly.com) trust the extension origin, the attacker can send credentialed requests to them, e.g. editing documents via `wss://dox.grammarly.com/documents/<document_id>/ws`. Responses from an attacker-controlled WS server are also parsed and re-emitted into the content script as commands.
**Escalation:** Chaining arbitrary WS connect with Grammarly's origin-trusting endpoints turns a generic SSRF-like primitive into authenticated document editing; server-supplied commands are also handled by background/content script, potentially triggering unintended business logic.
**Insight:** When auditing browser extensions, trace postMessage handlers that forward actions to the privileged background page; any `connect`/`fetch`/`send` primitive taking a URL becomes a cross-origin request forgery from the extension origin, which first-party WebSocket APIs often trust without Origin validation.

