Skip to content

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

Merged
warren618 merged 1 commit into
HKUDS:mainfrom
Robin1987China:safe-bind-default
Jul 1, 2026
Merged

fix(api): default bind to 127.0.0.1 and warn on non-loopback without API_AUTH_KEY#338
warren618 merged 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

@warren618 warren618 merged commit 09d5f16 into HKUDS:main Jul 1, 2026
1 check passed
@warren618

Copy link
Copy Markdown
Collaborator

Thanks for the clean secure-by-default fix. Merged in #338.

I verified the focused bind tests locally and also checked the combined merge with #349/#351. This closes the API default-bind hardening from #333.

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.

3 participants