Summary
docs/AUTH.md → "Current hardening gap" lists the fail-closed checks the Rust daemon should perform before creating, binding, or removing daemon state. Two are still unimplemented in crates/coven-cli/src/daemon.rs:
- A
COVEN_HOME that resolves through a symlink is not rejected. ensure_private_coven_home calls create_dir_all + set_permissions(0700) and will follow a symlinked home, chmod-ing and populating the link target.
- An existing socket path that is a symlink or non-socket file is not rejected.
bind_api_socket does if socket_path.exists() { remove_file(socket_path) } — it blindly removes whatever sits at coven.sock before binding, with no symlink/socket-type guard.
The permission hardening from the same list (0700 home, 0600 socket/status) and the body-cap / loopback-TCP work already landed — this is only the residual symlink/type guards. The COVEN_HOME ownership (euid) check is intentionally out of scope here since it needs a libc::geteuid dependency.
Why it matters
With a 0700 home these are defense-in-depth rather than a same-user break, but they are exactly the conditions AUTH.md says the daemon should "fail closed" on before broad distribution: a planted symlink at the home or socket path could redirect daemon state (socket, status, SQLite ledger) outside the trusted directory, and the unconditional remove_file will delete an unrelated regular file that happens to occupy the socket path.
Proposed fix (implemented, std-only)
ensure_private_coven_home: symlink_metadata the home; bail if it is a symlink.
bind_api_socket: symlink_metadata the socket path; bail on a symlink or any non-socket file; only remove_file a genuine stale socket; treat NotFound as fresh.
No new dependencies, no unsafe, Unix-gated. Three new #[cfg(unix)] tests cover a symlinked home, a symlinked socket path (and assert the link target is not deleted), and a non-socket file at the socket path.
Verification (Linux): cargo fmt --check, cargo clippy --workspace --all-targets -- -D warnings, and cargo test --workspace --locked all green (696 unit + 4 smoke; the 3 new tests pass, no regressions).
Branch
A branch is ready to PR when the contribution window reopens (July 2026, per CONTRIBUTING):
https://github.com/maplesyzzurp/coven/tree/fix/daemon-socket-hardening (commit 8c6dabb)
Filing as an issue rather than a PR per the current freeze notice.
Refs: docs/AUTH.md "Current hardening gap"; crates/coven-cli/src/daemon.rs (ensure_private_coven_home, bind_api_socket).
Summary
docs/AUTH.md→ "Current hardening gap" lists the fail-closed checks the Rust daemon should perform before creating, binding, or removing daemon state. Two are still unimplemented incrates/coven-cli/src/daemon.rs:COVEN_HOMEthat resolves through a symlink is not rejected.ensure_private_coven_homecallscreate_dir_all+set_permissions(0700)and will follow a symlinked home, chmod-ing and populating the link target.bind_api_socketdoesif socket_path.exists() { remove_file(socket_path) }— it blindly removes whatever sits atcoven.sockbefore binding, with no symlink/socket-type guard.The permission hardening from the same list (
0700home,0600socket/status) and the body-cap / loopback-TCP work already landed — this is only the residual symlink/type guards. TheCOVEN_HOMEownership (euid) check is intentionally out of scope here since it needs alibc::geteuiddependency.Why it matters
With a
0700home these are defense-in-depth rather than a same-user break, but they are exactly the conditions AUTH.md says the daemon should "fail closed" on before broad distribution: a planted symlink at the home or socket path could redirect daemon state (socket, status, SQLite ledger) outside the trusted directory, and the unconditionalremove_filewill delete an unrelated regular file that happens to occupy the socket path.Proposed fix (implemented, std-only)
ensure_private_coven_home:symlink_metadatathe home; bail if it is a symlink.bind_api_socket:symlink_metadatathe socket path; bail on a symlink or any non-socket file; onlyremove_filea genuine stale socket; treatNotFoundas fresh.No new dependencies, no
unsafe, Unix-gated. Three new#[cfg(unix)]tests cover a symlinked home, a symlinked socket path (and assert the link target is not deleted), and a non-socket file at the socket path.Verification (Linux):
cargo fmt --check,cargo clippy --workspace --all-targets -- -D warnings, andcargo test --workspace --lockedall green (696 unit + 4 smoke; the 3 new tests pass, no regressions).Branch
A branch is ready to PR when the contribution window reopens (July 2026, per CONTRIBUTING):
https://github.com/maplesyzzurp/coven/tree/fix/daemon-socket-hardening (commit 8c6dabb)
Filing as an issue rather than a PR per the current freeze notice.
Refs:
docs/AUTH.md"Current hardening gap";crates/coven-cli/src/daemon.rs(ensure_private_coven_home,bind_api_socket).