Skip to content

fix(server): bind the dashboard to loopback instead of every interface - #2

Open
sergiobuilds wants to merge 1 commit into
LilMGenius:ralphthonfrom
sergiobuilds:fix/bind-loopback
Open

fix(server): bind the dashboard to loopback instead of every interface#2
sergiobuilds wants to merge 1 commit into
LilMGenius:ralphthonfrom
sergiobuilds:fix/bind-loopback

Conversation

@sergiobuilds

Copy link
Copy Markdown

server/index.ts exports { port, fetch } with no hostname, so Bun binds 0.0.0.0. The startup line says http://localhost, which is the part that hides it.

Persona files are the most sensitive thing this project produces — persona.md carries the interview log, nuance.md the contradictions between self-layers. There is no auth, no session, no CORS restriction in front of them.

Measured

Started with PORT=38217 bun run server/index.ts on a Linux host:

$ ss -tlnp | grep 38217
LISTEN 0 512 *:38217 *:*   users:(("bun",pid=...))

$ curl -o /dev/null -w '%{http_code}' http://100.76.48.81:38217/api/personas   # Tailscale
200
$ curl -o /dev/null -w '%{http_code}' http://192.168.50.251:38217/api/personas # LAN
200

$ curl http://192.168.50.251:38217/api/personas/testuser
{"id":"testuser",...,"interview-log":{"entries":[{"date":"2026-08-24","content":"McAdams: ..."}]}}

Anyone who can route to the host reads the interview log. On a tailnet that is every device on the account.

After

scenario expected actual
ss -tlnp loopback only LISTEN 127.0.0.1:38218
LAN request refused connection refused (curl 000)
127.0.0.1 request 200 200
startup line the real address listening on http://127.0.0.1:38218
HOST=0.0.0.0 still possible, but loud binds wide and warns there is no authentication

Default is 127.0.0.1; HOST opts back out for anyone who deliberately wants a LAN dashboard. The log now prints the address it actually bound, so it can no longer claim localhost while serving the network.

- the server exported only `port`, so Bun bound it to 0.0.0.0 and served persona.md, nuance.md, and accounts.md to anyone who could route to the host, with no authentication, while the startup line claimed `http://localhost`; it now binds `127.0.0.1` by default, prints the address it actually bound, and warns when `HOST` opts into a wider bind
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.

1 participant