Skip to content

Harden daemon TCP transport: require loopback Host + reject cross-origin (CSRF/DNS-rebinding)#145

Merged
BunsDev merged 2 commits into
OpenCoven:mainfrom
maplesyzzurp:fix/daemon-tcp-origin-guard
May 30, 2026
Merged

Harden daemon TCP transport: require loopback Host + reject cross-origin (CSRF/DNS-rebinding)#145
BunsDev merged 2 commits into
OpenCoven:mainfrom
maplesyzzurp:fix/daemon-tcp-origin-guard

Conversation

@maplesyzzurp
Copy link
Copy Markdown
Contributor

Summary

coven daemon serve --tcp <addr> serves the full unauthenticated /api/v1 over loopback HTTP. bind_tcp_listener already refuses non-loopback binds, but the request handler did not check Host or Origin — so a web page the user visits could drive the daemon via a cross-origin "simple" request (CSRF), and DNS-rebinding (a foreign Host rebound to 127.0.0.1) could reach it. This adds a loopback guard to the TCP transport only; the Unix socket path is filesystem-gated and unchanged.

Why

docs/AUTH.md states the API must not be exposed "on localhost TCP ... or a browser page" without "an explicit additional auth and pairing design," and notes there is "no CSRF/origin policy." The --tcp feature (documented for "cockpit via Vite proxy") ships exactly that browser-reachable surface. This guard is the minimal origin/pairing design for it.

Changes (crates/coven-cli/src/daemon.rs)

  • read_http_headers now also captures Host and Origin.
  • handle_http_stream gains an enforce_loopback_guard flag. On the TCP path it:
    • rejects any request whose Host is not a loopback authority (127.x / localhost / ::1) → 403 (defeats DNS-rebinding);
    • rejects any request carrying a non-loopback Origin403 (defeats browser CSRF; a CLI/Vite-proxy client sends no cross-origin Origin).
  • The Unix socket call site passes false (unaffected). Adds write_forbidden (403) plus small host_is_loopback / origin_is_loopback / strip_port / is_loopback_host helpers.

No new dependencies, no unsafe, Unix-gated.

Verification

cargo fmt, cargo clippy --workspace --all-targets -- -D warnings (clean), and cargo test --workspace --locked all green on Linux: 697 pass, 0 fail. Four new tests cover the cross-origin block, the foreign-Host block, the loopback-origin allow, and the Unix path ignoring Origin.

Tracked by #143.


Note: PRs are frozen until July per CONTRIBUTING — opening this for visibility since it is a small, isolated security fix for the documented TCP/browser gap. Completely fine to close or hold until the window reopens; the branch will keep.

…P transport (CSRF/DNS-rebinding)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
is_loopback_host accepted any authority starting with "127.", so a
hostname like 127.evil.com passed the Host/Origin guard and defeated its
DNS-rebinding defense. Parse the host as an IpAddr and ask is_loopback();
keep the localhost literal.
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.

2 participants