119 lines
3.0 KiB
Go
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))
|
|
}
|
|
}
|