Skip to content

[build-tools] Fix iOS local build on macOS Tahoe — drop -v from find-identity in findIdentitiesByTeamId#3679

Open
kearnsm293-afk wants to merge 2 commits intoexpo:mainfrom
kearnsm293-afk:fix/keychain-find-identity-trust-chain-tahoe
Open

[build-tools] Fix iOS local build on macOS Tahoe — drop -v from find-identity in findIdentitiesByTeamId#3679
kearnsm293-afk wants to merge 2 commits intoexpo:mainfrom
kearnsm293-afk:fix/keychain-find-identity-trust-chain-tahoe

Conversation

@kearnsm293-afk
Copy link
Copy Markdown

Why

Closes #3678. On macOS 26 (Tahoe), eas build --profile development --platform ios --local fails at Prepare credentials with Distribution certificate ... hasn't been imported successfully even when the cert+key are correctly imported into the build keychain.

Keychain.findIdentitiesByTeamId runs:

security find-identity -v -s "(<teamId>)" <buildKeychainPath>

The -v ("valid identities only") flag requires the full trust chain (dist cert → Apple WWDR Intermediate → Apple Root CA) to resolve from the keychain(s) in the search list. The build keychain (created in Keychain.create()) only holds the cert + private key; Apple Root CA lives in /Library/Keychains/System.keychain and Apple WWDR G3 lives in the user's login keychain. security find-identity does not aggregate trust resolution across keychains passed as positional args — only security list-keychains -s does, and that change would be session-wide and undesirable.

On macOS 26 (Tahoe), this trust gate causes find-identity -v -s "(<teamId>)" <buildKeychainPath> to return 0 identities even when the cert+key were correctly imported, falsely tripping ensureCertificateImported.

How

Drop -v from the find-identity call. The remaining flags (-s "(<teamId>)" <buildKeychainPath>) still constrain the match to the right team and keychain, so the includes(fingerprint) check in ensureCertificateImported correctly answers "is the cert+key pair present in this keychain?" The cert appears in the output annotated (CSSMERR_TP_NOT_TRUSTED) — that's expected and ignored. Codesign performs its own trust resolution downstream via Security.framework (which does aggregate across keychains), so signing still succeeds end-to-end.

The change is one line in packages/build-tools/src/ios/credentials/keychain.ts plus a comment block explaining the reasoning so a future reader doesn't add -v back.

Test Plan

  • The existing integration test packages/build-tools/src/ios/credentials/__integration-tests__/keychain.test.ios.ts ("shouldn't throw any error if the certificate has been imported successfully") covers exactly this scenario. It currently fails on macOS 26 (Tahoe) due to this bug; the fix makes it pass.
  • Manually verified end-to-end: eas build --profile development --platform ios --local against an Expo-managed dist cert + ad-hoc provisioning profile completes successfully on macOS 26.0 (Tahoe) with the patch applied. Produces a signed .ipa that installs and runs on a registered iOS 26 device.
  • No regression risk on older macOS: dropping -v is strictly more permissive in what find-identity reports back. On systems where -v worked (older macOS, or systems where Apple Root CA happens to be visible in the build keychain's effective search list), the same cert+key pair still appears in the output without -v. The includes(fingerprint) check passes in both cases.

Checklist

  • CHANGELOG.md updated under ## main### 🐛 Bug fixes. (PR URL placeholder will be replaced with the real PR number once this is opened.)
  • Commit message follows the [package] Description format.
  • No public API change. No breaking change.

MikeK968 added 2 commits May 5, 2026 21:55
…identity in findIdentitiesByTeamId

`Keychain.findIdentitiesByTeamId` runs `security find-identity -v -s
"(<teamId>)" <buildKeychainPath>` to verify that the dist cert was
imported into the freshly-created build keychain. The `-v` ("valid
identities only") flag requires the full trust chain (dist cert ->
Apple WWDR Intermediate -> Apple Root CA) to resolve from the
keychain(s) in the search list. The build keychain only holds the
cert + private key; Apple Root CA lives in
/Library/Keychains/System.keychain. `security find-identity` does
not aggregate trust resolution across keychains passed as positional
args — only `security list-keychains -s` does, and that's
session-wide and would mutate the user's environment.

On macOS 26 (Tahoe), this caused `find-identity -v` to return 0
identities even when the cert+key were correctly imported, falsely
tripping `ensureCertificateImported` with "Distribution certificate
... hasn't been imported successfully".

Dropping `-v` fixes the presence check across macOS versions.
Codesign performs its own trust resolution downstream via
Security.framework (which does aggregate across keychains), so
signing still succeeds.

Existing integration test
`packages/build-tools/src/ios/credentials/__integration-tests__/keychain.test.ios.ts`
("shouldn't throw any error if the certificate has been imported
successfully") covers this scenario and now passes on Tahoe.

Closes expo#3678
@github-actions
Copy link
Copy Markdown

github-actions Bot commented May 6, 2026

Subscribed to pull request

File Patterns Mentions
**/* @douglowder

Generated by CodeMention

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

2 participants