Your APK is not a black box

Many Nigerian fintech developers treat their published APK like compiled, unreadable machine code. It is not. An Android APK is a ZIP archive containing Dalvik bytecode, resources, manifest files, and—if you are using React Native—a plain JavaScript bundle. Anyone can download it from Google Play, extract it, and read the contents.

At Simpa Labs, one of the first things we do in a mobile app penetration test is pull the APK and run it through jadx (a Dalvik-to-Java decompiler) and apktool (a resource decoder). The process takes seconds.

What attackers actually do

The workflow is straightforward and requires no specialized hardware:

Step 1: Obtain the APK

The attacker downloads the APK from any mirror site, extracts it from their own device with adb pull, or downloads it directly from Google Play using third-party tools. Your app is public. So is the binary.

Step 2: Decompile with jadx

Running jadx -d output/ yourapp.apk produces a full directory of decompiled Java source code. Class names, method signatures, string constants, and resource files are all readable. For Flutter apps, tools like Doldrums extract Dart snapshots. For React Native, the JS bundle is already text.

Step 3: Search for secrets

The attacker runs simple string searches across the decompiled codebase. They look for known key prefixes: sk_live_ (Paystack), FLWSECK- (Flutterwave), Bearer, api_key, secret, password, or Base64-encoded values. In most apps we test, this search returns results within seconds.

Real-World Finding

Payment gateway secret keys in production APKs

In 2025, we assessed a Nigerian lending platform and found the Paystack live secret key hardcoded in a Kotlin configuration class. With this key, an attacker could initiate refunds, view all transaction history, and create unauthorized transfers—entirely bypassing the mobile app. The key had been there since launch, exposed to anyone who cared to decompile the APK.

Why this is catastrophic for fintechs

A leaked payment gateway secret key does not just expose your app—it exposes your entire payment infrastructure. Depending on the provider and key permissions, an attacker can:

This is not theoretical. Payment gateway key leaks have caused real financial losses for Nigerian startups. The CBN takes a dim view of companies that fail to protect payment credentials—see the breach notification requirements.

Where secrets should actually live

The fundamental rule: secret keys must never exist in the mobile app binary. Not in source code, not in configuration files, not in environment variables baked into the build, not in encrypted strings that get decrypted at runtime (the decryption key is also in the binary).

The backend proxy pattern

Your mobile app should never communicate directly with payment gateways using secret keys. Instead, the app calls your own backend API. Your backend—where the secret key lives in an environment variable or secrets manager—makes the authenticated call to Paystack or Flutterwave. The mobile app only ever sees your API, authenticated with user-scoped tokens.

Build-time environment injection

For non-secret configuration (public keys, API base URLs, feature flags), inject values at build time using your CI/CD pipeline. In React Native, use react-native-config. In Flutter, use --dart-define. These values are still in the binary, so they must be values you are comfortable being public.

Secrets managers

On the backend, store secrets in AWS Secrets Manager, Google Secret Manager, HashiCorp Vault, or your cloud provider's equivalent. Never commit secrets to version control. Use .env files locally and secrets injection in CI/CD for deployments.

Not sure what your APK is exposing? We will decompile it, extract every secret, and show you the full attack surface in our mobile security assessment.

Get a Mobile Security Assessment

Common excuses (and why they fail)

"We encrypted the key in the app." The encryption key or decryption logic is also in the binary. An attacker just needs to find that too—and they will, because the app must decrypt it at runtime to use it.

"We used ProGuard/R8 obfuscation." Obfuscation renames classes and methods. It does not encrypt string constants. The API key sk_live_abc123... remains exactly the same in the obfuscated binary. Run strings on the APK and see for yourself.

"Nobody will bother to decompile our app." The tools are free, the process takes minutes, and the payoff for finding a payment secret key is potentially unlimited. If your app processes money, someone will look. Read our analysis on why attackers target Nigerian fintechs.

Audit your app today

Before your next release, pull your own APK, run it through jadx, and search for every string constant. If you find anything that looks like a secret, it is one—and it is already compromised. Rotate the key immediately, move it to your backend, and implement the proxy pattern described above. For a thorough review, see our mobile app pentest checklist.

Related reading

Blog: Reverse Engineering Android Fintech Apps · Securing Flutter & React Native Apps · Webhook Security for Payments

Guides: Mobile App Pentest Nigeria · Fintech Security Checklist · Pentest Tools & Methodology

Services: Penetration Testing · API Security · Vulnerability Assessment

Frequently asked questions

{faqs.map((faq) => (
{faq.q}

{faq.a}

))}