Skip to content

Use shared access group for macOS keychain secrets#14855

Closed
greg-openai wants to merge 7 commits intomainfrom
greg/macos-keychain-teamid-acl
Closed

Use shared access group for macOS keychain secrets#14855
greg-openai wants to merge 7 commits intomainfrom
greg/macos-keychain-teamid-acl

Conversation

@greg-openai
Copy link

@greg-openai greg-openai commented Mar 16, 2026

Problem

macOS keychain items are normally only accessible to the app that created them unless other builds are signed with a shared keychain access group. We want new Codex builds to converge on a shared secret container while older builds keep working with their legacy secrets during rollout.

Summary

  • use native Security.framework keychain access on macOS in codex-keyring-store
  • add the shared access group 2DC432GLL2.com.openai.codex.shared
  • make newly signed macOS Codex builds carry that entitlement by default
  • prefer the shared item whenever it already exists
  • if the shared item is missing, read the legacy item and backfill a shared copy without deleting the legacy value
  • if the shared backfill fails, continue using the legacy value for that read
  • write new values only to the shared item
  • delete both shared and legacy items on explicit delete
  • keep the old startup migration helper as a no-op so migration is on-demand rather than eager

Migration flow

flowchart TD
    A["New entitled Codex build reads secret"] --> B{"Shared item exists?"}
    B -->|Yes| C["Use shared item\n2DC432GLL2.com.openai.codex.shared"]
    B -->|No| D{"Legacy item exists?"}
    D -->|No| E["Return missing secret"]
    D -->|Yes| F["Read legacy item"]
    F --> G["Attempt to write shared copy"]
    G -->|Success| H["Return value and future reads prefer shared"]
    G -->|Failure| I["Return legacy value\nand keep legacy item unchanged"]

    J["New entitled Codex build writes secret"] --> K["Write shared item only"]
    K --> L["Legacy item is left untouched"]

    M["Older non-entitled build"] --> N["Continues reading legacy item"]
Loading

Expected behavior

  • all newly signed macOS Codex builds should carry the shared keychain-access-groups entitlement
  • on first access to a legacy-only secret, a new build may prompt for keychain access so it can read the legacy value and create the shared copy
  • older builds can continue using their legacy value because migration no longer moves or deletes legacy secrets during rollout
  • once a new build writes a newer value, that new value lives only in the shared item; older builds continue seeing the older legacy value until they also move to the shared entitlement path

Notes

  • this is a coexistence-oriented migration path, not an in-place move with SecItemUpdate
  • rollout is intentionally on-demand: we no longer sweep and migrate known services at startup
  • because writes are shared-only, mixed-version coexistence preserves access but not value synchronization
  • local testing showed that standalone binaries with keychain-access-groups are rejected by AMFI without the right provisioning context, so full end-to-end validation still has to happen in the signed Codex.app / shipping pipeline

Testing

  • cargo test -p codex-keyring-store
  • cargo test -p codex-cli
  • just fix -p codex-keyring-store
  • just fmt

@greg-openai greg-openai force-pushed the greg/macos-keychain-teamid-acl branch from ac9bfa4 to 4232b4c Compare March 17, 2026 20:25
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant