Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
37 changes: 36 additions & 1 deletion internal/common/targets.go
Original file line number Diff line number Diff line change
Expand Up @@ -299,6 +299,30 @@ 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, periods, and dashes
// everything else is replaced with an underscore
sanitizedTargetName := strings.Map(func(r rune) rune {
if r == '-' || r == '_' || r == '.' {
Comment thread
harp-intel marked this conversation as resolved.
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)
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) {
Expand All @@ -319,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(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())
Expand Down
45 changes: 45 additions & 0 deletions internal/common/targets_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -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)
})
}
}