If your iOS submission came back with a notice that names a key string from your binary, or App Store Connect sent a separate security message referencing a recoverable credential, the reviewer is telling you that an automated scan or a partner researcher pulled a secret out of your IPA. The notice rarely cites a clean guideline number, which makes the rejection confusing to read. The fix turns on what kind of key it is, how you rotate it, and how you answer the Resolution Center.
Short answer
Apple does not publish a single App Review Guideline that names hardcoded API keys. In practice, App Review sends a security disclosure, sometimes paired with Guideline 1.6 (Data Security), Guideline 2.3 (Accurate Metadata), or Guideline 5.1.1 (Privacy) when a scan reports a recoverable secret in your IPA. The recoverable secret is usually an AWS, Firebase Admin, Stripe, Twilio, SendGrid, or Google Cloud service key. The reviewer asks you to rotate the credential with the provider, remove it from the binary, and resubmit. Rebuilding without rotation is not enough.
What you should know
- The rejection is rarely framed as one guideline. Apple's automated and partner-researcher scans send a security disclosure that quotes the exposed string, then ask for rotation and removal.
- A scrubbed build that still references the same rotated key trips the second-round flag. App Review correlates the binary against the key fingerprint.
- Reverse engineering is the default threat model. The strings command on an unzipped IPA recovers most plaintext secrets in seconds.
- Some keys are designed to be public. Firebase web API keys, Google Maps client keys, and Stripe publishable keys are not secrets; provider-side restrictions are.
- The Resolution Center reply is part of the fix. Apple wants the rotation timestamp and the provider you rotated with, not a paragraph about future plans.
- CWE-798 (Use of Hardcoded Credentials) is the underlying weakness. Apple's notice often borrows that framing from the partner scan that produced the finding.
What rejection notice does Apple send for a hardcoded API key?
According to Apple's App Review Guidelines, Guideline 1.6 (Data Security) requires apps to implement appropriate security measures to handle user information, and Guideline 5.1.1(vi) removes developers from the program if they surreptitiously discover passwords or other private data. Neither rule names hardcoded API keys directly. The rejection notice usually arrives in one of three shapes.
The first shape is a Resolution Center message that names the guideline (often 1.6 or 2.3) and quotes the exposed string verbatim, sometimes redacted, with a paragraph asking the developer to rotate and remove the credential. The second shape is a separate Security Disclosure email or App Store Connect notice that references a vulnerability category (CWE-798, Use of Hardcoded Credentials) without citing a numbered guideline. The third shape is a Guideline 5.1.1 rejection that names the key only obliquely, framed as the app accessing backend data without permission, because the hardcoded key gates a service the user never authorized.
The shape matters for the reply, not the fix. The fix is the same in all three cases.
How does App Review actually find a key inside my IPA?
App Review unzips the IPA, walks the bundle, and runs binary inspection on the compiled binary and on every resource file. Apple does not publish the exact ruleset. In practice, three layers of detection produce most of the findings.
The first layer is regex-based fingerprinting against the public format of known cloud tokens. AWS access keys (AKIA prefix), Stripe live keys (sk_live_ prefix), Slack tokens (xoxb-), Google service account JSON, and SendGrid tokens (SG. prefix) carry recognizable signatures that match in milliseconds. The OWASP Mobile Top 10 documentation on reverse engineering notes that tools such as strings, otool, IDA Pro, and Hopper recover most plaintext secrets without specialized tooling, and that all mobile code is susceptible to reverse engineering at runtime.
The second layer is targeted file scanning. Info.plist, GoogleService-Info.plist, JavaScript bundles inside React Native or Capacitor apps, asset directories inside Flutter builds, and any .env or .config file packed into the bundle get inspected for credential-shaped values. The Cybernews investigation reported by The Hacker News found over twelve million authentication secrets and keys leaked across public code repositories in 2023, with mobile binaries representing a measurable share of the exposed surface.
The third layer is partner reporting. Independent researchers and security vendors run automated scans of public IPAs, decrypt them with sideloading tools or analyze them at submission time, and forward findings to Apple. The pipeline appears to consume similar feeds, based on the patterns reported by developers whose rejection notice quoted a string that only an external scanner would have produced.
Which keys most often trigger the security disclosure?
The table below maps the credential families that appear most often in hardcoded-key rejection notices, grouped by what an attacker can do once the key is exposed.
| Credential family | Common storage location in the build | Risk if exposed |
|---|---|---|
| AWS access key (AKIA prefix) | Info.plist, JavaScript bundle, native constants | S3 read and write, IAM enumeration, full account access if broadly scoped |
| Stripe secret key (sk_live_) | JS bundles in cross-platform apps, native constants | Charge creation, refund issuance, customer data read |
| Firebase Admin SDK service account | firebase-adminsdk.json packed in resources, GoogleService-Info.plist at admin scope | Full database and storage write, user impersonation |
| Twilio Auth Token | Native constants in messaging features | SMS sending charged to your account, phone number lookup |
| Google Maps server key without restrictions | Info.plist or AndroidManifest.xml | Quota theft, billing impact |
| SendGrid API key (SG. prefix) | Constants in email-sending features | Mass email sending under your domain |
| Supabase service role key | .env bundled into the JS payload | Full row-level security bypass on your Postgres |
The honest pattern: the riskier the scope of the credential, the more likely the rejection arrives as a separate security notice rather than a standard Resolution Center reply, because Apple treats account-level cloud credentials as a higher-severity finding than a feature-specific key.
How do I fix the rejection on the second submission?
The fix has four parts: rotate, remove, rebuild, and reply.
Rotate the key with the provider before touching the codebase. For AWS, deactivate the access key in IAM and issue a new one. For Stripe, roll the secret key in the Dashboard. For Firebase service accounts, delete the compromised JSON and generate a fresh credential. The reason rotation comes first is that the exposed key already sits in the IPA on the App Store servers, in any researcher's scan archive, and probably in a code-search index somewhere. Rotation closes the door before you rebuild.
Remove the key from the source. Move every secret behind a backend you control, fronted by an authentication layer that proves the request came from a real user of your app. The Firebase Authentication ID token, an Apple App Attest assertion, or a signed session JWT from your own server are all common patterns. For services that genuinely need a client-side identifier (Firebase web API key, Stripe publishable key), keep the identifier client-side and restrict it in the provider console (bundle ID restriction, allowed domains, allowed APIs).
Rebuild a clean IPA. Run the strings command on the final IPA before uploading: unzip MyApp.ipa && strings Payload/MyApp.app/MyApp | grep -E "AKIA|sk_live|SG\.|xox[baprs]-". If anything comes back, the rebuild is not clean.
Reply in the Resolution Center with the rotation timestamp, the provider you rotated with (Stripe Dashboard, AWS IAM, Firebase Console), and one sentence confirming the new build no longer contains client-side credentials. App Review reads the reply alongside the binary scan, so making the rotation legible saves a round.
Is rotating the key alone enough to clear the rejection?
No. Rotation closes the immediate exposure, but if the rebuilt binary still ships any credential that grants backend access, the second submission gets the same flag with a different key string. The two common failure modes are rotating in place without changing the architecture (the new key is still in the bundle) and rotating with a narrower scope but still leaving the key client-side (a less-privileged hardcoded key is still hardcoded).
The architectural fix is to move every secret to a server-side function (AWS Lambda, Cloudflare Worker, Supabase Edge Function, a small Express service) that signs and forwards the request to the actual provider. The client authenticates to your function with the user's session, never with a long-lived service credential.
For builders shipping AI-coded or no-code apps where multiple SDKs are wired in by an agent (Replit Agent, Cursor, Claude Code, FlutterFlow, Bubble), the auditing problem multiplies: the agent often writes the same hardcoded constant pattern into several files. A pre-submission scan of the compiled IPA (or AAB on Android) against the OWASP MASVS controls catches credential-shaped strings before App Review does. PTKD.com (https://ptkd.com) is one of the platforms focused on that kind of pre-submission read for iOS and Android builds.
What if the key is meant to be public, like a Firebase web API key?
Some keys are not secrets in the cryptographic sense. The Firebase documentation on API keys explicitly states that Firebase API keys for web and mobile apps are designed to be embedded in the client and identify your Firebase project to the API. They do not authorize access to data; Firebase Security Rules do that. Apple's scan can still flag the string because it matches the AIza-prefix pattern.
The clean reply in that case is a Resolution Center note explaining that the key is a public identifier (with a link to Firebase's documentation), confirming that the Realtime Database, Firestore, and Cloud Storage have rules in place that enforce per-user access, and that Cloud Functions called from the client require Firebase Authentication. App Review accepts that framing when the supporting evidence sits inside the reply.
The same pattern holds for Stripe publishable keys (pk_live_ prefix), Google Maps client keys with bundle restrictions, and Algolia search-only keys. The rule is that a public key requires provider-side restrictions, not removal.
What to watch out for
- Rotating to a new key but committing the new key the same way as the old one. The second submission carries the same risk and reviewers notice the pattern.
- Leaving the key in a JavaScript bundle inside a React Native or Capacitor build. The compiled binary path looks clean while the JS bundle still ships the secret in plaintext.
- Storing the encrypted key alongside the decryption key in the same binary. Both come out in the same strings pass.
- Hiding the key inside an asset file (image metadata, custom binary blob, font). Apple's scan reads through resource directories.
- The myth that minification or obfuscation removes the key. Minifiers rename variables, not string literals; the value still appears intact.
- The myth that production builds are signed and unreadable. App Store IPAs are encrypted on disk, but the decrypted binary is fully recoverable on a jailbroken device, and the review pipeline operates on the unencrypted artifact.
Key takeaways
- Apple's rejection for hardcoded API keys usually arrives as a security disclosure paired with Guideline 1.6 (Data Security) or Guideline 2.3 (Accurate Metadata), not as a single named rule.
- Detection layers include regex fingerprinting of known token prefixes (AKIA, sk_live_, SG., xoxb-), targeted scans of Info.plist, GoogleService-Info.plist, and JS bundles, plus third-party researcher feeds.
- The fix is a four-part sequence: rotate with the provider, remove from the source, rebuild a clean IPA verified with the strings command, and reply with the rotation timestamp.
- Some keys (Firebase web API key, Stripe publishable key, Google Maps client key) are designed to be public and require provider-side restrictions instead of removal; document the restrictions in the Resolution Center reply.
- For teams shipping AI-coded or no-code apps where credential patterns get spread across multiple files by an agent, scanning the compiled IPA or AAB against OWASP MASVS using a platform such as PTKD.com (https://ptkd.com) catches hardcoded keys, mis-scoped Firebase rules, and adjacent credential issues before App Review does.




