diff --git a/CHANGELOG.md b/CHANGELOG.md index 3abc8995..972e70da 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,10 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/), ## [Unreleased] +### Security + +- **Orchestrator API is no longer published on a routable host interface (GHSA-4f7g-w95g-5q2c).** Both deploy composes published the orchestrator's `:8000` on `0.0.0.0`, so anyone who could reach the host hit the control plane directly — bypassing nginx and, in the default header-trust posture (`ROBOCO_AGENT_AUTH_REQUIRED` unset, cloud auth off), reading/writing runtime settings and spoofing `X-Agent-Role: ceo` to spawn/stop agents with no credential. The publish is now bound to `127.0.0.1`; nginx reaches the API over the internal Docker network, so normal operation and on-host debugging are unchanged, while off-host access must go through nginx + cloud auth. The header-trust design itself is unchanged (it stays the deliberate local-no-login panel path); this closes the unintended off-host reachability that gave it teeth. + ## [0.25.0] - 2026-07-16 ### Added diff --git a/docker-compose.registry.yml b/docker-compose.registry.yml index 27acb84d..3dee1c1e 100644 --- a/docker-compose.registry.yml +++ b/docker-compose.registry.yml @@ -291,7 +291,12 @@ services: - data - render ports: - - "8000:8000" + # Loopback-only: the orchestrator API is an unauthenticated control plane + # in header-trust mode. nginx reaches it over the internal network, so it + # never needs a routable host publish; remote access goes via nginx + cloud + # auth. A 0.0.0.0 publish exposed spawn/stop and settings-write with no + # credential to anyone who could reach the host (GHSA-4f7g-w95g-5q2c). + - "127.0.0.1:8000:8000" environment: # DB network isolation is LIVE in this file (postgres/redis on the # data-only network): suppress the legacy prod-creds gate-env diff --git a/docker-compose.yaml b/docker-compose.yaml index abcb18dd..ee034c80 100644 --- a/docker-compose.yaml +++ b/docker-compose.yaml @@ -415,7 +415,12 @@ services: - data - render ports: - - "8000:8000" + # Loopback-only: the orchestrator API is an unauthenticated control plane + # in header-trust mode. nginx reaches it over the internal network, so it + # never needs a routable host publish; remote access goes via nginx + cloud + # auth. A 0.0.0.0 publish exposed spawn/stop and settings-write with no + # credential to anyone who could reach the host (GHSA-4f7g-w95g-5q2c). + - "127.0.0.1:8000:8000" environment: # Database (use container name, not localhost) ROBOCO_DATABASE_HOST: roboco-postgres diff --git a/docker-compose.yml b/docker-compose.yml index abcb18dd..ee034c80 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -415,7 +415,12 @@ services: - data - render ports: - - "8000:8000" + # Loopback-only: the orchestrator API is an unauthenticated control plane + # in header-trust mode. nginx reaches it over the internal network, so it + # never needs a routable host publish; remote access goes via nginx + cloud + # auth. A 0.0.0.0 publish exposed spawn/stop and settings-write with no + # credential to anyone who could reach the host (GHSA-4f7g-w95g-5q2c). + - "127.0.0.1:8000:8000" environment: # Database (use container name, not localhost) ROBOCO_DATABASE_HOST: roboco-postgres