Dev.to Security πŸ” Cybersecurity πŸ‘ 0 πŸ“– 4 min read

Finding Exposed API Keys in Shipped Apps Responsibly

You've probably seen headlines about API keys leaked in mobile apps or researchers finding exposed secrets in APKs. The findings are real. The impact is real. But the way many people go about finding and reporting these

You've probably seen headlines about API keys leaked in mobile apps or researchers finding exposed secrets in APKs. The findings are real. The impact is real. But the way many people go about finding and reporting these issues? Often counterproductive.

I've been on both sides β€” hunting for exposed credentials in shipped artifacts and receiving reports that range from helpful to hostile. The difference usually comes down to verification, context, and communication.

What "Shipped" Actually Means

Before you scan anything, clarify what you're looking at. "Shipped" covers several distinct surfaces:

Mobile binaries (APK/IPA) β€” These are the most common target. Built artifacts often contain API keys, Firebase configs, mapping SDK tokens, and analytics keys baked in at compile time. Tools like apktool, jadx, or ghidra make extraction trivial.

Desktop apps (Electron, Tauri, native) β€” Same problem, different wrapper. Electron apps ship as asar archives you can unpack with npx asar extract. Native binaries need strings analysis or decompilation.

Web bundles β€” Less common for server-side secrets, but frontend builds sometimes leak build-time variables (NEXT_PUBLIC_, VITE_, REACT_APP_*) that weren't meant for production.

Container images β€” docker save + tar -x + grep -r finds .env files, config.json, and hardcoded credentials left in layers.

Each surface requires different tooling, but the verification discipline stays the same.

The Verification Gap

Here's where most reports go wrong: finding a string that looks like a key β‰  finding an exposed key.

I learned this the hard way analyzing a reported CSRF_SECRET exposure in a library I maintain. The reporter found a cookie named csrfSecret and an environment variable CSRF_SECRET β€” assumed they were the same value leaking to the client. They weren't. The cookie held a per-session token; the env var was an HMAC signing key that never left server memory. The similarity was a naming collision, not a leak.

Before you report, verify:

  1. Is it actually a secret? Many "keys" are public identifiers: Google Maps API keys (meant for client use), Stripe publishable keys, Firebase project IDs. Check the provider's documentation.
  2. Does it work? Test the key against the provider's API. A revoked or restricted key isn't an active exposure.
  3. What's the scope? A key restricted to localhost or a specific referrer/domain has different severity than an unrestricted production key.
  4. Is it rotating? Some apps embed short-lived tokens that refresh on startup. Static analysis misses the rotation logic.

Tooling That Doesn't Waste Time

Skip the regex-only scanners. They produce noise. Use tools that understand context:

Tool Best For Why
trufflehog Git history, filesystems, containers Verifies secrets against live APIs, entropy analysis
gitleaks Pre-commit, CI, repo scans Fast, configurable, low false positives
mobsf Mobile binaries Static + dynamic analysis, API key extraction with context
apkleaks APKs specifically Purpose-built, decompiles + scans
docker-scout / trivy Container images Layer-aware, SBOM generation

Run these in a controlled environment. Don't scan production systems you don't own.

The "Without Being a Jerk" Part

Responsible disclosure isn't just a buzzword β€” it's the difference between a fix and a lawsuit.

Find the right channel. Check SECURITY.md, the vendor's website, or security@ email. Don't DM engineers on Twitter. Don't open public GitHub issues. Don't post to Reddit.

Lead with evidence, not alarm. A good report:

  • Identifies the exact file/line/artifact
  • Shows the key format (redacted: sk_live_****)
  • Documents your verification steps (what you tested, what worked)
  • States the impact if exploited
  • Asks for a timeline, doesn't demand one

Bad report: "Your app has exposed API keys!!! Fix immediately or I go public."

Good report: "In app-release.apk v3.2.1, assets/firebase-config.json contains a Firebase API key (AIza****). The key accepts unauthenticated requests to firestore.googleapis.com from any origin. I verified read access to the users collection. Please advise on your disclosure timeline."

Respect the timeline. Most vendors need 30-90 days. Some need more for coordinated releases across platforms. If they're unresponsive after 90 days, a polite follow-up is reasonable. Public disclosure without notice burns bridges and hurts users.

What Happens After You Report

You'll typically see one of three outcomes:

  1. Fix + rotation β€” Key revoked, new key issued, app updated. Best case.
  2. Mitigation β€” Key restricted (referrer allowlist, IP allowlist, scope reduction). Common for keys that can't be rotated immediately (e.g., embedded in hardware devices).
  3. Won't fix / by design β€” The key is public (Google Maps, Stripe publishable). You learn something; they close the ticket.

If it's #3, accept it. Don't argue with the vendor about their own architecture.

A Checklist Before You Hit Send

  • [ ] Verified the string is a secret, not a public identifier
  • [ ] Tested the key against the provider API (authenticated request succeeds)
  • [ ] Confirmed the key has excessive permissions for its context
  • [ ] Located the vendor's published security contact
  • [ ] Drafted report with artifact location, verification steps, impact
  • [ ] Redacted the full key in your report (use sk_live_**** format)
  • [ ] Set a calendar reminder for 90-day follow-up

The Bigger Picture

Finding exposed keys is easy. strings app.apk | grep -E '(sk_|pk_|AIza|ghp_)' takes five seconds. Doing it responsibly β€” verifying, contextualizing, communicating β€” takes longer but actually improves security.

The CSRF_SECRET confusion I mentioned? That reporter skipped verification. They pattern-matched, assumed, and escalated. The maintainer (me) spent hours proving a negative. That time could've gone to real issues.

Be the person who verifies first.

πŸ“° Read the original article on Dev.to Security

Originally published by Dev.to Security. Aggregated on AIWithGhost for educational purposes β€” full credit and traffic to the original publisher.