We should be reassured that Apple currently has no intention to stop us from running unsigned code in macOS, but it has stated clearly that “a future version” of macOS will check signatures more fully when opening apps which aren’t in quarantine. Depending on how its latest requirements for notarization work out, that “future version” could be 10.16, which we should start seeing in beta in less than seven months. Now is the time to start thinking about the consequences.
If we’ll still be able to run unsigned code in 10.16, but app signatures are checked more thoroughly whenever their code is run, the best plan for now is to ensure that as much of the executable code on your Mac is properly signed, and notarized where possible. If you do have a developer signature and write your own scripts, it seems wise now to ensure that all those scripts are signed, even when saved (for example) as Compiled OSA Scripts (.scpt).
One enemy of signing apps and any other form of executable file is that signatures aren’t always stored robustly. For example, if you Zip up a script at the command line, chances are that the signature and supporting information will be stripped from it, and lost. Any deliberate policy of stripping extended attributes will also cause problems. This is because, in some circumstances, signatures and supporting data are attached to scripts in the form of extended attributes, which can so easily and inadvertently be removed.
Simple apps, including AppleScripts exported in app form, are bundles, containing their signature in the _CodeSignature folder. Zip these up in Terminal, or move them using iCloud Drive, and their structure and signatures should be preserved. Signed single-file Mach-O executables should embed any signature and Info.plist file within their binary structure, so they should be safe too.
But sign a Script file, and there’s no way that its signature can be embedded other than as an attached extended attribute (xattr). Look at this using a xattr editor such as my free xattred and you’ll see not only its signature in the com.apple.cs.CodeSignature xattr, but three additional xattrs, com.apple.cs.CodeDirectory, com.apple.cs.CodeRequirements, and com.apple.cs.CodeRequirements-1. All of these are essential for that signature to pass Gatekeeper and similar checks.
This also applies to scripts and other single-file executable code (other than Mach-O binaries) which might be embedded in apps: they should be individually signed, and when their signatures are saved in xattrs, they are easily stripped.
So what actions will strip those xattrs and break the code’s signature?
- Compressing the file, alone or with others, using the
zipcommand tool. Although its man page implies that all xattrs are preserved, in reality all four signing xattrs are stripped.
- Passing the file through iCloud Drive to another system. This is strange, as three of the four xattrs are preserved, but com.apple.cs.CodeRequirements-1 is currently stripped, which would appear to be a bug. This results in a signing error -67061, indicating an invalid signature in which the signature has been modified.
The reason that the signing xattrs are stripped by the command tool version of
zip is that it only appears to preserve xattr types which are designated for preservation. Apple could of course fix this, either by overriding the system settings by appending #P to the xattr name, or by adding these xattr types to the default behaviour list, as explained here. It’s unclear why Apple has chosen to do neither, putting signature xattrs at risk in this way.
Actions which appear safe for the moment include:
- Transferring the file to another Mac using AirDrop. Curiously, this preserves all the essential xattrs, although it also attaches a quarantine flag, making them essential.
- Compressing the file, alone or with others, using Archive Utility, even when the destination format is a Zip file.
- Moving or copying between volumes and disks with APFS or HFS+ format.
The command tool
ditto is also xattr-preserving, as are disk images and installer packages, although under the new security rules in Catalina, they could also require to be signed and even notarized, of course, so may not be your preferred solution.
The practice of stripping xattrs from files to ‘clean’ then, or remove quarantine flags, is potentially harmful. If you need to remove quarantine flags from documents, for example, use my free utility Sandstrip, which doesn’t touch other xattrs. To check whether executable code is correctly signed, Taccy inspects single apps and packages, and Signet scans whole folders for you.
Actions which Apple can take to make this work better:
- Add xattr type com.apple.cs.CodeRequirements-1 to the list of xattrs preserved in iCloud Drive.
- Add all four code-signing xattrs to the system defaults list of xattrs which default to #P handling, so preserving them on export.
Thanks to @rosyna for drawing attention to these issues.