Recently, I’ve received many questions from users who write their own code, from shell scripts to Python, AppleScript and a few who use Xcode, asking what the requirements are in Big Sur for signing their code. This article is a short guide to dispel rumours that all coders now need to pay to join the Apple Developer Program: you don’t.
Big Sur requirements
Contrary to rumour, on Intel Macs, Big Sur hardly requires any code, from shell scripts to polished apps built with Xcode, to be signed at all. The only specialist exceptions to this are kernel and system extensions and their close relatives, which require special approvals from Apple. They’re hardly the sort of code that you’re likely to develop without being a member of the Apple Developer Program.
Apple’s new M1 Macs are different in this respect. Although they’ll happily run unsigned Intel code using Rosetta 2, for them to run any native ARM code, it’s a requirement that it’s signed. If it isn’t, then it will be blocked. This doesn’t apply to scripts or intermediate code, only to executables which can be loaded and run on ARM processors.
The reason for this requirement for code signing of native code isn’t to enable conventional code signature checks, but so that the executable code has a cdhash, which is used when macOS checks code before running it. So the signature used isn’t particularly important: if you don’t have an Apple-issued signing certificate, an ad-hoc certificate generated on your Mac is quite sufficient. For those without developer accounts, Xcode now defaults to applying ad-hoc signing to its projects.
The model which members of the Apple Developer Program are expected to conform to is different, as most are supplying apps and other software remotely, from their own website, or the App Store. In that case, Apple has three classes of software:
- Apple’s own products, which it signs as required.
- Third-party products supplied through the App Store, which comply with its rules and have Apple Mac OS Application Signing applied by Apple.
- All other third-party products, which are supplied by other means, and are now expected to be notarized.
If you write your own code and distribute it privately, there is no requirement or expectation that it will be notarized. Notarization provides reasonable assurance that a product being offered for download, whether or not it’s commercial, doesn’t contain malware. It’s therefore given an easy route through the checks which are performed by macOS on software which has been downloaded from the internet.
Quarantine and scripts
Apart from the special requirement for all executable code running native on Apple Silicon Macs, the main reason for signing code and (where applicable) notarization is Gatekeeper and the first run of that code. In most circumstances, executable code which has been downloaded from the internet has a quarantine flag attached to it. When that flag is set, for its first run, Gatekeeper runs additional checks. If the app has been notarized, the user is informed and asked to agree to that app being run, using a standard dialog. If the app hasn’t been notarized, the user is informed of that, and isn’t offered the chance to run it on that first asking. Instead, they have to try to open the app a second time, then agree to take the risk of running an app which hasn’t been checked as part of the notarization process.
Notarization doesn’t affect the running of apps or executables which don’t have the quarantine flag set, in the same way (although the requirements for notarization, such as the hardened runtime environment, should improve app security to some degree). So if you pass your app onto a friend on a USB ‘stick’, or go to a client and install it direct, this notarization check isn’t relevant. For many non-commercial developers, this means that notarization itself isn’t relevant.
Quarantine does, though, have effects on scripts which can catch users out. Script editors which run in a sandbox routinely set the quarantine flag on documents, including scripts, which they save, or sometimes just open without explicitly saving. Trying to run a script with the quarantine flag set should cause macOS to refuse to run that script. So if you create a shell script using a sandboxed editor, the resulting script shouldn’t work. The only way around this is to use an editor which doesn’t set the quarantine flag, or to strip the flag before trying to run it. The best editors, such as BBEdit, give you the option of turning off this disruptive behaviour.
So far I have considered two simple classes of code: scripts which are normally stored as text, and can only run inside a shell environment or interpreter, and executables which can be loaded onto the processor and run directly. Many scripting and similar systems use a third type of code which consists of an intermediate, which is then run in an execution environment. It’s important to know whether this applies to the code which you use, as the rules for executable code don’t then apply.
This gets more complicated when there are combinations available. An AppleScript .scpt file doesn’t contain code which is run directly on the processor, but turn that into a standalone app and that does contain proper executable code. On an M1 processor this is a significant difference, as the .scpt file doesn’t need to be signed, but the standalone app does. Script Editor and Script Debugger both provide support which makes the signing of standalone AppleScript apps much easier, and Script Debugger also has a companion tool SD Notary which makes notarization much easier if you aren’t building a vanilla app in Xcode.
For the vast majority of ‘hobbyist’ coders, there’s no need to sign any of your scripts or apps unless you build them to run native on the M1, in which case all you need do is sign them with an ad-hoc signature. Beware of quarantine flags being set on scripts, which will normally block their execution. Only when you start distributing ready-built apps over the internet do you run into the expectation of signing using an Apple-issued certificate and the rigours of notarization. If you’re still unsure, please ask.