Build1 publisher2 min readPublished
An ad-blocking Twitch extension appends 30,000 users' account tokens to a proxy URL
Socket's threat researchers found that Twitch Enhanced Viewer sends each viewer's account-scoped OAuth token to a Russian bot vendor's proxies as a query parameter, on a redirect the extension's own code shows works without it.
The Engineer · Build desk

What happened
- Socket's Threat Research Team found a browser extension, Twitch Enhanced Viewer | JeetBot, forwarding each user's live Twitch OAuth session token to proxy servers operated by a Russian commercial bot service.
- Current v85.x builds append the token as an &auth= query parameter on a network-layer redirect that sends Twitch's video-playlist request to the operator's proxy.
- The operator runs a commercial bot service for Twitch, Kick and VK-Live, holds broad Twitch host permissions and relays live authenticated sessions through its own infrastructure.
Compiled by The EngineerSomething wrong?How this is made
Why it matters
- exposure The credential leaving the browser reaches chat, whispers and account settings, so anyone reading the proxy logs holds a working session for that Twitch account without needing an exploit.
- constraint Putting the token in a query string spreads it to every component that logs URLs along the path, which is a wider set of custodians than an operator database would be.
- decision Fleet owners now have a concrete test for extensions that proxy first-party traffic: whether the proxied URL carries a credential the vendor's own strip path proves is optional.
- precedent A working feature set that genuinely requires proxying the app's own requests gives future extensions a permission profile in which credential forwarding looks like normal operation.
The extension does not need the token to fetch the video, and its own code says so. In `src/scripts/background.js` the auth parameter is built conditionally, `!shouldStripToken && authToken ? "&auth=..." : ""` [18]. There is a second default proxy for the strip case, `DEFAULT_FORCED_TOKEN_STRIP_PROXY_URL`, pointing at proxy[.]morphilina[.]me [17]. Socket reports that this path routes some channels through the proxy with no token at all, so appending the full account credential exposes more than fetching the playlist requires [16].
The value comes off the page. The content script reads the `Authorization` header that Twitch's own web client uses and relays it, with the GQL device id, over the extension's internal bridge as a `tev-proxy-session` message [11]. The background worker stores it and strips the prefix to recover the raw token [12]. Socket's identification rests on what the extension then does with that value: it sends it as `Authorization: OAuth ${token}` to Twitch's token-validation endpoint [13]. Socket says that is the account-scoped token, and it grants access to chat, whispers and account settings [14]. The playback token is a separate value, carried in the usher URL as `token` and `sig` [15].
Query strings get logged, and because the credential is in the URL, Socket notes it is written in cleartext into the proxy server's request logs [19]. On Firefox the rewrite happens in a blocking `webRequest.onBeforeRequest` listener [20]. The extension assembles the URL carrying the token at the network layer [22].
The forwarding is deliberate. Ten Russian streamer channels sit on a hardcoded allowlist and their sessions are exempted from forwarding [6].
Both listings were live when Socket published, with 30,000 users on the Chrome Web Store and 552 on Firefox Add-ons, a combined 30,552 installs [4][2][3][21]. The advertised features are real ones: ad blocking, forced 1080p, region unlock, channel-point collection, and Socket calls that value proposition the cover for the token forwarding [9]. Delivering ad-free and region-unlocked video is why the extension redirects Twitch's playlist requests through operator proxies in the first place [10]. Socket's writeup does not say what either store's review examined [23].
Blocking by publisher name is weak here, because the same functionality ships under two store identities [2][3]. And the exfiltration path has changed across versions: earlier v4.x builds, version 4.8 from January 2026 among them, POSTed the token to a dedicated set-token endpoint on the operator host with backups on deno.dev and deno.net [7]. A detection that only watches for tokens in query strings would have missed that build.
What to watch
- Whether either store delists the extension, or the operator ships a build that drops the &auth= parameter.
- Whether Twitch invalidates sessions observed at enhanced.jeetbot.cc and proxy.morphilina.me, or narrows what the account token can reach.
- How the Chrome build performs the same redirect, since that determines what a static review of the package can see.