AppForShare

iOS App Transport Security exceptions: what each key loosens

· 5 min read

iOS App Transport Security exceptions: what each key loosens

App Transport Security (ATS) is the iOS rule that network connections made with URLSession and the system's web views use HTTPS with modern TLS. It has been on by default since iOS 9. Developers can loosen it with keys in Info.plist, and most apps that do so added an exception once to talk to a staging server, an old API or a video host, then never removed it.

This guide explains what each ATS key does, which ones App Review may ask you to justify, and how to remove them without breaking the app.

What ATS requires by default

With no ATS keys at all, a connection must use HTTPS with TLS 1.2 or later, a cipher with forward secrecy, and a certificate with a strong key signed with SHA-256 or better. Plain http:// loads fail. That default covers nearly every modern backend and CDN.

The keys, one by one

KeyWhat it loosensTypical reason
NSAllowsArbitraryLoadsTurns ATS off for every domain not listed in exceptions"It did not work, so we turned it off"
NSAllowsArbitraryLoadsInWebContentLets web views load any content, while app network calls keep ATSA browser like feature or user supplied links
NSAllowsArbitraryLoadsForMediaLets AVFoundation play media that is not protected by ATSStreams from hosts you do not control
NSAllowsLocalNetworkingAllows plain connections to local names and IP addressesTalking to a device on the same Wi-Fi
NSExceptionDomainsA dictionary of domains, each with its own exceptionsOne old server or a staging host
NSExceptionAllowsInsecureHTTPLoadsPlain HTTP for that domainA server without TLS
NSExceptionMinimumTLSVersionAccepts an older TLS version for that domainA legacy server on TLS 1.0 or 1.1
NSExceptionRequiresForwardSecrecy set to NOAccepts ciphers without forward secrecyAn old load balancer
NSIncludesSubdomainsApplies the domain's exceptions to every subdomainConvenience, often wider than needed

One detail matters for reading an Info.plist: since iOS 10, when any of NSAllowsArbitraryLoadsInWebContent, NSAllowsArbitraryLoadsForMedia or NSAllowsLocalNetworking is present, the system ignores NSAllowsArbitraryLoads. Many apps carry both, and the result is less open than it looks.

Why it matters

Every exception is a place where traffic can be read or changed on the way, for example on public Wi-Fi. Plain HTTP exposes everything. Old TLS versions and ciphers without forward secrecy have known weaknesses. A subdomain wildcard can open far more hosts than the one server you meant. In the OWASP MASVS, this is MASVS-NETWORK: the app secures all network traffic according to current best practices.

App Review can ask why an app turns ATS off with NSAllowsArbitraryLoads. Narrow, per domain exceptions with a clear reason are easier to explain than a global switch.

How to find what your build carries

  1. Unzip the .ipa and run plutil -p Payload/MyApp.app/Info.plist. Look for NSAppTransportSecurity.
  2. Check each build configuration. Teams often add exceptions to the Debug Info.plist or through a build setting, and they leak into Release when the files are shared.
  3. Check app extensions too. Each one has its own Info.plist.
  4. Our free IPA inspector also reads the file in your browser and runs the store readiness rules, including a global ATS switch.

How to remove them safely

  1. List the hosts the app really calls. Turn on Network logging in Xcode or use a proxy on a test phone. Many exceptions point at servers that no longer exist.
  2. Fix the server, not the app. Most hosts now offer TLS 1.2 or 1.3 for free through their CDN or a free certificate. Once the server is fixed, delete the exception.
  3. Narrow what must stay. Replace NSAllowsArbitraryLoads with one entry in NSExceptionDomains, without NSIncludesSubdomains unless you need it.
  4. Keep test hosts out of Release. Use a separate Info.plist or a build setting so the staging exception exists only in Debug and Ad Hoc test configurations, and check the built file to be sure.
  5. Use the specific keys. If the exception exists for a web view or media player only, use the web content or media key instead of a global switch.

Checking every build automatically

AppForShare runs a security scan on every uploaded .ipa. For ATS it shows:

  • A warning when ATS is off for every domain.
  • A note for each exception domain, with what it loosens: plain HTTP, a lower minimum TLS version, no forward secrecy, or subdomains included.
  • A note when web views may load insecure content.

The same scan checks for get-task-allow in a build that is not development signed, and for local symbols left in the binary. Each finding carries a MASVS category and a fix. Free accounts see the counts; Pro and Team see the findings, and Team keeps a findings history per app, so you see in which build a finding appeared and in which it was fixed. The docs list every check.

It reads Info.plist only. It cannot see which hosts the app calls at runtime, and it does not test the servers themselves.

Common questions

Will App Store review reject an app with ATS exceptions?

Not automatically. Narrow exceptions are common. A global switch may draw a question, so be ready with a reason or remove it. Our App Store rejection reasons guide covers the usual causes.

Do ATS rules apply to other networking libraries?

ATS applies to the system's URL loading and web views. Libraries built on URLSession, which is most of them, follow it. Code that opens raw sockets does not, so check those paths yourself.

Is NSAllowsLocalNetworking a risk?

It is narrow: it covers local names and IP addresses. It is fine for apps that talk to devices on the same network, and worth removing if the app does not.

For the rest of the pre share checklist, see security checks before you share an IPA or APK and the iOS test build checklist. To see your build's ATS findings, create a free account and upload an IPA.

Keep reading

App Distribution Platform · · 5 min read

AppForShare File Size and Upload Limits

AppForShare limits the size of each build you upload by plan: 50 MB without an account, 150 MB on the Free plan, 2 GB on Pro and 4 GB on Team. Accounts also have a storage total, and every plan...