Skip to content

Commit 2d7f91d

Browse files
committed
Update
1 parent 994ba93 commit 2d7f91d

2 files changed

Lines changed: 31 additions & 7 deletions

File tree

internal/scan/apikeys.go

Lines changed: 12 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -365,11 +365,18 @@ func (s *APIKeyScanner) scanCredentialFiles() []models.Finding {
365365
// If home directory cannot be resolved, skip all ~-based paths to avoid
366366
// scanning incorrect root-relative paths (e.g. /.aws/credentials).
367367
homeDir := s.resolveHomeDir()
368+
// seenPath is shared across built-in and extra loops so that an extra path
369+
// duplicating a built-in (e.g. ~/.netrc in both lists) produces only one finding.
370+
seenPath := make(map[string]bool)
368371
for _, cf := range credentialFiles {
369372
if homeDir == "" && len(cf.Path) > 0 && cf.Path[0] == '~' {
370373
continue
371374
}
372-
expanded := expandHome(cf.Path, homeDir)
375+
expanded := filepath.Clean(expandHome(cf.Path, homeDir))
376+
if seenPath[expanded] {
377+
continue
378+
}
379+
seenPath[expanded] = true
373380
if fsutil.Exists(expanded) {
374381
findings = append(findings, models.Finding{
375382
Scanner: "api_keys",
@@ -381,17 +388,15 @@ func (s *APIKeyScanner) scanCredentialFiles() []models.Finding {
381388
}
382389

383390
// Extra credential files from user config.
384-
// Deduplicate by expanded path to avoid reporting the same file twice.
385-
seenExtraPath := make(map[string]bool, len(s.ExtraCredentialFiles))
386391
for _, cf := range s.ExtraCredentialFiles {
387392
if homeDir == "" && len(cf.Path) > 0 && cf.Path[0] == '~' {
388393
continue
389394
}
390-
expanded := expandHome(cf.Path, homeDir)
391-
if seenExtraPath[expanded] {
392-
continue // duplicate path in extras list
395+
expanded := filepath.Clean(expandHome(cf.Path, homeDir))
396+
if seenPath[expanded] {
397+
continue // already reported by built-in or earlier extra
393398
}
394-
seenExtraPath[expanded] = true
399+
seenPath[expanded] = true
395400
if fsutil.Exists(expanded) {
396401
findings = append(findings, models.Finding{
397402
Scanner: "api_keys",

internal/scan/apikeys_test.go

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -246,6 +246,25 @@ func TestAPIKeyScanner_NoDuplicateFindings(t *testing.T) {
246246
return tokenFile
247247
},
248248
},
249+
{
250+
name: "extra credential file duplicates built-in path",
251+
makeScanner: func(home string) *scan.APIKeyScanner {
252+
return &scan.APIKeyScanner{
253+
HomeDir: home,
254+
ExtraCredentialFiles: []config.CredentialFile{
255+
{Path: "~/.netrc", Label: "netrc (duplicate of built-in)"},
256+
},
257+
}
258+
},
259+
setup: func(t *testing.T, home string) string {
260+
netrcFile := filepath.Join(home, ".netrc")
261+
if err := os.WriteFile(netrcFile, []byte("machine example.com"), 0o600); err != nil {
262+
t.Fatalf("create .netrc: %v", err)
263+
}
264+
clearHighRiskEnv(t)
265+
return netrcFile
266+
},
267+
},
249268
}
250269

251270
for _, tc := range cases {

0 commit comments

Comments
 (0)