Files
ForgeBucket/internal/domain/scanning/secrets_test.go
T
2026-05-12 22:34:26 +02:00

119 lines
3.0 KiB
Go

package scanning
import (
"regexp"
"testing"
)
func TestPatternsCompile(t *testing.T) {
for _, p := range Patterns {
_, err := regexp.Compile(p.Raw)
if err != nil {
t.Errorf("pattern %q failed to compile: %v", p.Name, err)
}
}
}
func TestPatternsHaveNames(t *testing.T) {
for _, p := range Patterns {
if p.Name == "" {
t.Error("pattern with empty name")
}
if p.Description == "" {
t.Errorf("pattern %q has empty description", p.Name)
}
if p.Severity != "high" && p.Severity != "medium" && p.Severity != "low" {
t.Errorf("pattern %q has invalid severity %q", p.Name, p.Severity)
}
}
}
func TestAWSAccessKey(t *testing.T) {
re := regexp.MustCompile(`AKIA[0-9A-Z]{16}`)
cases := []struct {
input string
match bool
}{
{"AKIAIOSFODNN7EXAMPLE", true},
{"AKIA1234567890123456", true},
{"not-a-key", false},
{"SKIA1234567890123456", false},
}
for _, tc := range cases {
got := re.MatchString(tc.input)
if got != tc.match {
t.Errorf("input %q: got %v, want %v", tc.input, got, tc.match)
}
}
}
func TestGitHubToken(t *testing.T) {
re := regexp.MustCompile(`gh[pousr]_[A-Za-z0-9_]{36,}`)
cases := []struct {
input string
match bool
}{
{"ghp_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", true},
{"gho_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", true},
{"ghu_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", true},
{"ghs_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", true},
{"ghr_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", true},
{"not-a-token", false},
{"ghp_short", false},
}
for _, tc := range cases {
got := re.MatchString(tc.input)
if got != tc.match {
t.Errorf("input %q: got %v, want %v", tc.input, got, tc.match)
}
}
}
func TestPrivateKey(t *testing.T) {
re := regexp.MustCompile(`-----BEGIN\s+(RSA|EC|OPENSSH|DSA|PRIVATE)(\s+PRIVATE)?\s+KEY-----`)
cases := []struct {
input string
match bool
}{
{"-----BEGIN RSA PRIVATE KEY-----", true},
{"-----BEGIN EC PRIVATE KEY-----", true},
{"-----BEGIN OPENSSH PRIVATE KEY-----", true},
{"-----BEGIN DSA PRIVATE KEY-----", true},
{"-----BEGIN PRIVATE KEY-----", true},
{"-----BEGIN CERTIFICATE-----", false},
{"public key is here", false},
}
for _, tc := range cases {
got := re.MatchString(tc.input)
if got != tc.match {
t.Errorf("input %q: got %v, want %v", tc.input, got, tc.match)
}
}
}
func TestJWT(t *testing.T) {
re := regexp.MustCompile(`eyJ[A-Za-z0-9_-]{10,}\.[A-Za-z0-9_-]{10,}\.[A-Za-z0-9_-]{10,}`)
cases := []struct {
input string
match bool
}{
{"eyJhbGciOiJIUzI1NiJ9.eyJzdWIiOiIxMjM0NTY3ODkwIn0.dozjgNnZctV9XjvP_oGZQZxGdAqVxQ", true},
{"not-a-jwt", false},
}
for _, tc := range cases {
got := re.MatchString(tc.input)
if got != tc.match {
t.Errorf("input %q: got %v, want %v", tc.input, got, tc.match)
}
}
}
func TestTruncate(t *testing.T) {
if truncate("hello", 10) != "hello" {
t.Error("should not truncate short strings")
}
if truncate("hello world this is long", 10) != "hello worl..." {
t.Errorf("got %q", truncate("hello world this is long", 10))
}
}