Because signing needs the private key in a macOS keychain, and a CI machine should not leave that key lying in a long-lived one. A temporary keychain is created for the job, holds the certificate while the build signs, and is deleted afterwards. It also stops builds hanging on keychain prompts.
What the job does, step by step
The fastlane setup_ci action describes the pattern in three lines: it creates a new temporary keychain for use with match, switches match to read-only mode so CI does not create certificates or profiles, and sets up log and test result paths so they are easy to collect. By default the temporary keychain has a timeout of 3,600 seconds, and the action can make it the default keychain.
A hosted CI service's own guide to signing Xcode apps shows the same idea done by hand. The steps are:
- Decode the certificate and provisioning profile from stored secrets onto the runner's temp directory.
- Create a keychain with a random password.
- Unlock it, import the certificate, and allow Apple's signing tools to use the key.
- Add the keychain to the search list and copy the profile into the expected folder.
That guide recommends secrets for the certificate, its password, the profile and the keychain password, and says the keychain password can be any new random string because the keychain is new.
Why it matters for security
A fresh keychain per job gives you three things.
| Benefit | Why it helps |
|---|---|
| Isolation | The signing key is not mixed into a keychain other jobs or users read |
| Cleanup | Deleting one keychain removes the key from the machine |
| Reliability | The fastlane GitHub guide notes that without setup_ci the build could freeze and never finish |
The self-hosted catch
Hosted runners are isolated virtual machines destroyed after the job, so the certificate disappears with them. The same guide is explicit about self-hosted runners: the temp directory is cleaned, but the keychain and provisioning profile might still exist. It tells you to add a final step that deletes them, and to run it with an always condition so it executes even when the build fails. Our post on cleaning up a self-hosted Mac runner goes through the checklist.
Common mistakes
- Using the login keychain on a shared build Mac, so the key outlives the job.
- Setting the keychain timeout to never lock without deleting it afterwards.
- Writing the decoded certificate to a path inside the workspace, where it may be archived or cached.
- Leaving the cleanup step out of failure paths.
Where Safeguard fits
Safeguard does not handle keychains. It scans the dependencies your app builds with and can gate releases through policies. Start with a free scan.
Quick check
Is a temporary keychain a secret store?
No. It is a short-lived container for a key that came from your secret store. The secret store remains the source of truth.
Do hosted runners need the cleanup step?
The documentation says hosted runners are destroyed after the job, so cleanup matters mainly on self-hosted machines.
Sources
- fastlane docs: setup_ci
- fastlane docs: GitHub Actions integration
- GitHub Docs: installing an Apple certificate on macOS runners
Last reviewed: 19 October 2026.