From f664e0cf88a52f2e9dc51b31c812a612550f4584 Mon Sep 17 00:00:00 2001 From: kmg0308 <113580700+kmg0308@users.noreply.github.com> Date: Mon, 29 Jun 2026 19:40:35 +0900 Subject: [PATCH] Escape BasicAuth realm in challenge header --- middleware/basic_auth.go | 4 ++-- middleware/basic_auth_test.go | 27 +++++++++++++++++++++++++++ 2 files changed, 29 insertions(+), 2 deletions(-) create mode 100644 middleware/basic_auth_test.go diff --git a/middleware/basic_auth.go b/middleware/basic_auth.go index a546c9e9..90883730 100644 --- a/middleware/basic_auth.go +++ b/middleware/basic_auth.go @@ -2,8 +2,8 @@ package middleware import ( "crypto/subtle" - "fmt" "net/http" + "strconv" ) // BasicAuth implements a simple middleware handler for adding basic http auth to a route. @@ -28,6 +28,6 @@ func BasicAuth(realm string, creds map[string]string) func(next http.Handler) ht } func basicAuthFailed(w http.ResponseWriter, realm string) { - w.Header().Add("WWW-Authenticate", fmt.Sprintf(`Basic realm="%s"`, realm)) + w.Header().Add("WWW-Authenticate", "Basic realm="+strconv.Quote(realm)) w.WriteHeader(http.StatusUnauthorized) } diff --git a/middleware/basic_auth_test.go b/middleware/basic_auth_test.go new file mode 100644 index 00000000..da5d802b --- /dev/null +++ b/middleware/basic_auth_test.go @@ -0,0 +1,27 @@ +package middleware + +import ( + "net/http" + "net/http/httptest" + "testing" +) + +func TestBasicAuthEscapesRealm(t *testing.T) { + realm := `admin"ops\zone` + h := BasicAuth(realm, map[string]string{"user": "pass"})(http.HandlerFunc( + func(w http.ResponseWriter, r *http.Request) {}, + )) + + rr := httptest.NewRecorder() + req := httptest.NewRequest(http.MethodGet, "/", nil) + h.ServeHTTP(rr, req) + + if rr.Code != http.StatusUnauthorized { + t.Fatalf("status code = %d, want %d", rr.Code, http.StatusUnauthorized) + } + + const want = `Basic realm="admin\"ops\\zone"` + if got := rr.Header().Get("WWW-Authenticate"); got != want { + t.Fatalf("WWW-Authenticate = %q, want %q", got, want) + } +}