← Back to PRs

#7654: feat(security): zero-trust localhost auth with DNS rebinding protection

by joncode open 2026-02-03 02:55 View on GitHub →
docs gateway size: M
## Summary This PR addresses multiple security issues with a unified defense-in-depth approach: - **#4949** - DNS rebinding attacks - **#6609** - Browser bridge authentication - **#6606** - Telegram webhook security ## Changes ### Core Security Features 1. **Default zero-trust**: Localhost connections now require token auth by default. The nonce requirement is no longer skipped for local clients. 2. **Explicit opt-in**: Add `gateway.auth.trustLocalhost` config option (default: `false`) for users who need legacy behavior and understand the risks. 3. **Host header validation**: Add `gateway.auth.allowedHosts` config and `validateHostHeader()` function to reject requests with unexpected Host headers, protecting against DNS rebinding attacks even when `trustLocalhost` is enabled. ### Applied To - **WebSocket connections** (message-handler.ts) - **All HTTP endpoints** (server-http.ts) - **Browser control server** (browser/server.ts) - Host validation only - **Browser bridge server** (browser/bridge-server.ts) - Host validation + allowedHosts param ### New Exports from auth.ts - `validateHostHeader(req, allowedHosts)` - DNS rebinding protection - `shouldTrustLocalhost(req, auth, trustedProxies)` - Combined check ## Breaking Change Local clients that previously connected without tokens will now need to provide authentication. The CLI already sends tokens automatically, so most users won't notice. ## Config Migration Users who need unauthenticated localhost access can add: ```yaml gateway: auth: trustLocalhost: true # NOT recommended ``` Custom allowed hosts can be added via: ```yaml gateway: auth: allowedHosts: ["myhost.local"] ``` ## Testing - 10 new tests added to auth.test.ts (17 total) - All existing tests pass - Full test suite: 4998+ tests passing <!-- greptile_comment --> <h2>Greptile Overview</h2> <h3>Greptile Summary</h3> This PR tightens gateway security by introducing a zero-trust stance for localhost and adding Host header validation to mitigate DNS rebinding. Concretely: - Adds `gateway.auth.trustLocalhost` (default `false`) and `gateway.auth.allowedHosts` config, wiring these into `resolveGatewayAuth()` (`src/gateway/auth.ts`) and the config schema (`src/config/types.gateway.ts`, `src/config/zod-schema.ts`). - Introduces `validateHostHeader()` and `shouldTrustLocalhost()` helpers in `src/gateway/auth.ts`. - Enforces Host validation on the main HTTP server (`src/gateway/server-http.ts`), the WebSocket upgrade/connect path (`src/gateway/server/ws-connection/message-handler.ts`), and browser servers (`src/browser/server.ts`, `src/browser/bridge-server.ts`). - Updates docs to explain DNS rebinding protection and the new localhost trust behavior (`docs/gateway/security/index.md`). Key things to double-check before merge are test/type consistency around the expanded `ResolvedGatewayAuth` type and whether the `allowedHosts: []` behavior should intentionally disable validation. <h3>Confidence Score: 3/5</h3> - This PR is close to safe to merge, but there are a couple of correctness/config-footgun issues to address first. - Main logic changes are straightforward and consistent across HTTP/WS/browser entry points, but the expanded `ResolvedGatewayAuth` shape appears to break existing test literals, and the Host validation API currently allows a trivial opt-out via an empty allowlist that could defeat the intended security guarantee if misconfigured. - src/gateway/auth.test.ts; src/gateway/auth.ts <!-- greptile_other_comments_section --> <sub>(2/5) Greptile learns from your feedback when you react with thumbs up/down!</sub> <!-- /greptile_comment -->

Most Similar PRs