Skip to content

fix(cli): keep Claude MCP tokens out of config files#752

Closed
lilyshen0722 wants to merge 1 commit into
codex/public-claude-seatbeltfrom
codex/claude-mcp-env-only-token
Closed

fix(cli): keep Claude MCP tokens out of config files#752
lilyshen0722 wants to merge 1 commit into
codex/public-claude-seatbeltfrom
codex/claude-mcp-env-only-token

Conversation

@lilyshen0722

Copy link
Copy Markdown
Contributor

What

  • keep ${COMMONLY_*} placeholders literal in Claude's generated MCP JSON
  • pass only referenced runtime values through Claude's one-run child environment for native MCP expansion
  • assert the raw runtime token never enters the generated config or argv
  • extend the live macOS Seatbelt attack harness to inspect the actual materialized config and prove the declared MCP server receives a resolved token

Why

Phase III moved the MCP config outside the workspace and kernel-confined Claude, but the transient JSON still contained a raw cm_agent_* bearer token. Any trusted/co-confined child able to read that declared config directory could recover it. Claude Code supports native ${VAR} expansion in MCP config fields, so the token no longer needs to exist on disk.

Verification

  • npm test -- --runInBand --detectOpenHandles __tests__/adapters.claude.environment.test.mjs __tests__/seatbelt.test.mjs
    • 2 suites passed; 15 passed, 1 platform skip
  • full CLI suite
    • 16 suites passed; 178 passed, 10 skipped
  • live verify-public-claude-seatbelt.mjs attack run on macOS
    • all protected reads and the outside-workspace write were OS-denied
    • workspace write succeeded
    • generated MCP JSON retained ${COMMONLY_AGENT_TOKEN}
    • raw runtime token was absent from JSON and argv
    • declared MCP child confirmed the runtime token resolved without returning its value

Security boundary

The runtime token now exists only in Claude's one-run process environment and is necessarily delivered to the declared Commonly MCP child. Declared MCP servers remain trusted capabilities; this PR removes the token-at-rest/config-file exposure and does not claim to isolate mutually untrusted MCP servers from the parent environment.

Stacking

Draft, stacked on #751 (codex/public-claude-seatbelt). Merge #750, then #751, then retarget/rebase this PR so each layer receives its own CI run.

@lilyshen0722

Copy link
Copy Markdown
Contributor Author

Superseded by #754, which combines the already-approved phase ③ + ④ trees on current main after #751's base branch was deleted by the #750 squash merge.

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