Skip to content

fix(api): default bind to 127.0.0.1 and warn on non-loopback without API_AUTH_KEY#338

Open
Robin1987China wants to merge 1 commit into
HKUDS:mainfrom
Robin1987China:safe-bind-default
Open

fix(api): default bind to 127.0.0.1 and warn on non-loopback without API_AUTH_KEY#338
Robin1987China wants to merge 1 commit into
HKUDS:mainfrom
Robin1987China:safe-bind-default

Conversation

@Robin1987China

@Robin1987China Robin1987China commented Jun 30, 2026

Copy link
Copy Markdown
Contributor

Summary

Default the --host bind address from 0.0.0.0 to 127.0.0.1, and log a startup warning when binding to a non-loopback address without API_AUTH_KEY configured.

Why

The Docker compose already binds to 127.0.0.1:8899:8899, so loopback-only is the intended secure-by-default posture — but the bare CLI default of 0.0.0.0 did not match. The existing loopback peer-IP and DNS-rebinding checks still reject remote requests, but defense-in-depth argues the bind itself should default to loopback. Binding to all interfaces should be a conscious opt-in, with a warning when done without API_AUTH_KEY.

Changes

  • agent/api_server.py: --host default "0.0.0.0""127.0.0.1"; added _is_loopback_bind_host() (ipaddress.is_loopback + "localhost" fallback); startup warning when binding non-loopback without API_AUTH_KEY.
  • agent/cli/main.py: Typer serve command --host default also set to 127.0.0.1, so every serve entry point agrees. The console script and python -m cli already bound loopback (they route through the argparse path); this covers the python -m cli.main Typer path too.
  • agent/tests/test_serve_bind.py: new test coverage.

Docker is unaffected: the Dockerfile passes --host 0.0.0.0 explicitly and compose binds loopback on the host side — neither relies on the default.

I left out one reviewer-style nit — only computing the warning state lazily — because the check is a single comparison at startup, not a hot path.

Test Plan

  • ruff check (changed files) — clean (the 5 F821 in api_server.py pre-exist on origin/main; none introduced)
  • pytest tests/test_serve_bind.py — 14 passed (_is_loopback_bind_host truth table incl. IPv6/hostname/edge, loopback default, warning only on non-loopback without a key)
  • pytest (full, excl e2e) — passes, zero failures

Checklist

  • No changes to protected areas without prior discussion
  • No hardcoded values
  • Code follows CONTRIBUTING.md guidelines
  • Documentation updated (if user-facing change) — n/a, default/behavior change

Refs #333

…API_AUTH_KEY

Default the --host bind address to 127.0.0.1 instead of 0.0.0.0 to
match the secure-by-default posture already used in docker-compose.
Add a startup warning when binding to a non-loopback address without
API_AUTH_KEY configured — the existing loopback peer-IP and
DNS-rebinding checks still reject remote requests, but the warning
surfaces the misconfiguration at startup.

Also default the Typer `serve` command's --host to 127.0.0.1 so every
serve entry point agrees (the console script and `python -m cli` already
bound loopback; this covers the `python -m cli.main` path too).

Tests: _is_loopback_bind_host truth table (IPv4/IPv6/hostname/edge),
loopback default, and the warning firing only on a non-loopback bind
without a configured key.

Refs HKUDS#333

Signed-off-by: Robin1987China <41602358+Robin1987China@users.noreply.github.com>
@shadowinlife

Copy link
Copy Markdown
Contributor

LGTM

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

2 participants