Skip to content

fix(security): bind llama-server and host agent to loopback#988

Merged
Lightheartdevs merged 2 commits intoLight-Heart-Labs:mainfrom
yasinBursali:fix/security-loopback
Apr 27, 2026
Merged

fix(security): bind llama-server and host agent to loopback#988
Lightheartdevs merged 2 commits intoLight-Heart-Labs:mainfrom
yasinBursali:fix/security-loopback

Conversation

@yasinBursali
Copy link
Copy Markdown
Contributor

What

Binds native llama-server (macOS + Windows) and the Linux host agent fallback to 127.0.0.1 (loopback) instead of 0.0.0.0 (all interfaces).

Why

Native llama-server on macOS (Metal) and Windows (Lemonade + llama.cpp) previously listened on 0.0.0.0:8080, making the LLM inference API reachable from any device on the LAN without authentication. Similarly, when _detect_docker_bridge_gateway() failed on Linux, the host agent fell back to 0.0.0.0, exposing container management to the LAN.

How

Minimal 17+/17- diff across 8 files:

  • installers/macos/install-macos.sh + installers/macos/dream-macos.sh--host 127.0.0.1 on native llama-server launch
  • installers/windows/install-windows.ps1 + installers/windows/dream.ps1--host 127.0.0.1 on Lemonade + llama.cpp launch
  • scripts/bootstrap-upgrade.sh--host 127.0.0.1 on macOS rollback/upgrade paths
  • bin/dream-host-agent.py — Linux bridge-detection fallback changed from 0.0.0.0 to 127.0.0.1; startup warning updated to reflect the new guidance (directing operators to set DREAM_AGENT_BIND=<bridge-ip> if containers need to reach the agent in the failure-mode)
  • .env.example + .env.schema.json — doc strings updated to reflect the new Linux fallback

Users who legitimately need LAN exposure can still set DREAM_AGENT_BIND=0.0.0.0 explicitly — that override path is preserved.

Testing

  • Verified on macOS Apple Silicon install: lsof -nP -iTCP:7710 -sTCP:LISTEN shows 127.0.0.1:7710 only
  • Dashboard, Open WebUI, and Docker containers still reach llama via host.docker.internal (Docker Desktop routes host-gateway to loopback)
  • Shellcheck clean on all touched shell scripts
  • python3 -m py_compile bin/dream-host-agent.py passes

Platform Impact

  • macOS: native llama-server binds loopback-only. Dashboard/WebUI reach it via host.docker.internal. No user-visible regression for local use; LAN exposure closed.
  • Linux: host agent uses Docker bridge gateway IP on the normal path (unchanged). On bridge-detection failure, falls back to 127.0.0.1 instead of 0.0.0.0 — containers cannot reach the agent in that rare failure mode. Operators on non-standard Docker setups should set DREAM_AGENT_BIND=<bridge-ip> explicitly; startup warning directs them to this.
  • Windows: native Lemonade + llama.cpp bind loopback-only. Docker Desktop routes host.docker.internal to loopback — same mental model as macOS. No user-visible regression for local use.

macOS/Windows llama-server was binding to 0.0.0.0, exposing the
LLM inference API to the entire LAN without authentication.

Host agent on Linux fell back to 0.0.0.0 when Docker bridge
detection failed, exposing container management to the network.

Fixed all native llama-server launch paths across:
- macOS installer + CLI (install-macos.sh, dream-macos.sh)
- macOS host agent model swap (dream-host-agent.py)
- macOS bootstrap upgrade + rollback (bootstrap-upgrade.sh)
- Windows installer + CLI (install-windows.ps1, dream.ps1)

All now default to 127.0.0.1 (loopback only).
The unified BIND_ADDRESS knob from PR Light-Heart-Labs#964 was only being applied to
Docker-published ports. Native llama-server, Lemonade, and the host
agent's spawn path all hardcoded 127.0.0.1, so a user installing with
--lan (or setting BIND_ADDRESS=0.0.0.0 manually) silently lost direct
API access to the inference backend with no escape hatch — the design
became incoherent across the stack.

Read BIND_ADDRESS from .env at every native launch site (default-secure
loopback fallback when unset/empty). One knob, full-stack effect — now
matches the maintainer's Light-Heart-Labs#964 design.

Sites:
  - installers/macos/dream-macos.sh    (uses ENV_BIND_ADDRESS, already
                                        exported by read_dream_env)
  - installers/macos/install-macos.sh  (inline grep, matches local
                                        LLAMA_REASONING pattern)
  - bin/dream-host-agent.py            (env.get via existing load_env)
  - installers/windows/dream.ps1       (Read-DreamEnv hashtable)
  - installers/windows/install-windows.ps1 (read once, used twice)
  - scripts/bootstrap-upgrade.sh       (same pattern, rollback path too)
@Lightheartdevs Lightheartdevs merged commit 5bf3317 into Light-Heart-Labs:main Apr 27, 2026
27 of 28 checks passed
yasinBursali added a commit to yasinBursali/DreamServer that referenced this pull request Apr 29, 2026
…rt-Labs#988

fix/security-loopback (Light-Heart-Labs#988) changes the Linux Docker-bridge-gateway
detection fallback in bin/dream-host-agent.py from 0.0.0.0 to
127.0.0.1 (security fix: prevents LAN exposure when bridge detection
fails). docs/sync-documentation-with-codebase (Light-Heart-Labs#973) adds the Host
Agent Network Binding table whose Linux row documented pre-Light-Heart-Labs#988
behavior — the 0.0.0.0 fallback language is now stale.

Updates the Linux row to match the actual fallback.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
yasinBursali added a commit to yasinBursali/DreamServer that referenced this pull request Apr 29, 2026
… in SECURITY.md

Maintainer audit on PR Light-Heart-Labs#973 (Lightheartdevs, 2026-04-28):

  "Audit follow-up: needs rebase/update after the security merges.
   Light-Heart-Labs#988 is now on `main`, so docs should describe the safer loopback
   fallback behavior rather than the old exposure story. Please rebase
   this broad docs pass on current `main`, reconcile it with Light-Heart-Labs#988/Light-Heart-Labs#959,
   and make sure the host-agent/native binding sections consistently
   say `127.0.0.1` where that is now the implementation."

Light-Heart-Labs#988 (`fix/security-loopback`) changed `bin/dream-host-agent.py:2315`
to fall back to `127.0.0.1` instead of `0.0.0.0` when Docker bridge
detection fails. The "Host Agent Network Binding" table introduced
in this PR (commit `4ef9133c`) described pre-Light-Heart-Labs#988 behavior in the
Linux row. This commit corrects the cell with a parenthetical
pointing at Light-Heart-Labs#988 so the rationale isn't lost on future readers.

The other entries in the table (macOS/Windows already loopback,
override examples, bind-to-LAN warning) are unchanged.

Light-Heart-Labs#959-related changes: the token-spy proxy/upstream auth split is
already correctly captured by extension manifests + service
documentation that landed with Light-Heart-Labs#959; this PR's diff doesn't touch
those paths.

Closes the binding-doc audit ask. Branch is now rebased on current
upstream/main; rest of the docs sync (Qwen3.5/3 model names,
Windows-quickstart rewrite, FAQ expansions, langfuse README, etc.)
stands as before.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
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