Skip to content

security: host-agent still binds 0.0.0.0 on fresh install — #283 closure premature, secure default never applied #340

@yasinBursali

Description

@yasinBursali

Bug Report: host-agent still binds 0.0.0.0 on fresh install — closure of #283 was premature, secure default never applied

Severity: High
Category: Security / Network Exposure / Insecure Default
Platform: Linux (and Linux-equivalent paths on macOS / Windows-WSL2 via Docker Desktop)
Confidence: Confirmed

Followup of: #283 (Host agent binds to 0.0.0.0 — Docker control API exposed to LAN), CLOSED.
The original bug is still present at runtime on a fresh install — the bind line in bin/dream-host-agent.py is unchanged, the daemon emits a runtime warning admitting it, and the installer never sets the safer default that would silence the warning.

Description

#283 was filed for the fact that bin/dream-host-agent.py binds the agent HTTP server to 0.0.0.0, exposing the Docker control API and hook execution endpoints to the entire LAN. The issue was closed — presumably accepting the wide bind as required to keep the host-agent reachable from inside Docker containers (#283's body and Light-Heart-Labs/DreamServer#752 both note this trade-off). The compromise that was apparently agreed: keep the wide bind, emit a startup WARNING, and let users opt into DREAM_AGENT_BIND=127.0.0.1 via .env.

The closure is premature because the safer default isn't applied by the installer and the host-agent itself emits a warning admitting it on every boot. Users who don't read journal logs (which is most users) get LAN-exposed without ever knowing.

Affected File(s)

  • dream-server/bin/dream-host-agent.py — line that binds ("0.0.0.0", port) (still hardcoded; the env var DREAM_AGENT_BIND is checked by the daemon but only if set, and the installer doesn't set it).
  • dream-server/.env.example — should document DREAM_AGENT_BIND and set it to 127.0.0.1 by default.
  • dream-server/installers/phases/06-directories.sh (or wherever .env is generated from .env.example during install) — should explicitly write DREAM_AGENT_BIND=127.0.0.1 unless the install profile genuinely requires container-side reachability.

Root Cause

The 0.0.0.0 bind was deliberately chosen to fix Light-Heart-Labs/DreamServer#752 (host agent unreachable from Docker containers when bound to 127.0.0.1). The trade-off agreed at close time was: keep the wide bind, but emit a warning and offer an opt-in via DREAM_AGENT_BIND=127.0.0.1 in .env. The opt-in part never landed in the installer flow — fresh installs leave DREAM_AGENT_BIND unset, the daemon falls through to the default 0.0.0.0, and the warning fires forever.

Evidence

Fresh install of the integration branch (open PR stack Light-Heart-Labs#893–909 merged onto Light-Heart-Labs/DreamServer@c0600ca) on WSL2 / Ubuntu 24.04. bash install.sh --all --non-interactive --no-comfyui reaches phase 13 cleanly. Then:

$ systemctl --user restart dream-host-agent.service       # see #334 — installer doesn't restart it
$ journalctl --user -u dream-host-agent.service -n 5 --no-pager
Apr 12 00:11:41 ... python3[353285]: Dream Host Agent v1.0.0 listening on 0.0.0.0:7710
Apr 12 00:11:41 ... python3[353285]: WARNING: Agent is listening on all interfaces. Set DREAM_AGENT_BIND=127.0.0.1 in .env to restrict.
Apr 12 00:11:41 ... python3[353285]: Install dir: /home/rosenrot/dream-server | GPU: nvidia | Tier: 1

The host-agent itself logs the warning on every startup. So the daemon knows the default is unsafe.

$ ss -tlnp 2>&1 | grep 7710
LISTEN 0  5    0.0.0.0:7710    0.0.0.0:*    users:(("python3",pid=353285,fd=3))

Listening on all interfaces, port 7710. Confirmed via ss.

$ grep DREAM_AGENT_BIND ~/dream-server/.env
# (no match — installer didn't set it)

$ grep DREAM_AGENT_BIND ~/dream-server/.env.example
# (no match — also not documented in the example file)

The installer didn't set DREAM_AGENT_BIND in .env. .env.example doesn't even document the variable, so a user trying to find the right key to set wouldn't see it in the canonical reference. The only way to discover the safer default is to read the journal warning and grep the host-agent source.

Platform Analysis

  • Linux: Affected — port 7710 exposed to LAN. Most desktop Linux distros have no restrictive firewall by default. This is the Tier 1 default install path; verified end-to-end on WSL2 today.
  • macOS: Affected — macOS firewall is off by default per Host agent binds to 0.0.0.0 — Docker control API exposed to LAN #283's original analysis. Same code path runs.
  • Windows/WSL2: Partially affected — WSL2 NAT usually shields ports from the wider LAN, but the Docker Desktop config can expose them. Verified the bind is 0.0.0.0:7710 inside the WSL2 instance; whether the Windows host blocks LAN-side reach is environment-specific.

Reproduction

  1. bash install.sh --all --non-interactive on a fresh system. Reach phase 13.
  2. systemctl --user restart dream-host-agent.service (per bug: installer doesn't restart dream-host-agent.service after rewriting bin/dream-host-agent.py — leaves zombie reading deleted inode #334, the installer doesn't restart it after rewriting the binary).
  3. journalctl --user -u dream-host-agent.service -n 5 --no-pager — observe the WARNING about all-interfaces bind.
  4. ss -tlnp | grep 7710 — observe 0.0.0.0:7710.
  5. grep DREAM_AGENT_BIND ~/dream-server/.env — empty.
  6. grep DREAM_AGENT_BIND ~/dream-server/.env.example — empty.

The original symptom #283 describes is intact. The "fix" is a startup warning that nobody reads.

Impact

The class of bug #283 was filed about — exposing Docker control API to the LAN — is unchanged on a fresh install of the integration branch.

Suggested Approach

Minimum:

  1. Default .env to DREAM_AGENT_BIND=127.0.0.1 during install. Have the installer write it explicitly into the generated .env.
  2. Document DREAM_AGENT_BIND in .env.example with a comment explaining the trade-off (127.0.0.1 for safety, 0.0.0.0 if a containerized service needs to reach the host-agent across the Docker bridge).
  3. Stop emitting the WARNING when the bind is 127.0.0.1. Promote the warning to ERROR level when the bind is 0.0.0.0, so the next time someone reads journal they see it as a real problem rather than a routine info line.

Better:
4. Bind to 127.0.0.1 and the Docker bridge gateway IP (e.g. 172.17.0.1), or use a Unix socket bind-mounted into containers that need reach. This is what #283's body originally suggested. It maintains container reachability without LAN exposure. Requires a small refactor of ThreadedHTTPServer to bind multiple sockets (or to the bridge IP only), but it's the cleanest answer.

Ask the user at install time:
5. Prompt during --non-interactive setup whether the install is single-user-local (default → 127.0.0.1) or multi-container-with-host-agent-access (→ bridge IP or 0.0.0.0 with explicit warning). Don't make 0.0.0.0 the silent default.

Cross-references


Filed during full-stack integration test of open PR stack Light-Heart-Labs#893–909 on Light-Heart-Labs/DreamServer@c0600ca3. Environment: WSL2 / Ubuntu 24.04 / NVIDIA RTX 3070 Laptop / Tier 1.

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions