Cybersecurity

How to Find Hardcoded API Keys and Secrets in an APK

Springmusk Springmusk 9 min read 0 comments
Illustration of a magnifying glass revealing key icons and code brackets rising from an Android smartphone

TL;DR: Hardcoded API keys and secrets are one of the most common flaws in shipped Android apps. In April 2026, CloudSEK’s BeVigil scan of the top 10,000 apps found 32 live Google API keys hardcoded in 22 apps with over 500 million combined installs. This post walks through where secrets hide inside an APK, how to find them with APKLeaks, jadx, and grep, and what to do with a finding — whether you are auditing your own app or doing authorized security research.

Every Android APK is a zipped archive of everything an app needs to run. That includes things the developer never intended you to see: API keys, OAuth client secrets, Firebase URLs, AWS credentials, and internal endpoint addresses, all sitting in plain text in strings.xml, BuildConfig fields, or native libraries. Anyone with the APK file can extract them in minutes.

This used to be a known-but-manageable problem. In 2026 it got worse: Google’s API keys — long treated as public identifiers safe to embed in client-side code — can now silently become credentials for Gemini AI endpoints. The stakes of a hardcoded key are higher than they have ever been.

Why hardcoded keys got more dangerous in 2026

For more than a decade, Google’s documentation told developers that API keys in the AIza... format were safe to embed in client-side code and mobile app packages. They were public identifiers, not secrets — used for services like Maps, Firebase, and YouTube.

In February 2026, Truffle Security published research showing that when the Gemini API (the Generative Language API) is enabled on a Google Cloud project, every existing API key on that project silently gains access to Gemini endpoints — with no warning, no notification, and no confirmation dialog. Developers who followed Google’s own guidance suddenly held live AI credentials baked into their shipped apps.

CloudSEK’s BeVigil team then measured the real-world fallout. Their mobile app security search engine scanned the top 10,000 Android apps by install count, looking for hardcoded Google API keys, and verified each candidate against the Gemini API to confirm live access. The findings, published in their advisory on April 8, 2026:

Finding Number Source
Android apps scanned 10,000 CloudSEK BeVigil, Apr 2026
Live Google API keys found hardcoded 32 CloudSEK BeVigil, Apr 2026
Unique apps containing those keys 22 CloudSEK BeVigil, Apr 2026
Combined install base of those apps 500M+ CloudSEK BeVigil, Apr 2026

Some of the named apps: OYO Hotel (100M+ installs), Google Pay for Business (50M+), Taobao (50M+), apna Job Search App (50M+), ELSA Speak (10M+), The Hindu (10M+). In one confirmed case, researchers used a key from the ELSA Speak app to query the Gemini Files API and received a live response listing uploaded audio files — user speech recordings submitted for pronunciation coaching.

Exposed Gemini keys also carry financial risk. The CloudSEK report cited three publicly reported cases of Gemini API key misuse: a $15,400 bill for a solo developer, roughly 20.36 million yen for a Japanese company, and $82,314 in 48 hours for a Mexico-based team — 455 times their normal $180/month baseline.

Where secrets hide inside an APK

Before reaching for tools, it helps to know the hiding places. An APK is not one blob; it is a structured archive, and secrets concentrate in a few predictable spots:

Location What hides there How to read it
res/values/strings.xml API keys, endpoints, tokens stored as string resources apktool decode, or jadx resource view
BuildConfig fields Keys injected via buildConfigField in Gradle jadx decompiled sources
assets/ Config files like google-services.json remnants, JSON configs unzip the APK directly
AndroidManifest.xml Meta-data entries carrying keys and SDK tokens apktool decode
lib/*/*.so native libraries Keys compiled into C/C++ code, harder to spot strings, or Ghidra for deeper work
Smali / decompiled Java Hardcoded literals in networking and SDK init code jadx or baksmali, then grep

The fastest first pass costs nothing: unzip the APK and run strings on the raw binary. Many keys show up immediately because developers embed them as plain string literals.

The tools that actually find them

There are a few well-established approaches. They differ in how much work they do for you and how much noise they produce:

Tool How it works Strengths Weaknesses
APKLeaks Decompiles with jadx, scans every file against 50+ built-in regex patterns for URIs, endpoints, and secrets One command; purpose-built for this job; custom patterns via JSON Regex only — finds strings that look like secrets, needs manual triage
jadx + grep Decompile to Java, search for api_key, secret, token, AIza Full context around each hit; free; you already have jadx from our earlier guide Manual; noisy; misses obfuscated names
apktool + grep Decode resources and manifest, search XML and smali Best for strings.xml and manifest meta-data secrets Smali output is harder to read than Java
MobSF Full mobile security framework with automated static analysis Broad coverage: secrets, permissions, crypto misuse, trackers Heavier setup; broad output needs filtering
BeVigil CloudSEK’s search engine, pre-indexed scans of 1M+ Android apps No tooling needed; query apps already scanned Limited to what is indexed; not your own builds

APKLeaks is the natural starting point. It is open source (Apache-2.0) by dwisiswant0, with 6,362 stars and 599 forks on GitHub as of this week, and it is still maintained — last pushed August 2025. Install it with pip3 install apkleaks.

Walkthrough: scanning an APK with APKLeaks

Work only with apps you own or have explicit permission to test. Downloading a random APK from the internet and mining it for credentials is not research — the same steps below apply to your own debug builds or apps covered by a bug bounty scope.

Get the APK. For your own app, use the signed release APK, since debug builds often carry extra debug keys and logging that inflate results:

adb pull /data/app/com.example.app-1/base.apk app.apk

Run APKLeaks against it:

apkleaks -f app.apk -o results.txt

APKLeaks decompiles the APK with jadx (downloading it automatically on first run if missing), then scans every file against its bundled regexes.json — over 50 patterns covering AWS access keys, Google API keys, JWTs, Firebase URLs, Slack tokens, and similar formats. Matches are grouped by pattern name. For machine-readable output, add --json:

apkleaks -f app.apk --json -o results.json

Typical findings in a first run look like this: a Google_API_Key match in strings.xml, a Firebase_URL in a config class, maybe an AWS_Access_Key in a networking helper. Every one of them needs verification before you act on it.

Walkthrough: the manual jadx + grep pass

APKLeaks is regex-driven and can miss keys hidden behind custom variable names. A manual pass with jadx catches what patterns miss. If you followed our earlier jadx guide, the workflow is familiar:

jadx -d jadx-out app.apk
grep -rn "AIza" jadx-out/sources/ | head -20
grep -rniE "api[_-]?key|secret|token|passwd" jadx-out/sources/ --include="*.java" | head -40

Check the resource side too — many teams store keys as string resources:

apktool d app.apk -o apktool-out
grep -rniE "key|secret|token" apktool-out/res/values/strings.xml

For native libraries, extract and run strings:

unzip -q app.apk "lib/*" -d apk-lib
strings apk-lib/lib/arm64-v8a/*.so | grep -E "AIza|sk-|xoxb-|AKIA" | head -20

This layered pass — automated scan, decompiled-code search, resource search, native strings — is what separates a real audit from a single grep. Most findings come from the first two layers; the native layer is where the interesting ones hide.

Validating a finding (and what not to do)

A string that looks like a key is not a vulnerability until confirmed. Validation rules:

  • Check scope before touching anything. A Google API key restricted to Android apps with your package name and SHA-1 fingerprint is far less exposed than an unrestricted one. Google’s Cloud console lets key owners restrict keys by API, platform, and referrer — many leaked keys are already restricted.
  • Never use a found key against someone else’s services. Querying another developer’s Gemini endpoint or Firebase instance with their key is unauthorized access, not research. Validate only keys belonging to apps you own or have permission to test.
  • For your own keys, test in a throwaway project. Rotate the key, restrict the new one, and re-scan the app to confirm the old value is gone from the package.
  • Report through the right channel. If you find an exposed key in a third-party app within a bug bounty scope, report it per the program’s rules and include the restriction state — an unrestricted, live key is a meaningfully stronger finding.

If you ship an Android app: how to stop leaking keys

The fix is not “hide the key better” — anything shipped in the APK can be extracted, obfuscation only slows it down. The fixes that work:

  • Restrict every key in the Google Cloud console. Bind Android keys to your package name and signing certificate SHA-1; bind server keys to your server IPs. An unrestricted key is the actual vulnerability in the CloudSEK findings.
  • Move secrets behind your own server. The app should call your backend; your backend holds the key and calls the third-party API. The key never ships to devices.
  • Use the Android Keystore for device-side secrets. Keys generated or stored in the hardware-backed Keystore cannot be extracted by decompiling the APK.
  • Set quotas and billing alerts. The $82,314-in-48-hours case happened because nothing capped or alerted on the spike. Budgets and alerts in the Cloud console are a five-minute setup.
  • Scan your own APKs in CI. Run APKLeaks or a similar scanner on every release build before it ships. If a key shows up in your scan output, it will show up in an attacker’s.

Key takeaways

  • Hardcoded secrets remain one of the most common Android app flaws — and since the February 2026 Truffle Security finding, even “public” Google API keys can silently become Gemini credentials.
  • CloudSEK’s April 2026 scan of 10,000 apps found 32 live keys in 22 apps with 500M+ combined installs — this is a measured problem, not a theoretical one.
  • APKLeaks (6,362 GitHub stars, Apache-2.0) is the fastest first scan; follow it with a manual jadx + grep pass and a native-library strings check.
  • Validate scope before acting: a restricted key is a weaker finding, and someone else’s key is never yours to test.
  • If you ship apps: restrict keys, proxy through your server, use the Android Keystore, set billing alerts, and scan release APKs in CI.

References

  • CloudSEK — “Hardcoded Google API Keys in Top Android Apps Now Expose Gemini AI” (April 2026): https://www.cloudsek.com/blog/hardcoded-google-api-keys-in-top-android-apps-now-expose-gemini-ai
  • Infosecurity Magazine — “Google API Keys Quietly Gain Access to Gemini on Android Devices” (October 2026): https://www.infosecurity-magazine.com/news/google-api-keys-access-gemini/
  • ETCISO — “Critical Security Flaw Exposes Google Gemini AI in 500M Apps Due to Hardcoded API Keys” (April 11, 2026): https://ciso.economictimes.indiatimes.com/news/cybercrime-fraud/hardcoded-api-keys-expose-google-gemini-ai-via-apps-with-500m-installs/130183953
  • APKLeaks by dwisiswant0 (GitHub, Apache-2.0): https://github.com/dwisiswant0/apkleaks
  • AppSec Santa — “APKLeaks: Scan Android APKs for Secrets & Endpoints”: https://appsecsanta.com/apkleaks

Join the discussion

Your email address will not be published. Required fields are marked *