From b5e7afdd2d18dc684d0eb5ae289a0f110d2b6d85 Mon Sep 17 00:00:00 2001 From: Vishal Rana Date: Thu, 22 Oct 2026 15:46:08 -0700 Subject: [PATCH] fix(middleware): check Basic auth scheme boundary in v4 Backport #3138. Reject malformed schemes such as BasicX before decoding credentials or invoking the validator. v4 reads only its first Authorization header and has no AllowedCheckLimit, so its regression covers that API. Co-authored-by: Shubham Padkonde --- middleware/basic_auth.go | 2 +- middleware/basic_auth_test.go | 21 +++++++++++++++++++++ 2 files changed, 22 insertions(+), 1 deletion(-) diff --git a/middleware/basic_auth.go b/middleware/basic_auth.go index 4a46098e3..f92a318e7 100644 --- a/middleware/basic_auth.go +++ b/middleware/basic_auth.go @@ -78,7 +78,7 @@ func BasicAuthWithConfig(config BasicAuthConfig) echo.MiddlewareFunc { auth := c.Request().Header.Get(echo.HeaderAuthorization) l := len(basic) - if len(auth) > l+1 && strings.EqualFold(auth[:l], basic) { + if len(auth) > l+1 && auth[l] == ' ' && strings.EqualFold(auth[:l], basic) { // Invalid base64 shouldn't be treated as error // instead should be treated as invalid client input b, err := base64.StdEncoding.DecodeString(auth[l+1:]) diff --git a/middleware/basic_auth_test.go b/middleware/basic_auth_test.go index 2d3192615..9f9fc5744 100644 --- a/middleware/basic_auth_test.go +++ b/middleware/basic_auth_test.go @@ -118,6 +118,27 @@ func TestBasicAuth(t *testing.T) { } } +func TestBasicAuthRejectsInvalidSchemeBoundary(t *testing.T) { + e := echo.New() + validatorCalled := false + e.Use(BasicAuth(func(user, password string, c echo.Context) (bool, error) { + validatorCalled = true + return user == "joe" && password == "secret", nil + })) + e.GET("/", func(c echo.Context) error { + return c.NoContent(http.StatusNoContent) + }) + + req := httptest.NewRequest(http.MethodGet, "/", nil) + req.Header.Set(echo.HeaderAuthorization, "BasicX"+base64.StdEncoding.EncodeToString([]byte("joe:secret"))) + rec := httptest.NewRecorder() + e.ServeHTTP(rec, req) + + assert.Equal(t, http.StatusUnauthorized, rec.Code) + assert.Equal(t, basic+` realm="Restricted"`, rec.Header().Get(echo.HeaderWWWAuthenticate)) + assert.False(t, validatorCalled) +} + func TestBasicAuthRealm(t *testing.T) { e := echo.New() mockValidator := func(u, p string, c echo.Context) (bool, error) {