Skip to content

app-server: add codex-device-key crate#18429

Merged
euroelessar merged 1 commit intomainfrom
ruslan/device-key-crate
Apr 21, 2026
Merged

app-server: add codex-device-key crate#18429
euroelessar merged 1 commit intomainfrom
ruslan/device-key-crate

Conversation

@euroelessar
Copy link
Copy Markdown
Collaborator

@euroelessar euroelessar commented Apr 18, 2026

Why

Device-key storage and signing are local security-sensitive operations with platform-specific behavior. Keeping the core API in codex-device-key keeps app-server focused on routing and business logic instead of owning key-management details.

The crate keeps the signing surface intentionally narrow: callers can create a bound key, fetch its public key, or sign one of the structured payloads accepted by the crate. It does not expose a generic arbitrary-byte signing API.

Key IDs cross into platform-specific labels, tags, and metadata paths, so externally supplied IDs are constrained to the same auditable namespace created by the crate: dk_ followed by unpadded base64url for 32 bytes. Remote-control target paths are also tied to each signed payload shape so connection proofs cannot be reused for enrollment endpoints, or vice versa.

What changed

  • Added the codex-device-key workspace crate.
  • Added account/client-bound key creation with stable dk_ key IDs.
  • Added strict key_id validation before public-key lookup or signing reaches a provider.
  • Added public-key lookup and structured signing APIs.
  • Split remote-control client endpoint allowlists by connection vs enrollment payload shape.
  • Added validation for key bindings, accepted payload fields, token expiration, and payload/key binding mismatches.
  • Added flow-oriented docs on the validation helpers that gate provider signing.
  • Added protection policy and protection-class types without wiring a platform provider yet.
  • Added an unsupported default provider so platforms without an implementation fail explicitly instead of silently falling back to software-backed keys.
  • Updated Cargo and Bazel lock metadata for the new crate and non-platform-specific dependencies.

Stack

This is stacked on #18428.

Validation

  • cargo test -p codex-device-key
  • Added unit coverage for strict key_id validation before provider use.
  • Added unit coverage that rejects remote-control paths from the wrong signed payload shape.
  • just bazel-lock-update
  • just bazel-lock-check

Copy link
Copy Markdown
Contributor

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 69b06f874a

ℹ️ 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".

Comment thread codex-rs/device-key/src/lib.rs Outdated
@euroelessar euroelessar force-pushed the ruslan/device-key-crate branch from 69b06f8 to 789f413 Compare April 18, 2026 00:05
@euroelessar euroelessar force-pushed the ruslan/device-key-v2-protocol branch from 97a50d0 to b857fcc Compare April 18, 2026 00:05
@euroelessar euroelessar force-pushed the ruslan/device-key-crate branch 3 times, most recently from 3f5129c to 6f55c87 Compare April 18, 2026 00:22
@euroelessar euroelessar force-pushed the ruslan/device-key-v2-protocol branch from b857fcc to 9a85c6c Compare April 18, 2026 00:22
@euroelessar euroelessar force-pushed the ruslan/device-key-crate branch 4 times, most recently from d0ea927 to 7501a60 Compare April 18, 2026 00:40
Comment thread codex-rs/device-key/src/lib.rs Outdated
Comment thread codex-rs/device-key/src/lib.rs Outdated
Comment thread codex-rs/device-key/src/lib.rs Outdated
@euroelessar euroelessar force-pushed the ruslan/device-key-v2-protocol branch from 9a85c6c to bf613e8 Compare April 18, 2026 01:10
@euroelessar euroelessar force-pushed the ruslan/device-key-crate branch 2 times, most recently from b8a5f17 to e8bc757 Compare April 18, 2026 01:25
@euroelessar euroelessar force-pushed the ruslan/device-key-v2-protocol branch from bf613e8 to 9915c86 Compare April 18, 2026 01:25
@viyatb-oai
Copy link
Copy Markdown
Collaborator

viyatb-oai commented Apr 18, 2026

just make sure backend must verify signature against signed_payload_base64 bytes exactly. The crate now exposes exact bytes, but the security property is only real if the backend does NOT reserialize payloads. Please ensure backend verification uses the provided bytes and the token hash/nonce from the same challenge.

@euroelessar euroelessar force-pushed the ruslan/device-key-v2-protocol branch from 9915c86 to a38e6c1 Compare April 18, 2026 02:36
@euroelessar euroelessar force-pushed the ruslan/device-key-crate branch from e8bc757 to 4f7294e Compare April 18, 2026 02:36
@euroelessar
Copy link
Copy Markdown
Collaborator Author

[codex] Addressed in 4f7294e: signedPayloadBase64 now documents that it is the exact byte string covered by signatureDer, and that verifiers must verify those bytes directly instead of reserializing the structured payload.

@euroelessar euroelessar marked this pull request as draft April 18, 2026 02:38
@euroelessar euroelessar force-pushed the ruslan/device-key-v2-protocol branch from a38e6c1 to 3f76329 Compare April 18, 2026 19:25
@euroelessar euroelessar force-pushed the ruslan/device-key-crate branch 2 times, most recently from 069064a to 4189212 Compare April 18, 2026 19:31
@euroelessar euroelessar marked this pull request as ready for review April 20, 2026 21:14
Copy link
Copy Markdown
Contributor

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 4189212c8a

ℹ️ 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".

Comment thread codex-rs/device-key/src/lib.rs Outdated
Comment on lines +21 to +25
const REMOTE_CONTROL_CLIENT_PATHS: &[&str] = &[
"/api/codex/remote/control/client",
"/api/codex/remote/control/client/enroll",
"/wham/remote/control/client",
"/wham/remote/control/client/enroll",
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Split targetPath allowlists by payload audience

REMOTE_CONTROL_CLIENT_PATHS mixes /client and /client/enroll, and both payload validators call validate_remote_control_target unchanged. As a result, RemoteControlClientConnection accepts enrollment paths and RemoteControlClientEnrollment accepts websocket paths, violating each payload type’s route binding. This can permit cross-endpoint proof reuse if downstream verification assumes this crate enforces the path contract.

Useful? React with 👍 / 👎.

@viyatb-oai
Copy link
Copy Markdown
Collaborator

Non-blocking hardening note: validate key_id shape more strictly before using it downstream. Created ids are safe random dk_... values, but sign/get_public currently only reject empty key ids; the macOS provider later uses the caller-provided key_id in Keychain tags and binding metadata paths. Requiring exactly dk_ + unpadded base64url(32 bytes) would make this namespace auditable and remove path/tag weirdness.

@euroelessar euroelessar force-pushed the ruslan/device-key-crate branch from 4189212 to 41e132c Compare April 20, 2026 21:35
@euroelessar euroelessar marked this pull request as draft April 20, 2026 21:39
@euroelessar euroelessar marked this pull request as ready for review April 20, 2026 21:49
@euroelessar euroelessar marked this pull request as draft April 21, 2026 07:44
@euroelessar euroelessar force-pushed the ruslan/device-key-crate branch from 41e132c to e6e34ae Compare April 21, 2026 08:00
@euroelessar euroelessar force-pushed the ruslan/device-key-v2-protocol branch from 3f76329 to bd1ef3b Compare April 21, 2026 08:00
@euroelessar euroelessar marked this pull request as ready for review April 21, 2026 08:01
@euroelessar euroelessar force-pushed the ruslan/device-key-crate branch from e6e34ae to ed32f55 Compare April 21, 2026 08:39
Base automatically changed from ruslan/device-key-v2-protocol to main April 21, 2026 17:08
## Why

Device-key storage and signing are local security-sensitive operations with platform-specific behavior. Keeping the core API in codex-device-key keeps app-server focused on routing and business logic instead of owning key-management details.

The crate also keeps the signing surface intentionally narrow: callers can create a bound key, fetch its public key, or sign one of the structured payloads accepted by the crate. It does not expose a generic arbitrary-byte signing API.

Key IDs cross into platform-specific labels, tags, and metadata paths, so the crate constrains externally supplied IDs to the same auditable namespace it creates: dk_ plus unpadded base64url for 32 bytes. Remote-control target paths are tied to each signed payload shape so connection proofs cannot be reused for enrollment endpoints, or vice versa.

## What changed

- Added the codex-device-key workspace crate.
- Added account/client-bound key creation with stable dk_ key IDs.
- Added strict key_id validation before public-key lookup or signing reaches a provider.
- Added public-key lookup and structured signing APIs.
- Split remote-control client endpoint allowlists by connection vs enrollment payload shape.
- Added validation for key bindings, accepted payload fields, token expiration, and payload/key binding mismatches.
- Added flow-oriented docs on the validation helpers that gate provider signing.
- Added protection policy and protection-class types without wiring a platform provider yet.
- Added an unsupported default provider so platforms without an implementation fail explicitly instead of silently falling back to software-backed keys.
- Updated Cargo and Bazel lock metadata for the new crate and non-platform-specific dependencies.

## Validation

- just fmt
- cargo test -p codex-device-key
- just fix -p codex-device-key
- git diff --check
@euroelessar euroelessar force-pushed the ruslan/device-key-crate branch from ed32f55 to 3661fcf Compare April 21, 2026 17:16
@euroelessar euroelessar enabled auto-merge (squash) April 21, 2026 17:38
@euroelessar euroelessar merged commit 5bab04d into main Apr 21, 2026
38 of 39 checks passed
@euroelessar euroelessar deleted the ruslan/device-key-crate branch April 21, 2026 17:57
@github-actions github-actions Bot locked and limited conversation to collaborators Apr 21, 2026
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants