app-server: add macOS device key provider#18431
Conversation
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: c0fc5bb1ce
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
a6f5f5e to
e4e9f03
Compare
c0fc5bb to
4de8c7d
Compare
e4e9f03 to
f9220dd
Compare
cb9c2f2 to
e0eb231
Compare
f9220dd to
75ba150
Compare
e0eb231 to
d6970f9
Compare
b59b13f to
f7b198b
Compare
9ab7c21 to
ee62f13
Compare
54f7030 to
c4e3b95
Compare
0060869 to
ee406bb
Compare
c4e3b95 to
20c2078
Compare
20c2078 to
cd244b7
Compare
ee406bb to
2f748ae
Compare
2f748ae to
dc066ce
Compare
cd244b7 to
b371887
Compare
|
[P2] OS‑protected fallback load path doesn’t validate non‑extractable attrs on existing keys; it is tag‑based. If we want the degraded path to still enforce non‑exportable, consider validating key attributes when loading, not just on create. |
b371887 to
f664fa1
Compare
dc066ce to
30d2da0
Compare
|
[codex] Addressed in |
f664fa1 to
123af8e
Compare
e50e78c to
5ff2eec
Compare
cba35b7 to
05a41cc
Compare
5ff2eec to
e38f027
Compare
05a41cc to
3c1f8d4
Compare
e38f027 to
751e183
Compare
3c1f8d4 to
763ee60
Compare
## Summary Load LocalAuthentication.framework at runtime before constructing LAContext instead of linking the framework into every macOS target. The previous direct framework link made unrelated macOS Bazel targets link against an SDK-backed framework path, which caused the macOS CI jobs to fail during linking. The signing flow still uses LAContext for authenticated private-key operations; this only changes how the framework becomes available to the Objective-C runtime. ## Validation - just fmt - cargo test -p codex-device-key - just fix -p codex-device-key - git diff --check - bazel build //codex-rs/device-key:device-key
## Summary Add the required parameter-name comment for the None authentication-context argument in the macOS device-key lookup path. CI macOS argument-comment lint enforces these comments for positional literal-like arguments. ## Validation - just fmt - cargo test -p codex-device-key - just fix -p codex-device-key - bazel build --config=argument-comment-lint //codex-rs/device-key:device-key-unit-tests-bin - git diff --check Note: a full local just argument-comment-lint run reached the fixed device-key target, then failed later in an unrelated webrtc-sys build script with a stale sandbox path outside this PR changes.
751e183 to
eab5a71
Compare
f326b6b to
aa16360
Compare
The device-key crate needs a platform provider that can keep private keys non-extractable on macOS while preserving the crate-level protection policy and structured signing boundary. macOS has two useful local protection classes for this API: hardware-backed Secure Enclave keys when available, and OS-protected non-extractable keys as an explicit fallback. Reporting which class was selected keeps that distinction visible to callers. The Security.framework access-control flags used here provide device-local non-exportability and continuity while the user session is unlocked. They do not require UserPresence or Biometry for each signature, so the key itself is not treated as a complete same-controller compromise boundary; the API still relies on local-transport restriction, app-server authorization, and structured payload validation. - Added the macOS DeviceKeyProvider implementation backed by Security.framework. - Created and loaded P-256 private keys by stable device-key ID. - Preferred Secure Enclave keys by default and allowed OS-protected non-extractable fallback only when requested by policy. - Returned SPKI DER public keys and DER-encoded ECDSA signatures through the existing crate API. - Documented the macOS provider threat-model boundary around this-device-only keys without UserPresence or Biometry flags. - Added macOS-only Security.framework and CoreFoundation dependencies. - just fmt - cargo test -p codex-device-key - just fix -p codex-device-key - git diff --check - just bazel-lock-update - just bazel-lock-check
Require macOS-created device keys to prove user presence before private-key use by adding the UserPresence access-control flag at key creation time. This keeps the provider aligned with the device-ownership goal: a valid signature should require both the device-local private key and a successful local biometric or password authentication. Thread a process-local LAContext into signing lookups and reuse it across sign operations. Security.framework still owns the authentication policy and validity window, while the reusable context lets macOS reuse a recent successful authentication when policy permits instead of prompting on every connection. Public-key lookup and binding reads continue to avoid the authentication context because they do not use the private key. - just fmt - cargo test -p codex-device-key - just fix -p codex-device-key - git diff --check
## Summary Load LocalAuthentication.framework at runtime before constructing LAContext instead of linking the framework into every macOS target. The previous direct framework link made unrelated macOS Bazel targets link against an SDK-backed framework path, which caused the macOS CI jobs to fail during linking. The signing flow still uses LAContext for authenticated private-key operations; this only changes how the framework becomes available to the Objective-C runtime. ## Validation - just fmt - cargo test -p codex-device-key - just fix -p codex-device-key - git diff --check - bazel build //codex-rs/device-key:device-key
## Summary Add the required parameter-name comment for the None authentication-context argument in the macOS device-key lookup path. CI macOS argument-comment lint enforces these comments for positional literal-like arguments. ## Validation - just fmt - cargo test -p codex-device-key - just fix -p codex-device-key - bazel build --config=argument-comment-lint //codex-rs/device-key:device-key-unit-tests-bin - git diff --check Note: a full local just argument-comment-lint run reached the fixed device-key target, then failed later in an unrelated webrtc-sys build script with a stale sandbox path outside this PR changes.
|
Update pushed in two commits:
Local check against the OpenAI-signed debug CLI currently reproduces the remaining blocker at {
"failedMethod": "device/key/create",
"error": {
"code": -32603,
"message": "device key platform error: macOS Keychain entitlements are required to create persistent device keys"
}
}Command used: codex-rs/scripts/check-device-key-app-server.py --binary codex-rs/target/debug/codex |
|
Closing this pull request because it has had no updates for more than 14 days. If you plan to continue working on it, feel free to reopen or open a new PR. |
Why
The device-key crate needs a platform provider that can keep private keys non-extractable on macOS while preserving the crate-level protection policy and structured signing boundary.
macOS has two useful local protection classes for this API: hardware-backed Secure Enclave keys when available, and OS-protected non-extractable keys as an explicit fallback. Reporting which class was selected keeps that distinction visible to callers.
The Security.framework access-control flags used here provide device-local non-exportability and continuity while the user session is unlocked. They do not require UserPresence or Biometry for each signature, so the key itself is not treated as a complete same-controller compromise boundary. The API still relies on local-transport restriction, app-server authorization, and structured payload validation.
What changed
DeviceKeyProviderimplementation backed by Security.framework.Stack
This is stacked on #18430.
Validation
cargo test -p codex-device-keyjust bazel-lock-updatejust bazel-lock-check