Skip to content

feat(security): SEC-05 - Host/IP allowlist + mandatory ADMIN_TOKEN for non-localhost#62

Merged
Killea merged 1 commit intoKillea:mainfrom
bertheto:feat/SEC-05-host-security
Mar 19, 2026
Merged

feat(security): SEC-05 - Host/IP allowlist + mandatory ADMIN_TOKEN for non-localhost#62
Killea merged 1 commit intoKillea:mainfrom
bertheto:feat/SEC-05-host-security

Conversation

@bertheto
Copy link
Contributor

Summary

  • Fail-fast: startHttpServer() aborts with process.exit(1) when HOST != 127.0.0.1 (or SHOW_AD=true) and AGENTCHATBUS_ADMIN_TOKEN is not set — prevents accidental unsecured public deployment
  • IP allowlist: New env var AGENTCHATBUS_ALLOWED_HOSTS (comma-separated IPs/IPv4 CIDRs) blocks non-loopback requests with 403; loopback always bypasses
  • SHOW_AD write guard: When SHOW_AD=true, all write/delete endpoints require X-Admin-Token header; agent-auth endpoints (register, heartbeat, resume, unregister, POST /api/threads, POST /api/threads/:id/messages) and GET endpoints remain open
  • Token suppression: /api/agents/register strips token from JSON response when SHOW_AD=true to prevent credential leakage in public demo mode

Motivation

SHOW_AD=true currently only disables UI buttons (Close/Delete) client-side. Anyone can still call DELETE /api/threads/{id} directly via REST. This PR adds server-side enforcement to complement the existing UI-level guard.

All changes are backward-compatible: localhost users (HOST=127.0.0.1, SHOW_AD=false) see zero change in behavior.

New env vars

Env var Default Description
AGENTCHATBUS_ALLOWED_HOSTS (unset) Comma-separated list of allowed IPs/IPv4 CIDRs. Disabled when empty.

Test plan

  • npm test passes (29 new tests in test_sec05_host_security.test.ts, 523/523 total)
  • Fail-fast: start server with HOST=0.0.0.0 and no AGENTCHATBUS_ADMIN_TOKEN — should refuse to start
  • SHOW_AD guard: with SHOW_AD=true and AGENTCHATBUS_ADMIN_TOKEN=secret, DELETE /api/threads/{id} returns 401 without header, 200 with X-Admin-Token: secret
  • Token suppression: POST /api/agents/register returns no token field when SHOW_AD=true
  • Localhost unaffected: all operations work normally from 127.0.0.1 regardless of SHOW_AD

…non-localhost

- Fail-fast: startHttpServer() aborts with process.exit(1) when HOST != 127.0.0.1
  or SHOW_AD=true and AGENTCHATBUS_ADMIN_TOKEN is not set
- IP allowlist middleware: AGENTCHATBUS_ALLOWED_HOSTS (comma-separated IPs/IPv4 CIDRs)
  blocks non-loopback requests with 403; loopback always bypasses
- SHOW_AD write guard: when SHOW_AD=true, all write/delete endpoints require
  X-Admin-Token header; agent-auth endpoints and GETs remain open
- Token suppression: /api/agents/register strips token from response when SHOW_AD=true
  to prevent leakage in public demo mode
- New helpers in env.ts: isNonLocalhostDeployment, isIpAllowed, parseAllowedHosts
- 29 new tests in test_sec05_host_security.test.ts; 523/523 total tests pass
- All changes backward-compatible: localhost deployments unaffected

Backward-compatible: localhost users see zero change in behavior.
@Killea Killea merged commit e4b33c5 into Killea:main Mar 19, 2026
1 check passed
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