Skip to content

Commit 4f2c483

Browse files
committed
feat: expand provider coverage — 40+ new providers across AI, payments, comms, auth, observability, cloud, and DB
1 parent c7d8160 commit 4f2c483

3 files changed

Lines changed: 202 additions & 33 deletions

File tree

internal/scan/apikeys.go

Lines changed: 45 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,8 +43,15 @@ var providerNamePatterns = []*regexp.Regexp{
4343
regexp.MustCompile(`(?i)ASSEMBLYAI`),
4444
regexp.MustCompile(`(?i)AI21`),
4545
regexp.MustCompile(`(?i)NVIDIA_NIM`),
46+
regexp.MustCompile(`(?i)STABILITY`), // Stability AI — image generation
47+
regexp.MustCompile(`(?i)WANDB`), // Weights & Biases — ML experiment tracking
48+
regexp.MustCompile(`(?i)TAVILY`), // Tavily — AI search, common in agents
49+
regexp.MustCompile(`(?i)LANGCHAIN`), // LangSmith (LangChain tracing)
50+
regexp.MustCompile(`(?i)(^|_)FAL_`), // fal.ai — (^|_) anchor avoids mid-word false positives
4651
// Secrets managers
4752
regexp.MustCompile(`(?i)DOPPLER`),
53+
regexp.MustCompile(`(?i)VAULT`), // HashiCorp Vault
54+
regexp.MustCompile(`(?i)INFISICAL`), // Infisical secrets manager
4855
// Google AI (Gemini, Vertex AI, PaLM)
4956
regexp.MustCompile(`(?i)GEMINI`),
5057
regexp.MustCompile(`(?i)VERTEX`),
@@ -59,6 +66,10 @@ var providerNamePatterns = []*regexp.Regexp{
5966
regexp.MustCompile(`(?i)BRAINTREE`),
6067
regexp.MustCompile(`(?i)PAYPAL`),
6168
regexp.MustCompile(`(?i)SQUARE`),
69+
regexp.MustCompile(`(?i)ADYEN`), // Adyen — enterprise payments
70+
regexp.MustCompile(`(?i)RAZORPAY`), // Razorpay — dominant in South/SE Asia
71+
regexp.MustCompile(`(?i)MOLLIE`), // Mollie — dominant in EU
72+
regexp.MustCompile(`(?i)PADDLE`), // Paddle — SaaS subscription billing
6273
// Communication / messaging
6374
regexp.MustCompile(`(?i)TWILIO`),
6475
regexp.MustCompile(`(?i)SENDGRID`),
@@ -68,31 +79,59 @@ var providerNamePatterns = []*regexp.Regexp{
6879
regexp.MustCompile(`(?i)SPARKPOST`),
6980
regexp.MustCompile(`(?i)SLACK`),
7081
regexp.MustCompile(`(?i)DISCORD`),
82+
regexp.MustCompile(`(?i)VONAGE`), // Vonage/Nexmo — SMS/voice
83+
regexp.MustCompile(`(?i)KLAVIYO`), // Klaviyo — e-commerce email
84+
regexp.MustCompile(`(?i)MAILCHIMP`), // Mailchimp — customer lists
85+
regexp.MustCompile(`(?i)CUSTOMERIO`), // Customer.io — behavioral marketing
86+
regexp.MustCompile(`(?i)BREVO`), // Brevo/Sendinblue — EU email
7187
// Auth / identity
7288
regexp.MustCompile(`(?i)OKTA`),
7389
regexp.MustCompile(`(?i)AUTH0`),
90+
regexp.MustCompile(`(?i)CLERK`), // Clerk — popular Next.js auth
91+
regexp.MustCompile(`(?i)WORKOS`), // WorkOS — enterprise SSO
7492
// Observability
7593
regexp.MustCompile(`(?i)DATADOG`),
7694
regexp.MustCompile(`(?i)SENTRY`),
95+
regexp.MustCompile(`(?i)NEW_RELIC`), // New Relic — APM/log exfil
96+
regexp.MustCompile(`(?i)GRAFANA`), // Grafana Cloud
97+
regexp.MustCompile(`(?i)HONEYCOMB`), // Honeycomb — observability
7798
// Cloud / hosting platforms
7899
regexp.MustCompile(`(?i)VERCEL`),
79100
regexp.MustCompile(`(?i)NETLIFY`),
80101
regexp.MustCompile(`(?i)CLOUDFLARE`),
81102
regexp.MustCompile(`(?i)HEROKU`),
82103
regexp.MustCompile(`(?i)RAILWAY`),
83-
regexp.MustCompile(`(?i)(^|_)FLY_`), // (^|_) anchor avoids mid-word false positives
104+
regexp.MustCompile(`(?i)(^|_)FLY_`), // (^|_) anchor avoids mid-word false positives
105+
regexp.MustCompile(`(?i)DIGITALOCEAN`), // DigitalOcean — full infra control
106+
regexp.MustCompile(`(?i)LINODE`), // Linode/Akamai — full infra control
107+
regexp.MustCompile(`(?i)RENDER`), // Render — deploy platform
108+
regexp.MustCompile(`(?i)PULUMI`), // Pulumi — IaC state
109+
regexp.MustCompile(`(?i)CLOUDINARY`), // Cloudinary — media storage
84110
// Source control
85111
regexp.MustCompile(`(?i)GITHUB`),
86112
regexp.MustCompile(`(?i)GITLAB`),
87113
regexp.MustCompile(`(?i)BITBUCKET`),
114+
regexp.MustCompile(`(?i)CIRCLECI`), // CircleCI — CI supply chain
88115
// Productivity / project tools
89116
regexp.MustCompile(`(?i)(^|_)LINEAR_`), // (^|_) anchor avoids mid-word false positives
90117
regexp.MustCompile(`(?i)NOTION`),
91118
regexp.MustCompile(`(?i)AIRTABLE`),
119+
regexp.MustCompile(`(?i)ATLASSIAN`), // Atlassian/Jira — project data, PII
120+
regexp.MustCompile(`(?i)JIRA`), // Jira
121+
regexp.MustCompile(`(?i)ZENDESK`), // Zendesk — customer support PII
122+
regexp.MustCompile(`(?i)INTERCOM`), // Intercom — customer chat PII
123+
regexp.MustCompile(`(?i)HUBSPOT`), // HubSpot CRM — customer PII
124+
regexp.MustCompile(`(?i)SALESFORCE`), // Salesforce — enterprise CRM
125+
regexp.MustCompile(`(?i)SHOPIFY`), // Shopify — store orders, customer data
126+
regexp.MustCompile(`(?i)SEGMENT`), // Segment — all customer behavioral events
127+
regexp.MustCompile(`(?i)ALGOLIA`), // Algolia — search index admin
92128
// Database-as-a-service
93129
regexp.MustCompile(`(?i)SUPABASE`),
94130
regexp.MustCompile(`(?i)(^|_)NEON_`), // (^|_) anchor avoids mid-word false positives
95131
regexp.MustCompile(`(?i)PLANETSCALE`),
132+
regexp.MustCompile(`(?i)TURSO`), // Turso — SQLite-at-edge
133+
regexp.MustCompile(`(?i)UPSTASH`), // Upstash — serverless Redis/Kafka
134+
regexp.MustCompile(`(?i)ELASTIC`), // Elasticsearch/Elastic Cloud
96135
}
97136

98137
// credentialSuffixPatterns matches generic credential terms in env var names.
@@ -150,6 +189,11 @@ var valuePatterns = []valuePattern{
150189
{prefix: "ghu_", totalLen: 40, severity: models.SeverityHigh, providerTag: "GitHub user token"},
151190
{prefix: "ghs_", totalLen: 40, severity: models.SeverityHigh, providerTag: "GitHub app installation token"},
152191
{prefix: "ghr_", totalLen: 40, severity: models.SeverityHigh, providerTag: "GitHub refresh token"},
192+
// Tavily — tvly- prefix + 40 chars = 45 total.
193+
{prefix: "tvly-", totalLen: 45, severity: models.SeverityHigh, providerTag: "Tavily search"},
194+
// LangSmith — lsv2_pt_ (personal access) or lsv2_sk_ (service key) prefix + 40 chars.
195+
{prefix: "lsv2_pt_", totalLen: 48, severity: models.SeverityHigh, providerTag: "LangSmith API key"},
196+
{prefix: "lsv2_sk_", totalLen: 48, severity: models.SeverityHigh, providerTag: "LangSmith service key"},
153197
}
154198

155199
// credentialFiles is the list of credential files/dirs to check.

internal/scan/apikeys_test.go

Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,18 @@ func TestAPIKeyScanner_HighRiskEnvKeysContainsKnownKeys(t *testing.T) {
4444
"GITHUB_TOKEN",
4545
"STRIPE_SECRET_KEY",
4646
"DATABASE_URL",
47+
// New entries
48+
"STABILITY_API_KEY",
49+
"WANDB_API_KEY",
50+
"VAULT_TOKEN",
51+
"INFISICAL_TOKEN",
52+
"CLERK_SECRET_KEY",
53+
"DIGITALOCEAN_TOKEN",
54+
"PULUMI_ACCESS_TOKEN",
55+
"SHOPIFY_API_SECRET_KEY",
56+
"HUBSPOT_ACCESS_TOKEN",
57+
"TURSO_AUTH_TOKEN",
58+
"UPSTASH_REDIS_REST_TOKEN",
4759
}
4860
for _, key := range known {
4961
if !scan.HighRiskEnvKeys[key] {
@@ -387,6 +399,9 @@ func TestAPIKeyScanner_ValuePatterns(t *testing.T) {
387399
{"HuggingFace", "ML_MODEL_CRED", "hf_" + strings.Repeat("b", 34), "HIGH", "HuggingFace"},
388400
{"GitHub classic PAT", "WORK_GH_TOKEN", "ghp_" + strings.Repeat("c", 36), "HIGH", "GitHub"},
389401
{"Twilio SID", "CRED_SID", "SK" + strings.Repeat("f", 32), "UNCERTAIN", "Twilio"},
402+
{"Tavily", "SEARCH_KEY", "tvly-" + strings.Repeat("t", 40), "HIGH", "Tavily"},
403+
{"LangSmith personal token", "TRACE_KEY", "lsv2_pt_" + strings.Repeat("l", 40), "HIGH", "LangSmith"},
404+
{"LangSmith service key", "TRACE_SVC_KEY", "lsv2_sk_" + strings.Repeat("l", 40), "HIGH", "LangSmith"},
390405
}
391406

392407
for _, tc := range cases {
@@ -444,6 +459,11 @@ func TestAPIKeyScanner_NameRegex_AnchoredPatterns(t *testing.T) {
444459
shouldMatch: map[string]string{"XAI_API_KEY": "real-xai-key", "MY_XAI_KEY": "also-real"},
445460
shouldNotMatch: map[string]string{"PROXAI_ENDPOINT": "https://api.proxai.com", "RELAXAI_MODE": "true"},
446461
},
462+
{
463+
name: "FAL_",
464+
shouldMatch: map[string]string{"FAL_API_KEY": "real-fal-key", "MY_FAL_KEY": "also-real"},
465+
shouldNotMatch: map[string]string{"DEFAULT_CONFIG": "v", "HALFLIFE_COUNT": "v"},
466+
},
447467
}
448468

449469
for _, tc := range cases {
@@ -504,6 +524,56 @@ func TestAPIKeyScanner_NameRegex_NewProviders(t *testing.T) {
504524
{"ASSEMBLYAI_API_KEY", "aai-key-value"},
505525
{"AI21_API_KEY", "ai21-key-value"},
506526
{"NVIDIA_NIM_API_KEY", "nim-key-value"},
527+
// New AI/ML providers
528+
{"STABILITY_API_KEY", "stability-key-value"},
529+
{"WANDB_PROJECT_KEY", "wandb-key-value"},
530+
{"TAVILY_API_KEY", "tavily-key-value"},
531+
{"LANGCHAIN_API_KEY", "langchain-key-value"},
532+
{"AZURE_OPENAI_API_KEY", "azure-oai-key"},
533+
{"FAL_API_KEY", "fal-key-value"},
534+
// Secrets managers
535+
{"VAULT_API_TOKEN", "vault-key-value"},
536+
{"INFISICAL_API_TOKEN", "infisical-key-value"},
537+
// New payment providers
538+
{"ADYEN_API_KEY", "adyen-key-value"},
539+
{"RAZORPAY_SECRET_KEY", "razorpay-key-value"},
540+
{"MOLLIE_API_KEY", "mollie-key-value"},
541+
{"PADDLE_API_KEY", "paddle-key-value"},
542+
// New communication providers
543+
{"VONAGE_API_SECRET", "vonage-key-value"},
544+
{"KLAVIYO_API_KEY", "klaviyo-key-value"},
545+
{"MAILCHIMP_API_KEY", "mailchimp-key-value"},
546+
{"CUSTOMERIO_API_KEY", "customerio-key-value"},
547+
{"BREVO_API_KEY", "brevo-key-value"},
548+
// New auth providers
549+
{"CLERK_SECRET_KEY", "clerk-key-value"},
550+
{"WORKOS_API_KEY", "workos-key-value"},
551+
// New observability providers
552+
{"NEW_RELIC_LICENSE_KEY", "newrelic-key-value"},
553+
{"GRAFANA_API_KEY", "grafana-key-value"},
554+
{"HONEYCOMB_API_KEY", "honeycomb-key-value"},
555+
// New cloud / IaC providers
556+
{"DIGITALOCEAN_API_KEY", "do-key-value"},
557+
{"LINODE_API_TOKEN", "linode-key-value"},
558+
{"RENDER_API_KEY", "render-key-value"},
559+
{"PULUMI_ACCESS_TOKEN", "pulumi-key-value"},
560+
{"CLOUDINARY_API_SECRET", "cloudinary-key-value"},
561+
// New CI/CD
562+
{"CIRCLE_TOKEN", "circle-key-value"},
563+
// New dev tools / CRM
564+
{"ATLASSIAN_API_TOKEN", "atlassian-key-value"},
565+
{"JIRA_API_TOKEN", "jira-key-value"},
566+
{"ZENDESK_API_TOKEN", "zendesk-key-value"},
567+
{"INTERCOM_ACCESS_TOKEN", "intercom-key-value"},
568+
{"HUBSPOT_API_KEY", "hubspot-key-value"},
569+
{"SALESFORCE_CLIENT_SECRET", "sf-key-value"},
570+
{"SHOPIFY_API_SECRET_KEY", "shopify-key-value"},
571+
{"SEGMENT_WRITE_KEY", "segment-key-value"},
572+
{"ALGOLIA_API_KEY", "algolia-key-value"},
573+
// New database providers
574+
{"TURSO_AUTH_TOKEN", "turso-key-value"},
575+
{"UPSTASH_REDIS_REST_TOKEN", "upstash-key-value"},
576+
{"ELASTIC_API_KEY", "elastic-key-value"},
507577
}
508578

509579
for _, tc := range cases {

internal/scan/scan.go

Lines changed: 87 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -156,18 +156,25 @@ var K8SProdPatterns = []string{"prod", "production", "prd", "live"}
156156
// only the key name is used.
157157
var HighRiskEnvKeys = map[string]bool{
158158
// AI / ML inference
159-
"OPENAI_API_KEY": true,
160-
"ANTHROPIC_API_KEY": true,
161-
"COHERE_API_KEY": true,
162-
"MISTRAL_API_KEY": true,
163-
"REPLICATE_API_KEY": true,
164-
"HUGGINGFACE_TOKEN": true,
165-
"HF_TOKEN": true, // Hugging Face canonical short name (used by huggingface-hub)
166-
"TOGETHER_API_KEY": true,
167-
"GROQ_API_KEY": true,
168-
"VOYAGE_API_KEY": true,
169-
"ELEVEN_LABS_API_KEY": true,
170-
"PINECONE_API_KEY": true,
159+
"OPENAI_API_KEY": true,
160+
"ANTHROPIC_API_KEY": true,
161+
"COHERE_API_KEY": true,
162+
"MISTRAL_API_KEY": true,
163+
"REPLICATE_API_KEY": true,
164+
"HUGGINGFACE_TOKEN": true,
165+
"HF_TOKEN": true, // Hugging Face canonical short name (used by huggingface-hub)
166+
"TOGETHER_API_KEY": true,
167+
"GROQ_API_KEY": true,
168+
"VOYAGE_API_KEY": true,
169+
"ELEVEN_LABS_API_KEY": true,
170+
"PINECONE_API_KEY": true,
171+
"STABILITY_API_KEY": true, // Stability AI — pay-per-image generation
172+
"WANDB_API_KEY": true, // Weights & Biases — model/experiment data
173+
"TAVILY_API_KEY": true, // Tavily search — widely used in LangChain/LangGraph agents
174+
"LANGCHAIN_API_KEY": true, // LangSmith tracing (LangChain ecosystem)
175+
"AZURE_OPENAI_API_KEY": true, // Azure OpenAI — distinct from service principal creds
176+
"FAL_KEY": true, // fal.ai — GPU inference, financial risk
177+
"NVIDIA_API_KEY": true, // NVIDIA NIM — enterprise GPU inference
171178

172179
// Cloud: env-based credentials
173180
"AWS_ACCESS_KEY_ID": true,
@@ -178,44 +185,92 @@ var HighRiskEnvKeys = map[string]bool{
178185
"AZURE_CLIENT_ID": true,
179186
"AZURE_TENANT_ID": true,
180187

188+
// Secrets managers (key to all other secrets)
189+
"VAULT_TOKEN": true, // HashiCorp Vault — grants access to all managed secrets
190+
"OP_SERVICE_ACCOUNT_TOKEN": true, // 1Password Connect service account
191+
"OP_CONNECT_TOKEN": true, // 1Password Connect API token
192+
"INFISICAL_TOKEN": true, // Infisical secrets manager
193+
181194
// Source control & CI/CD
182195
"GITHUB_TOKEN": true,
183196
"GITLAB_TOKEN": true,
184197
"BITBUCKET_APP_PASSWORD": true,
185198
"NPM_TOKEN": true,
186199
"PYPI_API_TOKEN": true,
200+
"CIRCLE_TOKEN": true, // CircleCI — CI supply chain attack surface
187201

188202
// Payment
189203
"STRIPE_SECRET_KEY": true,
190204
"BRAINTREE_PRIVATE_KEY": true,
191205
"PAYPAL_CLIENT_SECRET": true,
192206
"SQUARE_ACCESS_TOKEN": true,
193-
194-
// Messaging & comms (can exfiltrate data at scale)
195-
"TWILIO_AUTH_TOKEN": true,
196-
"SENDGRID_API_KEY": true,
197-
"MAILGUN_API_KEY": true,
198-
"SLACK_BOT_TOKEN": true,
199-
"DISCORD_BOT_TOKEN": true,
207+
"ADYEN_API_KEY": true, // Adyen — enterprise e-commerce payments
208+
"RAZORPAY_KEY_SECRET": true, // Razorpay — dominant in South/SE Asia
209+
"MOLLIE_API_KEY": true, // Mollie — dominant in EU
210+
"PADDLE_API_KEY": true, // Paddle — SaaS billing
211+
212+
// Messaging & comms (can exfiltrate data or send spam at scale)
213+
"TWILIO_AUTH_TOKEN": true,
214+
"SENDGRID_API_KEY": true,
215+
"MAILGUN_API_KEY": true,
216+
"SLACK_BOT_TOKEN": true,
217+
"DISCORD_BOT_TOKEN": true,
218+
"VONAGE_API_SECRET": true, // Vonage/Nexmo — SMS/voice telephony
219+
"KLAVIYO_API_KEY": true, // Klaviyo — e-commerce email, customer PII
220+
"MAILCHIMP_API_KEY": true, // Mailchimp — customer lists, PII
221+
"CUSTOMERIO_API_KEY": true, // Customer.io — behavioral marketing, PII
222+
"BREVO_API_KEY": true, // Brevo (Sendinblue) — EU email, PII
200223

201224
// Identity & auth
202225
"OKTA_API_TOKEN": true,
203226
"AUTH0_CLIENT_SECRET": true,
204-
205-
// Observability & infra
206-
"DATADOG_API_KEY": true,
207-
"SENTRY_AUTH_TOKEN": true,
208-
"VERCEL_TOKEN": true,
209-
"NETLIFY_AUTH_TOKEN": true,
210-
"CLOUDFLARE_API_TOKEN": true,
211-
"HEROKU_API_KEY": true,
212-
"RAILWAY_TOKEN": true,
213-
"FLY_API_TOKEN": true,
227+
"CLERK_SECRET_KEY": true, // Clerk — popular Next.js auth, auth bypass risk
228+
"WORKOS_API_KEY": true, // WorkOS — enterprise SSO
229+
230+
// Observability
231+
"DATADOG_API_KEY": true,
232+
"SENTRY_AUTH_TOKEN": true,
233+
"NEW_RELIC_LICENSE_KEY": true, // New Relic — APM data, log exfil
234+
"NEW_RELIC_API_KEY": true, // New Relic user/account API key
235+
"GRAFANA_API_KEY": true, // Grafana Cloud
236+
"GRAFANA_TOKEN": true, // Grafana Cloud access policy token
237+
"HONEYCOMB_API_KEY": true, // Honeycomb — trace data
238+
239+
// Cloud / hosting / IaC
240+
"VERCEL_TOKEN": true,
241+
"NETLIFY_AUTH_TOKEN": true,
242+
"CLOUDFLARE_API_TOKEN": true,
243+
"HEROKU_API_KEY": true,
244+
"RAILWAY_TOKEN": true,
245+
"FLY_API_TOKEN": true,
246+
"DIGITALOCEAN_TOKEN": true, // DigitalOcean — full infra control
247+
"DO_API_TOKEN": true, // DigitalOcean alternative env var name
248+
"LINODE_TOKEN": true, // Linode/Akamai — full infra control
249+
"RENDER_API_KEY": true, // Render — deploy platform access
250+
"PULUMI_ACCESS_TOKEN": true, // Pulumi — IaC state = all infra secrets
251+
"TFE_TOKEN": true, // Terraform Cloud — IaC state
252+
"CLOUDINARY_API_SECRET": true, // Cloudinary — media storage
214253

215254
// Databases (connection strings often embed credentials)
216-
"DATABASE_URL": true,
217-
"MONGODB_URI": true,
218-
"REDIS_URL": true,
255+
"DATABASE_URL": true,
256+
"MONGODB_URI": true,
257+
"REDIS_URL": true,
258+
"MONGODB_ATLAS_PRIVATE_KEY": true, // MongoDB Atlas admin API (separate from connection string)
259+
"TURSO_AUTH_TOKEN": true, // Turso — SQLite-at-edge DB access
260+
"UPSTASH_REDIS_REST_TOKEN": true, // Upstash — serverless Redis/Kafka
261+
"ELASTIC_API_KEY": true, // Elasticsearch — data exfil risk
262+
"ELASTIC_CLOUD_API_KEY": true, // Elastic Cloud management API
263+
264+
// CRM / e-commerce / dev tools
265+
"ATLASSIAN_API_TOKEN": true, // Atlassian/Jira — project data, PII
266+
"JIRA_API_TOKEN": true, // Jira alternative env var
267+
"HUBSPOT_ACCESS_TOKEN": true, // HubSpot CRM — customer PII + sales data
268+
"SALESFORCE_CLIENT_SECRET": true, // Salesforce — enterprise CRM
269+
"SHOPIFY_API_SECRET_KEY": true, // Shopify — store orders, customer PII
270+
"ZENDESK_API_TOKEN": true, // Zendesk — customer support PII
271+
"INTERCOM_ACCESS_TOKEN": true, // Intercom — customer chat PII
272+
"SEGMENT_WRITE_KEY": true, // Segment — all customer behavioral events
273+
"ALGOLIA_API_KEY": true, // Algolia — search index admin access
219274
}
220275

221276
// Summarise computes a Summary from a slice of ScanResults.

0 commit comments

Comments
 (0)