diff --git a/internal/gatewayapi/securitypolicy.go b/internal/gatewayapi/securitypolicy.go index 224a3cc4d7..f8f1181833 100644 --- a/internal/gatewayapi/securitypolicy.go +++ b/internal/gatewayapi/securitypolicy.go @@ -6,6 +6,8 @@ package gatewayapi import ( + //nolint:gosec // SHA1 is required to validate htpasswd {SHA} format. + "crypto/sha1" "crypto/tls" "encoding/base64" "encoding/json" @@ -1828,6 +1830,14 @@ func validateHtpasswdFormat(data []byte) error { if !strings.HasPrefix(password, "{SHA}") { return fmt.Errorf("unsupported htpasswd format: please use {SHA}") } + // Envoy BasicAuth only supports unsalted SHA1 {SHA} generated by htpasswd. + shaBytes, err := base64.StdEncoding.DecodeString(strings.TrimPrefix(password, "{SHA}")) + if err != nil { + return fmt.Errorf("invalid htpasswd format: {SHA} must be base64-encoded SHA1") + } + if len(shaBytes) != sha1.Size { + return fmt.Errorf("invalid htpasswd format: {SHA} must be SHA1 (%d bytes)", sha1.Size) + } } return nil } diff --git a/internal/gatewayapi/securitypolicy_test.go b/internal/gatewayapi/securitypolicy_test.go index c0261c0837..7967a781f3 100644 --- a/internal/gatewayapi/securitypolicy_test.go +++ b/internal/gatewayapi/securitypolicy_test.go @@ -681,12 +681,12 @@ func Test_validateHtpasswdFormat(t *testing.T) { }{ { name: "valid htpasswd with SHA format", - htpasswd: "user1:{SHA}hashed_user1_password\nuser2:{SHA}hashed_user2_password", + htpasswd: "user1:{SHA}W6ph5Mm5Pz8GgiULbPgzG37mj9g=\nuser2:{SHA}qUqP5cyxm6YcTAhz05Hph5gvu9M=", wantError: false, }, { name: "valid htpasswd with SHA format and empty lines", - htpasswd: "user1:{SHA}hashed_user1_password\n\nuser2:{SHA}hashed_user2_password\n", + htpasswd: "user1:{SHA}W6ph5Mm5Pz8GgiULbPgzG37mj9g=\n\nuser2:{SHA}qUqP5cyxm6YcTAhz05Hph5gvu9M=\n", wantError: false, }, { @@ -709,9 +709,14 @@ func Test_validateHtpasswdFormat(t *testing.T) { htpasswd: "user1{SHA}hashed_user1_password", wantError: true, }, + { + name: "invalid htpasswd with hex sha1", + htpasswd: "user1:{SHA}5baa61e4c9b93f3f0682250b6cf8331b7ee68fd8", + wantError: true, + }, { name: "mixed valid and invalid formats", - htpasswd: "user1:{SHA}hashed_user1_password\nuser2:$apr1$hashed_user2_password", + htpasswd: "user1:{SHA}W6ph5Mm5Pz8GgiULbPgzG37mj9g=\nuser2:$apr1$hashed_user2_password", wantError: true, }, } diff --git a/release-notes/current.yaml b/release-notes/current.yaml index 792dc71653..33fa9b587f 100644 --- a/release-notes/current.yaml +++ b/release-notes/current.yaml @@ -10,6 +10,7 @@ security updates: | new features: | bug fixes: | + Fixed SecurityPolicy BasicAuth validation to reject invalid {SHA} htpasswd entries. Allowed single-label backend hostnames when running with the Host infrastructure, enabling Docker Compose service names for telemetry backends. # Enhancements that improve performance.