Skip to content

Commit 095e3b9

Browse files
committed
fix: narrow XAI pattern to (^|_)XAI_ to avoid false positives on PROXAI_, RELAXAI_ etc
1 parent c7b9c00 commit 095e3b9

2 files changed

Lines changed: 31 additions & 3 deletions

File tree

internal/scan/apikeys.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ import (
1616
// credentialSuffixRe matches env var names that contain a credential-related term.
1717
// Provider name patterns require this suffix to avoid false positives on non-credential
1818
// vars like GITHUB_WORKSPACE or OPENAI_BASE_URL.
19-
var credentialSuffixRe = regexp.MustCompile(`(?i)(KEY|TOKEN|SECRET|PASSWORD|CRED)`)
19+
var credentialSuffixRe = regexp.MustCompile(`(?i)(^|_)(KEY|TOKEN|SECRET|PASSWORD|CRED)(S?)(_|$)`)
2020

2121
// providerNamePatterns matches env var names containing a known provider keyword.
2222
// These only produce a finding when the name also matches credentialSuffixRe.
@@ -39,7 +39,7 @@ var providerNamePatterns = []*regexp.Regexp{
3939
regexp.MustCompile(`(?i)DEEPSEEK`),
4040
regexp.MustCompile(`(?i)PERPLEXITY`),
4141
regexp.MustCompile(`(?i)CEREBRAS`),
42-
regexp.MustCompile(`(?i)XAI`),
42+
regexp.MustCompile(`(?i)(^|_)XAI_`), // (^|_) avoids TAXI_KEY, PROXAI_TOKEN while matching XAI_API_KEY, MY_XAI_KEY
4343
regexp.MustCompile(`(?i)ASSEMBLYAI`),
4444
regexp.MustCompile(`(?i)AI21`),
4545
regexp.MustCompile(`(?i)NVIDIA_NIM`),

internal/scan/apikeys_test.go

Lines changed: 29 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -639,6 +639,30 @@ func TestAPIKeyScanner_NameRegex_NewAIProviders(t *testing.T) {
639639
}
640640
}
641641

642+
func TestAPIKeyScanner_NameRegex_XAI_Anchored(t *testing.T) {
643+
clearAllEnv(t)
644+
// XAI embedded mid-word with no credential suffix — should NOT be flagged.
645+
t.Setenv("PROXAI_ENDPOINT", "https://api.proxai.com")
646+
t.Setenv("RELAXAI_MODE", "true")
647+
// These SHOULD be flagged.
648+
t.Setenv("XAI_API_KEY", "real-xai-key")
649+
t.Setenv("MY_XAI_KEY", "also-real-xai-key")
650+
651+
s := newScannerWithHome(t.TempDir())
652+
result := s.Scan()
653+
654+
assertResource(t, result.Findings, "XAI_API_KEY")
655+
assertResource(t, result.Findings, "MY_XAI_KEY")
656+
for _, f := range result.Findings {
657+
if f.Resource == "PROXAI_ENDPOINT" {
658+
t.Error("PROXAI_ENDPOINT should not be flagged by XAI pattern")
659+
}
660+
if f.Resource == "RELAXAI_MODE" {
661+
t.Error("RELAXAI_MODE should not be flagged by XAI pattern")
662+
}
663+
}
664+
}
665+
642666
func TestAPIKeyScanner_ExtraEnvKeys_NoDuplicateWithNameRegex(t *testing.T) {
643667
const key = "MY_OPENAI_KEY" // matches OPENAI nameRegexPattern AND is in ExtraEnvKeys
644668
t.Setenv(key, "sk-test-value")
@@ -692,13 +716,17 @@ func TestAPIKeyScanner_NameRegex_ProviderWithoutSuffix_NotFlagged(t *testing.T)
692716
t.Setenv("GITHUB_ACTIONS", "true")
693717
t.Setenv("OPENAI_BASE_URL", "https://api.openai.com")
694718
t.Setenv("STRIPE_WEBHOOK_ENDPOINT", "https://example.com/webhook")
719+
// Substring false positives: MONKEY contains KEY, DONKEY contains KEY.
720+
t.Setenv("GITHUB_MONKEY", "banana")
721+
t.Setenv("OPENAI_DONKEY", "hee-haw")
695722

696723
s := newScannerWithHome(t.TempDir())
697724
result := s.Scan()
698725

699726
for _, f := range result.Findings {
700727
switch f.Resource {
701-
case "GITHUB_WORKSPACE", "GITHUB_ACTIONS", "OPENAI_BASE_URL", "STRIPE_WEBHOOK_ENDPOINT":
728+
case "GITHUB_WORKSPACE", "GITHUB_ACTIONS", "OPENAI_BASE_URL", "STRIPE_WEBHOOK_ENDPOINT",
729+
"GITHUB_MONKEY", "OPENAI_DONKEY":
702730
t.Errorf("%s should not be flagged (provider keyword without credential suffix)", f.Resource)
703731
}
704732
}

0 commit comments

Comments
 (0)