From c12cbf6d058b38f0c7abfcbc9936d4772b6ab8f3 Mon Sep 17 00:00:00 2001 From: "Harper, Jason M" Date: Tue, 6 May 2025 13:59:58 -0700 Subject: [PATCH 1/4] make sure target name in targets.yaml file doesn't include any characters that can alter the output location Signed-off-by: Harper, Jason M --- internal/common/targets.go | 28 +++++++++++++++++++++++++++- 1 file changed, 27 insertions(+), 1 deletion(-) diff --git a/internal/common/targets.go b/internal/common/targets.go index 5841cb16..cccfbb07 100644 --- a/internal/common/targets.go +++ b/internal/common/targets.go @@ -299,6 +299,32 @@ type targetsFile struct { Targets []targetFromYAML `yaml:"targets"` } +func sanitizeTargetName(targetName string) string { + // remove any invalid characters from the target name + // this is needed for the report file names + // we only allow alphanumeric characters, underscores, and dashes + // everything else is replaced with an underscore + sanitizedTargetName := strings.Map(func(r rune) rune { + if r == '-' || r == '_' || r == '.' { + return r + } + if r >= 'a' && r <= 'z' { + return r + } + if r >= 'A' && r <= 'Z' { + return r + } + if r >= '0' && r <= '9' { + return r + } + return '_' + }, targetName) + if sanitizedTargetName == "" { + sanitizedTargetName = "unknown" + } + return sanitizedTargetName +} + // getTargetsFromFile reads a targets file and returns a list of target objects. // It takes the path to the targets file and the local temporary directory as input. func getTargetsFromFile(targetsFilePath string, localTempDir string) (targets []target.Target, targetErrs []error, err error) { @@ -321,7 +347,7 @@ func getTargetsFromFile(targetsFilePath string, localTempDir string) (targets [] } for _, t := range targetsFile.Targets { // create a target object - newTarget := target.NewRemoteTarget(t.Name, t.Host, t.Port, t.User, t.Key) + newTarget := target.NewRemoteTarget(sanitizeTargetName(t.Name), t.Host, t.Port, t.User, t.Key) newTarget.SetSshPass(t.Pwd) // create a sub-directory for the target in the localTempDir localTargetDir := path.Join(localTempDir, newTarget.GetName()) From 65b116374c20deb30be51c736a4595ad438a6b91 Mon Sep 17 00:00:00 2001 From: "Harper, Jason M" Date: Tue, 6 May 2025 14:05:23 -0700 Subject: [PATCH 2/4] update comment Signed-off-by: Harper, Jason M --- internal/common/targets.go | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/internal/common/targets.go b/internal/common/targets.go index cccfbb07..74b8e171 100644 --- a/internal/common/targets.go +++ b/internal/common/targets.go @@ -299,10 +299,11 @@ type targetsFile struct { Targets []targetFromYAML `yaml:"targets"` } +// sanitizeTargetName sanitizes the target name by removing any invalid characters. func sanitizeTargetName(targetName string) string { // remove any invalid characters from the target name // this is needed for the report file names - // we only allow alphanumeric characters, underscores, and dashes + // we only allow alphanumeric characters, underscores, periods, and dashes // everything else is replaced with an underscore sanitizedTargetName := strings.Map(func(r rune) rune { if r == '-' || r == '_' || r == '.' { From e7c30b3200e0a05411d40c6e5b028bdd4a24d1fa Mon Sep 17 00:00:00 2001 From: "Harper, Jason M" Date: Tue, 6 May 2025 14:19:41 -0700 Subject: [PATCH 3/4] Enhance target name sanitization to prevent duplicates in targets file Signed-off-by: Harper, Jason M --- internal/common/targets.go | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/internal/common/targets.go b/internal/common/targets.go index 74b8e171..b7bb8607 100644 --- a/internal/common/targets.go +++ b/internal/common/targets.go @@ -320,9 +320,6 @@ func sanitizeTargetName(targetName string) string { } return '_' }, targetName) - if sanitizedTargetName == "" { - sanitizedTargetName = "unknown" - } return sanitizedTargetName } @@ -346,9 +343,20 @@ func getTargetsFromFile(targetsFilePath string, localTempDir string) (targets [] if err != nil { return } + targetNameUsed := make(map[string]bool) for _, t := range targetsFile.Targets { // create a target object - newTarget := target.NewRemoteTarget(sanitizeTargetName(t.Name), t.Host, t.Port, t.User, t.Key) + // target name is not required, but if it is provided there must not be duplicate names + var targetName string + if t.Name != "" { + targetName = sanitizeTargetName(t.Name) + if targetNameUsed[targetName] { + err = fmt.Errorf("duplicate target name (after sanitized) found in targets file: original: %s, sanitized: %s", t.Name, targetName) + return + } + targetNameUsed[targetName] = true + } + newTarget := target.NewRemoteTarget(targetName, t.Host, t.Port, t.User, t.Key) newTarget.SetSshPass(t.Pwd) // create a sub-directory for the target in the localTempDir localTargetDir := path.Join(localTempDir, newTarget.GetName()) From 21924cdc77262d5e261912955c04246fd110e4e3 Mon Sep 17 00:00:00 2001 From: "Harper, Jason M" Date: Wed, 7 May 2025 05:51:20 -0700 Subject: [PATCH 4/4] Add unit tests for sanitizeTargetName function to validate name sanitization Signed-off-by: Harper, Jason M --- internal/common/targets_test.go | 45 +++++++++++++++++++++++++++++++++ 1 file changed, 45 insertions(+) diff --git a/internal/common/targets_test.go b/internal/common/targets_test.go index 27c6914a..01cc43af 100644 --- a/internal/common/targets_test.go +++ b/internal/common/targets_test.go @@ -142,3 +142,48 @@ invalid line format`, }) } } +func TestSanitizeTargetName(t *testing.T) { + tests := []struct { + name string + input string + expected string + }{ + { + name: "Valid name with allowed characters", + input: "valid_name-123.txt", + expected: "valid_name-123.txt", + }, + { + name: "Name with invalid characters", + input: "invalid@name#123!", + expected: "invalid_name_123_", + }, + { + name: "Name with spaces", + input: "name with spaces", + expected: "name_with_spaces", + }, + { + name: "Empty name", + input: "", + expected: "", + }, + { + name: "Name with only invalid characters", + input: "@#$%^&*()", + expected: "_________", + }, + { + name: "Name with mixed valid and invalid characters", + input: "valid@name#123!.txt", + expected: "valid_name_123_.txt", + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + result := sanitizeTargetName(tt.input) + assert.Equal(t, tt.expected, result) + }) + } +}