Open files from unidentified developers from the command line in macOS

Open files from unidentified developers from the command line in macOS

It usually happens that you can not run a downloaded binary from the command line.

The OS would complain that

"watchman" cannot be opened because the developer cannot be verified.

macOS cannot verify that this app is free from malware.

Chrome downloaded this file today at 9:30 AM from github.com

Many online tutorials instruct you to overcome this restriction by navigating to the binary file location, right-click, selecting open, and confirming.

macOS cannot verify the developer of "watchman". Are you sure you want to open it?

By opening this app, you will be overriding system security which can expose your computer and personal information to malware that may harm your Mac or compromise your privacy.

Chrome downloaded this file today at 9:30 AM from github.com

However, this approach has two demerits.

  • It requires GUI. Thus, it is not possible to apply to several files at once.
  • To mark some files safe, they must be opened (executed).

Workaround 1

Use xattr -dr com.apple.quarantine <directory, binary, .app, or dylib path>


Workaround 2

Suppose that the path of the binary you want to mark as safe is /opt/watchman/bin/watchman.

  • Step 1: run xattr -p com.apple.quarantine /opt/watchman/bin/watchman. This will print a string starting with 0081;, for example 0081;5e7fec61;Chrome;6585C1D3-E260-4275-9E6E-505DF8D6B7EE.
  • Step 2: Copy the output string, replace the first 4 characters with 00c1.
  • Step 3: run xattr -w com.apple.quarantine "00c1;5e7fec61;Chrome;6585C1D3-E260-4275-9E6E-505DF8D6B7EE" /opt/watchman/bin/watchman

The binary /opt/watchman/bin/watchman can be run from the command line without any complaint from the OS.

Those above steps can be combined in one composed of commands.

xattr -w com.apple.quarantine "$(xaatr -p com.apple.quarantine /opt/watchman/bin/watchman | sed 's/^.\{4\}/00c1/')" /opt/watchman/bin/watchman

Further information

To list all file attributes use one of the following commands.

  • ls -al@ <path>
  • attr -lr <path>

What does each value in the attribute mean?

  • 00c1: flag for a quick lookup. This is a magic number defined by apple. See this link for further analysis.
  • 5e7fec61: date in hex format.

Convert this value to a date:

In Linux:

hex=5e7fec61
date -d @$(echo $((16#${hex})))
# Sun 29 Mar 2020 09:31:29 AM JST

In Mac:

hex=5e7fec61
date -r $(echo $((16#${hex})))

#Sun Mar 29 09:31:29 JST 2020

Generate a value from the current timestamp:

In Linux:

printf %x $(($(date +%s) - $(date -d "2001-01-01T00:00 UTC" +%s)))
# output: 24f34922

In Mac:

printf %x $(($(date +%s) - $(TZ=UTC date -jf '%F %T' "2001-01-01 00:00:00" +%s)))
# output: 24f34f38

Why 2001-01-01? Because Apple's absolute time is Jan 2001 00:00:00 GMT. See CFAbsoluteTime.

  • Chrome: app name (arbitrary string value).
  • 6585C1D3-E260-4275-9E6E-505DF8D6B7EE: uuid used to look up other information about the file.

Lookup for information from the uuid.

uuid=6585C1D3-E260-4275-9E6E-505DF8D6B7EE
/usr/bin/sqlite3 ~/Library/Preferences/com.apple.LaunchServices.QuarantineEventsV2 "SELECT * FROM LSQuarantineEvent WHERE LSQuarantineEventIdentifier == '${uuid}'"

Output:

6585C1D3-E260-4275-9E6E-505DF8D6B7EE|607134674.0|com.google.Chrome|Chrome|https://pipelines.actions.githubusercontent.com/G9fMED6cdPFXyiEGn3n1jhGAY8W1pSRpkNfzWNYHidH52XdARZ/_apis/pipelines/1/runs/351/signedartifactscontent?artifactName=watchman&urlExpires=2020-03-29T00%3A32%3A11.2036918Z&urlSigningMethod=HMACV1&urlSignature=82lAU9QVnN0n8z1OYpo%2BshRvDMj6kKxJEulbSOwhi2g%3D|||0||https://github.com/facebook/watchman/actions/runs/32012692|

Insert a new entry to the database. (replace the date=... with appropriate MacOS version above if you are using Mac)

url="https://github.com/facebook/watchman/actions/runs/32012692"
date=$(printf %x $(($(date +%s) - $(date -d "2001-01-01T00:00 UTC" +%s)))
)
app_name=Chrome
/usr/bin/sqlite3 ~/Library/Preferences/com.apple.LaunchServices.QuarantineEventsV2 "INSERT INTO \"LSQuarantineEvent\" VALUES('${uuid}',${date},NULL,'${app_name}','${url}',NULL,NULL,0,NULL,'${url}',NULL);"

Set the attribute on an existing file ${file}. (replace the date=... with appropriate MacOS version above if you are using Mac)

app_name=chrome
date=$(printf %x $(($(date +%s) - $(date -d "2001-01-01T00:00 UTC" +%s))))
uuid=uuid=6585C1D3-E260-4275-9E6E-505DF8D6B7EE
/usr/bin/xattr -w com.apple.quarantine "0002;${date};${app_name};${uuid}" "${file}"

Generate a new uuid:

/usr/bin/uuidgen
# Linux: 84e2caa7-62cd-423f-85fa-2026a1b71ee5
# Mac: E7BF43F8-E2BB-4124-8EAE-6F1CDDB46835

Source

Buy Me A Coffee