[PSA/Security] Backdoor found in SillyTavern-BotBrowser extension (mia13165) — steals ALL your API keys

update

some people say you need to clear your browser cache, so go ahead. But for me, everything disappeared after deleting the extension. I honestly don't understand how no one has look into DevTools since November and seen anything suspicious... well, shit happens... Btw, he deleted gm92342 account. my bad

TL;DR

The third-party extension mia13165/SillyTavern-BotBrowser contains a multi-stage trojan that silently steals all your LLM API keys (OpenAI, Claude, Gemini, NovelAI, OpenRouter, DeepSeek, and all other providers in ST), proxy passwords, connection profiles, server URLs, and reverse proxy credentials. If you have this extension installed, remove it immediately and revoke all your API keys.

Your chats and character cards are not exfiltrated - only credentials and connection settings.

And sorry for slop text below. You can check everything manually.

What does it steal?

  • All API keys: OpenAI, Claude/Anthropic, Google/Gemini, NovelAI, DreamGen, Featherless, DeepSeek, OpenRouter, xAI/Grok, AIML API, Hugging Face, Together AI, Moonshot AI, Fireworks AI, Vertex AI, ElectronHub, Azure OpenAI, Oobabooga, Horde, Mistral AI, Groq, Perplexity, NanoGPT, ZAI/GLM, and any custom keys
  • All proxy configurations (name, URL, password)
  • Reverse proxy URLs and passwords
  • Custom OpenAI-compatible endpoint URLs
  • Connection profiles (including resolved API keys from secret-id references)
  • Server URLs and server history (textgenerationwebui, power_user servers)
  • Azure OpenAI settings (base URL, deployment name, API version)
  • Vertex AI settings (auth mode, region, project ID)
  • OAI settings (custom_model, custom_url, proxy_password)
  • Backup secrets - it downloads your ST user backup ZIP, extracts secrets.json, settings.json, and any secrets_migration_*.json backup files
  • If you are admin on a multi-user ST instance: it enumerates ALL users and steals credentials for every single one

What it does not steal: chat logs, character cards, images. Verified this by fully deobfuscating the payload - the only outbound data transfer contains credentials and settings, not chat content.

How it works (full attack chain)

This is a sophisticated 3-stage attack:

Stage 1: HTML injection via poisoned card database

The extension's modules/services/cache.js hardcodes a second attacker repo (mia13165/updated_cards) as a card database. On load, it silently renders a "default avatar" card whose metadata field contains a malicious <img> tag:

<img src="data:image/gif;base64,R0lGODlh..." onload="[obfuscated loader]">

The extension's detailModal.js injects this via innerHTML without any sanitization — classic XSS.

Stage 2: Delayed remote code execution

The onload handler sets a sessionStorage timer and waits 15–25 minutes (random) before fetching and eval-ing a remote script from https://raw.githubusercontent.com/gm92342/sdhiabfkgcnf/main/run.js.

The delay is deliberate - by the time the payload activates, you've long closed any "new extension" tabs and aren't watching DevTools.

Stage 3: Lua VM credential harvester

run.js loads fengari-web (a Lua 5.3 VM for browsers) and executes a heavily obfuscated Lua script from a GitHub gist (gm92342/deddbd095a67a28da4b4b7b65533561f).

The Lua payload:

  1. Checks sessionStorage['session-2389432'] — only runs once per browser session
  2. Checks /api/secrets/settings for allowKeysExposure — if false, aborts (can't read keys). Old ST versions (404) are attacked regardless.
  3. If current user is admin, fetches /api/users/list and processes every user
  4. For each user: calls /api/users/backup to download the full backup ZIP into browser memory, then uses JSZip (loaded from CDN) to extract only secrets.json, settings.json, and backup migration files
  5. Collects API keys, proxies, endpoints, connection profiles, server URLs from both live settings and backup files
  6. Encrypts everything with a trivial cipher (key: st-anchor-2025, Vigenere-like addition mod 256)
  7. POSTs the encrypted JSON payload to an ephemeral C2 server at *.srv.us (SSH tunnel service)

The obfuscation uses a custom string decoder (T(v, f)) with a seeded LCG PRNG — every string in the Lua code (822 total) is encoded.

The Lua also uses 7 different methods to call Promise .then() (direct bracket notation, Function.prototype.call, Reflect.apply, .bind(), etc.), cycling through them to evade anti-hooking detection by other extensions or security tools.

IOCs (Indicators of Compromise)

Check these to see if you were affected:

  • sessionStorage key: session-2389432 (on your ST origin, e.g. 127.0.0.1:8000)
  • Extension folder: data/default-user/extensions/third-party/SillyTavern-BotBrowser/
  • Settings file: check data/default-user/settings.json for a BotBrowser section
  • Network: any requests to *.srv.us domains (C2 exfil endpoint)
  • Stage 2 URL: https://raw.githubusercontent.com/gm92342/sdhiabfkgcnf/refs/heads/main/run.js

Attacker GitHub accounts

  • mia13165 (user ID 202182454) — created Nov 2025, owns the trojan extension repo. 125 stars, 13 forks.
  • gm92342 — owns the stage-2 loader repo (sdhiabfkgcnf) and the Lua payload gist.
  • Second attacker data repo: mia13165/updated_cards — contains the poisoned card JSON.

What to do if you had this extension installed

  1. Delete the extension folder immediately
  2. Revoke ALL API keys for every provider you had configured in ST — they are compromised
  3. Change all proxy passwords if you used any reverse proxies
  4. Remove the BotBrowser section from data/default-user/settings.json — this is not necessary.
Edit

Pub: 28 Apr 2026 12:24 UTC

Edit: 28 Apr 2026 16:11 UTC

Views: 8244