Skip to content

Demonstrating a severe bug of UIDocumentBrowserViewController causing an app failing to open its own documents

License

Notifications You must be signed in to change notification settings

frankshaka/uti-race-demo

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

7 Commits
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Overview

This repository demonstrates how the UIDocumentBrowserViewController component is broken by a race condition issue caused by multiple iOS apps trying to register different Uniform Type Identifiers (aka. UTI) against the same filename extension.

This issue affects ALL iOS apps that adpot UIDocumentBrowserViewController since iOS 11 and, when it happens, the whole app is malfunctioning because it can NOT open its own documents. It must be fixed, and can only be fixed, by Apple.

Steps to Reproduce

  1. Clone this repository.

  2. Open the "InnocentApp" project (a minimal Document-based App) using Xcode, select a testing device (either a simulator or a real device, iPad recommended), build and run the app.

    Screenshot of the InnocentApp Xcode project

  3. When the "InnocentApp" is launched, tap the "+" button to create a few empty documents, e.g. New Document.innocent.

    Screenshot of the InnocentApp' document browser with available documents

  4. Try tapping these files, and make sure that they can be opened in a simple document view.

    Screenshot of the InnocentApp's document view

  5. Return to Xcode, and open the "MalicousApp" project, build and run it on the same device chosen above.

    Screenshot of the MaliciousApp Xcode project

  6. When the "MaliciousApp" is installed and launched, you don't even need to perform any interaction with this app, just simply return to the Home Screen and re-open the "InnocentApp" (or you can do so using the App Switcher).

  7. Here the "MAGIC" happens: All .innocent documents in the document browser can NO LONGER be opened inside the "InnocentApp"! You can NOT even rename or delete them! And the most weird thing is that you CAN still create new .innocent documents, but you can NO LONGER re-open them! Now the app becomes totally useless since no documents created by the app can be opened from within the app.

    Screenshot of the InnocentApp's document browser with unavailable documents

  8. Now return to the Home Screen, delete the "MaliciousApp", and return to the "InnocentApp". You should be able to open/edit/rename/delete those documents again.

What's Wrong?

The "InnocentApp" declares an "Exported UTI" named me.frankshaka.file.innocent and associate it with the filename extension innocent, according to this developer guide from Apple about Declaring New UTIs.

Screenshot of the InnocentApp's document type declarations

The "MaliciousApp" also declares an "Exported UTI" to be associated with this filename extension, but using a different identifier me.frankshaka.file.malicious.

Screenshot of the MaliciousApp's document type declarations

When an app is installed (or updated), the operating system reads the app's UTI declarations and automatically registers them in the File Metadata Core Service. This behavior is the same on both iOS and macOS.

Obviously, one kind of filename extensions can only be associated with one UTI across the system. So, when the "MalicousApp" is installed, all .innocent files across the system will hence be regarded as documents of type me.frankshaka.file.malicious.

What's actually wrong is that UIDocumentBrowserViewController thinks that the "InnocentApp" is not permitted to open .innocent files just because the app is not associated with the malicious UTI. This does NOT make sense. The document browser is just a normal component of the app from the user's point of view, rather than a system widget like a Share Sheet or a Document Picker, and thus it should behave the same way and obey the same rules as other components of the same app, no matter how it works.

This issue is disgusting because, as the developer of the "InnocentApp", you've done nothing wrong. You precisely followed the Apple's documentation and tutorials, and even created the app from the Xcode template "Document-based App". But one day, you suddenly receive thousands of emails from angry users, or even thousands of 1-star comments to your app in the App Store, reporting that your app does not work any more, just because they installed another app developed by a third-party developer!

Sure you can ask your users to delete that third-party app. But in a real world, big companies can make small mistakes. That third-party app could happen to be Twitter, Facebook, Youtube, Instagram, Dropbox, Spotify, or even a popular game. It doesn't have to be a "Document-based App", all it needs is to carelessly include several lines of code in their Info.plist file and submit the update to the App Store, and ... "Boooom!" You're done.

What You Can Do

If you've also encountered this issue, there's rarely anything you can do to quickly recover from the consequence. Here's my advice.

  1. Ask the third-party developer to update their app by either removing that UTI declaration or using the same declaration as yours. If you can't contact them directly, you can try asking Apple to mediate between you and the third-party developer. And, WAIT for the updated version of that app to be submitted, promoted, and finally downloaded and installed by all of the users affected.
  2. Submit a bug report to Apple and, again, WAIT for Apple to fix this bug.

If you're just interested in this issue, it's welcome for you to

  1. Star this repository or watch for updates;
  2. Leave comments in Issues, and share your thoughts on this.

License

MIT

About

Demonstrating a severe bug of UIDocumentBrowserViewController causing an app failing to open its own documents

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Languages