Skip to content

Commit 07d2d00

Browse files
authored
Fix Duplicate Secret Realtime Results In MultiLine (AST-0000) (#1247)
* refactor: rename function to createResultsPerLocationMap for clarity * test: add test for RunSecretsRealtimeScan with multi-line result * fix: update location key formatting in results processing * fix: correct formatting of resultKey in results processing * fix: add SecretValue field to SecretsRealtimeResult and update related logic
1 parent ba573ed commit 07d2d00

File tree

3 files changed

+35
-8
lines changed

3 files changed

+35
-8
lines changed

internal/services/realtimeengine/secretsrealtime/config.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import "github.com/checkmarx/ast-cli/internal/services/realtimeengine"
55
type SecretsRealtimeResult struct {
66
Title string `json:"Title"`
77
Description string `json:"Description"`
8+
SecretValue string `json:"SecretValue"`
89
FilePath string `json:"FilePath"`
910
Severity string `json:"Severity"`
1011
Locations []realtimeengine.Location `json:"Locations"`

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

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -107,7 +107,7 @@ func (s *SecretsRealtimeService) RunSecretsRealtimeScan(filePath, ignoredFilePat
107107
}
108108

109109
results := convertToSecretsRealtimeResult(report)
110-
resultsPerLineMap := createResultsPerLineMap(results)
110+
resultsPerLineMap := createResultsPerLocationMap(results)
111111
results = filterGenericAPIKeyVulIfNeeded(results, resultsPerLineMap)
112112

113113
if ignoredFilePath == "" {
@@ -163,6 +163,7 @@ func convertSecretToResult(secret *secrets.Secret) SecretsRealtimeResult {
163163
return SecretsRealtimeResult{
164164
Title: secret.RuleID,
165165
Description: secret.RuleDescription,
166+
SecretValue: secret.Value,
166167
Severity: getSeverity(secret),
167168
FilePath: secret.Source,
168169
Locations: locations,
@@ -182,15 +183,17 @@ func getSeverity(secret *secrets.Secret) string {
182183
}
183184
}
184185

185-
func createResultsPerLineMap(results []SecretsRealtimeResult) map[string][]SecretsRealtimeResult {
186-
resultsPerLine := make(map[string][]SecretsRealtimeResult)
186+
func createResultsPerLocationMap(results []SecretsRealtimeResult) map[string][]SecretsRealtimeResult {
187+
resultsPerLocation := make(map[string][]SecretsRealtimeResult)
187188
for _, result := range results {
189+
var locationKey string
188190
for _, location := range result.Locations {
189-
lineKey := fmt.Sprintf("%s:%d", result.FilePath, location.Line)
190-
resultsPerLine[lineKey] = append(resultsPerLine[lineKey], result)
191+
locationKey = fmt.Sprintf("%s:%d", locationKey, location.Line)
191192
}
193+
resultKey := fmt.Sprintf("%s%s", result.FilePath, locationKey)
194+
resultsPerLocation[resultKey] = append(resultsPerLocation[resultKey], result)
192195
}
193-
return resultsPerLine
196+
return resultsPerLocation
194197
}
195198

196199
func filterGenericAPIKeyVulIfNeeded(

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

Lines changed: 25 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -139,8 +139,31 @@ func TestRunSecretsRealtimeScan_ValidFile_Success(t *testing.T) {
139139

140140
assert.NoError(t, err)
141141
assert.NotNil(t, results)
142-
// Note: The actual results depend on the 2ms scanner behavior
143-
// This test mainly verifies that the function completes without error
142+
}
143+
144+
func TestRunSecretsRealtimeScan_MultiLineResult_Success(t *testing.T) {
145+
mock.Flag = wrappers.FeatureFlagResponseModel{Name: wrappers.OssRealtimeEnabled, Status: true}
146+
value := "PRIVATE_KEY = \"\"\"\n-----BEGIN RSA PRIVATE KEY-----\nMIIEpAIBAAKCAQEA7v8wF+SECRETKEYEXAMPLE+QIDAQABAoIBAQC0\n-----END RSA PRIVATE KEY-----\n\"\"\""
147+
// Create a temporary file for testing
148+
tempDir := t.TempDir()
149+
tempFile := filepath.Join(tempDir, "test-secrets.txt")
150+
testContent := value
151+
err := os.WriteFile(tempFile, []byte(testContent), 0644)
152+
assert.NoError(t, err)
153+
154+
service := &SecretsRealtimeService{
155+
JwtWrapper: &mock.JWTMockWrapper{},
156+
FeatureFlagWrapper: &mock.FeatureFlagsMockWrapper{},
157+
}
158+
159+
results, err := service.RunSecretsRealtimeScan(tempFile, "")
160+
161+
assert.NoError(t, err)
162+
assert.NotNil(t, results)
163+
assert.Len(t, results, 1)
164+
assert.Len(t, results[0].Locations, 3)
165+
assert.NotEmpty(t, results[0].SecretValue)
166+
144167
}
145168

146169
func TestReadFile_ValidFile_Success(t *testing.T) {

0 commit comments

Comments
 (0)