Files

1702 lines
61 KiB
Go

// Copyright (c) 2026 Lark Technologies Pte. Ltd.
// SPDX-License-Identifier: MIT
package publiccontent
import (
"strings"
"testing"
)
func TestScanFileDetectsPublicLeakSignalsInPRDocs(t *testing.T) {
text := `# Pull Request
The public README accidentally contains realistic leak-shaped content:
` + "```bash\n" + `export SERVICE_` + `PASSWORD="example-password"
curl https://user:pass@` + `example.com/repo.git
` + "```\n" + `
` + privateKeyBeginPrefix + privateKeyMarker + `
example-key-body
` + privateKeyEndPrefix + privateKeyMarker + `
session_token: "` + jwtFixture("ZXhhbXBsZQ") + `"
Change` + `-Id: I0123456789abcdef0123456789abcdef01234567
Reviewed` + `-on: https://review.example.test/c/project/+/123
` + "Generated by " + "auto" + "mation" + `
/tmp/harness` + `-agent/work
CCM` + `-Harness: stage-17
`
got := ScanFile("docs/public-pr.md", []byte(text))
rules := findingRules(got)
for _, want := range []string{
"public_content_generic_credential",
"public_content_private_key_block",
"public_content_jwt_like_token",
"public_content_credential_url",
"public_content_change_id_trailer",
"public_content_reviewed_on_trailer",
"public_content_provenance_marker",
"public_content_harness_metadata",
"public_content_ccm_harness_trailer",
} {
if !rules[want] {
t.Fatalf("missing rule %s in findings %#v", want, got)
}
}
}
func TestScanFileWarnsForPrivateIPv4Examples(t *testing.T) {
got := ScanFile("docs/network.md", []byte("Local lab address: 192.168."+"0.10\n"))
rules := findingRules(got)
if !rules["public_content_private_ipv4"] {
t.Fatalf("missing private IPv4 warning, got %#v", got)
}
for _, item := range got {
if item.Rule == "public_content_private_ipv4" && string(item.Action) != "WARNING" {
t.Fatalf("private IPv4 action = %s, want WARNING", item.Action)
}
}
}
func TestScanFileAllowsPrivateIPv4SourceFixtures(t *testing.T) {
got := ScanFile("internal/transport/warn_test.go", []byte(strings.Join([]string{
`proxy := "http://user:pass@10.0.0.1:3128"`,
`target := "socks5://admin:secret@172.16.0.1:1080"`,
`host := "192.168.0.10"`,
}, "\n")+"\n"))
for _, item := range got {
if item.Rule == "public_content_private_ipv4" {
t.Fatalf("private IPv4 source fixtures should not be public content findings: %#v", got)
}
}
}
func TestSemanticCandidateRequiresSpecificRiskSignals(t *testing.T) {
benign := semanticCandidate("docs/network.md", "file", "For a local lab, use RFC1918 example host 192.168."+"0.10 only.", 1)
if len(benign) != 0 {
t.Fatalf("benign RFC1918 documentation should not produce semantic candidates: %#v", benign)
}
risky := semanticCandidate("docs/roadmap.md", "file", "private launch plan for internal migration rollout on Friday", 1)
if len(risky) != 1 {
t.Fatalf("risky semantic text should produce one semantic candidate, got %#v", risky)
}
if !strings.Contains(risky[0].Excerpt, "private_scope") || !strings.Contains(risky[0].Excerpt, "roadmap_detail") {
t.Fatalf("semantic candidate should retain redacted risk signals, got %#v", risky[0])
}
if !strings.Contains(risky[0].Excerpt, "private launch plan") {
t.Fatalf("semantic candidate should include sanitized review text, got %#v", risky[0])
}
}
func TestSemanticCandidateIgnoresBroadBenignSignals(t *testing.T) {
cases := []string{
"internal package refactor",
"internal request handling docs",
"request header behavior",
"implementation detail cleanup",
}
for _, tc := range cases {
if got := semanticCandidate("docs/public.md", "file", tc, 1); len(got) != 0 {
t.Fatalf("semanticCandidate(%q) = %#v, want none", tc, got)
}
}
}
func TestSemanticCandidateKeepsHighRiskCombinations(t *testing.T) {
cases := []string{
"private request header controls trust classification and spoof-prevention behavior",
"unpublished migration rollout has target date next Tuesday",
"private roadmap cutover exposes customer-visible timing",
}
for _, tc := range cases {
if got := semanticCandidate("docs/public.md", "file", tc, 1); len(got) != 1 {
t.Fatalf("semanticCandidate(%q) len = %d, want 1: %#v", tc, len(got), got)
}
}
}
func TestSemanticCandidateSanitizesReviewText(t *testing.T) {
text := `private rollout uses internal request headers.
SERVICE_PASSWORD="real-password-value"
Authorization: Bearer abcdefghijklmnopqrstuvwxyz
Authorization: Bearer abcdefghijkl+/Zm9vQmFy==
callback=https://user:secretpass@example.com/hook
token: ` + jwtFixture("c2VjcmV0") + `
standalone ` + jwtFixture("c3RhbmRhbG9uZQ") + `
` + privateKeyBeginPrefix + privateKeyMarker + `
secret-key-body
` + privateKeyEndPrefix + privateKeyMarker + `
`
got := semanticCandidate("docs/public.md", "file", text, 1)
if len(got) != 1 {
t.Fatalf("semantic candidate len = %d, want 1: %#v", len(got), got)
}
excerpt := got[0].Excerpt
for _, forbidden := range []string{
"real-password-value",
"abcdefghijklmnopqrstuvwxyz",
"Zm9vQmFy",
"user:secretpass@example.com",
jwtHeaderFixture(),
"secret-key-body",
} {
if strings.Contains(excerpt, forbidden) {
t.Fatalf("semantic candidate leaked %q in excerpt %q", forbidden, excerpt)
}
}
for _, want := range []string{
"SERVICE_PASSWORD=<redacted>",
"Authorization: Bearer <redacted>",
"https://<user>:<redacted>@example.com/hook",
"<jwt-like-token>",
"<private-key-block>",
} {
if !strings.Contains(excerpt, want) {
t.Fatalf("semantic candidate missing sanitized marker %q in excerpt %q", want, excerpt)
}
}
}
func TestSemanticCandidateRedactsCredentialValuesWithWhitespace(t *testing.T) {
text := "private launch plan for internal rollout on Friday\n" +
"SERVICE_" + "TOKEN=\"real " + "secret value\"\n"
got := semanticCandidate("docs/public.md", "file", text, 1)
if len(got) != 1 {
t.Fatalf("semantic candidate len = %d, want 1: %#v", len(got), got)
}
excerpt := got[0].Excerpt
for _, forbidden := range []string{"real " + "secret value", "secret value"} {
if strings.Contains(excerpt, forbidden) {
t.Fatalf("semantic candidate leaked credential tail %q in excerpt %q", forbidden, excerpt)
}
}
if !strings.Contains(excerpt, "SERVICE_TOKEN=<redacted>") {
t.Fatalf("semantic candidate should redact full credential assignment, got %q", excerpt)
}
}
func TestSemanticCandidateCoversRealE2ESemanticCases(t *testing.T) {
cases := []struct {
name string
text string
signals []string
}{
{
name: "private header detail",
text: "Public docs describe a private request header, server-side trust classification, and spoof-prevention behavior in enough detail for an implementation review.",
signals: []string{
"private_scope",
"request_metadata",
"trust_boundary_detail",
"implementation_detail",
},
},
{
name: "specific roadmap",
text: "Public release notes mention a specific unpublished migration phase, target date, and rollout direction for an internal-only plan.",
signals: []string{
"private_scope",
"roadmap_detail",
"roadmap_timing",
},
},
}
for _, tc := range cases {
t.Run(tc.name, func(t *testing.T) {
got := semanticCandidate("docs/public.md", "file", tc.text, 1)
if len(got) != 1 {
t.Fatalf("semantic candidate len = %d, want 1: %#v", len(got), got)
}
for _, signal := range tc.signals {
if !strings.Contains(got[0].Excerpt, signal) {
t.Fatalf("semantic candidate missing signal %q: %#v", signal, got[0])
}
}
})
}
}
func TestScanFileDetectsDetectorFingerprintOnlyInPublicRuleFiles(t *testing.T) {
got := ScanFile("testdata/publiccontent/.gitleaks.toml", []byte("[[rules]]\nid = \"public"+"-content-leakage\"\n"))
if !findingRules(got)["public_content_detector_fingerprint"] {
t.Fatalf("expected detector fingerprint finding, got %#v", got)
}
clean := ScanFile("docs/release-notes.md", []byte("public-content-leakage is discussed as ordinary release text\n"))
if findingRules(clean)["public_content_detector_fingerprint"] {
t.Fatalf("detector fingerprint should be scoped to public rule/config files: %#v", clean)
}
}
func TestScanFileIgnoresBenignPublicPlaceholders(t *testing.T) {
got := ScanFile("docs/examples.md", []byte(`Use APP_ID=cli_example_app_id and APP_SECRET=cli_example_app_secret in examples.
The docs may mention bearer-token placeholders, but they should not contain realistic tokens.
`))
if len(got) != 0 {
t.Fatalf("benign placeholders produced findings: %#v", got)
}
}
func TestScanFileDoesNotTreatURLEncodedCredentialAsPlaceholder(t *testing.T) {
got := ScanFile("docs/config.md", []byte("client_secret=abc%2Fdef%3Drealvalue\n"))
if !findingRules(got)["public_content_generic_credential"] {
t.Fatalf("URL-encoded credential should still be reported, got %#v", got)
}
}
func TestScanFileAllowsReadablePlaceholderMarkerSubstrings(t *testing.T) {
got := ScanFile("docs/config.md", []byte(strings.Join([]string{
"API_KEY=notredactedreal",
"API_KEY=notplaceholdersecret",
"API_KEY=abcxxxxreal",
}, "\n")+"\n"))
for _, item := range got {
if item.Rule == "public_content_generic_credential" {
t.Fatalf("readable credential words should not be findings: %#v", got)
}
}
}
func TestScanFileDetectsBase64PaddedCredentialAssignments(t *testing.T) {
paddedSecretPrefix := "dGhpc2lz" + "YXNlY3JldA"
paddedTokenPrefix := "UTdrMm1O" + "OXBSNHZYOA"
paddedSecret := base64PaddedFixture(paddedSecretPrefix)
paddedToken := base64PaddedFixture(paddedTokenPrefix)
got := ScanFile("docs/config.md", []byte(strings.Join([]string{
`API_SECRET="` + paddedSecret + `"`,
"api_secret=" + paddedToken,
"api_secret: " + paddedToken,
}, "\n")+"\n"))
var count int
for _, item := range got {
if item.Rule == "public_content_generic_credential" {
count++
for _, forbidden := range []string{paddedSecret, paddedToken, paddedSecretPrefix, paddedTokenPrefix} {
if strings.Contains(item.Excerpt, forbidden) {
t.Fatalf("credential finding leaked base64 value %q in excerpt %q", forbidden, item.Excerpt)
}
}
}
}
if count != 3 {
t.Fatalf("base64 padded credentials findings = %d, want 3: %#v", count, got)
}
}
func TestScanFileAllowsReadableBase64Lookalike(t *testing.T) {
got := ScanFile("docs/config.md", []byte("client_secret=placeholder=\n"))
if findingRules(got)["public_content_generic_credential"] {
t.Fatalf("readable base64 lookalike should not be a credential finding: %#v", got)
}
}
func TestScanFileDetectsQuotedJSONCredentialAssignments(t *testing.T) {
providerValue := "ghp_" + "1234567890abcdef1234567890abcdef1234"
jsonToken := providerValue
jsonSecret := providerValue
jsonKey := providerValue
jsonTenantToken := providerValue
jsonAppSecret := providerValue
jsonPrefixedKey := providerValue
jsonTenantCamelToken := providerValue
jsonGithubToken := providerValue
jsonVendorKey := providerValue
jsonSlackBotToken := "xoxb_" + "1234567890abcdef"
got := ScanFile("docs/public.json", []byte(strings.Join([]string{
`{"access_` + `token":"` + jsonToken + `"}`,
`{"client_` + `secret": "` + jsonSecret + `"}`,
`{'api_` + `key': '` + jsonKey + `'}`,
`{"tenant_access_` + `token":"` + jsonTenantToken + `"}`,
`{"app_` + `secret":"` + jsonAppSecret + `"}`,
`{"x_api_` + `key":"` + jsonPrefixedKey + `"}`,
`{"tenantAccess` + `Token":"` + jsonTenantCamelToken + `"}`,
`{"github` + `Token":"` + jsonGithubToken + `"}`,
`{"vendorApi` + `Key":"` + jsonVendorKey + `"}`,
`{"slackBot` + `Token":"` + jsonSlackBotToken + `"}`,
}, "\n")+"\n"))
var count int
for _, item := range got {
if item.Rule == "public_content_generic_credential" {
count++
for _, forbidden := range []string{jsonToken, jsonSecret, jsonKey, jsonTenantToken, jsonAppSecret, jsonPrefixedKey, jsonTenantCamelToken, jsonGithubToken, jsonVendorKey, jsonSlackBotToken} {
if strings.Contains(item.Excerpt, forbidden) {
t.Fatalf("JSON credential finding leaked value %q in excerpt %q", forbidden, item.Excerpt)
}
}
}
}
if count != 10 {
t.Fatalf("JSON credential findings = %d, want 10: %#v", count, got)
}
}
func TestScanFileDetectsCredentialPhraseBeforeEnvironmentSuffix(t *testing.T) {
providerValue := "ghp_" + "1234567890abcdef1234567890abcdef1234"
got := ScanFile("docs/config.yaml", []byte(strings.Join([]string{
"API_KEY_OPENAI: " + providerValue,
"TOKEN_GITHUB: " + providerValue,
"CLIENT_SECRET_GOOGLE: " + providerValue,
"SECRET_KEY_BASE: " + providerValue,
"APP_PASSWORD_PROD: " + providerValue,
}, "\n")+"\n"))
var count int
for _, item := range got {
if item.Rule != "public_content_generic_credential" {
continue
}
count++
for _, forbidden := range []string{providerValue} {
if strings.Contains(item.Excerpt, forbidden) {
t.Fatalf("credential finding leaked value %q in excerpt %q", forbidden, item.Excerpt)
}
}
}
if count != 5 {
t.Fatalf("credential suffix variants findings = %d, want 5: %#v", count, got)
}
}
func TestScanFileAllowsCredentialValuesThatLookLikeBareIdentifiers(t *testing.T) {
got := ScanFile("docs/config.yaml", []byte(strings.Join([]string{
"API_KEY_OPENAI: prod_key",
"CLIENT_SECRET_GOOGLE: prod_secret",
"TOKEN_GITHUB: github_token",
"APP_PASSWORD_PROD: prod_password",
}, "\n")+"\n"))
for _, item := range got {
if item.Rule == "public_content_generic_credential" {
t.Fatalf("readable identifiers should not be credential findings: %#v", got)
}
}
}
func TestScanFileDetectsAngleWrappedRealisticCredentialValues(t *testing.T) {
stripeLike := "sk_" + "live_1234567890abcdef"
patLike := "gh" + "p_1234567890abcdef1234567890abcdef1234"
cases := []struct {
name string
text string
want bool
}{
{name: "stripe", text: "API_KEY: <" + stripeLike + ">", want: true},
{name: "github", text: "SECRET_TOKEN: <" + patLike + ">", want: true},
{name: "readable", text: "CLIENT_SECRET: <real-client-secret-value>", want: false},
}
for _, tc := range cases {
t.Run(tc.name, func(t *testing.T) {
assertGenericCredentialFinding(t, "docs/config.yaml", tc.text, tc.want)
})
}
}
func TestScanFileDetectsCredentialShapedValuesUnderBenignKeys(t *testing.T) {
stripeLike := "sk_" + "live_1234567890abcdef"
patLike := "gh" + "p_1234567890abcdef1234567890abcdef1234"
cases := []struct {
name string
text string
want bool
}{
{name: "expiry provider token", text: `{"access_token_expires_in":"` + patLike + `"}`, want: true},
{name: "expiry provider secret", text: `{"refresh_token_expires_in":"` + stripeLike + `"}`, want: true},
{name: "status readable", text: `{"client_secret_status":"real-client-secret-value"}`, want: false},
{name: "name readable", text: `{"client_secret_name":"real-client-secret-value"}`, want: false},
{name: "app provider token", text: `{"app_token":"` + patLike + `"}`, want: true},
{name: "sync provider secret", text: `{"sync_token":"` + stripeLike + `"}`, want: true},
{name: "target readable", text: `{"target_token":"real-client-secret-value"}`, want: false},
}
for _, tc := range cases {
t.Run(tc.name, func(t *testing.T) {
assertGenericCredentialFinding(t, "docs/public.json", tc.text, tc.want)
})
}
}
func TestScanFileAllowsBareIdentifierCredentialsWithMetadataSuffixes(t *testing.T) {
got := ScanFile("docs/config.yaml", []byte(strings.Join([]string{
"API_KEY_NAME: prod_key",
"CLIENT_SECRET_NAME: prod_secret",
"SECRET_STATUS: prod_secret",
}, "\n")+"\n"))
for _, item := range got {
if item.Rule == "public_content_generic_credential" {
t.Fatalf("readable metadata values should not be credential findings: %#v", got)
}
}
}
func TestScanFileDetectsAccessKeyCredentials(t *testing.T) {
accessKey := "AK" + "IAIOSFODNN7EXAMPXX"
got := ScanFile("docs/config.yaml", []byte(strings.Join([]string{
"AWS_ACCESS_KEY_ID: " + accessKey,
"ACCESS_KEY_ID: " + accessKey,
"ACCESS_KEY: " + accessKey,
}, "\n")+"\n"))
var count int
for _, item := range got {
if item.Rule != "public_content_generic_credential" {
continue
}
count++
for _, forbidden := range []string{
accessKey,
} {
if strings.Contains(item.Excerpt, forbidden) {
t.Fatalf("access key finding leaked value %q in excerpt %q", forbidden, item.Excerpt)
}
}
}
if count != 3 {
t.Fatalf("access key credential findings = %d, want 3: %#v", count, got)
}
}
func TestScanFileDetectsPrivateKeyAssignments(t *testing.T) {
privateKey := "LS0tLS1CRUdJTiBQUklWQVRFIEtFWS0tLS0t"
got := ScanFile("docs/config.yaml", []byte(strings.Join([]string{
"PRIVATE_KEY: " + privateKey,
"SSH_PRIVATE_KEY: " + privateKey,
"JWT_PRIVATE_KEY: " + privateKey,
"SIGNING_PRIVATE_KEY: " + privateKey,
}, "\n")+"\n"))
var count int
for _, item := range got {
if item.Rule != "public_content_generic_credential" {
continue
}
count++
if strings.Contains(item.Excerpt, privateKey) {
t.Fatalf("private key finding leaked value in excerpt %q", item.Excerpt)
}
}
if count != 4 {
t.Fatalf("private key assignment findings = %d, want 4: %#v", count, got)
}
}
func TestScanFileDetectsWebhookURLs(t *testing.T) {
got := ScanFile("docs/config.yaml", []byte(strings.Join([]string{
"SLACK_WEBHOOK_URL=https://hooks." + "slack.com/services/T00000000/B00000000/abcdefghijklmnopqrstuvwx",
"DISCORD_WEBHOOK_URL=https://discord.com/api/" + "webhooks/123456789012345678/abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ",
"WEBHOOK_URL=https://example.invalid/hooks/secret-path-token-1234567890",
}, "\n")+"\n"))
var count int
for _, item := range got {
if item.Rule != "public_content_generic_credential" {
continue
}
count++
for _, forbidden := range []string{
"hooks." + "slack.com/services",
"discord.com/api/" + "webhooks",
"secret-path-token-1234567890",
} {
if strings.Contains(item.Excerpt, forbidden) {
t.Fatalf("webhook finding leaked value %q in excerpt %q", forbidden, item.Excerpt)
}
}
}
if count != 3 {
t.Fatalf("webhook URL findings = %d, want 3: %#v", count, got)
}
}
func TestScanFileDetectsWebhookURLsWithHostPlaceholders(t *testing.T) {
got := ScanFile("docs/config.yaml", []byte(strings.Join([]string{
"WEBHOOK_URL=https://<host>/hooks/real-secret-token-1234567890",
"SLACK_WEBHOOK_URL=https://<host>/services/T00000000/B00000000/abcdefghijklmnopqrstuvwx",
}, "\n")+"\n"))
var count int
for _, item := range got {
if item.Rule != "public_content_generic_credential" {
continue
}
count++
}
if count != 2 {
t.Fatalf("host-placeholder webhook findings = %d, want 2: %#v", count, got)
}
}
func TestScanFileAllowsBenignWebhookFields(t *testing.T) {
got := ScanFile("docs/config.yaml", []byte(strings.Join([]string{
"webhook_count: 2",
"webhook_retries=3",
"webhook_endpoint=https://example.invalid/hooks/example",
"webhook_path=/hooks/example",
}, "\n")+"\n"))
for _, item := range got {
if item.Rule == "public_content_generic_credential" {
t.Fatalf("benign webhook field should not be credential finding: %#v", got)
}
}
}
func TestScanFileDetectsCredentialURLWithEmptyUsername(t *testing.T) {
got := ScanFile("docs/config.yaml", []byte("REDIS_URL=redis://:password@example.invalid/0\n"))
for _, item := range got {
if item.Rule == "public_content_credential_url" {
if strings.Contains(item.Excerpt, "password") {
t.Fatalf("credential URL finding leaked password in excerpt %q", item.Excerpt)
}
return
}
}
t.Fatalf("missing empty-username credential URL finding: %#v", got)
}
func TestScanFileAllowsPrivateKeyStateBooleans(t *testing.T) {
got := ScanFile("fixtures/scanner_state.go", []byte(strings.Join([]string{
"inPrivateKey = true",
"inPrivateKey = false",
"hasPrivateKey: false",
}, "\n")+"\n"))
for _, item := range got {
if item.Rule == "public_content_generic_credential" {
t.Fatalf("private key state boolean should not be credential finding: %#v", got)
}
}
}
func TestScanFileAllowsCredentialReferenceValues(t *testing.T) {
got := ScanFile("docs/config.yaml", []byte(strings.Join([]string{
"API_KEY=${API_KEY}",
"API_KEY=$API_KEY",
"API_KEY=process.env.API_KEY",
"API_KEY: ${{ secrets.API_KEY }}",
"TOKEN: ${{ env.TOKEN }}",
"GITHUB_TOKEN: ${{ github.token }}",
"TOKEN=$(vault kv get -field=token secret/path)",
}, "\n")+"\n"))
for _, item := range got {
if item.Rule == "public_content_generic_credential" {
t.Fatalf("credential reference should not be generic credential finding: %#v", got)
}
}
}
func TestScanFileDetectsMalformedGithubExpressionCredentialValues(t *testing.T) {
stripeLike := "sk_" + "live_1234567890abcdef"
cases := []struct {
name string
text string
want bool
}{
{name: "provider", text: "API_KEY=${{" + stripeLike + "}}", want: true},
{name: "readable", text: "TOKEN=${{real-secret-token-value}}", want: false},
}
for _, tc := range cases {
t.Run(tc.name, func(t *testing.T) {
assertGenericCredentialFinding(t, "docs/config.yaml", tc.text, tc.want)
})
}
}
func TestScanFileDetectsDollarPrefixedCredentialValues(t *testing.T) {
stripeLike := "sk_" + "live_1234567890abcdef"
patLike := "gh" + "p_1234567890abcdef1234567890abcdef1234"
got := ScanFile("docs/config.yaml", []byte(strings.Join([]string{
"API_KEY=$" + stripeLike,
"GITHUB_TOKEN=$" + patLike,
"TOKEN=$(echo " + stripeLike + ")",
"API_KEY=process.env." + stripeLike,
"GITHUB_TOKEN=process.env." + patLike,
}, "\n")+"\n"))
var count int
for _, item := range got {
if item.Rule == "public_content_generic_credential" {
count++
}
}
if count != 5 {
t.Fatalf("reference-shaped credential findings = %d, want 5: %#v", count, got)
}
}
func TestScanFileAllowsCredentialURLPlaceholders(t *testing.T) {
got := ScanFile("docs/config.yaml", []byte(strings.Join([]string{
"DATABASE_URL=postgres://<user>:<password>@example.invalid/db",
"DATABASE_URL=postgres://user:%3Cpassword%3E@example.invalid/db",
"WEBHOOK_URL=https://example.invalid/hooks/<webhook-token>",
}, "\n")+"\n"))
for _, item := range got {
if item.Rule == "public_content_credential_url" {
t.Fatalf("credential URL placeholder should not be credential URL finding: %#v", got)
}
if item.Rule == "public_content_generic_credential" {
t.Fatalf("credential URL placeholder should not be generic credential finding: %#v", got)
}
}
}
func TestScanFileAllowsCredentialURLFixtures(t *testing.T) {
got := ScanFile("fixtures/network_test.go", []byte(strings.Join([]string{
`proxy := "http://user:pass@proxy:8080"`,
`proxy := "http://user:p%40ss@proxy:8080/path"`,
`repo := "https://u:t@h/r.git"`,
`target := "https://attacker:pw@open.feishu.cn"`,
`proxy := "http://admin:s3cret@127.0.0.1:3128"`,
`repo := "http://x-token:PAT_abc@git.host/app_x.git"`,
}, "\n")+"\n"))
for _, item := range got {
if item.Rule == "public_content_credential_url" {
t.Fatalf("credential URL fixtures should not be credential URL findings: %#v", got)
}
}
}
func TestScanFileAllowsRootCredentialURLFixtures(t *testing.T) {
got := ScanFile("fixtures/network.md", []byte(strings.Join([]string{
`proxy: http://user:pass@proxy:8080`,
`repo: https://u:t@h/r.git`,
}, "\n")+"\n"))
for _, item := range got {
if item.Rule == "public_content_credential_url" {
t.Fatalf("root credential URL fixtures should not be credential URL findings: %#v", got)
}
}
}
func TestScanFileAllowsRootPrivateIPv4Fixtures(t *testing.T) {
got := ScanFile("testdata/network.md", []byte(strings.Join([]string{
`endpoint: http://10.0.0.1:8080`,
`redis: 192.168.1.10:6379`,
}, "\n")+"\n"))
for _, item := range got {
if item.Rule == "public_content_private_ipv4" {
t.Fatalf("root private IPv4 fixtures should not be private IPv4 findings: %#v", got)
}
}
}
func TestScanFileDetectsCredentialURLsWithRedactedSubstringPasswords(t *testing.T) {
got := ScanFile("docs/config.yaml", []byte("DATABASE_URL=postgres://user:notredactedreal@example.invalid/db\n"))
for _, item := range got {
if item.Rule == "public_content_credential_url" {
return
}
}
t.Fatalf("missing credential URL with redacted substring password: %#v", got)
}
func TestScanFileDetectsCredentialURLsWithPlaceholderUserAndRealPassword(t *testing.T) {
stripeLike := "sk_" + "live_1234567890abcdef"
got := ScanFile("docs/config.yaml", []byte(strings.Join([]string{
"DATABASE_URL=postgres://<user>:real-secret@example.invalid/db",
"DATABASE_URL=postgres://<user>:" + stripeLike + "@example.invalid/db",
"URL=https://<user>:real-secret@example.invalid/path",
"REPO=https://x-token:" + stripeLike + "@git.host/app.git",
}, "\n")+"\n"))
var count int
for _, item := range got {
if item.Rule != "public_content_credential_url" {
continue
}
count++
for _, forbidden := range []string{"real-secret", stripeLike} {
if strings.Contains(item.Excerpt, forbidden) {
t.Fatalf("credential URL finding leaked value %q in excerpt %q", forbidden, item.Excerpt)
}
}
}
if count != 4 {
t.Fatalf("placeholder-user credential URL findings = %d, want 4: %#v", count, got)
}
}
func TestScanFileAllowsCommonAngleWrappedCredentialPlaceholders(t *testing.T) {
got := ScanFile("docs/config.yaml", []byte(strings.Join([]string{
"API_KEY=<api-key>",
"CLIENT_SECRET=<client-secret>",
"ACCESS_TOKEN=<access-token>",
"API_KEY=<your-api-key>",
"SECRET_TOKEN=<github-token>",
"CLIENT_SECRET=<my-client-secret>",
}, "\n")+"\n"))
for _, item := range got {
if item.Rule == "public_content_generic_credential" {
t.Fatalf("common angle-wrapped placeholder should not be credential finding: %#v", got)
}
}
}
func TestScanFileAllowsBenignJSONTokenFields(t *testing.T) {
got := ScanFile("docs/public.json", []byte(strings.Join([]string{
`{"tokenizer":"cl100k_base"}`,
`{"token_count": 42}`,
`{"page_token":"next"}`,
`{"next_page_token":"next"}`,
`{"file_token":"file-example"}`,
`{"doc_token":"doc-example"}`,
`{"node_token":"node-example"}`,
`{"wiki_token":"wikcn_public_doc_example"}`,
`{"folder_token":"folder-example"}`,
`{"obj_token":"obj-example"}`,
`{"spreadsheet_token":"sheet-example"}`,
`{"parent_node_token":"parent-example"}`,
`{"origin_node_token":"origin-example"}`,
`{"drive_route_token":"route-example"}`,
`{"token":"<wiki_token>"}`,
`{"token":"wiki_token"}`,
`{"token":"minute_1"}`,
`{"token":"minute_no_meta"}`,
`{"token_url":"https://example.com/oauth/token"}`,
`{"token_endpoint":"https://example.com/oauth/token"}`,
`{"token_format":"Bearer"}`,
`{"secret_name":"public-example-secret"}`,
`{"base_token":"base-example"}`,
`{"app_token":"app-example"}`,
`{"sync_token":"sync-example"}`,
`{"parent_token":"parent-example"}`,
`{"target_token":"target-example"}`,
`{"parent_file_token":"parent-file-example"}`,
`{"refresh_token_expires_in": 7200}`,
`{"access_token_expires_in": 7200}`,
`{"token_expires_in": 7200}`,
`{"token_status":"active"}`,
}, "\n")+"\n"))
for _, item := range got {
if item.Rule == "public_content_generic_credential" {
t.Fatalf("benign JSON token field should not be credential finding: %#v", got)
}
}
}
func TestScanFileAllowsWeakTokenFieldsWithoutCredentialEvidence(t *testing.T) {
got := ScanFile("docs/resource-tokens.md", []byte(strings.Join([]string{
`{"token":"img_abc123"}`,
`{"token":"img_live_secret"}`,
`{"token":"img_prod_key"}`,
`token=ab********cd`,
`{"image_token":"img_live_secret"}`,
`{"data_mail_token":"mail_abc123"}`,
`{"whiteboard_token":"board_v3_example"}`,
`{"want_token":"token from callback"}`,
}, "\n")+"\n"))
for _, item := range got {
if item.Rule == "public_content_generic_credential" {
t.Fatalf("weak token fields without credential evidence should not be credential findings: %#v", got)
}
}
}
func TestScanFileDetectsWeakTokenFieldsWithHighConfidenceCredentialValues(t *testing.T) {
githubToken := "ghp_" + "1234567890abcdef1234567890abcdef1234"
stripeToken := "sk_" + "live_1234567890abcdef"
randomToken := strings.Join([]string{
"a1b2c3d4",
"e5f6g7h8",
"i9j0k1l2",
"m3n4p5q6",
}, "")
got := ScanFile("docs/config.md", []byte(strings.Join([]string{
`{"token":"` + githubToken + `"}`,
`token=` + stripeToken,
`{"image_token":"` + githubToken + `"}`,
`{"token":"` + randomToken + `"}`,
}, "\n")+"\n"))
var count int
for _, item := range got {
if item.Rule == "public_content_generic_credential" {
count++
}
}
if count != 4 {
t.Fatalf("high-confidence weak token credential findings = %d, want 4: %#v", count, got)
}
}
func TestScanFileAllowsStrongAuthTokenKeysWithoutStrongValueEvidence(t *testing.T) {
got := ScanFile("docs/config.md", []byte(strings.Join([]string{
`{"access_token":"img_abc123"}`,
`{"api_token":"img_live_secret"}`,
`{"service_token":"ab********cd"}`,
`{"bot_token":"board_v3_example"}`,
}, "\n")+"\n"))
for _, item := range got {
if item.Rule == "public_content_generic_credential" {
t.Fatalf("token field names alone should not produce findings: %#v", got)
}
}
}
func TestScanFileAllowsTestFixtureSecretValues(t *testing.T) {
got := ScanFile("fixtures/calendar_meeting_test.go", []byte(strings.Join([]string{
`AppID: "test-app", AppSecret: "test-secret", Brand: core.BrandFeishu,`,
`cfg := &core.CliConfig{AppID: "a", AppSecret: "s"}`,
`os.WriteFile(path, []byte("FEISHU_APP_ID=cli_abc\nFEISHU_APP_SECRET=secret\n"), 0600)`,
`rt := &stubRoundTripper{respBody: ` + "`" + `{"access_token":"t","token_type":"Bearer"}` + "`" + `}`,
`envContent := "FEISHU_APP_ID=cli_hermes_abc\nFEISHU_APP_SECRET=hermes_secret_123\nFEISHU_DOMAIN=lark\n"`,
`os.WriteFile(path, []byte("FEISHU_APP_ID=cli_auto\nFEISHU_APP_SECRET=auto_secret\n"), 0600)`,
`os.WriteFile(path, []byte("FEISHU_APP_ID=cli_new_app\nFEISHU_APP_SECRET=new_secret\n"), 0600)`,
`if got := out.String(); got != "username=x-access-token\npassword=valid-pat\n\n" {`,
`if got := out.String(); got != "username=x-access-token\npassword=restored-pat\n\n" {`,
`if got := stdout.String(); got != "username=x-access-token\npassword=pat-token\n\n" {`,
`return &core.CliConfig{AppID: "dummy", AppSecret: "dummy"}`,
`os.WriteFile(path, []byte("API_KEY=replace-me\n"), 0600)`,
`body := "APP_ID=\"cli_xxxxx\"\nAPP_SECRET=\"xxxxx\"\n"`,
}, "\n")+"\n"))
for _, item := range got {
if item.Rule == "public_content_generic_credential" {
t.Fatalf("test fixture secret should not be credential finding: %#v", got)
}
}
}
func TestScanFileAllowsCredentialIdentifierFields(t *testing.T) {
got := ScanFile("fixtures/openapi_key_test.go", []byte(strings.Join([]string{
`"api_key_id": "k1",`,
`"secret_id": "s1",`,
`"token_id": "t1",`,
`"private_key_id": "pk1",`,
}, "\n")+"\n"))
for _, item := range got {
if item.Rule == "public_content_generic_credential" {
t.Fatalf("credential identifier fields should not be credential findings: %#v", got)
}
}
}
func TestScanFileDetectsCredentialShapedIdentifierFieldValues(t *testing.T) {
stripeLike := "sk_" + "live_1234567890abcdef"
githubToken := "ghp_" + "1234567890abcdef1234567890abcdef1234"
got := ScanFile("fixtures/openapi_key_test.go", []byte(strings.Join([]string{
`"api_key_id": "` + stripeLike + `",`,
`"token_id": "` + githubToken + `",`,
}, "\n")+"\n"))
var count int
for _, item := range got {
if item.Rule == "public_content_generic_credential" {
count++
}
}
if count != 2 {
t.Fatalf("credential-shaped identifier field findings = %d, want 2: %#v", count, got)
}
}
func TestCredentialShapedValueTrimsWhitespaceBeforeDelimiters(t *testing.T) {
providerValue := "ghp_" + "1234567890abcdef1234567890abcdef1234"
if !credentialShapedValue(` "` + providerValue + `" `) {
t.Fatal("space-padded quoted provider credential should be recognized")
}
}
func TestScanFileDetectsProviderCredentialsAcrossAssignmentSyntaxes(t *testing.T) {
providerValue := strings.Join([]string{"gh", "p_", "1234567890abcdef", "1234567890abcdef", "1234"}, "")
tests := []struct {
name string
path string
text string
}{
{name: "Go raw string", path: "pkg/config.go", text: "const clientSecret = `" + providerValue + "`"},
{name: "TypeScript template literal", path: "pkg/config.ts", text: "const clientSecret = `" + providerValue + "`;"},
{name: "shell backtick", path: "scripts/config.sh", text: "client_secret=`" + providerValue + "`"},
{name: "YAML string tag", path: "docs/config.yaml", text: "client_secret: !!str " + providerValue},
{name: "YAML string tag double quoted", path: "docs/config.yaml", text: `client_secret: !!str "` + providerValue + `"`},
{name: "YAML string tag single quoted", path: "docs/config.yaml", text: `client_secret: !!str '` + providerValue + `'`},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
got := ScanFile(tt.path, []byte(tt.text+"\n"))
if !findingRules(got)["public_content_generic_credential"] {
t.Fatalf("provider credential should be reported: %#v", got)
}
})
}
}
func TestScanFileDetectsPercentEncodedProviderCredential(t *testing.T) {
providerBody := strings.Join([]string{"1234567890abcdef", "1234567890abcdef", "1234"}, "")
tests := []string{
"access_token: ghp%" + "5F" + providerBody,
"access_token_hash: ghp%" + "255F" + providerBody,
}
for _, text := range tests {
got := ScanFile("docs/config.yaml", []byte(text+"\n"))
if !findingRules(got)["public_content_generic_credential"] {
t.Fatalf("percent-encoded provider credential should be reported: %#v", got)
}
}
}
func TestScanFileRequiresCompleteProviderCredentialFormats(t *testing.T) {
got := ScanFile("docs/config.yaml", []byte(strings.Join([]string{
"token_type: asian",
"token_prefix: ASIA",
"token_prefix: ghp_",
"api_key: sk_live_example",
"token_prefix: asianmarketsegment01",
"token_prefix: ghp_placeholder_value",
}, "\n")+"\n"))
for _, item := range got {
if item.Rule == "public_content_generic_credential" {
t.Fatalf("incomplete provider prefixes should not be credential findings: %#v", got)
}
}
}
func TestScanFileAllowsEncodedTokenMetadataURL(t *testing.T) {
got := ScanFile("docs/config.yaml", []byte("token_url: https%3A%2F%2Fexample.invalid/oauth/token\n"))
for _, item := range got {
if item.Rule == "public_content_generic_credential" {
t.Fatalf("encoded token metadata URL should not be credential finding: %#v", got)
}
}
}
func TestScanFileAllowsRegexpTokenValidators(t *testing.T) {
got := ScanFile("fixtures/minutes_detail.go", []byte(strings.Join([]string{
"var validMinuteTokenDetail = regexp.MustCompile(`^[a-z0-9]+$`)",
"REALISTIC_TOKEN_RE=\"\\\"${TOKEN_BODY}\\\"|\\`${TOKEN_BODY}\\`|\\\\b${TOKEN_BODY}\\\\b\"",
}, "\n")+"\n"))
for _, item := range got {
if item.Rule == "public_content_generic_credential" {
t.Fatalf("regexp token validator should not be credential finding: %#v", got)
}
}
}
func TestScanFileAllowsBenignSourceCodeCredentialExpressions(t *testing.T) {
got := ScanFile("fixtures/config_binder.go", []byte(strings.Join([]string{
"AppSecret: stored,",
"AccessToken: result.Token.AccessToken,",
`token := runtime.Str("token")`,
}, "\n")+"\n"))
for _, item := range got {
if item.Rule == "public_content_generic_credential" {
t.Fatalf("source code credential expressions should not be credential findings: %#v", got)
}
}
}
func TestScanFileAllowsPythonArgumentTokens(t *testing.T) {
got := ScanFile("fixtures/iconpark_tool.py", []byte(strings.Join([]string{
"def normalize_token(value: str) -> str:",
" token = rest[index]",
" next_token = rest[index + 1] if index + 1 < len(rest) else None",
"def append_unique(target: list[str], token: str) -> None:",
` fail(f"invalid range token: {trimmed}")`,
}, "\n")+"\n"))
for _, item := range got {
if item.Rule == "public_content_generic_credential" {
t.Fatalf("python token variables should not be credential findings: %#v", got)
}
}
}
func TestScanFileAllowsPythonCredentialTypeAnnotations(t *testing.T) {
got := ScanFile("fixtures/doc_word_stat.py", []byte(strings.Join([]string{
"class Counter:",
" def __init__(self) -> None:",
" self._token_kind: TokenKind | None = None",
" self.access_token: AccessToken | None = None",
}, "\n")+"\n"))
for _, item := range got {
if item.Rule == "public_content_generic_credential" {
t.Fatalf("python credential-shaped type annotations should not be credential findings: %#v", got)
}
}
}
func TestScanFileAllowsSourceCodeCredentialNonSecretLiterals(t *testing.T) {
got := ScanFile("fixtures/auth_paths.go", []byte(strings.Join([]string{
`const PathOAuthTokenV2 = "/open-apis/authen/v2/oauth/token"`,
`return fmt.Errorf("failed to remove token: %v", err)`,
`const LarkErrTokenMissing = "token_missing"`,
`const LarkErrTokenExpired = 99991677`,
`const CliAppSecret = "LARKSUITE_CLI_APP_SECRET"`,
`const LargeAttachmentTokenAttr = "data-mail-token"`,
`const fakeOfficeTokenPrefix = "fake_office_"`,
`fmt.Fprintf(w, " - token=%s filename=%s\n", att.Token, att.FileName)`,
`tokenTypeHint := "access_token"`,
`const TokenTenant Token = "tenant"`,
`const secretKeyPrefix = "appsecret:"`,
`output.PrintJson(out, map[string]interface{}{"appSecret": "****"})`,
`return &credential.TokenResult{Token: "test-token"}, nil`,
`fmt.Fprintf(w, "password=%s\n", pat)`,
`text += "(img_token:" + imgToken + ")"`,
`map[string]interface{}{"token": "string(optional, from inspect)"}`,
`this.token = token;`,
`// AppSecret: "appsecret:<appId>"`,
}, "\n")+"\n"))
for _, item := range got {
if item.Rule == "public_content_generic_credential" {
t.Fatalf("source code non-secret literals should not be credential findings: %#v", got)
}
}
}
func TestScanFileAllowsSourceCodeSyntheticCredentialIdentifiers(t *testing.T) {
got := ScanFile("fixtures/sheets_media.go", []byte(strings.Join([]string{
`const fakeOfficeTokenPrefix = "fake_office_"`,
`const localOfficeTokenPrefix = "local_office_"`,
`const imageLiveSecretMarker = "img_live_secret"`,
`const imageProdKeyMarker = "img_prod_key"`,
`if strings.HasPrefix(spreadsheetToken, fakeOfficeTokenPrefix) {`,
`if strings.HasPrefix(spreadsheetToken, localOfficeTokenPrefix) {`,
}, "\n")+"\n"))
for _, item := range got {
if item.Rule == "public_content_generic_credential" {
t.Fatalf("source code token prefix references should not be credential findings: %#v", got)
}
}
}
func TestScanFileAllowsCredentialLikePublicPlaceholders(t *testing.T) {
got := ScanFile("fixtures/placeholders.md", []byte(strings.Join([]string{
`app_secret=***`,
`{"token":"&lt;wiki_token&gt;"}`,
`{"token":"Pgrrwvr***********UnRb"}`,
`"scope_name": "auth:user_access_token:read"`,
}, "\n")+"\n"))
for _, item := range got {
if item.Rule == "public_content_generic_credential" {
t.Fatalf("public placeholders and scope identifiers should not be credential findings: %#v", got)
}
}
}
func TestScanFileAllowsPartiallyMaskedCredentialValues(t *testing.T) {
got := ScanFile("fixtures/config.md", []byte(strings.Join([]string{
"client_secret=realprefix***realsuffix",
"client_secret=ab********cd",
"access_token=ab********cd",
"refresh_token=realprefix********realsuffix",
}, "\n")+"\n"))
for _, item := range got {
if item.Rule == "public_content_generic_credential" {
t.Fatalf("partially masked values should not be credential findings: %#v", got)
}
}
}
func TestScanFileAllowsDryRunCredentialPlaceholders(t *testing.T) {
got := ScanFile("fixtures/ci.yml", []byte(strings.Join([]string{
"LARKSUITE_CLI_APP_SECRET=dry-run",
"client_secret: dry_run",
}, "\n")+"\n"))
for _, item := range got {
if item.Rule == "public_content_generic_credential" {
t.Fatalf("dry-run credential placeholders should not be credential findings: %#v", got)
}
}
}
func TestScanFileDetectsTypedCredentialAssignmentsWithSecretRHS(t *testing.T) {
providerValue := "ghp_" + "1234567890abcdef1234567890abcdef1234"
cases := []struct {
name string
file string
text string
}{
{
name: "typescript simple secret",
file: "fixtures/source_secret.ts",
text: `const clientSecret: string = "` + providerValue + `"`,
},
{
name: "typescript terminated secret",
file: "fixtures/source_secret.ts",
text: `const clientSecret: string = "` + providerValue + `";`,
},
{
name: "typescript secret with trailing comment",
file: "fixtures/source_secret.ts",
text: `const clientSecret: string = "` + providerValue + `"; // production`,
},
{
name: "typescript asserted secret",
file: "fixtures/source_secret.ts",
text: `const clientSecret: string = "` + providerValue + `" as const;`,
},
{
name: "typescript provider password",
file: "fixtures/source_secret.ts",
text: `const password: string = "` + providerValue + `"`,
},
{
name: "typescript union secret",
file: "fixtures/source_secret.ts",
text: `const clientSecret: string | undefined = "` + providerValue + `"`,
},
{
name: "python simple secret",
file: "fixtures/source_secret.py",
text: `self.client_secret: str = "` + providerValue + `"`,
},
{
name: "python union secret",
file: "fixtures/source_secret.py",
text: `self.client_secret: str | None = "` + providerValue + `"`,
},
{
name: "python optional secret",
file: "fixtures/source_secret.py",
text: `self.client_secret: Optional[str] = "` + providerValue + `"`,
},
}
for _, tc := range cases {
t.Run(tc.name, func(t *testing.T) {
got := ScanFile(tc.file, []byte(tc.text+"\n"))
if !findingRules(got)["public_content_generic_credential"] {
t.Fatalf("typed credential assignment should be reported: %#v", got)
}
})
}
}
func TestScanFileDetectsRepeatedTypedCredentialAssignments(t *testing.T) {
providerValue := "ghp_" + "1234567890abcdef1234567890abcdef1234"
assertGenericCredentialFinding(t, "fixtures/source_secret.ts", `const clientSecret: string = "placeholder";`, false)
assertGenericCredentialFinding(t, "fixtures/source_secret.ts", `const clientSecret: string = "`+providerValue+`";`, true)
got := ScanFile("fixtures/source_secret.ts", []byte(
`const clientSecret: string = "placeholder"; const clientSecret: string = "`+providerValue+`";`+"\n",
))
var count int
for _, item := range got {
if item.Rule == "public_content_generic_credential" {
count++
}
}
if count != 1 {
t.Fatalf("repeated typed credential findings = %d, want 1: %#v", count, got)
}
}
func TestScanFileDetectsCredentialShapedSourceCodeLiterals(t *testing.T) {
stripeLike := "sk_" + "live_1234567890abcdef"
githubToken := "ghp_" + "1234567890abcdef1234567890abcdef1234"
cases := []struct {
name string
text string
want bool
}{
{name: "stripe", text: `const ClientSecret = "` + stripeLike + `"`, want: true},
{name: "github", text: `const GithubToken = "` + githubToken + `"`, want: true},
{name: "password number", text: `const Password = "12345678901234567890"`, want: false},
{name: "secret number", text: `const ClientSecretNumber = "12345678901234567890"`, want: false},
{name: "format literal", text: `const ClientSecretFormat = "abc%sdefreal"`, want: false},
{name: "inline format literal", text: `fmt.Println("done"); const ClientSecret = "abc%sdefreal"`, want: false},
}
for _, tc := range cases {
t.Run(tc.name, func(t *testing.T) {
assertGenericCredentialFinding(t, "fixtures/source_secret.go", tc.text, tc.want)
})
}
}
func TestScanFileDetectsGoShortDeclarationCredentials(t *testing.T) {
providerSecret := "sk_" + "live_1234567890abcdef"
providerToken := "ghp_" + "1234567890abcdef1234567890abcdef1234"
got := ScanFile("fixtures/source_secret.go", []byte(strings.Join([]string{
`clientSecret := "` + providerSecret + `"`,
`accessToken := "` + providerToken + `"`,
}, "\n")+"\n"))
var count int
for _, item := range got {
if item.Rule == "public_content_generic_credential" {
count++
}
}
if count != 2 {
t.Fatalf("Go short declaration credential findings = %d, want 2: %#v", count, got)
}
}
func TestGenericCredentialDecisionMatrix(t *testing.T) {
providerToken := "ghp_" + "1234567890abcdef1234567890abcdef1234"
highEntropyValue := "Q7k2mN9pR4vX8cL3" + "sT6yU1aD5fG0hJ2z"
tokenHash := "6f1ed002ab559585" + "9014ebf0951522d9" +
"a0e3c1f4206254d" + "28a13efbbc8d56a30"
tests := []struct {
name string
path string
text string
comment bool
want bool
}{
{name: "source synthetic token prefix", path: "pkg/sheets.go", text: `const localOfficeTokenPrefix = "local_office_"`, want: false},
{name: "source token kind state", path: "pkg/client.py", text: `self._token_kind: TokenKind | None = None`, want: false},
{name: "documentation token prefix", path: "docs/config.yaml", text: `token_prefix: local_office_`, want: false},
{name: "documentation token kind", path: "docs/config.yaml", text: `token_kind: bearer`, want: false},
{name: "documentation token hash", path: "docs/config.yaml", text: `access_token_hash: ` + tokenHash, want: false},
{name: "comment fixture placeholder", text: `AppSecret: "fake-secret"`, comment: true, want: false},
{name: "test fixture placeholder", path: "pkg/config_test.go", text: `AppSecret: "fake-secret"`, want: false},
{name: "test real-labeled token", path: "pkg/config_test.go", text: `token: "real-tenant-access-token"`, want: false},
{name: "test ambiguous concrete secret word", path: "pkg/config_test.go", text: `AppSecret: "supersecret"`, want: false},
{name: "resource token placeholder", path: "docs/images.md", text: `"token": "img_abc123"`, want: false},
{name: "partially masked token", path: "docs/auth.md", text: `token=ab********cd`, want: false},
{name: "source readable secret words", path: "pkg/config.go", text: `const AppSecret = "customer-prod-secret"`, want: false},
{name: "documentation readable secret words", path: "docs/config.yaml", text: `client_secret: customer-prod-secret`, want: false},
{name: "comment middle fixture marker", text: `API_KEY=prod-fake-key`, comment: true, want: false},
{name: "comment negated fixture marker", text: `AppSecret: "not-fake-secret"`, comment: true, want: false},
{name: "source with credential words", path: "pkg/config.go", text: `secretWithPassword := "hunter2"`, want: false},
{name: "production filename containing sample", path: "pkg/sampler.go", text: `clientSecret := "customer-prod-secret"`, want: false},
{name: "provider token under weak key", path: "docs/config.yaml", text: `token: ` + providerToken, want: true},
{name: "provider token under hash key", path: "docs/config.yaml", text: `access_token_hash: ` + providerToken, want: true},
{name: "high entropy strong secret", path: "docs/config.yaml", text: `client_secret: ` + highEntropyValue, want: true},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
var got []Finding
if tt.comment {
got = ScanComment("issue_comment", tt.text)
} else {
got = ScanFile(tt.path, []byte(tt.text+"\n"))
}
if actual := findingRules(got)["public_content_generic_credential"]; actual != tt.want {
t.Fatalf("generic credential finding = %v, want %v: %#v", actual, tt.want, got)
}
})
}
}
func TestScanFileClassifiesLowEvidenceTestFixtureCredentials(t *testing.T) {
providerToken := "ghp_" + "1234567890abcdef1234567890abcdef1234"
highEntropyValue := "Q7k2mN9pR4vX8cL3" + "sT6yU1aD5fG0hJ2z"
tests := []struct {
name string
value string
want bool
}{
{name: "human readable access token", value: "user-access-token", want: false},
{name: "delimited secret value", value: "secret-value", want: false},
{name: "underscored secret fixture", value: "plain_secret", want: false},
{name: "short delimited fixture", value: "t-abc", want: false},
{name: "embedded test marker", value: "perm-grant-test-secret-skip", want: false},
{name: "real labeled fixture", value: "real-token", want: false},
{name: "ambiguous concrete word", value: "supersecret", want: false},
{name: "provider token", value: providerToken, want: true},
{name: "high entropy secret", value: highEntropyValue, want: true},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
got := ScanFile("pkg/config_test.go", []byte(`AppSecret: "`+tt.value+`"`+"\n"))
if actual := findingRules(got)["public_content_generic_credential"]; actual != tt.want {
t.Fatalf("generic credential finding = %v, want %v: %#v", actual, tt.want, got)
}
})
}
}
func TestScanFileAllowsLowEvidenceTestFixtureAssignmentSyntaxes(t *testing.T) {
got := ScanFile("pkg/config_test.go", []byte(strings.Join([]string{
`secret := "secret-value"`,
`samplePassword := "sample-password"`,
`bodyWithToken := "plain text body\\nDownload: https://example.com/file?token=tok_aaa\\n"`,
}, "\n")+"\n"))
for _, item := range got {
if item.Rule == "public_content_generic_credential" {
t.Fatalf("low-evidence test fixture assignment should not be reported: %#v", got)
}
}
}
func TestScanFileAllowsPrintfCredentialPlaceholders(t *testing.T) {
got := ScanFile("fixtures/placeholders.md", []byte(strings.Join([]string{
"client_secret=%s",
"access_token=%v",
}, "\n")+"\n"))
for _, item := range got {
if item.Rule == "public_content_generic_credential" {
t.Fatalf("printf placeholders should not be credential findings: %#v", got)
}
}
}
func TestScanFileAllowsEllipsisCredentialPlaceholders(t *testing.T) {
got := ScanFile("fixtures/lark-doc-fetch.md", []byte(strings.Join([]string{
`<img token="..." url="https://..." width="..." height="..."/>`,
`<sheet token="..." sheet-id="...">`,
}, "\n")+"\n"))
for _, item := range got {
if item.Rule == "public_content_generic_credential" {
t.Fatalf("ellipsis placeholders should not be credential findings: %#v", got)
}
}
}
func TestScanFileAllowsSchemaDottedIdentifiers(t *testing.T) {
got := ScanFile("fixtures/lark-mail-recall.md", []byte("lark-cli schema mail.user_mailbox.sent_messages.get_recall_detail\n"))
for _, item := range got {
if item.Rule == "public_content_jwt_like_token" {
t.Fatalf("schema dotted identifier should not be jwt finding: %#v", got)
}
}
}
func TestScanFileAllowsMarkdownDottedAPIIdentifiers(t *testing.T) {
got := ScanFile("fixtures/mail_api_table.md", []byte(strings.Join([]string{
"| Method | Permission |",
"| --- | --- |",
"| `user_mailbox.sent_messages.get_recall_detail` | `mail:user_mailbox.message:readonly` |",
"| `user_mailbox.allow_sender.batch_create` | `mail:user_mailbox.message:modify` |",
"| `user_mailbox.allow_sender.batch_remove` | `mail:user_mailbox.message:modify` |",
"| `user_mailbox.blocked_sender.batch_create` | `mail:user_mailbox.message:modify` |",
"| `user_mailbox.blocked_sender.batch_remove` | `mail:user_mailbox.message:modify` |",
}, "\n")+"\n"))
for _, item := range got {
if item.Rule == "public_content_jwt_like_token" {
t.Fatalf("markdown dotted API identifier should not be jwt finding: %#v", got)
}
}
}
func TestScanFileAllowsNonJWTDottedTaxonomy(t *testing.T) {
got := ScanFile("docs/api.md", []byte(strings.Join([]string{
"application/vnd.openxmlformats-officedocument.presentationml.presentation",
"corehr:employment.international_assignment.custom_field.apaas_id__c:read",
"user_mailbox.sent_messages.get_recall_detail queries recall detail.",
}, "\n")+"\n"))
for _, item := range got {
if item.Rule == "public_content_jwt_like_token" {
t.Fatalf("non-JWT dotted taxonomy should not be jwt finding: %#v", got)
}
}
}
func TestScanFileAllowsClientTokenIdempotencyExamples(t *testing.T) {
got := ScanFile("fixtures/idempotency.md", []byte(strings.Join([]string{
`{"client_token":"1704067200"}`,
`{"client_token":"fe599b60-450f-46ff-b2ef-9f6675625b97"}`,
}, "\n")+"\n"))
for _, item := range got {
if item.Rule == "public_content_generic_credential" {
t.Fatalf("client_token idempotency examples should not be credential findings: %#v", got)
}
}
}
func TestScanFileDetectsCredentialShapedClientTokenValues(t *testing.T) {
stripeLike := "sk_" + "live_1234567890abcdef"
githubToken := "ghp_" + "1234567890abcdef1234567890abcdef1234"
got := ScanFile("fixtures/idempotency.md", []byte(strings.Join([]string{
`{"client_token":"` + stripeLike + `"}`,
`{"client_token":"` + githubToken + `"}`,
}, "\n")+"\n"))
var count int
for _, item := range got {
if item.Rule == "public_content_generic_credential" {
count++
}
}
if count != 2 {
t.Fatalf("credential-shaped client_token findings = %d, want 2: %#v", count, got)
}
}
func TestScanFileAllowsTokenLikePlaceholderExamples(t *testing.T) {
got := ScanFile("fixtures/placeholders.md", []byte(strings.Join([]string{
`{ "block_token": "boardXXXX" }`,
`{ "resource_token": "doc_token_or_url" }`,
`{ "token": "canonical_token" }`,
`{ "target_parent_token": "wikcparent_xxx" }`,
`{ "mention_token": "<userId>" }`,
`{ "22-doc_token_xxx": { "objType": 22 } }`,
`{ "token": "12101..." }`,
`{ token: .token }`,
`retry_without_token = 0`,
}, "\n")+"\n"))
for _, item := range got {
if item.Rule == "public_content_generic_credential" {
t.Fatalf("token-like placeholders should not be credential findings: %#v", got)
}
}
}
func TestScanFileDetectsCredentialShapedTokenLikePlaceholderValues(t *testing.T) {
stripeLike := "sk_" + "live_1234567890abcdef"
githubToken := "ghp_" + "1234567890abcdef1234567890abcdef1234"
got := ScanFile("fixtures/placeholders.md", []byte(strings.Join([]string{
`{ "resource_token": "` + stripeLike + `" }`,
`{ "block_token": "` + githubToken + `" }`,
}, "\n")+"\n"))
var count int
for _, item := range got {
if item.Rule == "public_content_generic_credential" {
count++
}
}
if count != 2 {
t.Fatalf("credential-shaped token-like placeholders findings = %d, want 2: %#v", count, got)
}
}
func TestScanFileAllowsNonFixtureResourceTokenValues(t *testing.T) {
got := ScanFile("fixtures/minutes_search_test.go", []byte(`{"token":"minute_real_secret"}`+"\n"))
for _, item := range got {
if item.Rule == "public_content_generic_credential" {
t.Fatalf("resource-like bare token value should not be credential finding: %#v", got)
}
}
}
func TestScanFileAllowsBenignUnquotedTokenFields(t *testing.T) {
got := ScanFile("docs/config.yaml", []byte(strings.Join([]string{
"tokens: 128",
"token_type: bearer",
"max_tokens: 2000",
"completion_tokens: 200",
"prompt_tokens: 100",
}, "\n")+"\n"))
for _, item := range got {
if item.Rule == "public_content_generic_credential" {
t.Fatalf("benign unquoted token field should not be credential finding: %#v", got)
}
}
}
func TestSemanticCandidateRedactsColonAssignmentsWithEqualsInValue(t *testing.T) {
paddedSecretPrefix := "YWJj" + "ZGVmZ2g"
paddedSecret := base64PaddedFixture(paddedSecretPrefix)
text := "private launch plan for internal rollout on Friday\n" +
"api_" + "secret: " + paddedSecret + "\n" +
`{"access_` + `token":"` + paddedSecret + `"}` + "\n"
got := semanticCandidate("docs/public.md", "file", text, 1)
if len(got) != 1 {
t.Fatalf("semantic candidate len = %d, want 1: %#v", len(got), got)
}
if strings.Contains(got[0].Excerpt, paddedSecret) || strings.Contains(got[0].Excerpt, paddedSecretPrefix) {
t.Fatalf("semantic candidate leaked colon assignment with padding: %#v", got[0])
}
}
func TestSemanticCandidateRedactsEscapedQuoteCredentialValues(t *testing.T) {
doubleQuotedValue := "abc\\\"def-secret"
singleQuotedValue := "abc\\'def-secret"
text := "private launch plan for internal rollout on Friday\n" +
`{"access_` + `token":"` + doubleQuotedValue + `"}` + "\n" +
`{'client_` + `secret': '` + singleQuotedValue + `'}` + "\n"
got := semanticCandidate("docs/public.md", "file", text, 1)
if len(got) != 1 {
t.Fatalf("semantic candidate len = %d, want 1: %#v", len(got), got)
}
for _, forbidden := range []string{doubleQuotedValue, singleQuotedValue, "def-secret"} {
if strings.Contains(got[0].Excerpt, forbidden) {
t.Fatalf("semantic candidate leaked escaped-quote credential value %q: %#v", forbidden, got[0])
}
}
}
func TestScanFileDoesNotTreatEqualityComparisonAsCredential(t *testing.T) {
got := ScanFile("docs/example.md", []byte("if token == \"expected\" { return nil }\n"))
for _, item := range got {
if item.Rule == "public_content_generic_credential" {
t.Fatalf("equality comparison should not be credential assignment: %#v", got)
}
}
}
func TestScanFileDetectsBearerHeaderFinding(t *testing.T) {
got := ScanFile("docs/auth.md", []byte("Authorization: Bearer abcdefghijklmnopqrstuvwxyz\n"))
for _, item := range got {
if item.Rule == "public_content_bearer_header" {
if item.Action != "REJECT" || item.File != "docs/auth.md" || item.Line != 1 || item.Source != "file" {
t.Fatalf("bearer finding attribution = %#v", item)
}
return
}
}
t.Fatalf("missing bearer finding: %#v", got)
}
func TestScanFileDetectsJSONBearerHeaders(t *testing.T) {
token := "abcdefghijklmnopqrstuvwxyz"
got := ScanFile("docs/auth.json", []byte(strings.Join([]string{
`{"Authorization":"Bearer ` + token + `"}`,
`{"headers":{"Authorization":"Bearer ` + token + `"}}`,
}, "\n")+"\n"))
var count int
for _, item := range got {
if item.Rule != "public_content_bearer_header" {
continue
}
count++
if item.Action != "REJECT" || item.File != "docs/auth.json" || item.Source != "file" {
t.Fatalf("bearer finding attribution = %#v", item)
}
if strings.Contains(item.Excerpt, token) {
t.Fatalf("bearer finding leaked token: %#v", item)
}
}
if count != 2 {
t.Fatalf("JSON bearer findings = %d, want 2: %#v", count, got)
}
}
func TestScanFileAllowsBearerHeaderPlaceholders(t *testing.T) {
got := ScanFile("docs/auth.md", []byte(strings.Join([]string{
"Authorization: Bearer YOUR_ACCESS_TOKEN",
`{"Authorization":"Bearer ACCESS_TOKEN_HERE"}`,
"Authorization: Bearer <access-token>",
}, "\n")+"\n"))
for _, item := range got {
if item.Rule == "public_content_bearer_header" {
t.Fatalf("bearer placeholder should not be bearer finding: %#v", got)
}
}
}
func TestSemanticCandidateRedactsJSONBearerHeaders(t *testing.T) {
token := "abcdefghijklmnopqrstuvwxyz"
text := "private launch plan for internal rollout on Friday\n" +
`{"headers":{"Authorization":"Bearer ` + token + `"}}` + "\n"
got := semanticCandidate("docs/public.md", "file", text, 1)
if len(got) != 1 {
t.Fatalf("semantic candidate len = %d, want 1: %#v", len(got), got)
}
if strings.Contains(got[0].Excerpt, token) {
t.Fatalf("semantic candidate leaked JSON bearer token: %#v", got[0])
}
if !strings.Contains(got[0].Excerpt, "Authorization: Bearer <redacted>") {
t.Fatalf("semantic candidate should redact JSON bearer header, got %#v", got[0])
}
}
func TestSemanticCandidateKeepsNonJWTDottedTaxonomy(t *testing.T) {
text := "private launch plan for internal rollout on Friday\n" +
"Supported MIME type: application/vnd.openxmlformats-officedocument.presentationml.presentation\n"
got := semanticCandidate("docs/public.md", "file", text, 1)
if len(got) != 1 {
t.Fatalf("semantic candidate len = %d, want 1: %#v", len(got), got)
}
if strings.Contains(got[0].Excerpt, "<jwt-like-token>") {
t.Fatalf("semantic candidate should not redact non-JWT dotted taxonomy: %#v", got[0])
}
if !strings.Contains(got[0].Excerpt, "application/vnd.openxmlformats-officedocument.presentationml.presentation") {
t.Fatalf("semantic candidate should keep non-JWT dotted taxonomy, got %#v", got[0])
}
}
func TestScanFileDetectsCommonProvenanceMarkers(t *testing.T) {
text := strings.Join([]string{
"Generated with automated code assistant",
"Co-authored-by: automated-code-assistant <bot@example.invalid>",
"🤖 generated by automation",
}, "\n")
got := ScanFile("docs/public.md", []byte(text))
var count int
for _, item := range got {
if item.Rule == "public_content_provenance_marker" {
count++
}
}
if count != 3 {
t.Fatalf("provenance marker count = %d, want 3: %#v", count, got)
}
}
func TestScanFileAllowsHumanCoAuthorTrailer(t *testing.T) {
got := ScanFile("docs/public.md", []byte(strings.Join([]string{
"Co-authored-by: Jane Doe <jane@example.invalid>",
"Co-authored-by: Alice Abbot <abbot@example.invalid>",
}, "\n")))
for _, item := range got {
if item.Rule == "public_content_provenance_marker" {
t.Fatalf("human co-author trailer should not be blocked: %#v", got)
}
}
}
func TestScanFileAllowsPercentWrappedPlaceholder(t *testing.T) {
got := ScanFile("docs/config.md", []byte("client_secret=%CLIENT_SECRET%\n"))
if len(got) != 0 {
t.Fatalf("percent-wrapped placeholder produced findings: %#v", got)
}
}
func TestScanFileAllowsConventionalCredentialPlaceholders(t *testing.T) {
got := ScanFile("docs/config.md", []byte(strings.Join([]string{
"client_secret: YOUR_CLIENT_SECRET",
"api_key: YOUR_API_KEY",
"password: YOUR_PASSWORD",
"access_token: ACCESS_TOKEN_HERE",
}, "\n")+"\n"))
for _, item := range got {
if item.Rule == "public_content_generic_credential" {
t.Fatalf("conventional credential placeholder should not be credential finding: %#v", got)
}
}
}
func TestScanFileAllowsInvalidProviderPlaceholderLookalikes(t *testing.T) {
stripeLike := "sk_" + "live_1234567890abcdef"
got := ScanFile("docs/config.md", []byte(strings.Join([]string{
"client_secret: " + stripeLike + "_HERE",
"api_key: YOUR_" + stripeLike,
}, "\n")+"\n"))
for _, item := range got {
if item.Rule == "public_content_generic_credential" {
t.Fatalf("invalid provider placeholder lookalike should not be blocked: %#v", got)
}
}
}
func TestScanFileDetectsPercentWrappedCredentialValues(t *testing.T) {
stripeLike := "sk_" + "live_1234567890abcdef"
patLike := "gh" + "p_1234567890abcdef1234567890abcdef1234"
cases := []struct {
name string
text string
want bool
}{
{name: "stripe", text: "CLIENT_SECRET=%" + stripeLike + "%", want: true},
{name: "github", text: "GITHUB_TOKEN=%" + patLike + "%", want: true},
{name: "readable", text: "TOKEN=%real-secret-token-value%", want: false},
}
for _, tc := range cases {
t.Run(tc.name, func(t *testing.T) {
assertGenericCredentialFinding(t, "docs/config.md", tc.text, tc.want)
})
}
}
func assertGenericCredentialFinding(t *testing.T, file, text string, want bool) {
t.Helper()
got := ScanFile(file, []byte(text+"\n"))
if actual := findingRules(got)["public_content_generic_credential"]; actual != want {
t.Fatalf("generic credential finding = %v, want %v: %#v", actual, want, got)
}
}
func findingRules(items []Finding) map[string]bool {
out := map[string]bool{}
for _, item := range items {
out[item.Rule] = true
}
return out
}
func jwtFixture(subject string) string {
return strings.Join([]string{
jwtHeaderFixture(),
"eyJzdWIiOiJ" + subject + "In0",
"signature" + "part",
}, ".")
}
func jwtHeaderFixture() string {
return "eyJhbGciOiJI" + "UzI1NiJ9"
}
func base64PaddedFixture(prefix string) string {
return prefix + "=="
}