2
0
Files
logikonline 7d852159aa
Some checks failed
Build and Release / Create Release (push) Has been skipped
Build and Release / Unit Tests (push) Successful in 3m20s
Build and Release / Lint (push) Failing after 4m55s
Build and Release / Build Binaries (amd64, windows, windows-latest) (push) Has been skipped
Build and Release / Build Binaries (amd64, linux, linux-latest) (push) Has been skipped
Build and Release / Build Binaries (amd64, darwin, macos-latest) (push) Has been skipped
Build and Release / Build Binaries (arm64, darwin, macos-latest) (push) Has been skipped
Build and Release / Build Binaries (arm64, linux, linux-latest) (push) Has been skipped
Build and Release / Integration Tests (PostgreSQL) (push) Successful in 4m59s
Server fixes
2026-01-17 01:59:38 -05:00

393 lines
13 KiB
Go

// Copyright 2026 MarketAlly. All rights reserved.
// SPDX-License-Identifier: MIT
package secretscan
import "regexp"
// Severity represents the severity level of a detected secret
type Severity string
const (
SeverityCritical Severity = "critical"
SeverityHigh Severity = "high"
SeverityMedium Severity = "medium"
SeverityLow Severity = "low"
)
// Category represents the category of a detected secret
type Category string
const (
CategoryAPIKey Category = "api-key"
CategoryPrivateKey Category = "private-key"
CategoryPassword Category = "password"
CategoryToken Category = "token"
CategoryCertificate Category = "certificate"
CategoryConnectionString Category = "connection-string"
CategoryCredential Category = "credential"
CategorySecret Category = "secret"
)
// Pattern represents a secret detection pattern
type Pattern struct {
ID string
Name string
Description string
Regex *regexp.Regexp
Severity Severity
Category Category
FalsePositiveRegexes []*regexp.Regexp
}
// builtinPatterns contains all built-in secret detection patterns
var builtinPatterns = []Pattern{
// ============================================
// PRIVATE KEYS (Critical)
// ============================================
{
ID: "private-key-rsa",
Name: "RSA Private Key",
Description: "RSA private key in PEM format",
Regex: regexp.MustCompile(`-----BEGIN (?:RSA )?PRIVATE KEY-----[\s\S]*?-----END (?:RSA )?PRIVATE KEY-----`),
Severity: SeverityCritical,
Category: CategoryPrivateKey,
},
{
ID: "private-key-openssh",
Name: "OpenSSH Private Key",
Description: "OpenSSH private key",
Regex: regexp.MustCompile(`-----BEGIN OPENSSH PRIVATE KEY-----[\s\S]*?-----END OPENSSH PRIVATE KEY-----`),
Severity: SeverityCritical,
Category: CategoryPrivateKey,
},
{
ID: "private-key-ec",
Name: "EC Private Key",
Description: "Elliptic Curve private key",
Regex: regexp.MustCompile(`-----BEGIN EC PRIVATE KEY-----[\s\S]*?-----END EC PRIVATE KEY-----`),
Severity: SeverityCritical,
Category: CategoryPrivateKey,
},
{
ID: "private-key-dsa",
Name: "DSA Private Key",
Description: "DSA private key",
Regex: regexp.MustCompile(`-----BEGIN DSA PRIVATE KEY-----[\s\S]*?-----END DSA PRIVATE KEY-----`),
Severity: SeverityCritical,
Category: CategoryPrivateKey,
},
{
ID: "private-key-pgp",
Name: "PGP Private Key",
Description: "PGP/GPG private key block",
Regex: regexp.MustCompile(`-----BEGIN PGP PRIVATE KEY BLOCK-----[\s\S]*?-----END PGP PRIVATE KEY BLOCK-----`),
Severity: SeverityCritical,
Category: CategoryPrivateKey,
},
// ============================================
// AWS (Critical)
// ============================================
{
ID: "aws-access-key",
Name: "AWS Access Key ID",
Description: "Amazon Web Services access key identifier",
Regex: regexp.MustCompile(`\b(A3T[A-Z0-9]|AKIA|AGPA|AIDA|AROA|AIPA|ANPA|ANVA|ASIA)[A-Z0-9]{16}\b`),
Severity: SeverityCritical,
Category: CategoryAPIKey,
},
{
ID: "aws-mws-key",
Name: "AWS MWS Key",
Description: "Amazon Marketplace Web Service key",
Regex: regexp.MustCompile(`(?i)amzn\.mws\.[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}`),
Severity: SeverityCritical,
Category: CategoryAPIKey,
},
// ============================================
// GOOGLE / GCP (Critical)
// ============================================
{
ID: "gcp-api-key",
Name: "Google API Key",
Description: "Google Cloud Platform API key",
Regex: regexp.MustCompile(`AIza[0-9A-Za-z_-]{35}`),
Severity: SeverityCritical,
Category: CategoryAPIKey,
},
{
ID: "gcp-service-account",
Name: "GCP Service Account",
Description: "Google Cloud service account key file",
Regex: regexp.MustCompile(`"type"\s*:\s*"service_account"[\s\S]*?"private_key"`),
Severity: SeverityCritical,
Category: CategoryPrivateKey,
},
// ============================================
// AZURE (Critical)
// ============================================
{
ID: "azure-connection-string",
Name: "Azure Connection String",
Description: "Azure service connection string",
Regex: regexp.MustCompile(`(?i)DefaultEndpointsProtocol=https?;AccountName=[^;]+;AccountKey=[A-Za-z0-9/+=]+`),
Severity: SeverityCritical,
Category: CategoryConnectionString,
},
// ============================================
// GITHUB (High)
// ============================================
{
ID: "github-token",
Name: "GitHub Token",
Description: "GitHub personal access token or OAuth token",
Regex: regexp.MustCompile(`\b(ghp|gho|ghu|ghs|ghr)_[A-Za-z0-9]{36,}\b`),
Severity: SeverityHigh,
Category: CategoryToken,
},
// ============================================
// GITLAB (High)
// ============================================
{
ID: "gitlab-token",
Name: "GitLab Token",
Description: "GitLab personal access token",
Regex: regexp.MustCompile(`\bglpat-[A-Za-z0-9_-]{20,}\b`),
Severity: SeverityHigh,
Category: CategoryToken,
},
// ============================================
// STRIPE (Critical)
// ============================================
{
ID: "stripe-secret-key",
Name: "Stripe Secret Key",
Description: "Stripe API secret key",
Regex: regexp.MustCompile(`\bsk_live_[0-9a-zA-Z]{24,}\b`),
Severity: SeverityCritical,
Category: CategoryAPIKey,
},
{
ID: "stripe-test-key",
Name: "Stripe Test Key",
Description: "Stripe API test key (still sensitive)",
Regex: regexp.MustCompile(`\bsk_test_[0-9a-zA-Z]{24,}\b`),
Severity: SeverityMedium,
Category: CategoryAPIKey,
},
// ============================================
// SLACK (High)
// ============================================
{
ID: "slack-token",
Name: "Slack Token",
Description: "Slack API token",
Regex: regexp.MustCompile(`\bxox[baprs]-[0-9]{10,13}-[0-9]{10,13}[a-zA-Z0-9-]*\b`),
Severity: SeverityHigh,
Category: CategoryToken,
},
{
ID: "slack-webhook",
Name: "Slack Webhook URL",
Description: "Slack incoming webhook URL",
Regex: regexp.MustCompile(`https://hooks\.slack\.com/services/T[A-Z0-9]+/B[A-Z0-9]+/[A-Za-z0-9]+`),
Severity: SeverityHigh,
Category: CategoryCredential,
},
// ============================================
// TWILIO (High)
// ============================================
{
ID: "twilio-api-key",
Name: "Twilio API Key",
Description: "Twilio API key SID",
Regex: regexp.MustCompile(`\bSK[0-9a-fA-F]{32}\b`),
Severity: SeverityHigh,
Category: CategoryAPIKey,
},
// ============================================
// SENDGRID (High)
// ============================================
{
ID: "sendgrid-api-key",
Name: "SendGrid API Key",
Description: "SendGrid email API key",
Regex: regexp.MustCompile(`\bSG\.[A-Za-z0-9_-]{22}\.[A-Za-z0-9_-]{43}\b`),
Severity: SeverityHigh,
Category: CategoryAPIKey,
},
// ============================================
// NPM (High)
// ============================================
{
ID: "npm-token",
Name: "NPM Access Token",
Description: "NPM registry access token",
Regex: regexp.MustCompile(`\bnpm_[A-Za-z0-9]{36}\b`),
Severity: SeverityHigh,
Category: CategoryToken,
},
// ============================================
// DATABASE CONNECTION STRINGS (Critical)
// ============================================
{
ID: "postgres-uri",
Name: "PostgreSQL Connection URI",
Description: "PostgreSQL connection string with credentials",
Regex: regexp.MustCompile(`(?i)postgres(?:ql)?://[^:]+:[^@]+@[^/]+/[^\s"']+`),
Severity: SeverityCritical,
Category: CategoryConnectionString,
},
{
ID: "mysql-uri",
Name: "MySQL Connection URI",
Description: "MySQL connection string with credentials",
Regex: regexp.MustCompile(`(?i)mysql://[^:]+:[^@]+@[^/]+/[^\s"']+`),
Severity: SeverityCritical,
Category: CategoryConnectionString,
},
{
ID: "mongodb-uri",
Name: "MongoDB Connection URI",
Description: "MongoDB connection string with credentials",
Regex: regexp.MustCompile(`(?i)mongodb(?:\+srv)?://[^:]+:[^@]+@[^/]+`),
Severity: SeverityCritical,
Category: CategoryConnectionString,
},
// ============================================
// GENERIC PASSWORDS (High)
// ============================================
{
ID: "password-assignment",
Name: "Password Assignment",
Description: "Hardcoded password in code",
Regex: regexp.MustCompile(`(?i)(?:password|passwd|pwd|secret|api_?key|auth_?token|access_?token)\s*[:=]\s*['"][^'"]{8,}['"]`),
Severity: SeverityHigh,
Category: CategoryPassword,
FalsePositiveRegexes: []*regexp.Regexp{
regexp.MustCompile(`\$\{.*\}`), // Template variables
regexp.MustCompile(`process\.env`), // Environment references
regexp.MustCompile(`\{\{.*\}\}`), // Handlebars/mustache
regexp.MustCompile(`<.*>`), // Placeholder text
regexp.MustCompile(`(?i)example`), // Example text
regexp.MustCompile(`(?i)placeholder`),
},
},
// ============================================
// JWT (Medium)
// ============================================
{
ID: "jwt-token",
Name: "JSON Web Token",
Description: "JWT token (may contain sensitive claims)",
Regex: regexp.MustCompile(`\beyJ[A-Za-z0-9_-]*\.eyJ[A-Za-z0-9_-]*\.[A-Za-z0-9_-]*`),
Severity: SeverityMedium,
Category: CategoryToken,
},
// ============================================
// DISCORD (High)
// ============================================
{
ID: "discord-token",
Name: "Discord Bot Token",
Description: "Discord bot or user token",
Regex: regexp.MustCompile(`[MN][A-Za-z\d]{23,}\.[\w-]{6}\.[\w-]{27}`),
Severity: SeverityHigh,
Category: CategoryToken,
},
{
ID: "discord-webhook",
Name: "Discord Webhook URL",
Description: "Discord webhook URL",
Regex: regexp.MustCompile(`https://discord(?:app)?\.com/api/webhooks/[0-9]+/[A-Za-z0-9_-]+`),
Severity: SeverityHigh,
Category: CategoryCredential,
},
// ============================================
// TELEGRAM (High)
// ============================================
{
ID: "telegram-bot-token",
Name: "Telegram Bot Token",
Description: "Telegram Bot API token",
Regex: regexp.MustCompile(`\b[0-9]{8,10}:[A-Za-z0-9_-]{35}\b`),
Severity: SeverityHigh,
Category: CategoryToken,
},
// ============================================
// SHOPIFY (High)
// ============================================
{
ID: "shopify-token",
Name: "Shopify Access Token",
Description: "Shopify private app or custom app token",
Regex: regexp.MustCompile(`shpat_[a-fA-F0-9]{32}`),
Severity: SeverityHigh,
Category: CategoryToken,
},
// ============================================
// HEROKU (High)
// ============================================
{
ID: "heroku-api-key",
Name: "Heroku API Key",
Description: "Heroku platform API key",
Regex: regexp.MustCompile(`(?i)heroku.*['\"][0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}['\"]`),
Severity: SeverityHigh,
Category: CategoryAPIKey,
},
}
// genericFalsePositivePatterns are patterns that indicate false positives across all detections
var genericFalsePositivePatterns = []*regexp.Regexp{
regexp.MustCompile(`^[xX]+$`), // All x's (placeholder)
regexp.MustCompile(`^[0]+$`), // All zeros
regexp.MustCompile(`(?i)example`), // Contains "example"
regexp.MustCompile(`(?i)sample`), // Contains "sample"
regexp.MustCompile(`(?i)dummy`), // Contains "dummy"
regexp.MustCompile(`(?i)placeholder`), // Contains "placeholder"
regexp.MustCompile(`(?i)your[_-]?(api[_-]?)?key`), // "your_key", "your_api_key", etc.
regexp.MustCompile(`__[A-Z_]+__`), // Python dunder-like placeholders
}
// GetBuiltinPatterns returns all built-in secret detection patterns
func GetBuiltinPatterns() []Pattern {
return builtinPatterns
}
// IsFalsePositive checks if a match is a false positive
func IsFalsePositive(match string, pattern *Pattern) bool {
// Check pattern-specific false positives
for _, fp := range pattern.FalsePositiveRegexes {
if fp.MatchString(match) {
return true
}
}
// Check generic false positives
for _, fp := range genericFalsePositivePatterns {
if fp.MatchString(match) {
return true
}
}
return false
}