From d25781556434ab708855dd89de7632d9cbbd225e Mon Sep 17 00:00:00 2001 From: rcourtman Date: Wed, 4 Feb 2026 15:01:09 +0000 Subject: [PATCH] Reject recovery via untrusted XFF --- internal/api/recovery_proxy_bypass_test.go | 25 ++++++++++++++++++++++ 1 file changed, 25 insertions(+) create mode 100644 internal/api/recovery_proxy_bypass_test.go diff --git a/internal/api/recovery_proxy_bypass_test.go b/internal/api/recovery_proxy_bypass_test.go new file mode 100644 index 0000000000..7590b07965 --- /dev/null +++ b/internal/api/recovery_proxy_bypass_test.go @@ -0,0 +1,25 @@ +package api + +import ( + "net/http" + "net/http/httptest" + "strings" + "testing" +) + +func TestRecoveryEndpointRejectsForwardedLoopbackFromUntrustedProxy(t *testing.T) { + router := newRecoveryRouter(t) + + // No trusted proxies configured; forwarded loopback should be rejected. + req := httptest.NewRequest(http.MethodPost, "/api/security/recovery", strings.NewReader(`{"action":"status"}`)) + req.RemoteAddr = "203.0.113.77:12345" + req.Header.Set("Content-Type", "application/json") + req.Header.Set("X-Forwarded-For", "127.0.0.1") + rec := httptest.NewRecorder() + + router.mux.ServeHTTP(rec, req) + + if rec.Code != http.StatusForbidden { + t.Fatalf("expected 403 for forwarded loopback from untrusted proxy, got %d", rec.Code) + } +}