Video hosted by Apple at devstreaming-cdn.apple.com

Configure player

Close

WWDC Index does not host video files

If you have access to video files, you can configure a URL pattern to be used in a video player.

URL pattern

preview

Use any of these variables in your URL pattern, the pattern is stored in your browsers' local storage.

$id
ID of session: wwdc2011-204
$eventId
ID of event: wwdc2011
$eventContentId
ID of session without event part: 204
$eventShortId
Shortened ID of event: wwdc11
$year
Year of session: 2011
$extension
Extension of original filename: m4v
$filenameAlmostEvery
Filename from "(Almost) Every..." gist: [2011] [Session 204] App Sandbox...

WWDC11 • Session 204

App Sandbox and the Mac App Store

Core OS • OS X • 38:56

Planning to distribute your application on the Mac App Store? Don’t miss this session! Learn how to adopt App Sandbox in your application in order to meet the Mac App Store Guidelines. (pre-req: Introducing App Sandbox)

Speaker: Ivan Krstić

Unlisted on Apple Developer site

Downloads from Apple

HD Video (148.3 MB)

Transcript

This transcript was generated using Whisper, it has known transcription errors. We are working on an improved version.

Hello, hello. How many repeat visitors do we have from the last session? All right. Lots of hands. Well, hello again. My name is still Ivan. I still work on CoreOS security. And you're here because you want to hear more about how App Sandbox will play with the Mac App Store and specifically what that means for those of you that either have apps in the store or plan to get apps into the store.

This is the quick refresher. I know that you were gone for over 15 minutes from the room, so some of this may have gotten forgotten. Bottom line: new feature in Lion, damage containment mechanism, last line of defense, not antivirus, drive security policy by user intent. Good? So as you heard Craig mention yesterday, Mac App Store submissions in November will be required to use App Sandbox.

And specifically what that means is that every executable that you submit to the store will need to specify App Sandbox entitlements that are appropriate for what that executable does. What��s more, in the process of actually submitting your app to the store, you��ll need to describe how each of the entitlements you requested is used or really why it��s needed.

So if you take one thing away from this talk, it's that choosing entitlements is the single possibly most important interaction that you have with the App Sandbox mechanism because The protection that App Sandbox can afford your app is really only as good as the entitlements that you selected. And that means that you need to be choosing the absolute minimum set of entitlements necessary to support the features that your app actually has.

And this is also important because when you do go and select entitlements, those entitlements need to match features that users can see and use from inside your app. So if you have a watchgrassgrow.app and it's displaying grass growing and it's requesting the address book entitlement, that's probably not very good. It's not clear why a watchgrassgrow.app would want address book access. And it would be not good for someone who can actually exploit grass growing to be able to get at your address book.

You'll have to figure out very carefully what is the minimum amount of entitlements that you guys need for your app to get its job done. And the best way to do this is to start with an absolute bare minimum of entitlements and then run your app and see what sandbox violations actually get reported and only add more entitlements in response to violations that make sense to you.

You don't have to squelch every violation if you find, for instance, that some of them are coming from frameworks or libraries that may not even be your own. You know, if there's no functional impact on your app, the right thing to do is not to add another entitlement to your app to make the violation go away.

The right thing to do is for you to realize, okay, this is good. My application is not affected. I'm not going to ask for another entitlement that I don't actually have a need for in my app. So I briefly in the last session showed you all the entitlements and I wanted to take you on more of a guided tour and tell you a bit more about each of them.

All of the App Sandbox entitlements live in the same namespace, which is com.apple.security. And com.apple.security.appsandbox is the big on/off switch for App Sandbox that controls whether any of the other App Sandbox entitlements are even looked at. When you flip that switch to on, when you say, yes, I want to be in an App Sandbox, what that actually means is your app is going to run in a container.

It will not have network access. It will not have access to user documents. It cannot use the Open or Save panels. It can't print. It can't look at the camera. It can't talk to the microphone. It's basically... Just able to run and access its container, and that��s it. So that's all you get when you flip the master switch. And then for everything else that you need that's more than that, you're going to have to select the appropriate entitlement and request it.

So probably the most important set of entitlements for all of you that have document-based applications will be entitlements that have to do with user-selected files. And this is basically a single entitlement that comes in two flavors: one read-only, one read-write. And picking these entitlements just means that your application is allowed to use the PowerBox facility.

Which means it's allowed to prompt the user with an open panel or a safe panel to select some files. That means that in the case of Watch Grass Grow, not having these entitlements means that even if the application was exploited and an attacker really wanted to pop up a dialog asking the user to select some important file, he couldn't do that because the facility would just not be available.

So, document applications, applications that want to be doing import and export and need to basically interact with user documents and files that the user selects in any way will need to be using these entitlements. And obviously, once again, the minimum set of entitlements also means that if your app never really modifies the files that it looks at, then obviously you should select the read-only entitlement instead of the read-write entitlement. Because that way, the damage containment that you get is that much stronger.

The network entitlements are just as simple. There��s only two of them. One for being able to make outgoing network connections, that��s the client entitlement. One for being able to receive incoming network connections, that��s the server entitlement. And at the moment, there��s really no, with App Sandbox in line, you cannot restrict this further.

You can��t say, I want to only be able to make network connections to specific domain names or ports or anything of the sort. So it��s essentially a binary switch for outbound connections and inbound connections. And this is obviously going to be pretty popular. Anything that needs to talk to the network is going to need, in most cases, the client entitlement. The server entitlement should be used more sparingly. Obviously, only if you have a legitimate need to be receiving network connections should you actually use that. So don��t assume that just because you want to do network access, you need both.

The personal information set of entitlements are some of the touchiest in terms of the privileges they cover because they directly expose user data. So these are entitlements for controlling access to the address book, the calendars, the user's location. These are things that all have very legitimate uses. So, you know, a calendar client obviously wants access to the user's calendars and things that are location-based applications and services totally want access to the location. But because they have such strong privacy ramifications for user data, it means that you really, really should only use these if you have a very legitimate need for them. So it's really true of all entitlements, but it's especially double super true for personal information entitlements.

We have some specific entitlements that grant you access to media assets that the user has, so their pictures, their movies, their music. And these, all three of these come in both read-only and read-write flavors. So if you're a music player app, you probably want access to the user's music, and you can think of other legitimate needs for these. Once again, if your app doesn't expose functionality so that it would be pretty clear to the user why your app would want to say have access to their pictures, then you shouldn't be requesting that entitlement.

Camera and microphone access are also quite touchy. It would be pretty bad if watchgrassgrow.app could spy on the user when the user isn't looking. Some applications have certain needs that are sort of beyond just these built-in devices and they, for instance, want to be able to talk to anything that's sitting on the USB bus. There's entitlement that lets you ask for that.

Once again, lots of apps that you can think of, podcast apps, apps that are meant to support particular peripherals that the user would plug in via USB, all have good needs for these. And then there is just a few more assorted other entitlements, things like the print entitlement.

If your app is both a document-based app and one that needs to be able to print stuff, then you need the print entitlement. And there is an entitlement called inherit, which really means that when you have bundled helper executables that are not XPC services, they're just raw executables that you're shipping as helpers and you're planning to run them via fork and exec.

You need some way to tell the operating system that those helpers need to inherit your main sandbox. And let me backtrack here and say, if you have raw helpers, so not XPC services, just binaries that you fork and exec, you cannot run them in a way that doesn't inherit your sandbox.

Your sandbox will be inherited by those helpers. Absolutely, there's no way to opt out of that. So the presence of the inherit entitlement is merely to indicate when you're submitting your application to the Mac App Store that, you know, I am aware as the developer that this binary will get executed and inherit the main app sandbox.

For most of you, we really hope that adopting App Sandbox is not going to be a ton of work. We gave you a nice graphical interface. You can check some check boxes and see where that gets you. And it should be in many cases a really straightforward process. For some other applications, adopting App Sandbox may actually take more work. You might have to really sort of break your application up into pieces and extract some of the functionality that needs more privilege and XPC services.

And we don��t want to make it so that you have to do all the work all at once before you start seeing any benefits. So to try and address this issue, we��ve created a set of... Temporary exception entitlements. And they are exactly what they sound like. They are temporary and they are exceptions. They are transitional entitlements that are meant to try and make it easier for you to initially adopt this technology.

And the way they do that is by opening up the sandbox in very specific ways that would not otherwise be available. So specifically things like being able to send Apple events or being able to look up Mach services. And the most obvious one, the ability to read and write files on disk that the user has not selected with an open or a save panel.

And, you know, some of you will find that some of your applications have core functionality that simply cannot be made to work under the current App Sandbox model in Lion. And in those cases, you would request temporary exception entitlements and obviously document why you have to request each one of them with technical detail because To fulfill this obligation to have applications in the Mac App Store in November specifying their entitlements. So those are the mechanics, but there is a lot more to how you actually go about building applications for App Sandbox and the kinds of things you need to keep in mind, and I want to guide you through just a few of those.

Possibly the most important takeaway is that APIs and system facilities that you've always used, that have always worked for you, can start failing. Because there's now a kernel enforcement mechanism that can decide, in certain cases, that APIs that you were completely sure are going to work are not going to work for you. And this means that it's more important than ever to have proper error handling.

Error handling is always important, but it��s more important now because we really want your apps to provide a good user experience. And if you don��t degrade gracefully when system APIs fail or where facilities are unavailable, you might beach ball your app, you might stall the system, you might really just give a bad experience to the user, and we don��t want that.

So, We've actually seen this in the wild, people writing error handling as a macro that takes an operation and simply tries it 4096 times in a loop, hoping that one of those times it will succeed. And you can imagine how well that works, but not just does it not work and still fails the 4097th time, but actually until that has happened, the user is sitting there wondering why their application is slow and why it's, you know, what's going on, everything is gummed up. We don't want that.

Check errors and degrade gracefully. If you find that there is an error somewhere that you expected, find a way for the application to deal with it and carry going. Don��t try and spin in loops. Don��t try and hope that magically if you try it enough times it will work properly. And this also means that when you are actually developing your app, when you are building it, you should be checking the console app frequently and seeing if Sandbox is logging any violations that your app is doing.

There is no UI that will jump out at you other than the system log to tell you that an application that you are developing or any of its frameworks or libraries tried to do something that Sandbox stopped. So keep console running. You can even use the search feature to just look at Sandbox violations and basically keep on top of what��s going on as you are building your software.

So I mentioned in the last talk introducing App Sandbox that we're giving each Sandbox application a container. And really the idea of the container is that it's sort of a per application home directory. Because when your app is asking what is the user's home directory, if it's Sandboxed it's going to be getting its own container.

And what this means is that if you use normal APIs like NSUserDefaults or CFPreferences, things that expect to basically go and read and write files from, let's say, Tilda Library or Tilda Library application support, all of this stuff will continue working because your application does have read and write access to its own container. So we want that container to be storing exactly these kinds of things that are not user documents, they're not things that the user created and expects to be able to find, but that are important for your application.

Things like preferences, things like caches, any databases that you might have, even documents. Documents that are only documents insofar as your app understands that, and they're not meant to be user visible. All of this can go in the container, there are no restrictions there, Sandbox will let you do whatever you want inside your own container.

And to fulfill this idea that container is the home directory, again, Apple API, but even just checking the environment variables, things like home will point you to the container instead of the real home directory. So it goes without saying that because the PowerBox and those trusted open and save panels that we discussed are a key mechanism for sandboxed applications to be able to operate on user documents, use them. Don't try to get direct access to files some other way because if you're running under an App Sandbox, that will simply be denied by the kernel.

Don't hardcode paths. It's always been a bad practice on any platform, not just Mac OS. But it's really important now because if any of you have software that hardcodes /temp as a location for writing temporary data, it's going to fail under App Sandbox. Sandbox tabs get no access to /temp, either for reading or for writing. But if you call Apple API asking, hey, where is the temporary directory? The directory that we hand you back, you will have both read and write access to.

So don't hardcode paths. It's not just through for /temp. There are a number of other directories like that that if you're hardcoding, you're going to see failures. Whereas if you're asking Apple API to tell you where you should be putting things, you'll get answers that will work, and all of your code will continue to work. There is an interesting illustrative example of this.

A lot of applications try to do a safe save, meaning that when they go to save a document, instead of trying to overwrite the existing document on disk, they first write out the new version to a different file and then they move that file in place to atomically overwrite the old file.

And if you're an NSDocument-based application, hopefully you have no code of your own that does this because NSDocument will just do it for you incorrectly. If you do have your own code, you should consider eliminating it in favor of NSDocument. But if you're not an NSDocument-based, trying to do safe save by hand will fail.

And here's why. When you -- let's say that the user is trying to save a document and you pop up in a save panel and they pick a file called grassgrowing.rtf as the name they want to save on the desktop. Well, let's say that you now want to save save and so you want to write grassgrowing.rtf.saveinprogress. You're going to fail because the user hasn't given you access to that file. He hasn't chosen that file through a save panel and so you have no access to it.

The kernel is simply not going to let you go and write there. However, if you use Apple API, in this case, there is an API called URL4Directory, you can actually ask, "Hey, Apple, what is the URL of the directory that's a item replacement directory appropriate for grassgrowing.rtf?" And you'll get back an answer that you will be able to use. And you can do your save save.

So we mentioned fork and exec very briefly. Fork and exec and post-expand continue to work under App Sandbox, but all of the Sandbox restrictions of the launching app are fully inherited. Which means that if you're launching tools that you don't control, you have to make sure they can deal with the Sandbox environment. Especially if you're passing any paths to these tools and expect them to operate on those paths, you have to make sure that the paths point within the Sandbox. Usually that means within the container, but it may also mean to a file that the user selected.

Basically, you have to make sure that these things will degrade gracefully and not present a poor experience. Now, Launch Services API is things like LS Open. When you have a document and you want to just invoke it in whatever app is appropriate for the system, that works. You can just call the API, it will do the right thing, and your own sandbox restrictions are not going to propagate to the app that Launch Services started up. So, you know, if you were doing this like we've been saying is the right thing to do, calling Launch Services, it will continue to work, it will be great, and you'll basically probably run into no issues. Apple Events are kind of an interesting point.

App Sandbox doesn't prevent you from receiving Apple events, which means if you're trying to make your own apps cryptable, You can continue doing that. You can have a scripting dictionary. People can make use of that. However, App Sandbox does not let you send any Apple events. And you can imagine why that is.

Apple Events are meant as a mechanism of controlling other applications and telling them to do things. And so if your application is trying to be contained but has the ability to go tell Finder, for instance, to do whatever, then there's not a lot of containment there. So there's no ability to send Apple Events. However, for most applications, there is alternative API that does exactly what they're trying to do and doesn't require Apple Events.

One of the most common uses that we've seen for Apple Events is popping open a Finder window, just a reveal in Finder, essentially. And you can't do that with an Apple Event under App Sandbox, but if you call NSWorkspace API, the Open File API, the exact same end effect is achieved. It's visually indistinguishable. It's exactly that. It's revealing a file in Finder, and it works under App Sandbox with no Apple Events.

Now, in some cases, there are applications whose core functionality actually depends on full Apple event use. If you imagine an application that's like a remote control for iTunes and is using Apple events as its way of controlling iTunes, then there's really no, you know, alternative API replacement, and at that point, you'll need to request a temporary exception entitlement to a particular target. So you can request a temporary exception entitlement to iTunes. Apple event sending to iTunes, and then basically your app will be allowed to do just that, but not send events to other applications.

Spotlight also bears quick mention. When you invoke Spotlight APIs from inside your app, the searches are constrained to your container. And the reason that is, think about it, is because if Spotlight returned documents that were anywhere in any of its indices, Even if it gave you URLs or file names or paths, your application wouldn't be able to open them because it's sandboxed and the kernel wouldn't let it because the user hasn't selected any of those files.

So in order to not give you a non-functional API and also one that would leak things like the names of documents that the user has, it's simply the case that if you're trying to do spotlight searches from within your sandboxed app, you'll only get results in the container. This is still tremendously useful to a lot of applications, anything like mail clients or other apps that have their data stores that are not user documents in the container and want to be able to search through them quickly. That works great.

But the one important takeaway here is that documents, user documents that your app writes, that the user selects through a save panel, are still searchable to that user through, you know, the Spotlight menu or through any of the normal facilities that users use when trying to search for files. So even though your app can't search for things outside of the container, documents produced by your app are still searchable and findable by Spotlight and by the user.

So I want to talk about privilege separation because it's a key element of the overall security picture that we're trying to get to. And I think we've been mentioning this for a number of years at WWDC, but the facilities and tools that we have available for privilege separation now are just better than ever.

And I thought because I like looking back into history and trying to understand where things came from, I thought I'd tell you just a brief anecdote. I promise this will be my only history lesson in this talk about... When the industry, when some of the people involved in computing realized the need for privilege separation. So this is a story from the 60s and 70s. There was a company called Timeshare, very popular. They made these giant mainframes.

And... One of the very popular things that a timeshare mainframe could do for you is actually you could have a compiler and you could submit jobs to the compiler and you would be billed for the compile jobs that you did. And the way this was structured is that there were two special files on the system. One was called stat for statistics, another was called bill for billing. And they were only writable by the compiler, not by any user of the system.

But the compiler, when you invoked it, actually also accepted another command line parameter that was an optional file name where it should write the debug output. So if there are failures during compilation, it can write them to that file. And of course, very quickly, someone realized that if you provide bill as the name of the debug output file name, the compiler would overwrite all of its billing and you wouldn't get charged for your compile jobs.

And, you know, this was in the 60s and 70s, and people were sort of their minds boggled at how a system that seemed structurally to be perfectly sound sort of crumbled under, you know, interaction with a real user that is willing to take different parts of a program that have different amounts of privilege and basically put them in clash with one another.

We have the need to be able to separate out privilege today because, once again, there is no way to assign different amounts of privilege to different parts of the same process. We can't say, "Well, this part of my process only needs network access, but it should never be able to see a user document, and this other part of my process only needs to be able to see user documents, but if it's compromised, it should never be able to send them on the network." We can't do that within the boundary of a single process.

So the game becomes making it really, really easy to take different parts of an app's functionality and break them out into different processes. And some of the guidelines here are to try and in fact do, when you're trying to choose basically where to make those incisions, where to do the breaks and extract functionality, some basic guidelines to keep in mind is try and separate things that talk to the network from things that don't talk to the network. And try as much as you can to isolate anything that has access to the user's personal information, private data, anything that's sensitive or irreplaceable.

And one point that��s more subtle about this and that I can��t do justice in a presentation but I��ll be happy to talk to you about in the lab tomorrow is that when you��re doing the separation, it��s not enough just to take code that you already have and put it in a separate process and say, "I��m done." You have to make sure that the code that you just separated out Won't just blindly obey any command that's sent to it, because if you do that, You've invalidated the security advantage of actually having the code moved out.

So you can imagine that if a

[Transcript missing]

I want to show you this diagram because the sample code that we have is an application called sandboxedfetch. It's just a little downloader app and, in fact, I'll show you what that looks like in a moment. But it's an app that if you give it a URL, it will download whatever is at that URL and then it will compress it with gzip and put it on the user's desktop or anywhere else that the user wants to put it.

And if you--this very simple application that doesn't do a whole lot previously would have to have all of the user's privilege because, you know, it needs to be able to write this file out, so it needs to be able to write anywhere on the file system and it needs to be able to make network connections.

So if this app now becomes exploited in any way, it can read any file from the disk and just send it over to network and it's game over. So what we did instead with sandboxedfetch is we simply broke the-- we put this up into a main application, the sandboxedfetcher, and two XPC services, the downloader with network access but no file system access, and a compressor which has only access to its own container, so no real file system access and no network access.

I'm going to show you what this looks like in a moment. Again, it's totally available to you and I really encourage you to download this code and take a look, not just because of the App Sandbox ramifications, but also because it's a very, very small, easy to understand example of XPC services in practice, especially ones that then have different entitlements and different containers.

So here's my project. Pretty small. And we're not going to go through all the code. Really what I want to show you is that if you select the project itself, you can see the targets that we have available. And so here's our main application. Simply clicking the target in the summary pane, we can see our nice graphical way of selecting which entitlements the app should have.

Enabling App Sandbox is as simple as clicking this main one and then choosing any additional entitlements that are necessary. And so for our main application, we're going to allow So, we have user-selected file writing, which means this application is allowed to pop open a save panel and ask the user to write a file, you know, select a file anywhere to be saved.

And then our fetch service, So, the app is going to be able to make outgoing network connections but has no real file system access. It can't ask the user to select any files. And finally, our zip service is an app sandbox that doesn't allow anything other than what we discussed earlier, which is basically container access. So, the compressor is not going to be able to peer out of its container at all, no network access, no anything. And so with this configuration, if I simply build and run, here is my little application. We are going to download a beautiful image of iCloud.

Here comes my save panel. Save one that's on the desktop. Save it there. And that was Now, you've seen a trivial application that just did something. You know, a sheet came up. It was all integrated with the program. Everything was happy. No idea that under the covers this was spinning up two different XPC services and sending around files and doing all the stuff inside a sandbox. You saw one simple seamless integrated experience and that was it.

So once again, this is sample code. It comes with a readme file that sort of gives you some more explanation about all of what this does. And you can see that there's just not a lot of code. It's a couple of screenfuls of code to do all of this stuff.

And most of that is just talking to the services as you might expect. But ultimately very easy to do this kind of separation and to build applications in this way. So you build services, you put them in your app bundle, we will manage all of the lifecycle, we'll manage even if you choose to use it, we'll even manage when the service needs to be torn down because it's being inactive and not doing any work. No launch DP lists, no extraneous work to get this up and running. You basically just put it in your bundle and start sending it messages and everything else is just about handled for you.

Each service has its own entitlements, its own container. You get to pick what that service is supposed to be able to do and no more. And because the services don��t share your main app's container, it really means that any information that you plan to exchange between an app and its services has to be explicitly sent over IPC.

In other words, it's not enough to just send a service a path name to something that your app can access because the service can't get at it. It has its own container, the kernel is enforcing a different set of restrictions on it. Instead, you actually have to send the file if that's what's necessary, or any other data that's important, you have to send that over as well.

Once you have communication be explicit, it's a lot easier, even if you just think about it, to convince yourself about what can�� what kind of damage can happen if a service is exploited or if the main app is exploited. It becomes a lot easier to reason about the security ramifications once data flows have become explicit and you've sort of very intentionally put them there.

So I want to just mention some very brief odds and ends. We have a tool called AS Kettle that will let you do various manipulations on containers. There's a manual page for it that you can take a look at. Here you can see I asked it where is the container for preview and it told me it's in tilde library containers, com.apple.preview. This is also useful because I mentioned that containers are bound to applications code identities and not their names. And AS Kettle lets you easily manipulate the code identity restrictions that are placed upon individual containers.

And for apps that already exist, so that have been written before App Sandbox, we realized that those applications used to run not in a container, so they probably have things like caches or preferences or custom preferences or some databases strewn around maybe Tilda Library or Tilda Library application support, basically in these places that the App Sandbox would no longer let you directly access. So to address this, we have a facility called Container Migration Manifests. They are very simple plists. You basically tell us using some substitution variables that we have documented that, you know, my caches live here until the library application support my app/caches.

And you can do that for the locations that make sense. And then the very first time that your app is ever run under App Sandbox, the system will simply do, you know, a simple request to let you know that you have a location that makes sense. will simply do the migration for you.

And that way, your application doesn't have to try and somehow deal with both cases, preferences or caches, turn around the real tilde, which it now can't access, or in the container. No. Your app basically just expects to find them as it always did, which is now in the container, and the migration manifests as a way of making that true, even if you have installed a prior version that has those resources elsewhere. One more time, App Sandbox is trying to be the last line of defense against exploitation and coding errors for your application.

Pick your entitlements wisely because those entitlements really determine how good the protection is that we can afford you. Always use Apple APIs when you're actually interacting with the system. And usually, the higher level the API that you can use, the better, because if you don't, if you're hard coding paths or using inappropriate APIs, you might find that even though the APIs work and give you back paths-- for instance, you just have no access to them.

The kernel will simply not let you do that. So make sure you use high level Apple APIs. And remember that starting in November, you will have to declare all of your AppSandbox entitlements for all of the executables that you submit to the Mac App Store. Thank you so much, and I hope I'll see you tomorrow at the lab.