# 9router /v1 APIs has unauthenticated access via reverse proxy locality collapse

9router trusts loopback socket addresses, so nginx-proxied public requests to /v1/* skip API-key auth, exposing model catalog and upstream provider credentials.

- Payout: Research
- Severity: high
- Program: 9router
- Found by: dinhvaren
- Disclosed: 2026-09-23
- CVE: CVE-2026-56675
- Write-up quality: 7/10
- Original: https://github.com/advisories/GHSA-x5c9-v98j-722r
- Library page: https://bugbountylibrary.com/r/ghsa%3AGHSA-x5c9-v98j-722r
- Tags: area:web domain:api domain:web impact:data-leak impact:internal-access kind:research platform:ghsa sev:high tech:nginx technique:source-review vuln:access-control vuln:auth-bypass vuln:misconfiguration

**Target:** /v1/* API endpoints behind same-host reverse proxy
**Root cause:** Backend decides local vs remote by perceived socket address; nginx connects from 127.0.0.1 so every internet client is stamped loopback and treated as local, skipping the /v1 API-key requirement. Forwarded X-Real-IP/X-Forwarded-For are ignored for this decision.
**Steps:**
1. `docker compose up --build` to start direct backend (18081) and nginx proxy (18080)
2. Baseline: `curl -i http://127.0.0.1:18081/v1/models` returns 401
3. Spoof control: `curl -i -H "X-9r-Real-IP: 127.0.0.1" http://127.0.0.1:18081/v1/models` still 401 (header overwritten with real socket addr)
4. Bypass: `curl -i http://127.0.0.1:18080/v1/models` returns 200 with full model catalog, no API key
5. Origin control: `curl -i -H "Origin: http://evil.example" http://127.0.0.1:18080/v1/models` returns 401
**How found:** Reporter compared direct backend vs proxied path behavior and ran a header-spoof control to prove the bug is loopback-locality trust after proxying, not naive client header spoofing; also tested Origin header to scope which clients are affected.
**Exploitation:** Attacker sends unauthenticated non-Origin requests (curl/SDK/server-side) to the public nginx endpoint; nginx forwards to backend over 127.0.0.1, backend classifies as local and serves /v1 endpoints. Attacker enumerates models and can call /v1/chat/completions to spend the operator's configured upstream provider keys/quota.
**Escalation:** From model enumeration to abuse of operator's upstream provider credentials via /v1/chat/completions and other proxy endpoints, depending on configured providers.
**Insight:** When a service gates auth on 'is this request local', test it through the documented reverse-proxy deployment: the proxy's loopback source address collapses all remote clients into the trusted bucket. A direct header-spoof control that still 401s confirms the trust is on socket locality, not headers.

