Quarantine, SIP, and MACL: macOS per-file security controls

At least three extended attributes (xattrs) have important roles to play in security and privacy: the ‘quarantine flag’ com.apple.quarantine, the xattr which protects an item using System Integrity Protection com.apple.rootless, and the new xattr com.apple.macl, whose precise purpose has yet to be discovered. This article explores their behaviours, with particular respect to the last of the three.

The quarantine flag

com.apple.quarantine is probably the stickiest of all xattrs, and propagates too. Although it’s attached voluntarily to the great majority of files downloaded from the Internet, it’s also attached to anything transferred by AirDrop and similar local transfers which are open to abuse. Download a Zip archive and decompress it into its constituents, and every one of those will also have a quarantine flag attached, although that isn’t mandatory behaviour.

For an app, it determines whether opening it will result in the full Gatekeeper first run checks occurring. But more recently, quarantine flags are being commonly attached to documents even when they haven’t left the boot volume: the default behaviour of all sandboxed apps (including those from the App Store) is now to write a quarantine flag to each document that they open. As most can’t undergo any meaningful malware checks and aren’t signed, it’s a mystery as to the purpose of this promiscuous use of quarantine flags.

The SIP flag

In Catalina, the great majority of items which are protected by SIP are those on the read-only System volume. However, there are two other methods for bringing outlying folders and files within this protection: configuration files stored in /System/Library/Sandbox, and attachment of the com.apple.rootless xattr, the ‘SIP flag’. This is much more fragile and decidedly non-sticky: copy an item with this xattr attached to it even within the same volume and the xattr is stripped. It also only works on the current boot Volume Group, so is easily worked around.

With the new System volume, the use of com.apple.rootless appears in decline. Its only important usage now seems to be to protect Safari, which isn’t kept on the System volume for ease of updating, and the sake of simplicity.

MACL

The com.apple.macl xattr appears to be new to Catalina, and I think was first reported properly by Jeff Johnson. It contains UUIDs which appear to be references to apps in a whitelist of those which can open the document to which it’s attached. This seems to play a role in per-document privacy protection, but Apple hasn’t even mentioned its existence, let alone described what it does. Unlike the other two xattrs discussed here, this seems to be a facilitatory flag, not a restrictive one, so it should work in the user’s favour. It’s therefore puzzling that this xattr is protected by SIP, yet many apps are capable of adding and modifying it.

Because it contains references by UUID, this xattr has proved almost impossible to investigate any further. SIP provides an additional complication, and some have gone to the lengths of working out how to strip it using the zip command, which can remove all xattrs if you wish, including com.apple.quarantine.

Thankfully, life doesn’t have to be so complex if you experiment a bit more. One guaranteed way to generate a file with a com.apple.macl xattr attached is to take a screenshot in Catalina: the resulting image then has this xattr, and attempts to remove it when the file is still in the folder in which your screenshots are delivered meets resistance from SIP, as expected. Copy or move that image to another location on the same volume, and the xattr remains and is still protected.

However, the moment that it’s copied to another (external) volume, while the com.apple.macl xattr goes with it, it loses its protection from SIP. That’s an expected behaviour, as SIP is only intended to protect items on the boot Volume Group. So if you really want to strip this xattr, simply copy the item to a non-boot volume and remove it using the xattr -d command or my free utility xattred.

The most bizarre behaviour of all with the com.apple.macl xattr is what happens when you try to remove it, but can’t. In the ordinary run of such errors, I had expected to see the kernel come up with a sandbox error to account for the refusal, but I can’t find that happening in the log. Instead, the kernel reports that the xattr is “restored”: in other words, removing the protected xattr is allowed, but as soon as that happens, the sandbox mechanism puts it back.

Here are the relevant log entries, starting with the mouse click in xattred to Cut the xattr:
00.882985 5098783 92573 xattred AppKit sendAction:
00.883452 5098783 0 kernel Sandbox restored 1 MACL entries to /users/hoakley/documents/screenshot.png

So within 0.0005 of a second, during which various clipboard operations take place, the com.apple.macl xattr is removed and immediately replaced.

This log message gives further clues as to how these xattrs work, in referring to “1 MACL entries”: the UUIDs given in the com.apple.macl xattr refer to a list which contains these MACL entries. It is strongly suggestive that the ACL refers to access control list. All we have to do now is discover where this MACL is stored.

This behaviour is being handled by the kernel and sandbox, so is part of SIP. But who has come across a situation where SIP allows an action to happen, only to reverse it immediately, and restore the MACL? When the xattr doesn’t refer to that (boot) volume’s MACL, though, it won’t be restored and is thus no longer protected by SIP. And that protection looks as if its main purpose is to ensure the xattr isn’t stripped inadvertently: there are no controls over changing the contents of the MACL xattr, nor deleting the whole document.