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

AppPublisherKey artifactUser base
VirusTotal Mobile
com.funnycat.virustotal
FunnyCatHardcoded API key in BuildConfig.java;
unchanged across the two versions we compared (~8 years apart)
~5M+ downloads
(per Play listing)
Mac OS X Uploader
com.virustotal.VirusTotalUploader
VirusTotal itselfHardcoded API key obfuscated across 10 string fragmentsSmall 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.

VirusTotal’s marketing email pushing the third-party Android app

📝 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:

Google Play listing, 5M+ downloads, 4.0★

In-app screenshots: old Holo-era UI, scan results page

And yes the app is clearly outdated.

The in-app UI is dated too

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:

VirusTotal’s website showcasing the Mac OS X Uploader, note the scan date 5/23/14

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:

VirusTotal scan of the uploader binary, unsigned

And again, the app is clearly outdated.

The Mac OS X Uploader app itself, dated

3. The two keys are mirror images of each other

Functional testing showed the two keys have complementary access:

FeatureAndroid 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.1 header 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:

DefenseAndroid appmacOS uploader
API key protection❌ Plaintext in BuildConfig⚠️ 10 string fragments
SSL/TLS pinningunknown
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.