diff --git a/api/http/middlewares/plaintext_http_request.go b/api/http/middlewares/plaintext_http_request.go new file mode 100644 index 000000000..668346098 --- /dev/null +++ b/api/http/middlewares/plaintext_http_request.go @@ -0,0 +1,36 @@ +package middlewares + +import ( + "net/http" + "slices" + + "github.com/gorilla/csrf" +) + +var ( + // Idempotent (safe) methods as defined by RFC7231 section 4.2.2. + safeMethods = []string{"GET", "HEAD", "OPTIONS", "TRACE"} +) + +type plainTextHTTPRequestHandler struct { + next http.Handler +} + +func (h *plainTextHTTPRequestHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) { + if slices.Contains(safeMethods, r.Method) { + h.next.ServeHTTP(w, r) + return + } + + req := r + // If original request was HTTPS (via proxy), keep CSRF checks. + if xfproto := r.Header.Get("X-Forwarded-Proto"); xfproto != "https" { + req = csrf.PlaintextHTTPRequest(r) + } + + h.next.ServeHTTP(w, req) +} + +func PlaintextHTTPRequest(next http.Handler) http.Handler { + return &plainTextHTTPRequestHandler{next: next} +} diff --git a/api/http/server.go b/api/http/server.go index 3f45f667d..8f2c52d5c 100644 --- a/api/http/server.go +++ b/api/http/server.go @@ -349,7 +349,7 @@ func (server *Server) Start() error { log.Info().Str("bind_address", server.BindAddress).Msg("starting HTTP server") httpServer := &http.Server{ Addr: server.BindAddress, - Handler: handler, + Handler: middlewares.PlaintextHTTPRequest(handler), ErrorLog: errorLogger, } diff --git a/go.mod b/go.mod index 5eafa9aa7..f2985a2a5 100644 --- a/go.mod +++ b/go.mod @@ -27,7 +27,7 @@ require ( github.com/gofrs/uuid v4.2.0+incompatible github.com/golang-jwt/jwt/v4 v4.5.2 github.com/google/go-cmp v0.6.0 - github.com/gorilla/csrf v1.7.2 + github.com/gorilla/csrf v1.7.3 github.com/gorilla/mux v1.8.1 github.com/gorilla/websocket v1.5.0 github.com/hashicorp/go-version v1.7.0 diff --git a/go.sum b/go.sum index a666c5366..aeb09fc4d 100644 --- a/go.sum +++ b/go.sum @@ -311,8 +311,8 @@ github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510 h1:El6M4kTTCOh6aBiKaU github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510/go.mod h1:pupxD2MaaD3pAXIBCelhxNneeOaAeabZDe5s4K6zSpQ= github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= -github.com/gorilla/csrf v1.7.2 h1:oTUjx0vyf2T+wkrx09Trsev1TE+/EbDAeHtSTbtC2eI= -github.com/gorilla/csrf v1.7.2/go.mod h1:F1Fj3KG23WYHE6gozCmBAezKookxbIvUJT+121wTuLk= +github.com/gorilla/csrf v1.7.3 h1:BHWt6FTLZAb2HtWT5KDBf6qgpZzvtbp9QWDRKZMXJC0= +github.com/gorilla/csrf v1.7.3/go.mod h1:F1Fj3KG23WYHE6gozCmBAezKookxbIvUJT+121wTuLk= github.com/gorilla/mux v1.7.0/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs= github.com/gorilla/mux v1.8.1 h1:TuBL49tXwgrFYWhqrNgrUNEY92u81SPhu7sTdzQEiWY= github.com/gorilla/mux v1.8.1/go.mod h1:AKf9I4AEqPTmMytcMc0KkNouC66V3BtZ4qD5fmWSiMQ=