|
1 | 1 |
|
2 | 2 | # macOS sandboxing |
3 | 3 |
|
4 | | -The itch.io sandbox uses built-in macOS facility `sandbox-exec`. |
| 4 | +The itch.io app uses macOS's built-in `sandbox-exec` facility to sandbox games. Each time a game launches, the app dynamically generates a sandbox policy written in Apple's Sandbox Profile Language (SBPL) and stores it at `{install_folder}/.itch/isolate-app.sb`. |
5 | 5 |
|
6 | | -It dynamically generates sandbox policy when launching a game, which: |
7 | | - |
8 | | - * gives read access to the usual things needed by games |
9 | | - * gives write access to a few ~/Library folders |
10 | | - * explicitly denies a few known sensitive locations |
| 6 | +The policy starts from a **deny-all** default and explicitly allows only the permissions a game needs to run. |
11 | 7 |
|
12 | 8 | Here's the policy template the itch app uses: |
13 | 9 |
|
14 | | - * <https://github.com/itchio/itch/blob/master/src/constants/sandbox-policies/macos-template.js> |
| 10 | + * <https://github.com/itchio/smaug/blob/master/runner/policies/sandboxexec.go> |
| 11 | + |
| 12 | +## How it works |
| 13 | + |
| 14 | +When a game launches with the sandbox enabled: |
| 15 | + |
| 16 | +1. The app generates an SBPL policy file tailored to the game's install location |
| 17 | +2. The environment is filtered to an allowlist of safe variables (`HOME`, `USER`, `PATH`, locale settings, `TMPDIR`, and itch.io launch variables) |
| 18 | +3. The game is launched through `sandbox-exec -f {policy_file}` |
| 19 | + |
| 20 | +For **app bundles** (`.app` directories), the app creates a temporary shim bundle that wraps the original binary with a shell script invoking `sandbox-exec`. This allows app bundles to launch through the standard macOS app mechanism while still being sandboxed. |
| 21 | + |
| 22 | +For **standalone executables**, `sandbox-exec` is invoked directly. |
| 23 | + |
| 24 | +## Policy modes |
| 25 | + |
| 26 | +The sandbox supports two policy modes: |
| 27 | + |
| 28 | +- **Balanced** (default) — A hardened profile that limits device access to `/dev/null`, `/dev/random`, and `/dev/urandom` only. |
| 29 | +- **Legacy** — A broader profile for compatibility with older games. Allows full `/dev` access and wider read access to `/private`. |
| 30 | + |
| 31 | +The policy mode can be configured in the app's preferences. If a game fails to launch under the balanced profile, try switching to legacy mode before reporting an issue. |
| 32 | + |
| 33 | +## What the sandbox allows |
| 34 | + |
| 35 | +### Filesystem write access |
| 36 | + |
| 37 | +- `~/Library` subpaths: Application Support, Preferences, Logs, Caches, KeyBindings, Saved Application State |
| 38 | +- The game's own install folder (full read-write) |
| 39 | +- `/var/folders` and `/private/var/folders` (macOS temp storage) |
| 40 | + |
| 41 | +### Filesystem read access |
| 42 | + |
| 43 | +- System libraries and binaries: `/usr/local`, `/usr/share`, `/usr/lib`, `/usr/bin`, `/bin`, `/System/Library` |
| 44 | +- Rosetta 2 translation support: `/usr/libexec/rosetta`, `/Library/Apple/usr/libexec/oah` (for running x86_64 games on Apple Silicon) |
| 45 | +- Java: `/Library/Java/JavaVirtualMachines` |
| 46 | +- System preferences: `/etc`, `/private/etc`, `/Library/Preferences` |
| 47 | +- Fonts and audio: `/Library/Audio`, `/Library/Fonts`, `~/Library/Fonts` |
| 48 | +- Input methods and keyboard layouts: `~/Library/Keyboard Layouts`, `~/Library/Input Methods` |
| 49 | +- `/Applications` (read-only) |
| 50 | + |
| 51 | +### Explicitly denied |
| 52 | + |
| 53 | +Even though `~/Library/Application Support` is writable, the following subpaths are explicitly blocked to prevent credential theft: |
| 54 | + |
| 55 | +- `~/Library/Application Support/itch` and `~/Library/Application Support/kitch` (itch.io app config) |
| 56 | +- `~/Library/Application Support/Google` (Chrome data) |
| 57 | +- `~/Library/Application Support/Mozilla` (Firefox data) |
| 58 | + |
| 59 | +### Network |
| 60 | + |
| 61 | +Network access (`network-bind` and `network-outbound`) is allowed by default. It can be disabled with the **Disable network access in sandbox** preference. |
| 62 | + |
| 63 | +### IPC and system access |
| 64 | + |
| 65 | +The following are allowed for compatibility with game frameworks like SDL2 and Electron: |
| 66 | + |
| 67 | +- Mach IPC (`mach-lookup`, `mach-register`) |
| 68 | +- POSIX shared memory (`ipc-posix*`) |
| 69 | +- System sockets (`system-socket`) |
| 70 | +- IOKit device access (`iokit-open`) |
| 71 | +- Process forking and execution (`process-fork`, `process-exec`) |
| 72 | +- Hardware/OS limit probing (`sysctl-read`) |
| 73 | + |
| 74 | +## Settings |
| 75 | + |
| 76 | +The sandbox can be configured from the itch.io app's preferences: |
| 77 | + |
| 78 | +- **Enable itch.io sandbox** — Master toggle to enable or disable sandboxing |
| 79 | +- **Disable network access in sandbox** — Prevents all network access from sandboxed games |
| 80 | +- **Policy mode** — Choose between **Balanced** (default) or **Legacy** for broader compatibility |
| 81 | +- **Allowed environment variable names** — A comma or whitespace-separated list of extra host environment variable names to pass into the sandbox |
| 82 | + |
| 83 | +Games can detect that they are running inside the sandbox by checking for the `ITCHIO_SANDBOX=1` environment variable. |
15 | 84 |
|
16 | 85 | ## Troubleshooting |
17 | 86 |
|
18 | | -If your game is broken by the itch.io sandbox on macOS, we recommend using |
19 | | -the built-in `Console.app` to watch out for permission denials. Look in |
20 | | -particular for `sandboxd` messages. |
| 87 | +If a game is broken by the sandbox: |
| 88 | + |
| 89 | +1. **Check Console.app.** Open the built-in Console.app and look for `sandboxd` messages to see which permissions are being denied. Shutting down other applications can help reduce noise in the logs. |
| 90 | + |
| 91 | +2. **Try legacy mode.** If the game fails under the default balanced policy, switch the policy mode to legacy in the app's preferences and try again. |
21 | 92 |
|
22 | | -Since Console.app shows system-wide logs for all applications, it may be a bit |
23 | | -chatty. Shutting down applications you don't actively use can help reduce |
24 | | -the amount of irrelevant messages. |
| 93 | +3. **Inspect the policy.** Open `{install_folder}/.itch/isolate-app.sb` to see the exact SBPL policy being applied to the game. |
25 | 94 |
|
26 | | -The default sandbox policy should be more than enough to get most games running, |
27 | | -but if you run into an issue that you need help resolving, feel free to open |
28 | | -an issue on our [Issue Tracker](https://github.com/itchio/itch/issues) |
| 95 | +4. **Report the issue.** If you can't resolve the problem, open an issue on our [issue tracker](https://github.com/itchio/itch/issues) with the Console.app output and the contents of the `.sb` file. |
0 commit comments