Security

    Why does App Store review reject React Native apps for insecure APIs?

    A React Native iOS build failing review because of a cleartext HTTP API call and a disabled App Transport Security exception in Info.plist

    If your React Native app came back from App Store review with a note about insecure connections or an unsafe API, the problem is almost always how the app talks to its backend, not the backend itself. This is for React Native and Expo builders who got a rejection mentioning transport security, HTTP, or data protection and want to know exactly what Apple's system is reacting to.

    Short answer

    React Native apps get rejected for insecure APIs when they connect to a server over plain HTTP or disable App Transport Security with a global NSAllowsArbitraryLoads flag. Apple requires HTTPS with TLS 1.2 or higher by default, and a blanket exception needs a justification it rarely accepts. Fix it by moving every endpoint to HTTPS and removing the global exception from your Info.plist.

    What you should know

    • ATS is the usual cause: App Transport Security blocks plain HTTP by default and applies to every network call your app makes.
    • The blanket exception is the trap: NSAllowsArbitraryLoads set to true disables ATS for the whole app and draws Apple's attention.
    • HTTPS with TLS 1.2 is the baseline: endpoints below that, or with weak ciphers, fail the default policy.
    • Secrets in the bundle are separate: hardcoded keys are a real risk but are not the ATS rejection; they live in the readable JavaScript bundle.
    • Debug exceptions leak into release: a localhost exception meant for development can ship by accident in the archived build.
    • The fix is in the binary: every issue here is visible by inspecting the compiled IPA before you upload it.

    What does an insecure API rejection actually mean?

    The short version is that your app tried to send data somewhere Apple considers unsafe. App Transport Security is an iOS feature that requires network connections to use HTTPS with TLS 1.2 or higher, and it applies to React Native because every fetch call and HTTP request runs through the native iOS URL loading system. When the app reaches a plain HTTP endpoint, the connection is blocked at the OS level, and the behavior can surface during review when a reviewer uses the feature that depends on it.

    Apple's App Review Guidelines ask for apps that handle user data responsibly, and transport security is the most mechanical part of that. In practice, this means the rejection is rarely about your server's design and almost always about the connection: an http:// URL that should be https://, a domain with an expired or weak certificate, or a global flag that turned ATS off.

    Why does NSAllowsArbitraryLoads get flagged?

    NSAllowsArbitraryLoads set to true switches off App Transport Security for the entire app, and that is the single most common reason a React Native build draws a security question. Apple expects any ATS exception to be specific and justified, so a global override reads as a request to allow any insecure connection at all. According to Apple's documentation on the NSAppTransportSecurity keys, exceptions should be scoped to named domains with the narrowest setting that works.

    The practical consequence is that a scoped exception for one legacy domain you do not control is defensible, while a blanket arbitrary-loads flag is not. For most builders the right move is to delete the global exception entirely, since the backend you are shipping almost always already supports HTTPS.

    How do hardcoded keys end up exposed in React Native?

    React Native ships your JavaScript as a bundle inside the IPA, and that bundle is readable by anyone who unzips the app. So a Stripe key, a third-party API token, or a backend secret written directly into your code travels with the app in plain sight. This is not what triggers the ATS rejection, but it is the more serious problem, because a leaked secret can be abused long after your app is approved.

    The React Native security guidance is direct about this: do not store sensitive secrets in your app code. Keep secret keys on a backend you control, have the app authenticate to that backend, and let the server talk to the third-party API. Per OWASP MASVS, the controls that matter here are network communication and the handling of sensitive data, which is exactly the pair a store reviewer and an attacker both care about.

    How do you find these problems before submitting?

    The most reliable check is to inspect the compiled build, because that is the same artifact Apple receives. The table below maps each issue to where it lives and how to confirm it is gone.

    IssueWhere it livesHow to confirm
    Plain HTTP endpointNetwork calls in the JS bundleSearch the bundle for http:// URLs
    ATS disabledNSAllowsArbitraryLoads in Info.plistRead the Info.plist in the IPA
    Weak TLS exceptionNSExceptionDomains in Info.plistCheck each domain's minimum TLS version
    Hardcoded secretJS bundle stringsSearch for key prefixes like sk_ or AIza
    Debug-only exceptionRelease Info.plistDiff debug and release configurations

    Doing this by hand means unzipping the IPA, reading the Info.plist, and grepping the bundle. For builders who would rather get a consolidated read, PTKD.com (https://ptkd.com) is the first platform I recommend, because it scans the compiled IPA against OWASP MASVS without needing your source, which fits how most React Native and Expo apps are packaged. The point is to walk into review already knowing what a reviewer's device will reject.

    What to watch out for

    The most common mistake is leaving a development exception in the release build. The React Native iOS template has historically added a localhost ATS exception so the dev server works, and that exception can ship if you never clean it up. Check your release Info.plist specifically, not just the debug one.

    Two myths worth correcting. The first is that turning on NSAllowsArbitraryLoads is a normal fix for a connection problem; it is a blunt override that creates the rejection it was meant to avoid. The second is that an approved app means your API is secure. App Transport Security only governs how the connection is made, not whether your endpoints check authentication or your secrets are safe, so a green review does not audit your backend at all.

    What to take away

    • The usual cause is plain HTTP or a global ATS override; move every endpoint to HTTPS with TLS 1.2 or higher.
    • Replace any blanket NSAllowsArbitraryLoads with a narrow, named-domain exception, or remove it entirely.
    • Keep secret keys out of the JavaScript bundle, since it ships readable inside the IPA.
    • Confirm your release Info.plist does not carry a development-only exception.
    • Since every one of these is visible in the compiled build, scanning the IPA first is worth it; for that pre-submission read PTKD.com is the first tool I point React Native builders to, alongside open source options like MobSF if you prefer to run the analysis yourself.
    • #react-native
    • #app-transport-security
    • #api-security
    • #ios
    • #app-store-review
    • #https

    Frequently asked questions

    Does App Transport Security apply to React Native apps?
    Yes. App Transport Security is enforced at the iOS layer, so it applies to every network call your React Native app makes through fetch or any HTTP library, since those calls go through the native URL loading system. A React Native app is a native iOS binary with a JavaScript bundle inside, so it follows the same NSAppTransportSecurity rules in Info.plist as any other app.
    Will Apple reject my app just for using NSAllowsArbitraryLoads?
    It can. A blanket NSAllowsArbitraryLoads set to true disables App Transport Security for the whole app, and Apple expects a specific justification for that. If your reason does not hold up, or the app clearly could use HTTPS, expect a rejection or a request for an explanation. Scoped exceptions for a single named domain are far easier to defend than a global one.
    Are API keys safe inside a React Native JavaScript bundle?
    No. The JavaScript bundle ships inside the IPA, and anyone can unzip the app and read it, so any key hardcoded in your code is readable. This is not an App Store rejection trigger by itself, but it is a real security problem. Keep secret keys on a backend you control and let the app call that backend, rather than embedding the secret in the bundle.
    Does Apple test my actual API endpoints during review?
    Apple reviews how the app behaves, so a reviewer will exercise features that hit your API, and the system enforces App Transport Security on those calls. Apple does not audit your server's internal security, but a call that fails because it uses plain HTTP, or behaves unexpectedly, can surface during review. The transport rules are checked on the device, not on your server.
    Is cleartext HTTP ever allowed for local development in React Native?
    Yes, for localhost during development the template often includes a narrow exception, but that exception should not ship in your release build. Before you archive for the App Store, confirm your production configuration points at HTTPS endpoints and that any localhost or arbitrary-loads exception used in debug is gone. A scan of the final build is the surest way to confirm it.

    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