diff --git a/internal/config/config.go b/internal/config/config.go index cc72af59c..f0f5489e2 100644 --- a/internal/config/config.go +++ b/internal/config/config.go @@ -46,7 +46,8 @@ const ( // Regular expression to match invalid characters in paths. // It matches whitespace, control characters, non-printable characters, and specific Unicode characters. - regexInvalidPath = "\\s|[[:cntrl:]]|[[:space:]]|[[^:print:]]|ㅤ|\\.\\.|\\*" + regexInvalidPath = "\\s|[[:cntrl:]]|[[:space:]]|[[^:print:]]|ㅤ|\\.\\.|\\*" + regexLabelPattern = "^[a-zA-Z0-9]([a-zA-Z0-9-_]{0,254}[a-zA-Z0-9])?$" ) var viperInstance = viper.NewWithOptions(viper.KeyDelimiter(KeyDelimiter)) @@ -931,7 +932,9 @@ func resolveLabels() map[string]interface{} { result[trimmedKey] = parseJSON(trimmedValue) default: // String - result[trimmedKey] = trimmedValue + if validateLabel(trimmedValue) { + result[trimmedKey] = trimmedValue + } } } @@ -940,6 +943,19 @@ func resolveLabels() map[string]interface{} { return result } +func validateLabel(labelValue string) bool { + const maxLength = 256 + labelPattern := regexp.MustCompile(regexLabelPattern) + if len(labelValue) > maxLength || !labelPattern.MatchString(labelValue) { + slog.Warn("Label value contains unsupported character or exceed maximum length of 256 characters ", + "label_value", labelValue) + + return false + } + + return true +} + func resolveEnvironmentVariableLabels() map[string]string { envLabels := make(map[string]string) envInput := viperInstance.GetString(LabelsRootKey) diff --git a/internal/config/config_test.go b/internal/config/config_test.go index f55afee23..b47e02253 100644 --- a/internal/config/config_test.go +++ b/internal/config/config_test.go @@ -1234,7 +1234,7 @@ func createConfig() *Config { { Action: "insert", Key: "label1", - Value: "label 1", + Value: "label-1", }, { Action: "insert", @@ -1314,7 +1314,7 @@ func createConfig() *Config { }, }, Labels: map[string]any{ - "label1": "label 1", + "label1": "label-1", "label2": "new-value", "label3": 123, }, @@ -1410,3 +1410,59 @@ func createDefaultCollectorConfig() *Collector { }, } } + +func TestValidateLabel(t *testing.T) { + tests := []struct { + name string + input string + expected bool + }{ + { + name: "Test 1: Valid label - simple", + input: "label123", + expected: true, + }, + { + name: "Test 2: Valid label - with dash and underscore", + input: "label-123_abc", + expected: true, + }, + { + name: "Test 3: Invalid label - too long", + input: strings.Repeat("a", 257), + expected: false, + }, + { + name: "Test 4: Invalid label - special char", + input: "label$", + expected: false, + }, + { + name: "Test 5: Invalid label - starts with dash", + input: "-label", + expected: false, + }, + { + name: "Test 6: Invalid label - ends with dash", + input: "label-", + expected: false, + }, + { + name: "Test 7: Invalid label - empty", + input: "", + expected: false, + }, + { + name: "Test 8: Invalid label - contains spaces", + input: "label 123", + expected: false, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + actual := validateLabel(tt.input) + assert.Equal(t, tt.expected, actual) + }) + } +} diff --git a/internal/config/testdata/nginx-agent.conf b/internal/config/testdata/nginx-agent.conf index 9df36198d..1444daeef 100644 --- a/internal/config/testdata/nginx-agent.conf +++ b/internal/config/testdata/nginx-agent.conf @@ -13,7 +13,7 @@ watchers: - \.*log$ labels: - label1: label 1 + label1: label-1 label2: new-value label3: 123