Sandboxing for macOS

From Lazarus wiki
Revision as of 09:52, 18 December 2019 by Trev (talk | contribs) (Fixed template issue)

English (en)

macOSlogo.png

This article applies to macOS only.

See also: Multiplatform Programming Guide

Overview

Sandboxing was introduced in 10.7 Lion and is a requirement for all Apple App Store applications. You can also sandbox applications which you distribute outside the App Store, but it is not required.

Sandboxing is an access control technology provided in macOS and enforced at the kernel level. It is designed to contain damage to the system and the user’s data if an app becomes compromised. Apps distributed through the Apple App Store must be sandboxed. Apps code signed and distributed outside of the App Store with an Apple Developer certificate can be sandboxed as well but it is not required.

The Hardened runtime (introduced in macOS 10.14 Mojave) and sandboxing prevent an application from doing things it would ordinarily have had permission to do. It should be noted that these two protections are overlapping. The sandbox and the hardened runtime could prevent the same action, so even if the hardened runtime would allow the action, the sandbox may prevent it, and vice versa. See the external links below to Apple's lists of hardened runtime entitlements and sandboxing entitlements.

Sandboxing requirements

To sandbox an application the following requirements must be met:

  1. a 64 bit executable application
  2. uses the Lazarus Cocoa widgets dnd not the 32 bit Carbon widgetset
  3. code signed with an Apple developer certificate

Additionally, for security reasons, you should not include any sandbox entitlements that your application does not to need to exercise its full functionality.

Enabling sandboxing

An application is sandboxed by using a sandbox entitlements file which is in the plist format. The example below simply enables sandboxing without providing any sandbox entitlements:

<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
    <key>com.apple.security.app-sandbox</key>
    <true/>
</dict>
</plist>

This entitlements file can be called anything and is not included in your application bundle. To check that the format of your plist files is valid, open a terminal and running the following command on your file:

plutil entitlements.plist

If the file is valid, the command will return output similar to the following:

entitlements.plist: OK

Make sure that the application bundle does not use a symlink to the executable, which is the default for applications created in Lazarus. To code sign the application using this entitlements file, open a terminal and run the following command:

codesign -f --timestamp --entitlements entitlements.plist -s "Developer ID Application: YOUR NAME (TEAM_ID)" /path/to/bundle.app

Now run the application as usual. To check that the application has in fact been sandboxed, simply check the /Users/<username>/ Library/Containers/ for the application's CFBundleIdentifier key. For example:

/Users/<username>/Library/Containers/com.example.MyApp

If the application's CFBundleIdentifier key is there, you know your application was sandboxed when it was executed.

Alternatively, you can check that the application is properly code signed and also display its entitlements by opening a terminal and running the following command:

codesign -dv --entitlements :- /path/to/MyApp.app

which should produce output similar to the following:

Executable=/path/to/MyApp.app/Contents/MacOS/PICinfo
Identifier=com.example.MyApp
Format=app bundle with Mach-O thin (x86_64)
CodeDirectory v=20200 size=101490 flags=0x0(none) hashes=3164+5 location=embedded
Signature size=9063
Timestamp=8 Dec 2019 at 21:21:02
Info.plist entries=16
TeamIdentifier=<10 alpha numeric digits>
Sealed Resources version=2 rules=13 files=45
Internal requirements count=1 size=180
<?xml version="1.0" encoding="utf-8"?>
<plist version="1.0">
  <dict>
    <key>com.apple.security.app-sandbox</key>
    <true/>
  </dict>
</plist>

Adding sandbox entitlements

Assuming for the moment that your application needs to access the Internet via HTTP to check if it is up to date, your application will currently be denied any network access. To add missing entitlements, edit the entitlements.plist file and modify it to add the two additional entitlements for network access as below:


<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
    <key>com.apple.security.app-sandbox</key>
    <true/>
    <key>com.apple.security.network.client</key>
    <true/>
    <key>com.apple.security.network.server</key>
    <true/>
</dict>
</plist>

Re-code sign and open your application. It should now be able to perform its HTTP check over the Internet.

The full list of sandbox entitlements may be found in Apple's documentation in the external links below.

See also

External Links