Localhost security
Hallway is local-only: the daemon listens on 127.0.0.1 and nothing is exposed to your network. But “only on
localhost” isn’t the same as “only reachable by you”. Any web page you visit can try to talk to a local server, either
through DNS rebinding (a hostile domain that resolves to 127.0.0.1) or by sending a cross-site “simple” request.
Since the daemon can edit your config, start and stop services and speak MCP, it defends against both, the same way Local Review does.
The rules
Section titled “The rules”- Loopback only. The daemon binds
127.0.0.1, never0.0.0.0. - Host allowlist. Every request’s
Hostheader must belocalhost,127.0.0.1or[::1](any port), or the configured dashboard hostname in fronted mode. Anything else gets403 forbidden host. This is what defeats DNS rebinding. - Writes must be JSON. Every write must be
Content-Type: application/json, which forces the browser to send a CORS preflight, and no CORS headers are ever sent, so the preflight always fails. ADELETEhas no body, so it is exempt from the content-type rule but not from the next one. - Origin check. If a write carries an
Originheader, it must be one of the allowed hosts. - The MCP endpoint follows the same rules, as MCP’s own guidance for HTTP servers asks: a foreign
HostorOrigingets403, and requests must be JSON.
There is no login. Anything that runs as you can already edit the data home directly, so a password on the API would add friction without adding protection.
Why this forces Host rewriting
Section titled “Why this forces Host rewriting”Many local apps, Local Review included, defend themselves the same way, and would answer 403 forbidden host to a
request arriving as review.localhost. That is why Hallway’s proxy rewrites Host to the upstream address by default
in fronted mode. See Host-header rewriting.
And the rest of the machine
Section titled “And the rest of the machine”- Managed services are started with
HOST=127.0.0.1, so they stay off the network. - The dashboard flags apps listening on all interfaces as exposed, and
hallway doctorlists them. - The dnsmasq configuration for custom domains binds to loopback only, so it can’t become an open resolver.
- In fronted mode, Caddy listens on loopback only, runs as you, and its admin API is a private Unix socket, not a port. See The security model.
- Screenshots (opt-in) are taken by a browser in your data home and never leave your machine.
Found a problem? See the repository’s security policy on GitHub.