# DNS rebinding past localhost trust checks

Local listeners that trust hostname, User-Agent or Origin prefix instead of the resolved peer IP

_Area: Web infrastructure and server-side requests. Seen in 3 disclosed reports; one confirmed bounty: $15,000; latest 2026-09-15. Updated 2026-11-02._

## How it works
A service binds to loopback (or a private address) and assumes that only local, trusted software can reach it. That assumption is false: a page in the victim's browser can be made to resolve an attacker-controlled name to 127.0.0.1 (DNS rebinding), so the browser itself becomes the transport into the local listener. The boundary that actually holds is the resolved peer address plus a strict Host/Origin allowlist — not the hostname string, not a User-Agent prefix, not "it's on loopback". When the listener validates any of those weaker signals, or validates nothing, the local service is reachable from any web page the user visits [E1](https://bugbountylibrary.com/r/h1%3A873614.md)[E2](https://bugbountylibrary.com/r/ghsa%3AGHSA-q279-jhrf-cc6v.md)[E3](https://bugbountylibrary.com/r/ghsa%3AGHSA-vmp7-252j-cwp7.md).

## Where it shows up
- Local HTTP/WebSocket/IPC listeners on 127.0.0.1 with no Origin or Host check [E1](https://bugbountylibrary.com/r/h1%3A873614.md)[E3](https://bugbountylibrary.com/r/ghsa%3AGHSA-vmp7-252j-cwp7.md)
- "Browser blocking" implemented as `User-Agent startsWith 'Mozilla'` [E2](https://bugbountylibrary.com/r/ghsa%3AGHSA-q279-jhrf-cc6v.md)
- Transport/server objects constructed without DNS-rebinding options (`enableDnsRebindingProtection`, `allowedHosts`, `allowedOrigins`) [E3](https://bugbountylibrary.com/r/ghsa%3AGHSA-vmp7-252j-cwp7.md)
- Express/Node apps where `express.json()` is mounted globally and no middleware rejects unexpected Host/Origin before the sensitive route [E3](https://bugbountylibrary.com/r/ghsa%3AGHSA-vmp7-252j-cwp7.md)
- Electron apps exposing command handlers (`setUrl`, `setUrlDefaultBrowser`) over a local socket, especially with `nodeIntegration:true` [E1](https://bugbountylibrary.com/r/h1%3A873614.md)
- Unauthenticated management APIs (`/api/jobs`) reachable on a fixed port [E2](https://bugbountylibrary.com/r/ghsa%3AGHSA-q279-jhrf-cc6v.md)

## How to review
Find every listener bound to loopback/private ranges and ask: what does it check before acting? The invariant: a request is only honored if the resolved peer IP is local AND the Host header matches an expected name AND (for browser-reachable transports) Origin is absent or allowlisted. A check on hostname text, User-Agent, or "came from localhost" does not satisfy this. For Electron, confirm `nodeIntegration` is off and that IPC commands cannot load arbitrary remote content. For SDK transports, confirm the rebinding-protection flags are actually set, not just defaulted. Treat loopback binding alone as no boundary [E3](https://bugbountylibrary.com/r/ghsa%3AGHSA-vmp7-252j-cwp7.md).

## How finders spotted it
- Enumerated running processes with procmon/netstat, spotted a local websocket on port 1235, proxied its JSON traffic through Burp, then grepped `app.asar` for `commandHandler` to enumerate commands and swapped source/target fields to redirect them [E1](https://bugbountylibrary.com/r/h1%3A873614.md)
- Read the browser-defense code, saw it was a User-Agent prefix heuristic, and reasoned that Firefox/Safari `fetch` allows overriding User-Agent (Chrome does not), then paired it with rebinding [E2](https://bugbountylibrary.com/r/ghsa%3AGHSA-q279-jhrf-cc6v.md)
- Code review of `index.ts`: noticed global `express.json()` with no Host/Origin allowlist and a transport built without the SDK's rebinding options, while default HOST is 127.0.0.1 [E3](https://bugbountylibrary.com/r/ghsa%3AGHSA-vmp7-252j-cwp7.md)

## Variants seen
- Missing Origin check on a local websocket plus an unauthenticated command that loads attacker JS with nodeIntegration on [E1](https://bugbountylibrary.com/r/h1%3A873614.md)
- User-Agent-prefix "browser block" bypassed via fetch UA override, combined with rebinding [E2](https://bugbountylibrary.com/r/ghsa%3AGHSA-q279-jhrf-cc6v.md)
- Streamable HTTP MCP transport with no Host/Origin allowlisting, loopback as sole boundary [E3](https://bugbountylibrary.com/r/ghsa%3AGHSA-vmp7-252j-cwp7.md)

## Impact and severity
E1 reached full RCE from any website in any browser by chaining three weaknesses [E1](https://bugbountylibrary.com/r/h1%3A873614.md). E2 was critical unauthenticated RCE via the dashboard API [E2](https://bugbountylibrary.com/r/ghsa%3AGHSA-q279-jhrf-cc6v.md). E3 escalated from cross-origin reachability to reading GitLab CI/CD variables when a token was supplied or reused [E3](https://bugbountylibrary.com/r/ghsa%3AGHSA-vmp7-252j-cwp7.md). Impact rises with each chained weakness and with what the local API can do once reached.

## Seen in real software
Open-source packages and projects, and products, where this pattern was found. If the target runs one, compare the version it runs with the fix.
- **@zereight/mcp-gitlab (npm)** < 2.1.30, fixed in 2.1.30: @zereight/mcp-gitlab: DNS rebinding reaches local Streamable HTTP MCP transport (CVE-2026-61568). Report: https://bugbountylibrary.com/r/ghsa%3AGHSA-vmp7-252j-cwp7.md. Fix: https://github.com/zereight/gitlab-mcp/commit/52207c6f5c0e7a39e9235d491225edbb562a0290
- **ray (pip)** < 2.52.0, fixed in 2.52.0: Ray is vulnerable to Critical RCE via Safari & Firefox Browsers through DNS Rebinding Attack (CVE-2025-62593). Report: https://bugbountylibrary.com/r/ghsa%3AGHSA-q279-jhrf-cc6v.md. Fix: https://github.com/ray-project/ray/commit/70e7c72780bdec075dba6cad1afe0832772bfe09

## Evidence
- E1: https://bugbountylibrary.com/r/h1%3A873614.md
- E2: https://bugbountylibrary.com/r/ghsa%3AGHSA-q279-jhrf-cc6v.md
- E3: https://bugbountylibrary.com/r/ghsa%3AGHSA-vmp7-252j-cwp7.md
