"User interaction is not allowed" trying to sign an OSX app using codesign

Using Security to create a Keychain for /usr/bin/codesign

Importing the certificate and having it work with codesign programmatically isn't a matter of using login or System keychains or praying to some god of codesign. You just need to have the correct permissions set. I recommend creating a new keychain specifically for codesign purposes.

These days to get codesign to not yield an errSecInternalComponent you need to get the partition list (ACLs) correct. I'll walk through the steps:

Create the Keychain

security create-keychain -p "${KEYCHAIN_PASSWORD}" "${KEYCHAIN_NAME}"

at this point the keychain is unlocked but won't appear in Keychain Access.

Add the new Keychain to the search list

security list-keychains -s "${KEYCHAIN_NAME}" "${OLD_KEYCHAIN_NAMES[@]}"

Add the new Keychain to the list. If you don't first grab out the original list from list-keychains you'll no longer have login.keychain in your search-list.

Unlock the keychain

security unlock-keychain -p "${KEYCHAIN_PASSWORD}" "${KEYCHAIN_NAME}"

This is redundant if you created the Keychain above, but if the Keychain already existed it is necessary.

Remove the defaults from the Keychain

security set-keychain-settings "${TESTING_KEYCHAIN}"

By not specifying any arguments this will set the auto-lock timeout to unlimited and remove auto-lock on sleep.

Import your signing certs from a .p12

security import "${DIST_CER}" -P "${CERTIFICATE_PASSWORD}" -k "${KEYCHAIN_NAME}" -T /usr/bin/codesign

Import the certs and gives codesign access through the -T option.

Set the ACL on the keychain

security set-key-partition-list -S apple-tool:,apple: -s -k "${KEYCHAIN_PASSWORD}" "${KEYCHAIN_NAME}"

This is a requirement that many people miss. You can see what macOS does by using dump-keychain. Which in the case of codesigning requires apple: and apple-tool:. -s refers to signing certificates.

Where's my signing certificate?

Always a good idea to make sure you can find your certificates

security find-identity -p codesigning -v /path/to/keychain

Gitlab-Runner, Jenkins and the like

One very important thing for any CI-type runner or build system is to make sure the process is started from launchd correctly. Make sure your plist contains <SessionCreate> </true>.

Not correctly matching the the owner of the keychain with the build process and making sure a security session is created will result is all sorts of headaches. Diagnostically speaking you can introduce list-keychains and see if the output matches your expectations.

This is from the launchd.plist man-page:

SessionCreate <boolean>

This key specifies that the job should be spawned into a new security audit session rather than the default session for the context is belongs to. See auditon(2) for details.

UserName <string>

This optional key specifies the user to run the job as. This key is only applicable for services that are loaded into the privileged system domain.

GroupName <string>

This optional key specifies the group to run the job as. This key is only applicable for services that are loaded into the privileged system domain. If UserName is set and GroupName is not, then the group will be set to the primary group of the user.

Example /Library/LaunchDaemons/com.company.gitlab-runner.plist

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
  <dict>
    <key>Label</key>
    <string>com.company.gitlab-runner</string>
    <key>SessionCreate</key><true/>
    <key>KeepAlive</key><true/>
    <key>Disabled</key><false/>
    <key>UserName</key>
    <string>bob</string>
    <key>GroupName</key>
    <string>staff</string>
    <key>ProgramArguments</key>
    <array>
      <string>/usr/local/opt/gitlab-runner/bin/gitlab-runner</string>
      <string>run</string>
      <string>--working-directory</string>
      <string>/Users/bob/gitlab-runner</string>
      <string>--config</string>
      <string>/Users/bob/gitlab-runner/config.toml</string>
      <string>--service</string>
      <string>gitlab-runner</string>
      <string>--syslog</string>
    </array>
    <key>EnvironmentVariables</key>
      <dict>
        <key>PATH</key>
        <string>/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin</string>
    </dict>
  </dict>
</plist>

Register the runner

gitlab-runner register \
  --non-interactive \
  --tls-ca-file "{{ gitlab_runner_dir }}/certs/git.company.com.crt" \
  --config "{{ gitlab_runner_dir }}/config.toml" \
  --builds-dir "{{ gitlab_runner_dir }}/builds" \
  --url "{{ gitlab_ci }}" \
  --registration-token "{{ gitlab_token }}" \
  --name "{{ computername }}" \
  --tag-list "{{ gitlab_runner_tags }}" \
  --output-limit 16384 \
  --executor shell \
  --shell bash

Finally codesign

You can lookup the signing certificates hash using find-identity

security find-identity -p codesigning -v

Before beginning signing Xcode sets the environment variable CODESIGN_ALLOCATE to use the codesign_allocate that comes with Xcode, not in /usr/bin.

export CODESIGN_ALLOCATE="$( xcrun --find codesign_allocate )"

Codesign a framework, dylib, etc.

If you're codesigning manually, start with the frameworks and dylibs and after they are all signed, then sign the .app. Or in other words - you codesign from the bottom up.

/usr/bin/codesign --verbose=4 -f -s "$SIGNER_HASH" "$SIGNABLE"

Codesign the app bundle

After all the other signables are signed, sign the .app itself. In theory, you could do this all in one go with --deep, however, you would still need to make sure your app has entitlements and possibly other flags.

/usr/bin/codesign --verbose=4 -f -s "$SIGNER_HASH" "$SIGNABLE"

Flag passed to all items:

  • --timestamp=none disable timestamps

Other flags to the app signing step:

  • --entitlements /path/to/entitlements.xcent new entitlements
  • --preserve-metadata=entitlements keep current entitlements

New codesign requirement - DER encoded entitlements

Apple has recently started requiring entitlements to not be embedded only in plist form, but also in DER encoded form. If you are using an older Mac/Xcode you might encounter the error...

The code signature version is no longer supported


None of the other answers worked for me.

What eventually saved me was this post

To sum it up, this can be caused by a default timeout of 5 minutes, that will trigger this error after a long build.

To fix:

security set-keychain-settings -t 3600 -l ~/Library/Keychains/login.keychain

I too have been fighting this. Nothing helped until I tried the suggestion on http://devnet.jetbrains.com/thread/311971. Thanks ashish agrawal!

Login your build user via the GUI and open Keychain Access. Select your signing private key, right-click, choose Get Info, change to the Access Control tab and select the "Allow all applications to access this item".

access control tab


Well, I guess I get to answer my own question today, because after stabbing at it over two and a half days, one of the things I tried seems to have worked. I'm just going to back away from it now and hope it keeps working.

Essentially, it looks like it comes down to -d system not actually working. So a lot of answers to other questions around here should probably be updated to reflect that.

security -v list-keychains -s "$KEYCHAIN" "$HOME/Library/Keychains/login.keychain"
security list-keychains # so we can verify that it was added if it fails again
security -v unlock-keychain -p "$KEYCHAIN_PASSWORD" "$KEYCHAIN"
codesign --sign "$SIGNER_IDENTITY" --force --signature-size 9600 \
         --resource-rules src/AppResourceRules.plist --timestamp --verbose \
         "$APP"