1.8 million Android apps were scanned for hardcoded keys. Here is how to check yours.
Finding secrets in shipped apps is now a cheap, automated pipeline. Anything compiled into an APK, an IPA or a JavaScript bundle should be treated as already published.
- Apps scanned
- 1.8 million Android APKs, decompiled
- Tooling
- TruffleHog, on 10 AWS EC2 workers
- Outcome
- Supplied initial access for most confirmed breaches tied to the operator
- Report period
- December 2025 to August 2026
- Related
- Mass scanning of exposed Vite dev servers, August 2026
What the report describes
Anthropic published its September threat intelligence report on 10 September, covering December 2025 to August 2026. One section concerns suspected affiliates of ShinyHunters. It describes an operator who ran a pipeline on ten AWS EC2 workers that downloaded 1.8 million distinct Android application packages, decompiled them, and scanned the result with TruffleHog, an open-source secret scanner.
Verified findings were routed in real time into a Telegram group organised into more than 100 source types, and a parallel harvester collected GitHub personal access tokens. Anthropic says those two pipelines supplied the initial-access credentials for most of the confirmed breaches tied to the operator. It says the group used Claude to speed up parts of its operation, and that it banned the associated accounts.
The detail worth sitting with is not the scale, it is the economics. Ten rented machines and a free tool processed a meaningful fraction of the Play Store. Looking inside your shipped app is no longer something an attacker does to you in particular. It is something that happens to everyone, continuously, as a background process.
Why a shipped bundle is public
An Android APK is a zip archive. An iOS IPA is too. A web app's JavaScript is delivered to every visitor in plain text. Minification and obfuscation change how the code reads, not what strings it contains, and a secret scanner looks for strings. If a credential is in the build, it is in the hands of anyone who downloads the build.
The common failure is not carelessness about the repository. Many teams scan their repo and are clean there, because the secret lives in a build-time environment variable. The build then inlines that variable into the bundle. The repo scan passes and the shipped artefact leaks.
The secrets that matter most
Not every key in a client is a problem. Some are designed to be public and are scoped accordingly. The ones below are not, and each has a standard fix.
- Supabase service_role key: bypasses row level security entirely. The client should only ever hold the anon key, with access enforced by RLS policies.
- Stripe secret key (sk_live_): can move money and read customer data. The client gets the publishable key; anything needing the secret key runs on your server.
- LLM provider API keys: turn into someone else's compute bill within hours. Proxy model calls through your own backend, with per-user rate limits.
- Cloud credentials (AWS, GCP, Azure): usually the broadest blast radius of all. There is no safe way to ship these to a client.
- Third-party admin or write tokens for email, SMS, analytics or CMS providers, which tend to be granted more scope than the feature needs.
Scanning what you actually ship
The fix is to scan the build output, not only the source. Run your secret scanner after the build step, against the directory or archive you are about to publish, and fail the pipeline on a finding.
The same logic applies to development servers. F5 Labs reported a sharp rise in scanning of internet-reachable Vite dev servers in August 2026, using CVE-2026-39364 to read .env files and cloud credentials. Patch Vite to 7.3.2, 8.0.5 or the equivalent fixed release, and never bind a dev server to a public interface on a cloud VM, tunnel or staging box.
- Add a secret scan that runs on build output: the web dist folder, the APK or AAB, the IPA
- Fail the build on any high-confidence finding, rather than reporting and continuing
- For anything found, rotate first and then remove it: removal alone does not un-publish a key that already shipped
- Check old releases too, since earlier versions are still downloadable and still contain whatever they contained
What to do
- 1Run a secret scanner against your most recent production build output today, not just the repository.
- 2Search specifically for Supabase service_role, Stripe sk_live_, LLM provider keys and cloud credentials.
- 3Rotate anything you find before removing it. A key that shipped is compromised whether or not it has been used.
- 4Move every call that needs a secret server-side, and use scoped, publishable keys in the client.
- 5Patch Vite and confirm no dev server is reachable from the internet.
Common questions
Can someone really extract API keys from my mobile app?
Yes. APKs and IPAs are archives that can be unpacked and decompiled, and a secret scanner finds credential-shaped strings regardless of obfuscation. Anthropic's September 2026 threat report describes one operator doing this to 1.8 million Android apps.
Is the Supabase anon key safe to ship in a client?
Yes, when row level security is enabled and your policies are correct: the anon key is designed to be public and access is enforced by RLS. The service_role key is not: it bypasses RLS and must never reach a client.
Is it safe to ship a Stripe publishable key?
Yes, the publishable key is designed for client use. The secret key, which starts with sk_live_ or sk_test_, must stay on your server.
I found a key in an old build. Is removing it enough?
No. Rotate it first. Old releases remain downloadable, so a key that shipped should be treated as compromised whether or not you can see it being used.
Sources
- Anthropic: Detecting and countering misuse of AI, September 2026
- F5 Labs: Mass scanning for exposed Vite endpoints
Read against the primary documentation rather than secondary coverage. Where a figure comes from a provider's own docs, it is quoted as published on 2026-09-17.
Related
More from Signals
Open the tool.
Ten production categories, three minutes, and a ranked list of what to fix first.
Check your own stack