Read registry credentials in the CLI, not the images helper#1874
Open
hsbt wants to merge 2 commits into
Open
Conversation
registry login stores the keychain item with an ACL that trusts only the writing process (the CLI, com.apple.container.cli), so reading it from the container-core-images helper, which has a different code identity, fails with errSecInteractionNotAllowed (-25308) in a non-interactive XPC service. Resolve the credential in the CLI where login wrote it and forward the Authorization header to the helper over XPC, fixing both pull and push. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Pins that the images helper builds its Authentication from the Authorization header forwarded over XPC rather than reading the keychain itself, guarding against a regression to the errSecInteractionNotAllowed (-25308) failure. Extracts the harness credential decoding into authentication(from:) so it can be exercised without a running daemon. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
00c0734 to
3f905c4
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
After a successful
container registry login,container image pullandcontainer image push(and base-image pulls duringcontainer build) fail to read registry credentials from the keychain, even when the login keychain is unlocked. This change moves the keychain read out of thecontainer-core-imageshelper and into thecontainerCLI, which is the process that wrote the item and therefore satisfies its access control. The resolvedAuthorizationheader is forwarded to the helper over XPC, and the helper no longer touches the keychain. This addresses the long-standing "Error querying keychain" /-25308family of reports, such as #1733, #1253, and #816.Symptom
-25308iserrSecInteractionNotAllowed. It reproduces even for public images, because the pull and push paths resolve stored credentials before contacting the registry.container registry loginitself succeeds, andsecurity find-internet-password -s registry-1.docker.io -wreturns the password, so the credential exists and is readable by the CLI. The failure happens only at pull and push time.Investigation
Credentials are stored in the macOS file-based login keychain. Both the store and the fetch live in the pinned
containerizationdependency (ContainerizationOS/Keychain/KeychainQuery.swift, surfaced throughContainerizationOCI.KeychainHelper). The write is a plainSecItemAddwith nokSecAttrAccessorkSecAttrAccessControl, and withoutkSecUseDataProtectionKeychain.Because no access control is supplied, macOS creates a default ACL that trusts only the creating process. As a result, the process that writes the credential and the process that reads it are different.
registry logincreates the ACL)/usr/local/bin/containercom.apple.container.clicontainer-core-imageshelpercom.apple.container.container-core-imagesThe item's ACL, seen via
security dump-keychain -a, trusts only the CLI.When the helper performs the lookup, the decrypt ACL check fails and securityd tries to prompt for approval. The helper is a non-interactive XPC service, so it cannot show the prompt and the call fails.
Adding the helper to the item's trusted-application list with
security ... -Tdoes not help. The modernSecItemCopyMatchingpath evaluates the partition list and code identity rather than the file ACL's application list. That is the direction taken by #997, and it is why that approach does not resolve the failure.Tracing every keychain reader in the tree confirms the asymmetry.
container registry list,container registry logout, andMachineClient.fetchMachineArtifact(which additionally swallows the error withtry?) all run inside thecontainerCLI process and so match the writer's ACL. The only reader that runs under a different identity isImagesService.withAuthentication, shared by bothpullandpush.container buildpulls base images throughClientImage.pullandClientImage.fetch, which also run in the CLI process.This fix was built with the project's supported toolchain (Swift 6.3 / macOS 26, matching CI) and verified end to end: after
registry login,container image pullandcontainer runsucceed with no-25308.Why this approach
KeychainQueryandKeychainHelperlive in thecontainerizationdependency, pinned to an exact version, so changing the write-time access control to a team-scoped ACL, or switching to the data-protection keychain with a shared access group, cannot be done from this repository. The shared-access-group direction is tracked separately in #1257. Reading the credential in the CLI and forwarding it is the option that is both correct and achievable here, and it matches the direction of #1215, which extracts keychain access into a client-sideRegistryKeychainClient.Code
ClientImage.registryAuthorization(for:)resolves the credential from the keychain on the client side and returns theAuthorizationheader value. It keys the lookup byresolvedDomain(e.g.registry-1.docker.io), matching whatregistry loginstores, and returnsnilwhen no entry exists so anonymous pulls keep working.ClientImage.pullandClientImage.pushset this value on the XPC request under a newregistryAuthorizationkey. These run in thecontainerCLI binary, so the read satisfies the item's ACL.ImagesServiceHarness.authentication(from:)decodes that key into anAuthenticationand hands it toImagesService.pullandpush, which now take anauthparameter.ImagesService.withAuthenticationno longer reads the keychain. It uses the forwarded credential and keeps the existing environment-variable precedence (CONTAINER_REGISTRY_*still wins) and the 401/403 handling. The forwarded value is wrapped in a smallResolvedAuthenticationwhosetoken()returns it verbatim. No credential or token is logged.Both readers are fixed because
pullandpushsharewithAuthentication, andcontainer buildis covered because it goes throughClientImage.pull.Testing
Built with the supported toolchain (Swift 6.3 / macOS 26) and verified manually: after
registry login,container image pullandcontainer runsucceed with no-25308. The same build, packaged and installed on a macOS 27 beta, was confirmed to work there as well. A newContainerImagesServiceTeststarget pins that the helper builds itsAuthenticationfrom the forwardedAuthorizationheader rather than reading the keychain, and returnsnilwhen no credential is forwarded. The existing suite never exercised this path: it only pulls public images anonymously and never logs in, which is why the regression went unnoticed by CI.Related
Same failure: #1733, #1253, #816, #1310, #254, and the earlier #704, #532, #976. Competing fix directions: #1215 (client-side keychain client, the same direction as this change), #1257 (shared keychain access group), and #997 (grant the helper keychain access, which the investigation above shows does not work). The keychain identifier itself was settled in #644 and #652.