Introducing the Trust Stores Observatory

For anyone interested in SSL/TLS, certificates, and trust, it has always been surpisingly difficult to get the list of root certificates trusted on each of the major platforms (Mozilla, Microsoft, etc.).

The only tool that I am aware of is the Certification Authority Trust Tracker (CATT), which I have been using for many years in order to retrieve the root stores to be used in SSLyze, the SSL scanning tool I work on. However and as useful as it has been, CATT has to be run manually every time, and is not easy to extend or troubleshoot as it relies on several scripts written in Bash or Perl.

Because it shouldn’t be this hard to retrieve and monitor the content of the main platforms’ root stores, I have been working on a new project called the Trust Stores Observatory; it provides the following features:

  • An easy way to download the most up-to-date root certificate stores, via a permanent link:
  • The ability to record any changes made to the root stores, by committing such changes to Git. This way we can keep the history of the root stores and for example keep track of when a new root certificate was added.
  • The ability to review and compare the content of the different root stores, by storing the content of each store in a YAML file.

Supported platforms

The Trust Stores Observatory currently supports the following platforms:

How it works

The project is implemented using Python 3.6. Each root store is stored in a YAML file in the project’s repository; the YAML file contains the subject name and the fingerprint of every trusted and blocked root certificate.

Once a week, a Travis cron is automatically run in order to retrieve the latest version of each root store, and to commit any changes to the observatory’s repository.

What’s next?

  • Support for additional platforms and root stores (Java, Ubuntu, etc.).
  • Support for also retrieving the list of EV OIDs.
  • Better handling of special restrictions (name constraints, notBefore, etc.) as several platforms have implemented custom restrictions for some CA certificates.

Check it out

Head to the project’s page for more information and feel free to reach out if you have questions or feedback!

January 16, 2018

Scanning for the ROBOT Vulnerability at Scale

I just released SSLyze 1.3.0, which adds support for scanning for the ROBOT vulnerability that was disclosed last week.

Using SSLyze’s Python API, it is possible to easily and quickly scan a lot of servers for the vulnerability. From my own testing and depending on the network conditions, it takes about 5 seconds to scan 20 servers. SSLyze also has the ability to scan servers that use StartTLS-based protocols (such as SMTP, XMPP, etc.), which the test script released along with ROBOT does not support.

The following script (tested on Python 3.6) demonstrates how it can be done:

Enjoy and happy scanning!

December 17, 2017

Mobile TLS Interception Presentation at BlueHat

Earlier today, Thomas Sileo and myself presented at the Microsoft BlueHat conference in Redmond.

The title of the talk was “Where, how, and why is SSL traffic on mobile getting intercepted? A look at ten million real-world SSL incidents”. This is a research project we’ve been working for a couple years; we’ve analyzed pinning failure reports that mobile developers who use TrustKit in their apps have shared with us.

So far, we’ve received about 10 million reports coming from devices all around the world, and we’ve discussed some of the results of our analysis in this presentation.

The slides are now available for download here.

November 08, 2017

SSLyze for Python 3 Released

I just released SSLyze v1.1.0, which finally adds support for Python 3! This means that both the command line tool and the Python API can be called using Python 3.3+. Python 2.7 is still supported, for now.

Head to the project’s page for more information.

Full Changelog

  • Added support for Python 3.3+ on Linux and MacOS. Windows will be supported later.
  • Added support for scanning for cipher suites on servers that require client authentication.
  • Certificate transparency SCTs via OCSP Stapling will be now displayed when running a CertificateInfoScanCommand.
  • Removed custom code for parsing X509 certificates, which was the source of numerous bugs and crashes when running a CertificateInfoScanCommand:
    • Certificates returned by the SSLyze Python API are now parsed using the cryptography library, making further processing a lot easier and cleaner.
    • Certificates returned in the XML and JSON output when using --certinfo are no longer parsed. XML/JSON consumers should instead parse the PEM-formatted certificate available in the output using their language/framework’s X509 libraries.
    • The --print_full_certificate option when using --certinfo is no longer available.
  • Bug fixes for the Heartbleed check.
  • Added unit tests for SSL 2.0, SSL 3.0, Heartbleed and OpenSSL CCS injection checks.

The Python API can do a lot more than this (such as scanning StartTLS endpoints, connecting through a proxy, or enabling client authentication); head to the project’s page or the documentation for more information.

April 22, 2017

SSLyze v1.0.0 Released

I just released a new version of SSLyze, my Python tool/library which can analyze the SSL configuration of a server by connecting to it and detect various issues (bad certificates, dangerous cipher suites, lack of session resumption, etc.).

After almost 20 releases over the past 6 years, SSLyze is now at version 1.0.0. This is a major release as I have completed a significant refactoring of SSLyze’s internals,in order to clean its Python API. The API should be considered stable and is now fully documented!

Using SSLyze as a Python module makes it easy to implement SSL/TLS scanning as part of continuous security testing platform, and detect any misconfiguration across a range of public and/or internal endpoints.

Sample Code

This sample code scans the endpoint to detect the list of SSL 3.0 cipher suites it accepts, whether it supports secure renegotiation, and will also review the server’s certificate:

Getting Started

The Python API can do a lot more than this (such as scanning StartTLS endpoints, connecting through a proxy, or enabling client authentication); head to the project’s page or the documentation for more information.

February 08, 2017

SSL Kill Switch and the iOS 10 Network Stack

After the release of the latest iOS 10 jailbreak, I started getting reports that SSL Kill Switch, my iOS tool to disable SSL pinning in Apps, was not working at all on this version of iOS.

This was very surprising since the tool directly patches the OS’ low-level TLS stack (called SecureTransport) which is used by all the higher-level network APIs on iOS/macOS (CFNetwork, NSURLSession, etc.) to setup a TLS/HTTPS connection with a server. The functions SSL Kill Switch patches are part of SecureTransport’s public API and therefore do not really change across iOS versions, making it unlikely that the tool would just stop working on a new release of iOS.

After doing some investigation, I discovered that the network stack on iOS 10 has changed significantly compared to iOS 9, and I will describe in this post what has changed, why it affected SSL Kill Switch, and how I fixed it.

If you’re looking for the latest SSL Kill Switch binary compatible with iOS 10, go to the Releases tab of the project’s page.

Getting Started

To try to understand why SSL Kill Switch stopped working on iOS 10, I used Xcode and a simple App that opens an HTTPS connection using the NSURLSession API and implements SSL pinning (specifically, the TrustKit Demo App). And as reported, SSL Kill Switch was not able to disable TLS validation when running the App on iOS 10 and trying to use the Burp proxy to intercept the HTTPS connection.

I now needed to figure out what had changed in iOS 10’s network stack, and started by grabbing the dyld shared cache from my iOS 10 device (it’s in /System/Library/Caches/ and opening it in this awesome disassembler called Hopper. Looking at the CFNetwork framework, I started checking TLS methods and symbols, to find the lowest-level TLS function that would be called during a TLS handshake:

Jumping around in various system frameworks and libraries, I eventually settled for the tls_handshake_set_callbacks function in libsystem_coretls.dylib. This function is used to setup callbacks for specific events happening during the TLS handshake; one thing that helped throughout the process is that libsystem_coretls.dylib used to be open-source (athough the iOS implementation might be different).

To try to understand the differences between the iOS 9 and iOS 10 network stacks, I then set a breakpoint on this function in Xcode, in order to be able to look at the stack trace, so I could see the execution flow from the high level NSURLSession network call initiated by my test App, all the way down to this low-level TLS function.

br set -n tls_handshake_set_callbacks
Breakpoint 3: where = libsystem_coretls.dylib`tls_handshake_set_callbacks, address = 0x000000010895928c

This would allow me to understand how the network stack differs on different versions of iOS.

iOS 9 Stack Trace

When the breakpoint is hit, Xcode displays the following stack trace on iOS 9 and 8:

The stack trace looks like this, from top to bottom:

  • tls_handshake_set_callbacks in libsystem_coretls.dylib
  • SSLCreateContextWithRecordFuncs in Security (specifically SecureTransport)
  • SSLCreateContext in Security (specifically SecureTransport)
  • SocketStream::securitySetInfo_NoLock in CFNetwork
  • [Higher level calls]

As expected, we can see SecureTransport functions (SSLCreateContextWithRecordFuncs and SSLCreateContext) being called during the TLS handshake. This is where the previous version of SSL Kill Switch would step in, by patching specific SecureTransport functions to disable TLS validation. Interestingly and as we can see, some of the actual code for the TLS logic is indeed in the libsystem_coretls.dylib library, which is called by SecureTransport. I previously thought that the TLS implementation was all part of SecureTransport.

iOS 10 Stack Trace

On iOS 10, the stack trace for the same breakpoint looks quite different:

More specifically, from top to bottom:

  • tls_handshake_set_callbacks in libsystem_coretls.dylib
  • nw_protocol_coretls_add_input_handler in libnetwork.dylib
  • [More libnetwork.dylib and dispatch calls…]
  • tcp_connection_set_tls in libnetwork.dylib
  • TCPIOConnection::_tlsEnable in CFNetwork
  • [Higher level calls]

As we can see, there are no SecureTransport functions called during the TLS handshake! Instead, some new functions within libnetwork.dylib are used, which then call libsystem_coretls.dylib, similarly to SecureTransport on iOS 9.


Apple has significantly changed the network stack on iOS 10:

  • On iOS 9, an HTTPS connection iniitiated via NSURLSession involves CFNetwork’s SocketStream, SecureTransport and libsystem_coretls.dylib.
  • On iOS 10, the same connection involves CFNetwork’s TCPIOConnection, libnetwork.dylib and libsystem_coretls.dylib

Without access to the source code, it is hard to tell how big of a change this is: is it some kind of refactoring / cleaning up that mainly affects the libraries’ interfaces and flows, or are the implementations also very different?

Also, libnetwork.dylib already existed on iOS 9, but did not have a lot of the functions that are used in iOS 10 for network connections (they are called nw_xxx). For instance, when trying to set a breakpoint for nw_protocol_coretls_add_input_handler on iOS 9, we can see that the function does not exist:

br set -n nw_protocol_coretls_add_input_handler
WARNING:  Unable to resolve breakpoint to any actual locations.

Because SecureTransport is no longer used by higher level APIs (such as CFNetwork or NSURLSession) on iOS 10, patching SecureTransport functions like SSL Kill Switch does has no effect on an App’s TLS connections. This expains why the tool completely stopped working.

I wonder if these changes mean that Apple will eventually deprecate SecureTransport and expose the iOS 10 network/TLS stack as a public API?

Fixing SSL Kill Switch on iOS 10

Now armed with a better understanding of the iOS 10 network stack, I started investigating how TLS validation was done in TCPIOConnectionand libnetwork.dylib, in order to find a way to disable the system’s default TLS validation and any code that customizes it (which is how SSL pinning is done).

When I did it for SecureTransport a few years ago for the previous versions of SSL Kill Switch, the customization mechanism for TLS validation was well-documented as SecureTransport is a public API, and therefore easy to understand.

However, TCPIOConnection, libnetwork.dylib and libsystem_coretls.dylib are all undocumented, private APIs, making this process a lot more time-consuming. Luckily, while playing around with some of the TLS functions in these libraries, I quickly stumbled upon an unexpected solution.

The tls_helper_create_peer_trust in libcoretls_cfhelpers.dylib seemed interesting, as it is used to retrieve the server’s SecTrustRef during the TLS handshake. In the Cocoa world, a SecTrustRef is an object that represents the server’s certificate chain and the policy to use to validate it; it is the main object to use when doing TLS validation. The open-source implementation of the function also made it a lot easier to confirm how it works and what it does:

OSStatus tls_helper_create_peer_trust(tls_handshake_t hdsk, bool server, SecTrustRef *trustRef);

The tls_helper_create_peer_trust function generates the server’s SecTrustRef from a tls_handshake_t object (which represents an ongoing TLS handshake) and puts it in the supplied trustRef argument. The trustRef object can then be used by the caller to do TLS validation and verify the server’s identity.

As a random experimentation, I patched this function (using Cydia Substrate) to make it not do anything:

static OSStatus replaced_tls_helper_create_peer_trust(void *hdsk, bool server, SecTrustRef *trustRef)
    return errSecSuccess;

With the patch applied, the trustRef does not contain anything at the end of the call to tls_helper_create_peer_trust.

I was expecting this change to completely crash the App during the TLS handshake, as whatever code that is doing the TLS validation (probably inside CFNetwork) would get a NULL trust object as the server’s identity (which can never happen), and wouldn’t be able to process further. However, instead of crashing, it completely disabled all TLS validation and pinning, which is exactly what I was trying to do!

It is still unclear to me why this actually works; it seems like the validation logic or callback somehow is ignored when the server’s SecTrustRef is NULL. This is obviously not a vulnerability, as I am injecting code in the App to trigger this behavior, but it is a bit surprising to me. If I ever have the time, I will dig further into this to try to understand what’s going on.

In the meantime enjoy the iOS 10 release!

February 05, 2017
ios, ssl

TrustKit Android Released

A couple days ago, a cowoker and I released TrustKit for Android: an open source library that makes it easy to deploy SSL public key pinning and reporting in any Android App.

This follows the release of TrustKit iOS two years ago, which has now been deployed in many iOS Apps, in order to make their network connections more secure. We hope that TrustKit Android will help developers get more visibliity in their App’s network behavior through TrustKit’s reporting mechanism, and more security via SSL pinning.


TrustKit Android works by extending the Android N Network Security Configuration in two ways:

  • It provides support for the <pin-set> (for SSL pinning) and <debug-overrides> functionality of the Network Security Configuration to earlier versions of Android, down to API level 17. This allows Apps that support versions of Android earlier than N to implement SSL pinning in a way that is future-proof.
  • It adds the ability to send reports when pinning validation failed for a specific connection. Reports have a format that is similar to the report-uri feature of HTTP Public Key Pinning and TrustKit iOS.

For better compatibility, TrustKit will also run on API levels 15 and 16 but its functionality will be disabled.

Getting Started

Check out the the project’s page on GitHub or jump straight into the documentation.

January 25, 2017
android, ssl

iOS 10 Security Changes Slide Deck

I hosted an online Tech Talk on October 19th about the security & privacy changes introduced in iOS 10. I talked about both user-facing and developer-facing changes that I thought were interesting. The last section also provides some guidelines on how to be ready for the App Transport Security requirements that Apple will start enforcing on January 2017.

You can download the slide deck here.

As I was preparing the presentation, I discovered that the Apple documentation about App Transport Security has changed significantly over the last couple months. For example, ATS exemptions for third-party domains (such as NSThirdPartyExceptionAllowsInsecureHTTPLoads) have been removed from the documentation, implying that developers can just use the regular exemptions even for third-party domains.

Hence, the slide deck contains the most up-to-date information about iOS 10 and ATS, but I will update the previous blogs posts with these additional changes.

September 19, 2016

Security and Privacy Changes in iOS 10

I just finished watching most of the WWDC 2016 videos and reviewing the iOS 10 API diffs, and put together some notes about the security and privacy changes brought by iOS 10 that I thought were interesting.

ATS required by 2017

App Transport Security was introduced last year and by default blocks “unprotected” connections initiated by Apps, ie. connections that do not use HTTPS with the strongest TLS version and cipher suites. Because switching servers to the strongest TLS configuration takes time, Apple also allowed App developers to selectively disable ATS requirements by adding exemptions in the App’s Info.plist.

This year at WWDC, Apple announced that Apps and their servers will be required to be ATS-compliant by January 2017 or App releases will be blocked when pushed to the App Store.

The “Getting Ready for ATS Enforcement in 2017” blog post provides more details about the announcement and what App developers should do to be compliant.

Purpose strings required

When built for iOS 10, an App will crash if it tries to request access for a data class that does not have a purpose string defined. Purpose string keys where introduced in iOS 6; there is one key defined for each type of privacy-sensitive data (contacts, camera, photo library, etc.). App developers can add these keys to the App’s Info.plist to provide a sentence that explains why the App needs access to the data; the explanation then gets displayed in the user-facing permission prompt:

Not providing a purpose string will now crash the App when the permission prompt was going to be displayed. Apple made this change for two reasons:

  • It forces App developers to inform the user about the reason why the App needs access to the data.
  • It prevents third-party SDKs within the App from requesting access to data the App developers never intended to access in the first place.

Additionally, there are several new consent alerts in iOS 10, with a corresponding purpose string:

  • Media Library, for allowing access to Apple Music subscriber status and playlists.
  • Speech Recognition, for allowing audio files to be sent to Apple for speech transcription done on behalf of the App.
  • SiriKit, for allowing the App to receive Siri requests.
  • TV Provider information (tvOS only), for automatically logging the user into streaming Apps based on their cable subscription.

Unified Security APIs for certificate and key management

Apple has made a significant effort to extend and standardize the SecKey APIs across all Apple platforms (iOS 10, macOS 10.12, tvOS 10 and watchOS 3). This will make it a lot simpler to write code to handle certificates or keys that can be shared across different Apps and platforms.

The SecKey APIs available within the Security framework are used for managing certificates, symmetric/asymmetric keys, and signatures. However, before iOS 10 and macOS 10.12, the functions available for interacting with this type of data behaved differently on iOS compared to macOS, and a lot of the functions were only available on macOS. For example, the SecCertificateCopyValues() function needed for extracting the public key from a certificate was not available on iOS, making it difficult to properly implement SSL pinning on iOS.

Stricter controls on Ad tracking

On iOS 10, when the “Limit Ad Tracking” setting is enabled by the user, the Advertiser ID (IDFA) returned to the App will be all 0s.

The App Store review process has always had strict guidelines about when it is acceptable for an App to collect the IDFA, and requires during the App submission flow a confirmation that the user’s “Limit Ad Tracking” setting is properly properly taken into account by the App:

Because the IDFA uniquely tracks a device and is the same value returned to all Apps on a given device, it is sensitive data which for example can be used by analytics SDKs to track a single user across different, unrelated Apps.

Prior to iOS 10, enforcement was only done during the App Store review process and there was no enforcement at the device-level of the “Limit Ad Tracking” setting; in theory, Apps could still query and use the IDFA regardless of the user’s choice. With iOS 10, the IDFA will be empty if “Limit Ad Tracking” is enabled, which will put an end to any kind of abuse where users would be tracked regardless of of the tracking preference.

Additionally, Apple will be providing more control and information about ads to the user:

  • In the Apple News and App Store Apps, any Ad displayed will have a new “About this Ad” button, which specifies why this Ad was displayed to the user (age range, location, etc.)
  • In the device’s privacy settings, a new “Ad Information” screen will provide details about the user’s Ad profiling information: the set of data used for displaying Ads targeting this specific user.

Pasteboard refinements

Along with the general pasteboard (where data gets put when the user manually copies data), named pasteboards have always been available on iOS and work like an App-generated piece of shared memory. Over the years, Apple has been making named pasteboards less and less useful as a hacky inter-App communication mechanism, especially with iOS 7, when named pasteboards could no longer be shared across Apps from different vendors.

iOS 10 deprecates persistent named pasteboards (ie. pasteboards which continue to exist past app terminations and across system reboots) and Apple is advising developers to use Shared Containers instead. Shared Containers were introduced more recently with iOS 8, but fulfill a similar purpose.

There also also additional pasteboard changes with iOS 10:

  • Content within the general pasteboard gets automatically synced across the user’s devices via Handoff. To exclude some content from Handoff, the UIPasteboardOptionLocalOnly option should be used.
  • With the UIPasteboardOptionExpirationDate, it is possible to set an expiration date for content put in a UIPasteboard. For most use cases this should be leveraged by App developers when putting content in the general pasteboard, which is accessible to all Apps.

Other interesting changes

  • Certificate transparency, which helps detect compromised Certificate Authorities and mis-issued SSL certificates, can be enforced within an App by adding the NSRequiresCertificateTransparency key to the App’s App Transport Security Policy. This requires the proper SSL certificates (from a CT-enabled CA such as Let’s Encrypt) and configuration to be deployed on the App’s servers.

  • The new unified logging APIs, which supersede ASL (Apple System Logger) and the Syslog APIs, will not log dynamic strings and complex dynamic objects by default, for privacy reasons. Logging of such objects can be forced by declaring the string public using the keyword public in the string format: %{public}s.

  • For some of the analytics data it is collecting from the user’s devices (such as popular words and emojis), Apple is using differential privacy to anonymize the data; this is explained in detail in the “Engineering Privacy for Your Users” WWDC presentation.

  • A new NSURLSession delegate method URLSession:task:didFinishCollectingMetrics: is available for collecting network statistics while the App is connecting to its servers. Currently, analytics SDKs generate these statistics by doing method hooking/swizzling on the NSURLConnection and NSURLSession APIs, which can impact stability and performance. This new delegate method provides a cleaner way to generate such statistics.

August 16, 2016

Getting Ready for ATS Enforcement in 2017

Edit: This blog post was updated on the 20th of October 2016 to take into account recent changes made by Apple to App Transport Security and how ATS exemptions work; for example, the third-party domain exemptions were removed from the documentation. Apple also released additional details in regards to the App Store review process and potential rejections due to ATS exemptions that are described here.

Edit 2: On the 21st of December 2016, Apple announced on its developer portal that the January 1st deadline “has been extended and [Apple] will provide another update when a new deadline is confirmed”. I will update this blog post with the new ATS deadline as soon as Apple announces it.

App Transport Security was introduced last year with iOS 9 as a security mechanism that blocks “unprotected” connections initiated by Apps, ie. connections that do not use HTTPS with the strongest TLS version and cipher suites.

Because switching servers to the strongest TLS configuration takes time, Apple also allowed developers to disable some or all of ATS’ requirements using various exemption keys to be added to the App’s Info.plist. Exemptions could be set for specific domains and/or specific ATS requirements (for example to allow TLS 1.0 instead of 1.2, or to re-enable plaintext HTTP connections).

ATS Enforcement in 2017

This year at WWDC, Apple announced that Apps and their servers will be required to be ATS-compliant by January 2017 or App releases will be blocked when pushed to the App Store. They specified three ATS exemptions that will trigger a rejection, unless a valid justification is supplied:

  • NSAllowsArbitraryLoads, which disables ATS for all domains. ATS can be re-enabled for specific domains by using an exception domain dictionary.
  • NSExceptionAllowsInsecureHTTPLoads, which disables ATS for a single domain, to allow insecure HTTP loads to that domain.
  • NSExceptionMinimumTLSVersion, which enables support for TLS versions that are older than 1.2 for a specific domain.

Hence and to avoid a rejection during the Apple App Store review process, care must be taken when building the App’s ATS policy, in order to avoid using blacklisted exemptions, or using such exemptions in a way that can be justified to the App Store review team.

There are mainly three different use cases to consider when building the ATS policy:

  • Servers under the developer team’s control that the App connects to.
  • Third-party servers that the App connects to, for example via connections initiated by SDKs.
  • Webviews displaying arbitrary websites to provide a browser-like functionality.

Servers Under the Developer’s Control

For App servers under the development team’s control (ie. not third-party servers) update the servers’ configuration to support HTTPS with TLS 1.2.

Then, remove any blacklisted exemption (NSAllowsArbitraryLoads, NSExceptionAllowsInsecureHTTPLoads and NSExceptionMinimumTLSVersion) from the App’s Info.plist and validate that the App can properly connect to its server endpoints on iOS 9+ devices.

Other ATS exemptions (such as NSExceptionRequiresForwardSecrecy) will not trigger an App Store rejection and, for now, can be left enabled if needed.

Third-Party Servers

For third-party servers that the App connects to, any ATS exemption can be used, including domain-specific blacklisted exemptions, as Apple has stated that not having control of the server was a reasonable justification.

Doing so will require identifying the list of third-party servers the App connects to, in order to be able to add the proper domain-specific ATS exemptions to the App.

WebViews Displaying Arbitrary Websites

For UIWebView and WKWebView webviews within the App that are used to display arbitrary websites (to provide a browser-like functionality), a well-defined list of third-party servers the App connects to cannot be built. Hence, Apple has provided two possible solutions for this specific use case.

A new NSAllowsArbitraryLoadsInWebContent ATS exemption introduced in iOS 10 can be used to disable ATS in all of the App’s webviews. Because this exemption will only work on iOS 10 devices, Apple has also introduced a new behavior in order to allow disabling ATS in webviews on iOS 9 devices: when combining NSAllowsArbitraryLoadsInWebContent with NSAllowsArbitraryLoads, the latter exemption will be ignored on iOS 10. Even though NSAllowsArbitraryLoads will trigger a deeper App review, using these two exemptions together for the webview use-case will be a reasonable justification, according to Apple statements on the developer forums.

However, a better, future-proof approach for displaying arbitrary websites is to leverage the SFSafariViewController introduced in iOS 9, which was specifically designed for this purpose. As mentioned in the Apple documentation:

“Use the SFSafariViewController class if your app lets users view websites from anywhere on the Internet. Use the WKWebView class if your app customizes, interacts with, or controls the display of web content.”

Specifically, the tradeoffs when using SFSafariViewController are the following:

  • ATS is disabled, allowing any website to be browsed regardless of the site’s HTTPS configuration.
  • Cookies and website data is shared with Safari, for example allowing the user to stay authenticated in websites accessed from your App.
  • App developers has very little control on the overall navigation experience compared to WKWebView.

When possible SFSafariViewController should be leveraged in order to display third-party websites within the App.


The overall approach the App Store review team will take when it comes to ATS exemptions was summed up on the Apple developer forums:

“The goal here is to flush out those folks who, when ATS was first released, simply turned it off globally and moved on. That will no longer be allowed.”

Hence, for a given App going through the App Store review process:

  • An easy policy to justify is to have NSAllowsArbitraryLoads disabled and a list of domain-specific exemptions for third-party domains the App connects to.
  • A policy that will be harder to justify is to have NSAllowsArbitraryLoads enabled and a list of domain-specific “un-exemptions” for the domains you control.
  • Lastly, a policy that will definitely trigger a rejection, as stated by Apple, is to have NSAllowsArbitraryLoads enabled with no additional ATS settings.

For more information, Apple added a section specifically about ATS and the App Store review process on the documentation website, a few weeks after the WWDC presentation.

Future ATS Requirements

For now, the NSExceptionRequiresForwardSecrecy key will not trigger a rejection, but this will most likely change next year. Hence, support for forward secrecy should be deployed on App servers in order to get rid of this ATS exemption.

Also, in the “What’s new in Security” WWDC presentation, Apple alluded to future requirements for ATS, potentially to be introduced next year:

  • SHA-1-signed certificates should no longer be used, and they are already getting blocked in web browsers.
  • 3DES TLS cipher suites, which are only needed for Windows XP compatibility, should be disabled.

During the presentation, Apple also heavily mentioned Certificate Transparency and OCSP Stapling as technologies that developers should start deploying on their App servers.

August 14, 2016
ios, ssl