[OSINT] The weird case of VirusTotal apps
A look at two VirusTotal apps (one third-party, one official) and the things that are sloppy, unexplained, or simply concerning about them.
TL;DR
VirusTotal promotes a third-party Android app (“VirusTotal Mobile” by a developer named FunnyCat) listed with 5M+ downloads, plus an official Mac OS X Uploader whose site page still shows a 2014 screenshot.
Both ship with hardcoded API keys belonging to the same account, one of which allows generous batch lookups against 77 antivirus engines.
The Android app also stores unencrypted data and has zero TLS pinning.
The cast of characters
| App | Publisher | Key artifact | User base |
|---|---|---|---|
VirusTotal Mobilecom.funnycat.virustotal | FunnyCat | Hardcoded API key in BuildConfig.java;unchanged across the two versions we compared (~8 years apart) | ~5M+ downloads (per Play listing) |
Mac OS X Uploadercom.virustotal.VirusTotalUploader | VirusTotal itself | Hardcoded API key obfuscated across 10 string fragments | Small userbase (quota intact) |
1. The Android app everyone (seems to) trusts (but shouldn’t)
1.1 It’s not even a VirusTotal app
I received a marketing email from VT promoting their free Android app, it’s linked from their own community apps docs but published by FunnyCat, a third party developer.
It’s named VirusTotal Mobile so users assume it’s official. The package name itself is a giveaway: com.funnycat.virustotal.

📝 I contacted VT support and they said The “VirusTotal Mobile” application is developed and maintained by a third party (FunnyCat); it is not an official VirusTotal application.
However, from their email: we also have a free Android application…
Confusing terms here.
1.2 The hardcoded API key
BuildConfig.java:12 contains, in plaintext:
933fc7bdb949cfd23c89fc0e1768e8bfb66b5cd9c56534fc0d42f88cc6eb4fa8
Anyone who runs jadx on the APK gets it. The same key is present in the two versions I compared; v1.0.10b (first release) and v2.5.8 (latest), roughly 8 years apart.
It grants access to VirusTotal’s partner endpoint, which batch-checks up to 50 hashes per request against 77 AV engines, with no obvious rate limiting in our testing.
1.3 The app that looks like 2012
The Google Play listing and in-app screenshots look like they were captured on a vintage Android device:


And yes the app is clearly outdated.

2. The Mac OS X Uploader: official, ancient, and leaking a key too
VirusTotal’s own Mac OS X Uploader is showcased on the VT website with a screenshot:

We can’t say when the binary was last built, but the docs page that promotes the app was touched no more than 7 months ago, and the screenshot on it still shows a 2014 scan date.
Still, it’s the official app, and it too embeds a default API key:
70f8a7ffa6685471afc85d9202468f7277ae20fa7f78163aa22b4c8822f18a5a
This one is obfuscated slightly better; QVtFile::GetApiKey() concatenates 10 string fragments from the binary’s literal pool at runtime, so a casual strings dump won’t reveal it:
"70f8a" + "7ffa6" + "68547" + "1afc8" + "5d9202" + "468f72" + "77ae" + "20fa7f7" + "816" + "3aa22b4c8822f18a5a"
A disassembler makes this trivially recoverable. And here’s the irony: this “obfuscated” key has standard v2/v3 access on the endpoints we tested, with quota still available, while the Android app’s plainly-visible key is restricted to the partner endpoint.
And notably, it ships unsigned:

And again, the app is clearly outdated.

3. The two keys are mirror images of each other
Functional testing showed the two keys have complementary access:
| Feature | Android key (933fc7…) | macOS key (70f8a7…) |
|---|---|---|
| Partner batch hash lookup | ✅ HTTP 200 | ❌ HTTP 403 |
| v3 file info (by hash) | ❌ 429 quota | ✅ HTTP 200 |
| v2 file/scan (upload) | ❌ 204 quota | ✅ 200 |
| v2 url/scan | ❌ 204 quota | ✅ 200 |
| v2 file/report | ❌ 204 quota | ✅ 200 |
| v2 url/report | ❌ 204 quota | ✅ 200 |
| API usage endpoint | ❌ 403 | ❌ 403 |
The Android app’s key is partner-only and its quota is permanently drained; consistent with thousands of users hammering the same key. The macOS key has standard v2/v3 access on the endpoints we tested and, because the app has a small userbase, quota is intact.
One key is effectively useless to an attacker right now (always 429), the other is a credential with broader access hidden behind a few string concatenations. Same account. Different worlds.
Rate limiting? What rate limiting?
10 concurrent requests to the v3 file-info endpoint with the macOS key all returned HTTP 200, no 429, no quota headers, nothing. That’s a small sample, not proof, but it’s already well beyond the documented free tier (4 req/min).
Either this key is special, or VT’s free-tier limits are looser than advertised.
4. The partner endpoint: undocumented, and generous in our testing
The Android app talks to www.virustotal.com/partners/android-app/file-reports, a partner endpoint that:
- Batch-checks up to 50 hashes per POST against 77 engines,
- Works when the public v3 API is returning HTTP 429 (quota exceeded),
- Requires only a
User-Agent: okhttp/3.12.1header to be treated as a partner, - Returns results as a JSON array where
null= “never seen this hash” and an object = pre-existing scan results.
Submit a file, poll until it’s scanned, and you’ve effectively got your own private scanning bot riding on someone else’s account, with no per-user rate limit visible to us, no audit trail, and no obvious way to distinguish the real app from a scraper.
5. The “obfuscation” table
For a security company’s own mobile apps, the defenses are conspicuously absent:
| Defense | Android app | macOS uploader |
|---|---|---|
| API key protection | ❌ Plaintext in BuildConfig | ⚠️ 10 string fragments |
| SSL/TLS pinning | ❌ | unknown |
| Root detection | ❌ (runs fine on rooted device) | — |
| Emulator detection | ❌ | — |
| Network security config | ❌ (none shipped) | — |
| Database encryption | ❌ plain SQLite | — |
| OkHttp logging | ⚠️ disabled but framework present ( Level.NONE) | — |
| Certificate transparency | ❌ | — |
Conclusion
Nothing here is catastrophic.
The Android key is quota-drained, the macOS key sits behind a niche app.
But that’s the point. VirusTotal, a Google-owned security company, ships an outdated, third-party-promoted-as-own app with a key unchanged for 8 years that quietly unlocks an undocumented 50-hash partner lookup endpoint; an official uploader whose “obfuscated” key has more access, and isn’t even signed. No pinning, no encryption, no rotation.
It’s not a bad hack, it’s a sloppy culture, and for a company selling trust, that’s the concerning part.
Annex, VirusTotal support response
Hello,
Thank you for the report and for using responsible disclosure.
The “VirusTotal Mobile” application is developed and maintained by a third party (FunnyCat); it is not an official VirusTotal application. Its implementation details (TLS pinning, root/emulator detection and the Firebase database (diesel-talon-824) you mention) belong to the developer’s own infrastructure, so those points are best raised with them directly.
Regarding the embedded API key: it is a restricted, rate-limited key. It does not grant access to premium features such as VT Intelligence, Hunting or Private Scanning, and its usage is subject to standard request quotas and monitoring; it does not carry privileges beyond those limits.