From de5b670f92023ec843e2ed3d582d6df33b441cf2 Mon Sep 17 00:00:00 2001 From: Claude Date: Thu, 20 Nov 2025 04:01:14 +0000 Subject: [PATCH] fix: validate WebSocket origin to prevent CSRF attacks CheckOrigin now validates that the Origin header matches the Host header instead of accepting all origins. Non-browser clients (no Origin) are still allowed for CLI compatibility. --- internal/web/terminal.go | 22 +++++++++++++++++++++- 1 file changed, 21 insertions(+), 1 deletion(-) diff --git a/internal/web/terminal.go b/internal/web/terminal.go index 33edbc04..f1c368ca 100644 --- a/internal/web/terminal.go +++ b/internal/web/terminal.go @@ -2,6 +2,7 @@ package web import ( "net/http" + "strings" "github.com/amir20/dozzle/internal/auth" "github.com/go-chi/chi/v5" @@ -13,7 +14,26 @@ var upgrader = websocket.Upgrader{ ReadBufferSize: 1024, WriteBufferSize: 1024, CheckOrigin: func(r *http.Request) bool { - return true + origin := r.Header.Get("Origin") + if origin == "" { + // No Origin header means this is not a browser request (e.g., CLI tools) + // Allow these requests as they're not subject to CSRF + return true + } + + // Extract host from Origin header (format: scheme://host[:port]) + originHost := origin + if idx := strings.Index(origin, "://"); idx != -1 { + originHost = origin[idx+3:] + } + // Remove any path component + if idx := strings.Index(originHost, "/"); idx != -1 { + originHost = originHost[:idx] + } + + // Compare with the Host header + host := r.Host + return strings.EqualFold(originHost, host) }, }