Repository navigation
Live credentials exposed on process argv, in plaintext logs/stdout, and in unredacted JSON output #1379
Copy link
Copy link
Open
Labels
bugSomething isn't workingSomething isn't working
Description
Workspace keys (rk_live_), agent tokens (at_live_), node tokens (nt_live_), and the cloud access token leak through four surfaces. This blocks fleet-wide credential rotation — rotated keys would re-leak immediately. Closes when the platform fix (credentials via env/file + redaction at the serialization boundary + explicit file modes) lands.
1. Secrets on child argv (visible in ps to any local user)
- The broker builds the agent-relay MCP config with
at_live_embedded (crates/broker/src/snippets.rs:326-334) and splicesrk_live_in for Claude (inject_api_key_into_mcp_json,snippets.rs:407), then pushes the whole JSON as one argv element:--mcp-config <json>(snippets.rs:837-850). - Codex gets one
--config key="value"argv pair per secret (snippets.rs:867-955). - Exposure is doubled: the broker re-execs itself (
crates/broker/src/worker.rs:310), so the JSON appears on the pty-worker argv and again on the real harness argv. agent-relay-brokeralso takes--api-key/--agent-tokenas CLI flags (crates/broker/src/cli/mod.rs:187) andcli_mcp_args.rs:30prints the computed config including secrets to stdout.- File-based writers already exist as the fix seam:
ensure_agent_relay_mcp_config()(snippets.rs:69, currently referenced only by its own tests),ensure_opencode_config_with_result(),ensure_cursor_mcp_config(). Note.claude/rules/mcp-injection.mdcurrently mandates inline embedding and must change with the fix;.cursor/mcp.jsonis not gitignored despite carrying live keys.
2. node up / node status print keys in plaintext
packages/cli/src/cli/lib/broker-lifecycle.ts:1521—Workspace Key: ${relay.workspaceKey}unconditionally on everynode up(pinned by seven test assertions incore.test.ts).node statusrepeats it (broker-lifecycle.ts:1795-1796) and prints an observer URL with the key as a query param.--workspace-keyis passed on the broker argv redundantly (packages/harness-driver/src/spawn-config.ts:125— the same key is already in the env block), and that argv is folded into every startup error string (broker-process.ts:148).--verboseprints the handshake message containing the key and the full spawn command line (packages/harness-driver/src/client.ts:466,:373).- Neither log sink redacts anything:
packages/utils/src/logger.ts(0644 append, bareJSON.stringify) and the Rust tracing appenders (crates/broker/src/runtime/util.rs:144-182, 0644).
3. Unredacted JSON output
agent-relay cloud session --jsonemits the raw cloud access token (packages/cli/src/cli/commands/cloud.ts:540). Sibling commands redact by explicit design (cloud enroll --jsonatcloud.ts:729-735— "Never print the node token, even in JSON mode";cloud worker status --jsonatcloud-worker.ts:361), so this is an oversight, not policy.workspace active --jsonprintskey+relaycastApiKey(workspace.ts:44-47);workspace createprints the key (workspace.ts:68);cloud-room.ts:561prints a bare invite token;cloud.ts:720dumps a record includingnodeTokento stderr on a failure path.- Redaction helpers exist but are effectively dead:
crates/broker/src/redact.rs:13has zero call sites; the only helper that knows the live-key prefixes is private tonode_control.rs(:418, one call site);packages/cli/src/cli/lib/redact.ts:24fires once and is value-blind (anrk_live_under a key namedurl/env/argspasses through). No masking utility (last4-style) exists anywhere.
4. World-readable credential files at rest
nt_live_node tokens:crates/broker/src/node_control.rs:1242—fs::writewith no mode → 0644 in a 0755 dir (~/Library/Application Support/agent-relay/node-tokens/); 91 such files observed on one dev machine.opencode.jsonand.cursor/mcp.json(both carryingrk_live_+at_live_): 0644 viawrite_pretty_json(snippets.rs:1486).connection.jsonis 0600 only by accident oftempfile's default (crates/broker/src/runtime/init.rs:153-170) — no test asserts the mode.~/.agentworkforce/relayhistory/auth.json(access + refresh tokens) has a 0644 window before chmod (packages/cli/src/cli/commands/reflex.ts:117-119).- The
.agentworkforce/relayparent dir is created without a mode at four of five call sites, so themode: 0o700atproject-workspace-key.ts:67is a no-op in practice — observeddrwxr-xr-xon disk. - The TypeScript cloud store does this right (0700 dir + 0600 file + atomic rename,
packages/cloud/src/auth.ts:139-160); the Rust side has zero explicit mode arguments anywhere.
🤖 Generated with Claude Code
Metadata
Metadata
Assignees
Labels
bugSomething isn't workingSomething isn't working
Activity
willwashburn commentedon Jul 29, 2026
PR A is #1380 (CLI output/error/argv surfaces; companion AgentWorkforce/relayfile#380 must merge and release first). Follow-ups surfaced by its adversarial review, for PR B/C or later in this train:
printJson(packages/cli/src/cli/lib/sdk-command.ts:64) is still not a redaction boundary — 40+ call sites, three hand-masked. A value-based pass (with an explicit opt-out for deliberate secret sinks likecloud room session --json) would make masking a property of the display path.create_workspacetool result returns the raw workspace key (packages/cli/src/cli/agent-relay-mcp.ts:437-441), andplugins/codex-relay-skill/SKILL.md+plugins/gemini-relay-extension/GEMINI.mdinstruct agents to print raw keys inside observer URLs. The skills repo has the same instruction in relay-team/relay-pipeline/relay-fanout.packages/climaskSecret,packages/cloudredactCredentialValues,packages/harness-driverprivatemaskWorkspaceKey) with diverging prefix lists;@agent-relay/utilsis the natural shared home.node statusoffers no way to obtain a working observer URL post-masking (template only);workspace key --reveal-secretscovers key retrieval, but a--reveal-secretsonstatus(or an observer-token-based URL, which is the correct auth model anyway) would restore the click-to-observe flow.🤖 Generated with Claude Code
khaliqgant commentedon Sep 6, 2026
Fresh live confirmation during Fleet cleanup safety inspection (2026-09-06 UTC): ordinary process-table inspection inside multiple Daytona Fleet nodes exposed Relay workspace/API and agent credentials in Claude/Codex
--mcp-configargv. No credential values are included here. This is not theoretical or confined to logs; any same-sandbox process able to read the process table can observe them. The planned PR C argv-to-file work remains a release blocker, and fleet qualification should add a redactedps//procabsence assertion after that fix.fix(broker): keep Relay credentials out of project working trees (#1997)