Skip to content

Commit 2244fb2

Browse files
committed
Add detection for:
Azure credentials Google Cloud credentials SSH keys in different formats API keys from more providers (Stripe, Twilio, etc.) Connection strings for various databases
1 parent e852039 commit 2244fb2

3 files changed

Lines changed: 192 additions & 4 deletions

File tree

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,3 +28,4 @@ HACKTOBERFEST_SETUP.md
2828
PR_DESCRIPTION.md
2929
commit
3030
test.txt
31+
AGENTS.md

internal/scrubber/scrubber.go

Lines changed: 190 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,50 @@ var (
4444
Redact: "${1}=\"[REDACTED_AWS_SECRET]\"",
4545
},
4646

47+
// Azure Credentials
48+
{
49+
Name: "Azure Client Secret",
50+
Pattern: regexp.MustCompile(`(?i)(azure[_-]?client[_-]?secret|AZURE_CLIENT_SECRET)\s*[=:]\s*["\']?([a-zA-Z0-9_\-\.~]{20,})["\']?`),
51+
Redact: "${1}=\"[REDACTED_AZURE_CLIENT_SECRET]\"",
52+
},
53+
{
54+
Name: "Azure Subscription Key",
55+
Pattern: regexp.MustCompile(`(?i)(azure[_-]?subscription[_-]?key|AZURE_SUBSCRIPTION_KEY)\s*[=:]\s*["\']?([a-zA-Z0-9]{32})["\']?`),
56+
Redact: "${1}=\"[REDACTED_AZURE_SUBSCRIPTION_KEY]\"",
57+
},
58+
{
59+
Name: "Azure Storage Key",
60+
Pattern: regexp.MustCompile(`(?i)(azure[_-]?storage[_-]?key|AZURE_STORAGE_KEY|AccountKey)\s*[=:]\s*["\']?([a-zA-Z0-9/+=]{88})["\']?`),
61+
Redact: "${1}=\"[REDACTED_AZURE_STORAGE_KEY]\"",
62+
},
63+
{
64+
Name: "Azure Service Principal",
65+
Pattern: regexp.MustCompile(`(?i)(azure[_-]?service[_-]?principal|AZURE_SERVICE_PRINCIPAL)\s*[=:]\s*["\']?([a-f0-9-]{36})["\']?`),
66+
Redact: "${1}=\"[REDACTED_AZURE_SERVICE_PRINCIPAL]\"",
67+
},
68+
69+
// Google Cloud Credentials
70+
{
71+
Name: "Google Cloud Service Account Key",
72+
Pattern: regexp.MustCompile(`(?i)(gcp[_-]?service[_-]?account[_-]?key|GOOGLE_APPLICATION_CREDENTIALS)\s*[=:]\s*["\']?([a-zA-Z0-9_\-\.@]+\.json)["\']?`),
73+
Redact: "${1}=\"[REDACTED_GCP_SA_KEY]\"",
74+
},
75+
{
76+
Name: "Google Cloud API Key",
77+
Pattern: regexp.MustCompile(`(?i)(gcp[_-]?api[_-]?key|GOOGLE_CLOUD_API_KEY)\s*[=:]\s*["\']?([a-zA-Z0-9_\-]{39})["\']?`),
78+
Redact: "${1}=\"[REDACTED_GCP_API_KEY]\"",
79+
},
80+
{
81+
Name: "Google Cloud OAuth Client",
82+
Pattern: regexp.MustCompile(`(?i)(gcp[_-]?oauth[_-]?client[_-]?secret|GOOGLE_OAUTH_CLIENT_SECRET)\s*[=:]\s*["\']?([a-zA-Z0-9_\-]{24})["\']?`),
83+
Redact: "${1}=\"[REDACTED_GCP_OAUTH_SECRET]\"",
84+
},
85+
{
86+
Name: "Google Cloud JSON Credentials",
87+
Pattern: regexp.MustCompile(`(?s)"type":\s*"service_account".*?"private_key":\s*"-----BEGIN PRIVATE KEY-----.*?-----END PRIVATE KEY-----`),
88+
Redact: "\"type\": \"service_account\",\n\"private_key\": \"[REDACTED_GCP_PRIVATE_KEY]\"",
89+
},
90+
4791
// Database Credentials
4892
{
4993
Name: "Database URL with Password",
@@ -88,12 +132,155 @@ var (
88132
Redact: "${1}=\"[REDACTED_SLACK_TOKEN]\"",
89133
},
90134

91-
// Private Keys
135+
// Payment & Communication APIs
136+
{
137+
Name: "Stripe API Key",
138+
Pattern: regexp.MustCompile(`(?i)(stripe[_-]?api[_-]?key|STRIPE_API_KEY)\s*[=:]\s*["\']?(sk_live_[a-zA-Z0-9]{24})["\']?`),
139+
Redact: "${1}=\"[REDACTED_STRIPE_KEY]\"",
140+
},
141+
{
142+
Name: "Stripe Publishable Key",
143+
Pattern: regexp.MustCompile(`(?i)(stripe[_-]?publishable[_-]?key|STRIPE_PUBLISHABLE_KEY)\s*[=:]\s*["\']?(pk_live_[a-zA-Z0-9]{24})["\']?`),
144+
Redact: "${1}=\"[REDACTED_STRIPE_PUBLISHABLE_KEY]\"",
145+
},
146+
{
147+
Name: "Twilio API Key",
148+
Pattern: regexp.MustCompile(`(?i)(twilio[_-]?api[_-]?key|TWILIO_API_KEY)\s*[=:]\s*["\']?(SK[a-f0-9]{32})["\']?`),
149+
Redact: "${1}=\"[REDACTED_TWILIO_API_KEY]\"",
150+
},
151+
{
152+
Name: "Twilio Auth Token",
153+
Pattern: regexp.MustCompile(`(?i)(twilio[_-]?auth[_-]?token|TWILIO_AUTH_TOKEN)\s*[=:]\s*["\']?([a-f0-9]{32})["\']?`),
154+
Redact: "${1}=\"[REDACTED_TWILIO_AUTH_TOKEN]\"",
155+
},
156+
{
157+
Name: "Twilio Account SID",
158+
Pattern: regexp.MustCompile(`(?i)(twilio[_-]?account[_-]?sid|TWILIO_ACCOUNT_SID)\s*[=:]\s*["\']?(AC[a-f0-9]{32})["\']?`),
159+
Redact: "${1}=\"[REDACTED_TWILIO_ACCOUNT_SID]\"",
160+
},
161+
162+
// Cloud & Infrastructure APIs
163+
{
164+
Name: "DigitalOcean API Key",
165+
Pattern: regexp.MustCompile(`(?i)(digitalocean[_-]?api[_-]?key|DIGITALOCEAN_API_KEY)\s*[=:]\s*["\']?([a-f0-9]{64})["\']?`),
166+
Redact: "${1}=\"[REDACTED_DIGITALOCEAN_KEY]\"",
167+
},
168+
{
169+
Name: "Heroku API Key",
170+
Pattern: regexp.MustCompile(`(?i)(heroku[_-]?api[_-]?key|HEROKU_API_KEY)\s*[=:]\s*["\']?([a-f0-9]{8}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{12})["\']?`),
171+
Redact: "${1}=\"[REDACTED_HEROKU_KEY]\"",
172+
},
173+
{
174+
Name: "Vercel API Key",
175+
Pattern: regexp.MustCompile(`(?i)(vercel[_-]?api[_-]?key|VERCEL_API_KEY)\s*[=:]\s*["\']?([a-zA-Z0-9_\-]{24})["\']?`),
176+
Redact: "${1}=\"[REDACTED_VERCEL_KEY]\"",
177+
},
178+
{
179+
Name: "Netlify API Key",
180+
Pattern: regexp.MustCompile(`(?i)(netlify[_-]?api[_-]?key|NETLIFY_API_KEY)\s*[=:]\s*["\']?([a-zA-Z0-9_\-]{40})["\']?`),
181+
Redact: "${1}=\"[REDACTED_NETLIFY_KEY]\"",
182+
},
183+
184+
// Database & Analytics APIs
92185
{
93-
Name: "Private Key",
94-
Pattern: regexp.MustCompile(`(?s)(-----BEGIN (?:RSA |EC |DSA |OPENSSH )?PRIVATE KEY-----).*?(-----END (?:RSA |EC |DSA |OPENSSH )?PRIVATE KEY-----)`),
186+
Name: "MongoDB Atlas API Key",
187+
Pattern: regexp.MustCompile(`(?i)(mongodb[_-]?api[_-]?key|MONGODB_API_KEY)\s*[=:]\s*["\']?([a-f0-9]{24}-[a-f0-9]{24})["\']?`),
188+
Redact: "${1}=\"[REDACTED_MONGODB_API_KEY]\"",
189+
},
190+
{
191+
Name: "SendGrid API Key",
192+
Pattern: regexp.MustCompile(`(?i)(sendgrid[_-]?api[_-]?key|SENDGRID_API_KEY)\s*[=:]\s*["\']?(SG\.[a-zA-Z0-9_\-\.]{22,}\.[a-zA-Z0-9_\-\.]{43})["\']?`),
193+
Redact: "${1}=\"[REDACTED_SENDGRID_KEY]\"",
194+
},
195+
{
196+
Name: "Mailgun API Key",
197+
Pattern: regexp.MustCompile(`(?i)(mailgun[_-]?api[_-]?key|MAILGUN_API_KEY)\s*[=:]\s*["\']?(key-[a-f0-9]{32})["\']?`),
198+
Redact: "${1}=\"[REDACTED_MAILGUN_KEY]\"",
199+
},
200+
201+
// Social & Auth APIs
202+
{
203+
Name: "Facebook App Secret",
204+
Pattern: regexp.MustCompile(`(?i)(facebook[_-]?app[_-]?secret|FACEBOOK_APP_SECRET)\s*[=:]\s*["\']?([a-f0-9]{32})["\']?`),
205+
Redact: "${1}=\"[REDACTED_FACEBOOK_SECRET]\"",
206+
},
207+
{
208+
Name: "Twitter API Key",
209+
Pattern: regexp.MustCompile(`(?i)(twitter[_-]?api[_-]?key|TWITTER_API_KEY)\s*[=:]\s*["\']?([a-zA-Z0-9]{25})["\']?`),
210+
Redact: "${1}=\"[REDACTED_TWITTER_API_KEY]\"",
211+
},
212+
{
213+
Name: "Twitter API Secret",
214+
Pattern: regexp.MustCompile(`(?i)(twitter[_-]?api[_-]?secret|TWITTER_API_SECRET)\s*[=:]\s*["\']?([a-zA-Z0-9]{50})["\']?`),
215+
Redact: "${1}=\"[REDACTED_TWITTER_API_SECRET]\"",
216+
},
217+
{
218+
Name: "LinkedIn Client Secret",
219+
Pattern: regexp.MustCompile(`(?i)(linkedin[_-]?client[_-]?secret|LINKEDIN_CLIENT_SECRET)\s*[=:]\s*["\']?([a-zA-Z0-9]{16})["\']?`),
220+
Redact: "${1}=\"[REDACTED_LINKEDIN_SECRET]\"",
221+
},
222+
223+
// SSH Keys and Private Keys in various formats
224+
{
225+
Name: "RSA Private Key",
226+
Pattern: regexp.MustCompile(`(?s)(-----BEGIN RSA PRIVATE KEY-----).*?(-----END RSA PRIVATE KEY-----)`),
227+
Redact: "${1}\n[REDACTED_RSA_PRIVATE_KEY]\n${2}",
228+
},
229+
{
230+
Name: "EC Private Key",
231+
Pattern: regexp.MustCompile(`(?s)(-----BEGIN EC PRIVATE KEY-----).*?(-----END EC PRIVATE KEY-----)`),
232+
Redact: "${1}\n[REDACTED_EC_PRIVATE_KEY]\n${2}",
233+
},
234+
{
235+
Name: "DSA Private Key",
236+
Pattern: regexp.MustCompile(`(?s)(-----BEGIN DSA PRIVATE KEY-----).*?(-----END DSA PRIVATE KEY-----)`),
237+
Redact: "${1}\n[REDACTED_DSA_PRIVATE_KEY]\n${2}",
238+
},
239+
{
240+
Name: "OpenSSH Private Key",
241+
Pattern: regexp.MustCompile(`(?s)(-----BEGIN OPENSSH PRIVATE KEY-----).*?(-----END OPENSSH PRIVATE KEY-----)`),
242+
Redact: "${1}\n[REDACTED_OPENSSH_PRIVATE_KEY]\n${2}",
243+
},
244+
{
245+
Name: "PKCS#8 Private Key",
246+
Pattern: regexp.MustCompile(`(?s)(-----BEGIN PRIVATE KEY-----).*?(-----END PRIVATE KEY-----)`),
95247
Redact: "${1}\n[REDACTED_PRIVATE_KEY]\n${2}",
96248
},
249+
{
250+
Name: "PGP Private Key",
251+
Pattern: regexp.MustCompile(`(?s)(-----BEGIN PGP PRIVATE KEY BLOCK-----).*?(-----END PGP PRIVATE KEY BLOCK-----)`),
252+
Redact: "${1}\n[REDACTED_PGP_PRIVATE_KEY]\n${2}",
253+
},
254+
{
255+
Name: "SSH Public Key (RSA)",
256+
Pattern: regexp.MustCompile(`(?i)(ssh[_-]?rsa[_-]?public[_-]?key|SSH_RSA_PUBLIC_KEY)\s*[=:]\s*["\']?(ssh-rsa [a-zA-Z0-9/+=]+ [a-zA-Z0-9._@-]+)["\']?`),
257+
Redact: "${1}=\"[REDACTED_SSH_RSA_PUBLIC_KEY]\"",
258+
},
259+
{
260+
Name: "SSH Public Key (ED25519)",
261+
Pattern: regexp.MustCompile(`(?i)(ssh[_-]?ed25519[_-]?public[_-]?key|SSH_ED25519_PUBLIC_KEY)\s*[=:]\s*["\']?(ssh-ed25519 [a-zA-Z0-9]+ [a-zA-Z0-9._@-]+)["\']?`),
262+
Redact: "${1}=\"[REDACTED_SSH_ED25519_PUBLIC_KEY]\"",
263+
},
264+
{
265+
Name: "SSH Public Key (ECDSA)",
266+
Pattern: regexp.MustCompile(`(?i)(ssh[_-]?ecdsa[_-]?public[_-]?key|SSH_ECDSA_PUBLIC_KEY)\s*[=:]\s*["\']?(ecdsa-sha2-[a-zA-Z0-9-]+ [a-zA-Z0-9/+=]+ [a-zA-Z0-9._@-]+)["\']?`),
267+
Redact: "${1}=\"[REDACTED_SSH_ECDSA_PUBLIC_KEY]\"",
268+
},
269+
{
270+
Name: "SSH Public Key (Generic)",
271+
Pattern: regexp.MustCompile(`(?i)(ssh[_-]?public[_-]?key|SSH_PUBLIC_KEY)\s*[=:]\s*["\']?(ssh-[a-zA-Z0-9-]+ [a-zA-Z0-9/+=]+ [a-zA-Z0-9._@-]+)["\']?`),
272+
Redact: "${1}=\"[REDACTED_SSH_PUBLIC_KEY]\"",
273+
},
274+
{
275+
Name: "SSH Authorized Keys",
276+
Pattern: regexp.MustCompile(`(?i)(ssh[_-]?authorized[_-]?keys|SSH_AUTHORIZED_KEYS)\s*[=:]\s*["\']?(ssh-[a-zA-Z0-9-]+ [a-zA-Z0-9/+=]+ [a-zA-Z0-9._@-]+)["\']?`),
277+
Redact: "${1}=\"[REDACTED_SSH_AUTHORIZED_KEYS]\"",
278+
},
279+
{
280+
Name: "SSH Private Key File Content",
281+
Pattern: regexp.MustCompile(`(?s)(-----BEGIN [A-Z ]+PRIVATE KEY-----\n)([A-Za-z0-9+/=\n]+)(\n-----END [A-Z ]+PRIVATE KEY-----)`),
282+
Redact: "${1}[REDACTED_SSH_PRIVATE_KEY_CONTENT]${3}",
283+
},
97284

98285
// JWT Tokens
99286
{

internal/scrubber/scrubber_test.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -134,7 +134,7 @@ ghijklmnopqrstuvwxyz
134134
if strings.Contains(result, "MIIEpAIBAAKCAQEA") || strings.Contains(result, "ghijklmnopqrstuvwxyz") {
135135
t.Errorf("ScrubDiff() failed to redact private key.\nOutput: %s", result)
136136
}
137-
if !strings.Contains(result, "[REDACTED_PRIVATE_KEY]") {
137+
if !strings.Contains(result, "[REDACTED_RSA_PRIVATE_KEY]") {
138138
t.Errorf("ScrubDiff() did not add redaction marker.\nOutput: %s", result)
139139
}
140140
}

0 commit comments

Comments
 (0)