go-scm/agentci/security.go
Snider e9fc6902b1
Some checks failed
Security Scan / security (push) Failing after 8s
Test / test (push) Successful in 1m57s
refactor: replace fmt.Errorf/errors.New with coreerr.E()
Replace all remaining fmt.Errorf and errors.New calls in production
code with coreerr.E("caller.Method", "message", err) from go-log.
This standardises error handling across 23 files using the structured
error convention already established in the plugin package.

Co-Authored-By: Virgil <virgil@lethean.io>
2026-03-16 20:37:25 +00:00

50 lines
1.4 KiB
Go

package agentci
import (
"os/exec"
"path/filepath"
"regexp"
"strings"
coreerr "forge.lthn.ai/core/go-log"
)
var safeNameRegex = regexp.MustCompile(`^[a-zA-Z0-9\-\_\.]+$`)
// SanitizePath ensures a filename or directory name is safe and prevents path traversal.
// Returns filepath.Base of the input after validation.
func SanitizePath(input string) (string, error) {
base := filepath.Base(input)
if !safeNameRegex.MatchString(base) {
return "", coreerr.E("agentci.SanitizePath", "invalid characters in path element: "+input, nil)
}
if base == "." || base == ".." || base == "/" {
return "", coreerr.E("agentci.SanitizePath", "invalid path element: "+base, nil)
}
return base, nil
}
// EscapeShellArg wraps a string in single quotes for safe remote shell insertion.
// Prefer exec.Command arguments over constructing shell strings where possible.
func EscapeShellArg(arg string) string {
return "'" + strings.ReplaceAll(arg, "'", "'\\''") + "'"
}
// SecureSSHCommand creates an SSH exec.Cmd with strict host key checking and batch mode.
func SecureSSHCommand(host string, remoteCmd string) *exec.Cmd {
return exec.Command("ssh",
"-o", "StrictHostKeyChecking=yes",
"-o", "BatchMode=yes",
"-o", "ConnectTimeout=10",
host,
remoteCmd,
)
}
// MaskToken returns a masked version of a token for safe logging.
func MaskToken(token string) string {
if len(token) < 8 {
return "*****"
}
return token[:4] + "****" + token[len(token)-4:]
}