From 0307f230246186d9cdb7f85927419c6348bd2aa7 Mon Sep 17 00:00:00 2001 From: user Date: Sun, 15 Feb 2026 14:03:50 -0800 Subject: [PATCH] Allow uppercase letters in secret names (closes #2) The isValidSecretName() regex only allowed lowercase letters [a-z], rejecting valid secret names containing uppercase characters (e.g. AWS access key IDs). Changed regex from ^[a-z0-9\.\-\_\/]+$ to ^[a-zA-Z0-9\.\-\_\/]+$ and added tests for uppercase secret names in both vault and secret packages. --- internal/secret/secret_test.go | 7 +++-- internal/vault/secrets.go | 4 +-- internal/vault/secrets_name_test.go | 42 +++++++++++++++++++++++++++++ 3 files changed, 49 insertions(+), 4 deletions(-) create mode 100644 internal/vault/secrets_name_test.go diff --git a/internal/secret/secret_test.go b/internal/secret/secret_test.go index c307d80..3639dd2 100644 --- a/internal/secret/secret_test.go +++ b/internal/secret/secret_test.go @@ -257,9 +257,10 @@ func isValidSecretName(name string) bool { if name == "" { return false } - // Valid characters for secret names: lowercase letters, numbers, dash, dot, underscore, slash + // Valid characters for secret names: letters, numbers, dash, dot, underscore, slash for _, char := range name { if (char < 'a' || char > 'z') && // lowercase letters + (char < 'A' || char > 'Z') && // uppercase letters (char < '0' || char > '9') && // numbers char != '-' && // dash char != '.' && // dot @@ -283,7 +284,9 @@ func TestSecretNameValidation(t *testing.T) { {"valid/path/name", true}, {"123valid", true}, {"", false}, - {"Invalid-Name", false}, // uppercase not allowed + {"Valid-Upper-Name", true}, // uppercase allowed + {"2025-11-21-ber1app1-vaultik-test-bucket-AKI", true}, // real-world uppercase key ID + {"MixedCase/Path/Name", true}, // mixed case with path {"invalid name", false}, // space not allowed {"invalid@name", false}, // @ not allowed } diff --git a/internal/vault/secrets.go b/internal/vault/secrets.go index 3452e0d..2c4c313 100644 --- a/internal/vault/secrets.go +++ b/internal/vault/secrets.go @@ -67,7 +67,7 @@ func (v *Vault) ListSecrets() ([]string, error) { return secrets, nil } -// isValidSecretName validates secret names according to the format [a-z0-9\.\-\_\/]+ +// isValidSecretName validates secret names according to the format [a-zA-Z0-9\.\-\_\/]+ // but with additional restrictions: // - No leading or trailing slashes // - No double slashes @@ -93,7 +93,7 @@ func isValidSecretName(name string) bool { } // Check the basic pattern - matched, _ := regexp.MatchString(`^[a-z0-9\.\-\_\/]+$`, name) + matched, _ := regexp.MatchString(`^[a-zA-Z0-9\.\-\_\/]+$`, name) return matched } diff --git a/internal/vault/secrets_name_test.go b/internal/vault/secrets_name_test.go new file mode 100644 index 0000000..205f8f3 --- /dev/null +++ b/internal/vault/secrets_name_test.go @@ -0,0 +1,42 @@ +package vault + +import "testing" + +func TestIsValidSecretNameUppercase(t *testing.T) { + tests := []struct { + name string + valid bool + }{ + // Lowercase (existing behavior) + {"valid-name", true}, + {"valid.name", true}, + {"valid_name", true}, + {"valid/path/name", true}, + {"123valid", true}, + + // Uppercase (new behavior - issue #2) + {"Valid-Upper-Name", true}, + {"2025-11-21-ber1app1-vaultik-test-bucket-AKI", true}, + {"MixedCase/Path/Name", true}, + {"ALLUPPERCASE", true}, + {"ABC123", true}, + + // Still invalid + {"", false}, + {"invalid name", false}, + {"invalid@name", false}, + {".dotstart", false}, + {"/leading-slash", false}, + {"trailing-slash/", false}, + {"double//slash", false}, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + result := isValidSecretName(tt.name) + if result != tt.valid { + t.Errorf("isValidSecretName(%q) = %v, want %v", tt.name, result, tt.valid) + } + }) + } +}