Improve blacklist to use regex matching

This commit is contained in:
2025-02-26 10:32:01 +02:00
parent b6dd77e57e
commit 5cf720103f
3 changed files with 350 additions and 55 deletions

View File

@@ -0,0 +1,295 @@
package blackList
import (
"os"
"regexp"
"testing"
"gemini-grc/config"
)
func TestIsBlacklisted(t *testing.T) {
// Save original blacklist to restore after test
originalBlacklist := Blacklist
defer func() {
Blacklist = originalBlacklist
}()
tests := []struct {
name string
setup func()
url string
expected bool
}{
{
name: "empty blacklist",
setup: func() {
Blacklist = []regexp.Regexp{}
},
url: "https://example.com",
expected: false,
},
{
name: "exact hostname match",
setup: func() {
regex, _ := regexp.Compile(`example\.com`)
Blacklist = []regexp.Regexp{*regex}
},
url: "example.com",
expected: true,
},
{
name: "hostname in URL match",
setup: func() {
regex, _ := regexp.Compile(`example\.com`)
Blacklist = []regexp.Regexp{*regex}
},
url: "https://example.com/path",
expected: true,
},
{
name: "partial hostname match",
setup: func() {
regex, _ := regexp.Compile(`example\.com`)
Blacklist = []regexp.Regexp{*regex}
},
url: "https://safe-example.com",
expected: true,
},
{
name: "full URL match",
setup: func() {
regex, _ := regexp.Compile(`https://example\.com/bad-path`)
Blacklist = []regexp.Regexp{*regex}
},
url: "https://example.com/bad-path",
expected: true,
},
{
name: "path match",
setup: func() {
regex, _ := regexp.Compile("/malicious-path")
Blacklist = []regexp.Regexp{*regex}
},
url: "https://example.com/malicious-path",
expected: true,
},
{
name: "subdomain match with word boundary",
setup: func() {
regex, _ := regexp.Compile(`bad\.example\.com`)
Blacklist = []regexp.Regexp{*regex}
},
url: "https://bad.example.com/path",
expected: true,
},
{
name: "multiple patterns, one match",
setup: func() {
regex1, _ := regexp.Compile(`badsite\.com`)
regex2, _ := regexp.Compile(`malicious\.org`)
regex3, _ := regexp.Compile(`example\.com/sensitive`)
Blacklist = []regexp.Regexp{*regex1, *regex2, *regex3}
},
url: "https://example.com/sensitive/data",
expected: true,
},
{
name: "multiple patterns, no match",
setup: func() {
regex1, _ := regexp.Compile(`badsite\.com`)
regex2, _ := regexp.Compile(`malicious\.org`)
regex3, _ := regexp.Compile(`example\.com/sensitive`)
Blacklist = []regexp.Regexp{*regex1, *regex2, *regex3}
},
url: "https://example.com/safe/data",
expected: false,
},
{
name: "pattern with wildcard",
setup: func() {
regex, _ := regexp.Compile(`.*\.evil\.com`)
Blacklist = []regexp.Regexp{*regex}
},
url: "https://subdomain.evil.com/path",
expected: true,
},
{
name: "pattern with special characters",
setup: func() {
regex, _ := regexp.Compile(`example\.com/path\?id=[0-9]+`)
Blacklist = []regexp.Regexp{*regex}
},
url: "https://example.com/path?id=12345",
expected: true,
},
{
name: "unicode character support",
setup: func() {
regex, _ := regexp.Compile(`example\.com/[\p{L}]+`)
Blacklist = []regexp.Regexp{*regex}
},
url: "https://example.com/café",
expected: true,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
tt.setup()
result := IsBlacklisted(tt.url)
if result != tt.expected {
t.Errorf("IsBlacklisted(%q) = %v, want %v", tt.url, result, tt.expected)
}
})
}
}
func TestLoadBlacklist(t *testing.T) {
// Save original blacklist to restore after test
originalBlacklist := Blacklist
originalConfigPath := config.CONFIG.BlacklistPath
defer func() {
Blacklist = originalBlacklist
config.CONFIG.BlacklistPath = originalConfigPath
}()
// Create a temporary blacklist file for testing
tmpFile, err := os.CreateTemp("", "blacklist-*.txt")
if err != nil {
t.Fatalf("Failed to create temporary file: %v", err)
}
defer os.Remove(tmpFile.Name())
// Test cases for LoadBlacklist
tests := []struct {
name string
blacklistLines []string
configPath string
wantErr bool
expectedLen int
}{
{
name: "empty path",
blacklistLines: []string{},
configPath: "",
wantErr: false,
expectedLen: 0,
},
{
name: "valid blacklist with comments",
blacklistLines: []string{"example\\.com", "# This is a comment", "malicious\\.org"},
configPath: tmpFile.Name(),
wantErr: false,
expectedLen: 2,
},
{
name: "invalid regex",
blacklistLines: []string{"example\\.com", "[invalid regex"},
configPath: tmpFile.Name(),
wantErr: true,
expectedLen: 0,
},
{
name: "nonexistent file",
blacklistLines: []string{},
configPath: "nonexistent-file.txt",
wantErr: true,
expectedLen: 0,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
// Reset blacklist
Blacklist = nil
// Set config path
config.CONFIG.BlacklistPath = tt.configPath
// Write test data to file if needed
if tt.configPath == tmpFile.Name() {
content := ""
for _, line := range tt.blacklistLines {
content += line + "\n"
}
if err := os.WriteFile(tmpFile.Name(), []byte(content), 0o644); err != nil {
t.Fatalf("Failed to write to temporary file: %v", err)
}
}
// Call the function
err := LoadBlacklist()
// Check results
if (err != nil) != tt.wantErr {
t.Errorf("LoadBlacklist() error = %v, wantErr %v", err, tt.wantErr)
return
}
if !tt.wantErr && len(Blacklist) != tt.expectedLen {
t.Errorf("LoadBlacklist() loaded %d entries, want %d", len(Blacklist), tt.expectedLen)
}
})
}
}
// TestIsBlacklistedIntegration tests the integration between LoadBlacklist and IsBlacklisted
func TestIsBlacklistedIntegration(t *testing.T) {
// Save original blacklist to restore after test
originalBlacklist := Blacklist
originalConfigPath := config.CONFIG.BlacklistPath
defer func() {
Blacklist = originalBlacklist
config.CONFIG.BlacklistPath = originalConfigPath
}()
// Create a temporary blacklist file for testing
tmpFile, err := os.CreateTemp("", "blacklist-*.txt")
if err != nil {
t.Fatalf("Failed to create temporary file: %v", err)
}
defer os.Remove(tmpFile.Name())
// Write test patterns to the blacklist file
blacklistContent := `# Test blacklist file
example\.com
malicious\.org
/phishing
.*\.evil\.com
\w+@spam\.com
`
if err := os.WriteFile(tmpFile.Name(), []byte(blacklistContent), 0o644); err != nil {
t.Fatalf("Failed to write to temporary file: %v", err)
}
// Set up the test
Blacklist = nil
config.CONFIG.BlacklistPath = tmpFile.Name()
// Load the blacklist
if err := LoadBlacklist(); err != nil {
t.Fatalf("LoadBlacklist() failed: %v", err)
}
// Test URLs against the loaded blacklist
tests := []struct {
url string
expected bool
}{
{"https://example.com", true},
{"https://safe-site.com", false},
{"https://malicious.org/path", true},
{"https://example.org/phishing", true},
{"https://subdomain.evil.com", true},
{"https://safe-site.com/safe-path", false},
{"mailto:user@spam.com", true},
}
for _, tt := range tests {
result := IsBlacklisted(tt.url)
if result != tt.expected {
t.Errorf("IsBlacklisted(%q) = %v, want %v", tt.url, result, tt.expected)
}
}
}