Skip to content

Commit 601185a

Browse files
authored
Filter out generic API key vulnerabilities in real-time scan results (AST-106731) (#1239)
* Filter out generic API key vulnerabilities in real-time scan results * Fix typo in generic API key constant name * Fix typo in generic API key constant name * Fix logic in filtering generic API keys in real-time scan results * Fix logic in filtering generic API keys in real-time scan results
1 parent bd17b99 commit 601185a

File tree

2 files changed

+66
-4
lines changed

2 files changed

+66
-4
lines changed

internal/services/realtimeengine/secretsrealtime/secrets-realtime.go

Lines changed: 40 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,10 @@ package secretsrealtime
33
import (
44
"encoding/json"
55
"fmt"
6+
"os"
7+
68
errorconstants "github.com/checkmarx/ast-cli/internal/constants/errors"
79
"github.com/checkmarx/ast-cli/internal/logger"
8-
"os"
910

1011
"github.com/checkmarx/2ms/v3/lib/reporting"
1112
"github.com/checkmarx/2ms/v3/lib/secrets"
@@ -22,6 +23,7 @@ const (
2223
criticalSeverity = "Critical"
2324
highSeverity = "High"
2425
mediumSeverity = "Medium"
26+
genericAPIKey = "generic-api-key"
2527
)
2628

2729
type SecretsRealtimeService struct {
@@ -105,6 +107,8 @@ func (s *SecretsRealtimeService) RunSecretsRealtimeScan(filePath, ignoredFilePat
105107
}
106108

107109
results := convertToSecretsRealtimeResult(report)
110+
resultsPerLineMap := createResultsPerLineMap(results)
111+
results = filterGenericAPIKeyVulIfNeeded(results, resultsPerLineMap)
108112

109113
if ignoredFilePath == "" {
110114
return results, nil
@@ -177,3 +181,38 @@ func getSeverity(secret *secrets.Secret) string {
177181
return highSeverity
178182
}
179183
}
184+
185+
func createResultsPerLineMap(results []SecretsRealtimeResult) map[string][]SecretsRealtimeResult {
186+
resultsPerLine := make(map[string][]SecretsRealtimeResult)
187+
for _, result := range results {
188+
for _, location := range result.Locations {
189+
lineKey := fmt.Sprintf("%s:%d", result.FilePath, location.Line)
190+
resultsPerLine[lineKey] = append(resultsPerLine[lineKey], result)
191+
}
192+
}
193+
return resultsPerLine
194+
}
195+
196+
func filterGenericAPIKeyVulIfNeeded(
197+
results []SecretsRealtimeResult,
198+
resultsPerLine map[string][]SecretsRealtimeResult,
199+
) []SecretsRealtimeResult {
200+
if len(results) == 0 || len(resultsPerLine) == 0 {
201+
return results
202+
}
203+
204+
var filtered []SecretsRealtimeResult
205+
for _, entries := range resultsPerLine {
206+
if len(entries) <= 1 {
207+
filtered = append(filtered, entries...)
208+
continue
209+
}
210+
211+
for i := 0; i < len(entries); i++ {
212+
if entries[i].Title != genericAPIKey {
213+
filtered = append(filtered, entries[i])
214+
}
215+
}
216+
}
217+
return filtered
218+
}

internal/services/realtimeengine/secretsrealtime/secrets-realtime_test.go

Lines changed: 26 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -73,12 +73,12 @@ func TestRunSecretsRealtimeScan_WithIgnoreFile_FiltersResult(t *testing.T) {
7373
tempDir := t.TempDir()
7474

7575
testFile := filepath.Join(tempDir, "test.txt")
76-
testContent := "aws_access_key_id = AKIAIOSFODNN7EXAMPLE\ngithub_token = ghp_XXXXXXXXXXXXXXXXXXXX"
76+
testContent := "pat = \"ghp_1234567890abcdef1234567890abcdef12345678\""
7777
assert.NoError(t, os.WriteFile(testFile, []byte(testContent), 0644))
7878

7979
ignoreFile := filepath.Join(tempDir, "ignored.json")
8080
ignored := []IgnoredSecret{
81-
{Title: "github-token", FilePath: "test.txt", Line: 2},
81+
{Title: "github-pat", FilePath: testFile, Line: 0},
8282
}
8383
data, _ := json.Marshal(ignored)
8484
assert.NoError(t, os.WriteFile(ignoreFile, data, 0644))
@@ -93,7 +93,30 @@ func TestRunSecretsRealtimeScan_WithIgnoreFile_FiltersResult(t *testing.T) {
9393
assert.NotNil(t, results)
9494

9595
for _, r := range results {
96-
assert.NotEqual(t, "github-token", r.Title)
96+
assert.NotEqual(t, "github-pat", r.Title)
97+
}
98+
}
99+
100+
func TestRunSecretsRealtimeScan_PatVulAndGenericVul_ReturnedOnlyPathVul(t *testing.T) {
101+
mock.Flag = wrappers.FeatureFlagResponseModel{Name: wrappers.OssRealtimeEnabled, Status: true}
102+
103+
tempDir := t.TempDir()
104+
105+
testFile := filepath.Join(tempDir, "test.txt")
106+
testContent := "token = \"ghp_1234567890abcdef1234567890abcdef12345678\""
107+
assert.NoError(t, os.WriteFile(testFile, []byte(testContent), 0644))
108+
109+
service := &SecretsRealtimeService{
110+
JwtWrapper: &mock.JWTMockWrapper{},
111+
FeatureFlagWrapper: &mock.FeatureFlagsMockWrapper{},
112+
}
113+
114+
results, err := service.RunSecretsRealtimeScan(testFile, "")
115+
assert.NoError(t, err)
116+
assert.NotNil(t, results)
117+
118+
for _, r := range results {
119+
assert.Equal(t, "github-pat", r.Title)
97120
}
98121
}
99122

0 commit comments

Comments
 (0)