auth: CODE_INDEX_DAEMON_NO_AUTH is a presence-check and is inherited by the spawned daemon #12

Closed
opened 2026-07-07 13:19:31 +02:00 by buildagent · 1 comment
Member

Severity: High · Category: Security (auth bypass)

The daemon disables the capability-token auth whenever CODE_INDEX_DAEMON_NO_AUTH is present in the environment — var_os(...).is_some() (crates/daemon/src/main.rs:143), so any value counts, even 0 or empty. The MCP server spawns the daemon with Command::new and no .env_clear() (crates/mcp-server/src/main.rs:390-397), so the child inherits the full parent environment.

Consequence: if the MCP process (or the shell / CI / agent harness that launched it) has CODE_INDEX_DAEMON_NO_AUTH set for any reason, a production daemon silently starts with auth OFF and no token in daemon.toml — reopening the "any local process can read the whole index over loopback" hole the token was designed to close. The only signal is a warn log.

Fix

  • On the production spawn path, cmd.env_remove("CODE_INDEX_DAEMON_NO_AUTH").
  • And/or gate the escape hatch behind #[cfg(test)] / a debug-build check rather than a runtime env var.
  • At minimum, treat only =="1" as enabling (not mere presence).
  • Windows: daemon.toml is 0600 on Unix only (lifecycle.rs:251-298); on Windows the token file gets default inherited ACLs — a separate low-severity hardening item, tracked in the polish backlog.

Filed from a deep multi-agent code review of the workspace (v0.5.7). Severity/category per the review; file:line refs were accurate at review time — verify against current master.

**Severity:** High · **Category:** Security (auth bypass) The daemon disables the capability-token auth whenever `CODE_INDEX_DAEMON_NO_AUTH` is *present* in the environment — `var_os(...).is_some()` (`crates/daemon/src/main.rs:143`), so **any** value counts, even `0` or empty. The MCP server spawns the daemon with `Command::new` and **no `.env_clear()`** (`crates/mcp-server/src/main.rs:390-397`), so the child inherits the full parent environment. Consequence: if the MCP process (or the shell / CI / agent harness that launched it) has `CODE_INDEX_DAEMON_NO_AUTH` set for any reason, a **production** daemon silently starts with auth OFF and no token in `daemon.toml` — reopening the "any local process can read the whole index over loopback" hole the token was designed to close. The only signal is a warn log. ### Fix - On the production spawn path, `cmd.env_remove("CODE_INDEX_DAEMON_NO_AUTH")`. - And/or gate the escape hatch behind `#[cfg(test)]` / a debug-build check rather than a runtime env var. - At minimum, treat only `=="1"` as enabling (not mere presence). ### Related - Windows: `daemon.toml` is `0600` on Unix only (`lifecycle.rs:251-298`); on Windows the token file gets default inherited ACLs — a separate low-severity hardening item, tracked in the polish backlog. --- _Filed from a deep multi-agent code review of the workspace (v0.5.7). Severity/category per the review; file:line refs were accurate at review time — verify against current `master`._
Author
Member

Fixed in 78c5737 (branch fix/ultradeep-review-findings).

Reassessed on current master — both claims held (var_os(...).is_some() presence-check in the production path at daemon/src/main.rs:141; no env_clear/env_remove on the mcp-server spawn path). Fix enforces the guarantee two ways:

  • daemon/main.rs: the escape hatch is honored only in debug builds — cfg!(debug_assertions) && var_os(...).is_some() — so a release-profile production daemon always mints a token regardless of the environment.
  • mcp-server/main.rs: cmd.env_remove("CODE_INDEX_DAEMON_NO_AUTH") on the spawn path, so a spawned daemon never inherits a stray parent value.

Test: mcp_smoke::spawned_daemon_does_not_inherit_no_auth_env sets the var in the MCP server's own environment, spawns a daemon through the real --daemon-bin path, and asserts the daemon published a non-empty token in daemon.toml. Because the spawned test daemon is a debug build (its compile-gate would otherwise honor an inherited var), this genuinely exercises the env-strip, not just the gate.

Fixed in `78c5737` (branch `fix/ultradeep-review-findings`). Reassessed on current master — both claims held (`var_os(...).is_some()` presence-check in the production path at `daemon/src/main.rs:141`; no `env_clear`/`env_remove` on the mcp-server spawn path). Fix enforces the guarantee two ways: - **daemon/main.rs**: the escape hatch is honored only in debug builds — `cfg!(debug_assertions) && var_os(...).is_some()` — so a release-profile production daemon always mints a token regardless of the environment. - **mcp-server/main.rs**: `cmd.env_remove("CODE_INDEX_DAEMON_NO_AUTH")` on the spawn path, so a spawned daemon never inherits a stray parent value. **Test:** `mcp_smoke::spawned_daemon_does_not_inherit_no_auth_env` sets the var in the MCP server's own environment, spawns a daemon through the real `--daemon-bin` path, and asserts the daemon published a non-empty token in `daemon.toml`. Because the spawned test daemon is a **debug** build (its compile-gate would otherwise honor an inherited var), this genuinely exercises the env-strip, not just the gate.
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
h-dv/code-index#12
No description provided.