Skip to content

feat(account): read Codex's account domain from auth.json - #397

Closed
blitzcrieg1 wants to merge 1 commit into
masterfrom
feature/codex-auth-domain
Closed

blitzcrieg1 wants to merge 1 commit into
masterfrom
feature/codex-auth-domain

Conversation

@blitzcrieg1

Copy link
Copy Markdown
Owner

Codex sits in "Accounts with no domain", because its session file holds only IDs, so the Identity page cannot say whether its account is personal. The maintainer decided on 2026-11-07 to read its sign-in file to answer that.

Review this one carefully: it makes a security sensor read a file holding live credentials.

What it reads

From auth.json under CODEX_HOME or ~/.codex:

  • Only the email claim of tokens.id_token, and only when auth_mode is chatgpt.
  • Only the domain is kept, with source codex_auth. The full address follows the existing AGENTMETRY_LOG_ACCOUNT_EMAIL=1 opt-in.
  • Nothing else in the file is copied, stored, logged or sent. An error carries no content from it.

The signature is not checked, so this is what the file says, not proof of who made a call. An API-key sign-in reports no domain. AGENTMETRY_CODEX_AUTH_DOMAIN=0 turns it off.

The cost

  • The hook loads a file holding live tokens on every Codex tool call, briefly and without keeping them.
  • Endpoint security tools may flag a process reading that file. This has not been tested against any EDR.
  • This reverses "auth.json is never read" from feat(dashboard): add an Identity section, with Codex and Antigravity accounts #395. The code, schema doc and changelog are updated. A search of the README, docs and site found no other page making that promise.

It is on by default for now. Reconsider making it opt-in before a public release or a pilot.

Also fixed

The Identity view lost a domain row's IDs when another agent reported that domain first, so Codex's IDs now survive joining a row.

Checks

Run from this branch on Windows:

  • pytest -q: 2287 passed, 7 skipped
  • ruff check agentmetry tests: clean
  • agentmetry benchmark: 0 missed, 0 false positives
  • Dashboard: 201 tests pass, type check clean
  • Fingerprint: 15846a0915769d4a, with no frozen file touched
  • Tests with synthetic tokens: the access token, refresh token, API key, name, subject and full email reach neither the hook payload nor the stored event
  • On the maintainer's real file, showing keys only: domain and IDs found in about 3 ms, classified as personal, with no email key and no token in the block

Not proven

  • No real Codex session has produced the domain through a live hook. That test comes after merge.
  • Behaviour under any EDR, including whether the read raises an alert.
  • Other operating systems and other Codex versions, where this undocumented layout may differ.

🤖 Generated with Claude Code

Codex sat in "Accounts with no domain", because its session file holds only IDs, so
the Identity page could not say whether its account was personal. In the case this
feature exists for, that is the question. The maintainer decided to read the sign-in
file to answer it.

Only the `email` claim of `id_token` is read and only the domain is kept, with source
`codex_auth`. Nothing else in the file is copied, stored, logged or sent, and an error
carries no content from it. The signature is not checked, so this is what the file
says, not proof of who made a call. An API-key sign-in reports no domain, and
AGENTMETRY_CODEX_AUTH_DOMAIN=0 turns it off.

This reverses "auth.json is never read", which the code and docs from #395 said, so
those now say what happens. The cost is real: the hook loads a file holding live
tokens on every Codex tool call, and endpoint security tools may flag that read. It
should be reconsidered as opt-in before a public release or a pilot.

The Identity view also lost a domain row's IDs when another agent reported that
domain first, so Codex's IDs now survive joining a row.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@blitzcrieg1

Copy link
Copy Markdown
Owner Author

Replaced by #398. The secret scan flagged a test fixture here: a synthetic token part that decodes to "not json", not a real secret. #398 carries the same change with that value built at runtime.

@blitzcrieg1 blitzcrieg1 closed this Nov 7, 2026
@github-actions github-actions Bot locked and limited conversation to collaborators Nov 7, 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.

1 participant