Security

    Can Apple see my hardcoded secrets in a minified bundle?

    Minified iOS bundle showing hardcoded API keys remaining visible to the strings command

    The question usually shows up an hour before submission. You ran expo build or npm run build, the JS bundle came out minified, the function names look like a, b, c1, and somewhere in there is a Stripe publishable key, a Supabase service role token, or a Firebase admin secret you swore you would move to the backend later. The bundle is opaque to you. So the reasoning goes: it must be opaque to a reviewer too.

    That intuition is wrong. The reviewer is not the audience you should be worrying about.

    Short answer

    Apple's App Review process does not actively scan for hardcoded secrets in your bundle. Reviewers look at entitlements, Privacy Manifests, required-reason APIs, and visible behavior; they do not run strings against your binary to flag a leaked Stripe key. The risk is not Apple noticing. The risk is that anyone who downloads your .ipa can run unzip and strings and read every embedded credential in minutes. Minification renames variables; it does not encrypt string literals.

    What you should know

    • Minification is not encryption. It shortens identifiers and removes whitespace. String literals that hold your API keys stay readable in plain UTF-8 inside the bundle.
    • Apple's automated review focuses on metadata, not secrets. The ITMS validator checks entitlements, Privacy Manifest entries, and required-reason API declarations, not for AWS access keys or Stripe tokens.
    • Any iOS .ipa is a ZIP archive. An attacker downloads the app, unzips it, runs strings on the binary or the main.jsbundle, and gets every embedded string in seconds.
    • OWASP MASVS treats this as a critical control. MASWE-0005 (API Keys Hardcoded in the App Package) and MASWE-0013 (Hardcoded Cryptographic Keys in Use) document the failure mode.
    • The fix is structural, not cosmetic. A backend proxy or short-lived token service is the only approach that survives reverse engineering.

    Does App Review actually scan for hardcoded secrets?

    No. App Review's automated layer, the ITMS validator, runs against the binary you upload through App Store Connect, and its checks are documented in the App Store Review Guidelines. The validator flags missing Purpose Strings, undeclared use of required-reason APIs like UserDefaults or system_boot_time, missing Privacy Manifest entries for SDKs on Apple's published list, and entitlement mismatches. It does not run a credential scanner against your Mach-O binary or your JavaScript bundle.

    Human reviewers spend roughly fifteen minutes on the average submission, mostly clicking through user flows and confirming the app matches the metadata. They do not decompile, they do not run strings, they do not inspect main.jsbundle for tokens. The submission volume per day rules out any deep static analysis at scale.

    If Apple did flag your hardcoded Stripe publishable key, it would be a favour. The truth is the opposite: the build passes review, ships to the App Store, and only then does the embedded secret become an attacker's problem.

    What does minification actually do to my JavaScript bundle?

    Minification is a compiler pass that strips comments, removes whitespace, and renames local variables and function arguments to one or two characters. That is its full scope. Tools like esbuild, swc, and Terser are aggressive at it. None of them touch string literals; doing so would break runtime equality checks, JSON parsing, API URL construction, and any code that uses a string as a key.

    Here is what survives minification untouched: every string in "..." or '...', every key in a JSON object literal, every regex source, every URL, every API endpoint, every secret. Open a minified bundle in any text editor and search for https://, pk_live_, sk_, AIza, or eyJ; you will see the values without doing any reverse engineering.

    A quick demonstration in plain shell:

    unzip MyApp.ipa -d MyApp
    cd MyApp/Payload/MyApp.app
    strings main.jsbundle | grep -E "(sk_|pk_|AIza|eyJ|AWSAccess)"
    

    That is the entire attack. No jailbreak. No Frida. No Hopper. Three commands.

    What minification hidesWhat minification leaves visible
    Local variable namesAPI endpoint URLs
    Function parameter namesJSON keys and values
    Comments and whitespaceAll string literals
    Source map filenames (when not bundled)Regex sources
    Dead-code identifiersStripe, Firebase, AWS, Supabase keys
    Block-scoping artefactsJWT bearer tokens

    How does an attacker extract secrets from a minified IPA?

    The pipeline for the lazy attacker has three steps. The first is acquisition: download the .ipa from a tool like ipatool, or pull it via iMazing from a connected device. The second is unpacking: an .ipa is a renamed ZIP archive, so unzip does the job. The third is scanning.

    Scanning has two flavours. Static scanning runs strings against the binary and grep against bundled resources, then matches known prefixes (Stripe keys start with pk_ and sk_, Google API keys with AIza, Slack tokens with xox, JWTs with eyJ). Dynamic scanning runs the app under Frida or Objection, hooks the network methods, and reads outbound credentials in plaintext at the moment they are sent.

    The Spaceraccoon writeup Low-Hanging Apples found SDK credential misuse in 68 of 100 popular iOS apps using only static methods. Tools like trufflehog, gitleaks, and MobSF automate the scan across thousands of patterns.

    Obfuscation past minification has limited value. As the Approov whitepaper on hardcoded keys puts it, even when keys are obfuscated or hidden in some way, they are still compiled into or linked into the release package. The credential has to leave the device at some point; whoever owns the device can intercept it.

    Why is Apple not your real threat model here?

    The audience that worries about your hardcoded key is not App Review. It is:

    • The security researcher running their first iOS audit who wants a writeup for their blog.
    • The competitor downloading your app to find your third-party API costs.
    • The person on a forum trading API keys to bypass rate limits.
    • The opportunist running automated scanners against the top free apps in a category.

    App Review is a gate against policy violations and crash-on-launch builds. It is not a security audit, and Apple has never claimed it is. OWASP MASVS, Apple's own developer documentation, and Google's Hardcoded Cryptographic Secrets guidance all converge on the same point: the threat model for embedded secrets is the user with a copy of your app, not the platform's review queue.

    For an external read of what an attacker would actually find in your IPA before submission, scanning tools like PTKD.com (https://ptkd.com) run static analysis against the compiled build and flag the categories OWASP MASVS treats as critical: hardcoded keys (MASWE-0005), insecure storage (MASVS-STORAGE-1), and required-reason API gaps. The point is to see what you ship through the same lens as someone who downloaded it.

    How do I actually keep secrets out of the binary?

    The principle is simple: anything the device holds, the device leaks. The secret has to live on a server you control. Three patterns work in practice.

    The first is a thin backend proxy. The mobile app authenticates the user, gets a short-lived token, and calls your backend. The backend holds the third-party API key and forwards the request. Stripe, OpenAI, and most paid APIs assume this pattern.

    The second is short-lived credentials. AWS Cognito, Firebase App Check, and Auth0 issue tokens that expire in minutes. Even if extracted, the token is dead by the time the attacker uses it.

    The third is server-side configuration delivery. The app fetches non-secret config at launch from your backend, signed and pinned. No keys ship in the binary.

    For build-time injection, environment variables in .env files do not solve the problem; they are read at bundle time and inlined into the JS. An EXPO_PUBLIC_STRIPE_KEY in app.config.js ends up as a literal in the JS bundle. The PUBLIC_ convention exists because everything prefixed that way is visible by design.

    What to watch out for

    • "It is obfuscated, attackers will not bother" is wishful thinking. Automated scanners are run against every popular app weekly. Obfuscation slows a manual analyst by a day; it slows automated detection by zero seconds.
    • Source maps in production. A leaked .map file restores variable names, defeating even good minification. Confirm your CI does not publish maps to the public bundle.
    • Plist files copied as resources. GoogleService-Info.plist is plaintext XML inside the IPA. Treat its keys as public.
    • "This is only a publishable key" still costs money. A leaked Mapbox or Stripe publishable token is throttled per account and shows up on the bill.
    • Apple's Privacy Manifest is not a secrets manager. It documents data flows, not credential storage. Filling it out does not satisfy MASVS-CRYPTO.

    Key takeaways

    • Apple's App Review process does not scan for hardcoded API keys. Passing review is not evidence that your secrets are safe.
    • Minification renames identifiers and strips whitespace. It leaves every string literal, including every API key, visible in the bundle.
    • The threat is the attacker with a copy of your IPA, not the reviewer. Extraction takes three commands and no special tools.
    • Backend proxies, short-lived tokens, and server-side config are the only approaches that survive reverse engineering. Build-time .env substitution does not.
    • For builders who want a pre-submission read of what an attacker would find in their compiled build, PTKD.com (https://ptkd.com) is one of the platforms that runs OWASP-aligned static analysis against APK, AAB, and IPA artefacts before they reach the store.
    • #ios
    • #app-store
    • #api-keys
    • #minification
    • #reverse-engineering
    • #owasp-masvs
    • #secrets

    Frequently asked questions

    Does App Review run any static analysis on the binary?
    Yes, but not for secrets. The ITMS validator inspects the Mach-O binary for required-reason API calls (UserDefaults, system_boot_time, file timestamps, disk space), checks Privacy Manifest entries, validates entitlements, and confirms metadata against the build. It does not search for hardcoded API keys, JWT tokens, or third-party credentials. Apple's automated review treats secrets management as the developer's problem.
    Will obfuscation hide my Stripe key from reverse engineering?
    Not in any meaningful way. Obfuscation past minification (string scrambling, control-flow flattening) raises the cost of manual analysis but leaves automated scanners largely untouched. The key still has to be reconstructed at runtime to send the network request, so Frida-style hooking captures it at the moment of use. The Approov whitepaper on hardcoded keys concludes obfuscation does not solve the underlying problem.
    Is a Firebase API key actually a secret?
    Most Firebase config keys (the ones in GoogleService-Info.plist) are scope-limited identifiers, not secrets, and Google publishes them as intentionally client-side. Firebase Admin SDK service-account JSON files, by contrast, are full credentials and must never ship in a mobile app. The same distinction applies to Stripe publishable keys (client-safe) versus secret keys (backend only). Read the SDK docs before assuming a key is safe to embed.
    What is the fastest pre-submission check for embedded secrets?
    Run unzip on your IPA, then strings Payload/MyApp.app/MyApp piped to grep for prefixes like sk_, pk_, AIza, eyJ, AWS, and xox. The same loop works for main.jsbundle when you ship a React Native or Expo build. Anything that surfaces is a secret you have shipped to every user. Tools like MobSF, trufflehog, and OWASP MASTG samples automate the same check across more patterns.
    Does Apple ever reject a build because of leaked credentials?
    Almost never as a direct rejection reason. Apple has issued post-publication takedowns when leaked credentials caused user-data breaches reported by third parties, but those are enforcement actions, not pre-submission catches. A build that contains a hardcoded Mailgun key and a Twilio token typically passes review on the first try. The cost arrives later, as fraud, throttling, or unexpected bills against the leaked account.

    Keep reading

    Scan your app in minutes

    Upload an APK, AAB, or IPA. PTKD returns an OWASP-aligned report with copy-paste fixes.

    Try PTKD free