Playing in your Mac's sandbox

21 Nov 2008

One of the things I love about the Mac is that not only does Apple make the UI side of the world well polished and (mostly) easy to use, they also apply the same care and attention to the unix underpinnings and the command line tools.

One of these features I found recently by reading through the slides from Jordan Hubbard’s talk at the LISA 08 conference. Full of interesting things, but this one in particularly I liked.

Typically when you run a program, it has as much access to the rest of the computer as you do – you need to trust it not to delete all your files, or start clobbering your network, and so on. The same applies to system programs running in the background, and this is why security exploits are so damaging – it’s not that people can gain access, more that they can do unrestricted damage when they do.

In Mac OS X Leopard Apple decided to do something about this. They introduced Sandboxing, whereby you can limit what things an application can do on a per invocation basis – put another way, you can specify when you run an application what files it can access, what system calls it can access, and so on. On Leopard many of the system services run in such a sandbox to prevent any exploits getting too much access to the system should anyone break in.

This is very good, but what’s really nice is that it’s so easy to make use of this functionality yourself at the command line. There’s a small utility called sandbox-exec, which lets you specify a set of access permissions in a script, and then that program runs with only those permissions you let it.

For example, if I have the following script which limits programs to only accessing files that end in .txt:

(version 1)
(debug deny)
(import “bsd.sb”)
(deny default)
(allow process*)
(allow file-read-data file-read-metadata
(regex #”^.*\.txt$”))

and I put it in a file called filelimit.sb I can do the following (for non-nerds, cat is just a program that shows the contents of any file passed to it:

sandbox-exec -f filelimit.sb cat foo.txt
Hello world!

And I’d be shown the contents of the file foo.txt, as it matches the rule I’ve specified, but if I try to do the same with foo.html it would not work, as I’ve not given the program permission to do that.

sandbox-exec -f testsandbox.sb cat foo.html
cat: foo.html: Permission denied

For more details, it’s worth poking around /usr/bin/sandbox and looking at the sandbox scripts there. Apple warn that this isn’t a public interface, and might change, but it’s an excellent idea, and so easy to leverage.

As a programmer I’d love to move away from the idea that by default programs that run have access to everything, when they don’t need to. We programmers aren’t infallible, and occasionally make mistakes, so I’m careful to try and limit the impact of my programs. This idea of easily scriptable sandboxing would make the work I do in embedded devices for instance a lot easier, as when things go wrong in an embedded environment it’s hard to fix. Having the permission controls in one place that’s easily understood and easy to alter would be fantastic.