Has anyone figured out how to get CLI tools to work on Catalina?

(as in, without first opening the containing folder, and right-clicking "Open" and "Allow"?)

Most of the resources I found talk about how to enable or disable Gatekeeper wholesale, but that's not what you typically want to do, y'know?

I had to figure this out for webinstall.dev, specifically so that unsigned tools like bat can be installed.

How to Make Magic Happen

You're going to be using one or both of these commands:

xattr -r -d com.apple.quarantine "$FILE"
spctl -a "$FILE"

And if it's acceptable to have the GUI security prompt, you'll want to use sudo:

sudo spctl -a "$FILE"

How to allow a specific command

If you want to "bless" CLI commands so that gatekeeper doesn't hate them:

spctl --add "$HOME/bin/foo"

A note on sudo

If you use sudo, you can prevent the GUI window from popping up on most of these interactions.

For example, this will pop up a GUI interaction with a password prompt:

spctl --list

Whereas this will ask for a password in Terminal, but will not give a GUI prompt:

sudo spctl --list

How to view the whitelist

This will show all "blessed" or allowed applications

spctl --list
8[Apple System] P20 allow lsopen
    anchor apple
3[Apple System] P20 allow execute
    anchor apple
2[Apple Installer] P20 allow install
    anchor apple generic and certificate 1[subject.CN] = "Apple Software Update Certification Authority"
...

It appears to list every possible name and hash of every CLI binary on the system. Wow.

How to see if a particular app is enabled

You can grep the whitelist, but that requireds sudo.

You can also check specifically by path:

# no output
spctl -a /Applications/VLC.app

# always rejected, but also can be valid
spctl -a "$HOME/bin/foo"

IMPORTANT Note: "rejected" apps can be "valid"!!!

This is very confusing, but this means that it is allowed:

/Users/me/bin/foo: rejected (the code is valid but does not seem to be an app)

Also, that output will go to stderr rather than stdout. If you want to check it, you have to redirect and grep:

spctl -a "$HOME/bin/foo" 2>&1 | grep valid
  • If there's no output, then it's perfectly valid, and the status code $? will be 0.
    • ""
  • If it's rejected and also valid, the status code will be 3.
    • "rejected (the code is valid but does not seem to be an app)"
  • If it's solid rejected, the status code is also 3.
    • "rejected"

Ugh...

How to disable Gatekeeper completely

sudo spctl --master-disable

To re-enable:

sudo spctl --master-enable

Putting it all together: The Magic Snippet

If this doesn't make sense, read up above on the specifics.

bless-cli.sh:

set -e
set -u

cli_bin=${1} # ex: "/path/to/foo"
xattr -r -d com.apple.quarantine "$cli_bin" || true
is_allowed="$(spctl -a "$cli_bin" 2>&1 | grep valid)"
if [ -z "$is_allowed" ]; then
    echo "Requesting permission to execute 'foo' on macOS 11+"
    spctl --add "$cli_bin"
fi
bash bles-cli.sh /path/to/foo

By AJ ONeal

If you loved this and want more like it, sign up!


Did I make your day?
Buy me a coffeeBuy me a coffee  

(you can learn about the bigger picture I'm working towards on my patreon page )