fix(dashboard): remove X-Real-IP trust from localhost-only guards (PILOT-301)#24
fix(dashboard): remove X-Real-IP trust from localhost-only guards (PILOT-301)#24matthew-pilot wants to merge 1 commit into
Conversation
…LOT-301) The localhostOnly middleware and the /api/nodes and /api/snapshot handlers all trusted the X-Real-IP header when RemoteAddr was loopback. In a typical reverse-proxy setup where nginx runs on the same host, an attacker reaching the proxy from anywhere can send X-Real-IP: 127.0.0.1 and bypass the localhost gate, gaining access to internal endpoints (/api/nodes listing, snapshot trigger, pprof, metrics). Fix: remove X-Real-IP entirely from the localhost check. The only thing that matters is the actual TCP peer address. If RemoteAddr is loopback, the request is local — regardless of header claims. X-Real-IP can be set by anyone and should not be trusted for access-control decisions. Updated test: TestLocalhostOnly_HonorsXRealIPFromLocalhost renamed to TestLocalhostOnly_IgnoresXRealIPFromLocalhost — now asserts that X-Real-IP is ignored and loopback requests always pass. Closes PILOT-301
Codecov Report✅ All modified and coverable lines are covered by tests. 📢 Thoughts on this report? Let us know! |
🤖 PR Status (matthew-pr-worker)PR: #24 — fix(dashboard): remove X-Real-IP trust from localhost-only guards (PILOT-301) CI Checks (2/2 passing ✅)
Diff Stats
ClassificationWave 1 · Action: matthew-pr-worker tick 2026-05-30T18:20Z |
🤖 PR Explain (matthew-pr-worker)What this PR does (PILOT-301)Problem: The Fix: Remove Walkthrough
Security implicationThis was a real access-control bypass. Scope
matthew-pr-worker tick 2026-05-30T18:20Z |
🤖 PR Status CheckPR #24: fix(dashboard): remove X-Real-IP trust from localhost-only guards (PILOT-301) matthew-pr-worker • 2026-05-31T11:58:00Z |
🤖 PR Explanationfix(dashboard): remove X-Real-IP trust from localhost-only guards (PILOT-301) SummaryWhat failedThe
Changes+9/−28 lines across 2 file(s):
Files Changed
matthew-pr-worker • 2026-05-31T11:58:00Z |
What failed
The
localhostOnlymiddleware and the inline checks in/api/nodesand/api/snapshothandlers all trusted theX-Real-IPheader whenRemoteAddrwas loopback. In a typical reverse-proxy setup where nginx runs on the same host as the rendezvous, an attacker reaching the proxy from anywhere could sendX-Real-IP: 127.0.0.1and bypass the localhost gate, gaining access to:/api/nodes— node listing with addresses and hostnames/api/snapshot— snapshot trigger/metrics— Prometheus metrics/debug/pprof/*— profiling endpointsThe fix
Remove
X-Real-IPentirely from the localhost check. The only thing that matters is the actual TCP peer address (RemoteAddr). IfRemoteAddris loopback, the request is local — regardless of header claims.X-Real-IPcan be set by anyone and must not be trusted for access-control decisions.Files changed
dashboard/dashboard.go— simplifiedlocalhostOnlyhelper,/api/nodes, and/api/snapshothandlersdashboard/zz_more_test.go— renamedTestLocalhostOnly_HonorsXRealIPtoTestLocalhostOnly_IgnoresXRealIPwith inverted assertionVerification
Closes PILOT-301