You've probably seen headlines: "Millions of API keys leaked in mobile apps." The reality is less dramatic but more pervasive—hardcoded secrets ship in production apps every day, often in plain sight.
I've spent years building tooling around this problem. Here's what works for finding exposed keys and how to handle findings responsibly.
Where Secrets Actually Hide
Secrets don't just live in source code. In shipped apps, they end up in:
Mobile binaries (APK/IPA): Strings embedded in compiled code, resources, or native libraries. Tools like strings, jadx, or ghidra extract them trivially.
Frontend bundles: JavaScript bundles served to browsers often contain API keys, Firebase configs, or third-party SDK credentials. View source or check the Network tab.
Desktop apps: Electron apps ship as ASAR archives. npx asar extract app.asar out gives you the full source tree. Tauri and Wails binaries embed resources similarly.
Configuration files: google-services.json, GoogleService-Info.plist, awsconfiguration.json—these ship with apps and contain keys by design.
Build artifacts: CI/CD logs, Docker images, and package registries sometimes leak secrets from build-time injection.
Practical Discovery Workflow
1. Start with automated scanning
Don't grep manually. Use purpose-built tools:
# Mobile
mobsfscan --format json --output results.json ./app.apk
trufflehog filesystem --directory ./extracted-apk --json
# Frontend
trufflehog github --repo=https://github.com/org/repo --json
trufflehog filesystem --directory ./dist --json
# Desktop (Electron)
npx asar extract app.asar extracted
trufflehog filesystem --directory ./extracted --json
trufflehog and gitleaks understand entropy-based detection and known key formats (AWS, Stripe, GitHub, Slack, etc.). They catch high-entropy strings that regex misses.
2. Validate before reporting
False positives waste time. For each candidate:
-
Check the key format: Does it match the provider's documented pattern? (e.g.,
sk_live_for Stripe,AKIAfor AWS) -
Test if it's valid: Most providers have lightweight validation endpoints. For AWS:
aws sts get-caller-identity --access-key $KEY --secret-key $SECRET. For Stripe:curl -u $KEY: https://api.stripe.com/v1/account. -
Determine scope: Is it a publishable key (safe by design) or a secret key? Firebase config objects contain
apiKeyfields meant to be public—they're not secrets.
3. Assess actual impact
Not every exposed key is a crisis. Ask:
- What permissions does this key have? (Read-only analytics vs. full database write)
- Is it rotatable? (Most are, but some legacy integrations aren't)
- Is there evidence of misuse? Check provider logs if accessible.
- Can the app function without it? Some keys are for optional features.
Reporting Without Being a Jerk
The goal is remediation, not clout.
Find the right channel
-
Security.txt: Check
/.well-known/security.txtor/security.txton their domain -
GitHub: Look for
SECURITY.mdin the repo - Platform programs: Apple, Google, Microsoft, and major SaaS providers have dedicated security@ emails or bug bounty platforms (HackerOne, Bugcrowd)
-
Last resort:
security@<domain>or general contact form with "SECURITY" in subject
Write a useful report
Subject: Potential exposed API key in [App Name] v[version] - [Key Type]
Hi [Team],
I found what appears to be a [provider] [key type] key in [location: e.g., the shipped APK at res/values/strings.xml, the production JS bundle at /main.abc123.js, the Electron asar archive].
Key prefix: sk_live_abc123... (redacted)
Location: [exact path]
App version: [version/build number]
Platform: [iOS/Android/Web/Desktop]
The key appears to be [valid/invalid/untested]. Based on [provider] documentation, this key type grants [permissions scope].
Steps to reproduce:
1. [Download link or store link]
2. [Extraction steps]
3. [Verification command]
Happy to coordinate rotation timing. Let me know if you need more details.
Thanks,
[Your name/contact]
Key principles:
- Redact the full key in the initial report
- Include exact location and reproduction steps
- State the impact factually—no hyperbole
- Offer coordination on rotation timeline
- No demands, no deadlines, no threats
What not to do
- Post findings publicly before disclosure
- Demand payment (unless through a formal bug bounty)
- Test the key beyond basic validation (don't enumerate resources, don't write data)
- Share the key with anyone
- Follow up aggressively—give them 7-14 days for initial response
Prevention: The Better Fix
Finding keys is reactive. The sustainable fix is preventing them from shipping.
For mobile
- Never put secrets in the app bundle. Use a backend proxy: app → your API → third-party API. Your backend holds the secret; the app gets a short-lived token.
- Use platform keystores: Android Keystore, iOS Keychain. They raise the bar.
-
CI scanning: Add
trufflehogorgitleaksto your release pipeline. Fail the build on secrets.
For frontend
-
Environment variables at build time only:
NEXT_PUBLIC_/VITE_/REACT_APP_prefixes mean "this ships to the browser." Only put publishable keys there. - Runtime config: Fetch sensitive config from your backend at app init, behind auth.
- Content Security Policy: Limit where scripts can load from, reducing impact of key theft.
For desktop (Electron/Tauri/Wails)
- Don't bundle secrets in asar/resources. Same proxy pattern as mobile.
-
Use OS credential managers:
keytar(Node),keyring(Python), platform APIs directly. - Sign and notarize: Makes tampering harder.
For all platforms
- Rotate regularly: Automate rotation where providers support it (AWS IAM, Stripe, GitHub).
- Scope narrowly: Use least-privilege keys. A key that only reads analytics is less damaging than one with full write access.
- Monitor usage: Most providers show last-used timestamps and call volumes. Anomalies = investigation.
A Note on "Public" Keys
Some keys are meant to be public:
- Stripe publishable keys (
pk_live_,pk_test_) - Firebase
apiKeyin config objects - Google Maps API keys (with referrer restrictions)
- Sentry DSNs
- Algolia search-only API keys
These aren't vulnerabilities. Don't report them. Learn each provider's key taxonomy—it saves everyone time.
The Long Game
If you do this regularly, build relationships. Security teams remember reporters who:
- Send clear, reproducible reports
- Respect coordination timelines
- Don't grandstand
- Follow up to confirm fix deployment
Those reporters get faster responses, direct contacts, and sometimes early access to new features or beta programs.
Top comments (0)