Skip to content

Commit 1583168

Browse files
Merge branch 'main' into miryamFoifer/LimitedHelmContext
2 parents 8a915d6 + e470dc5 commit 1583168

File tree

8 files changed

+122
-33
lines changed

8 files changed

+122
-33
lines changed

go.mod

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ require (
1111
github.com/Checkmarx/secret-detection v0.0.3-0.20250327150305-31c2c3be9edf
1212
github.com/MakeNowJust/heredoc v1.0.0
1313
github.com/bouk/monkey v1.0.0
14-
github.com/checkmarx/2ms/v3 v3.20.0
14+
github.com/checkmarx/2ms/v3 v3.21.0
1515
github.com/gofrs/flock v0.12.1
1616
github.com/golang-jwt/jwt/v5 v5.2.2
1717
github.com/gomarkdown/markdown v0.0.0-20241102151059-6bc1ffdc6e8c

go.sum

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -219,8 +219,8 @@ github.com/charmbracelet/x/term v0.2.1 h1:AQeHeLZ1OqSXhrAWpYUtZyX1T3zVxfpZuEQMIQ
219219
github.com/charmbracelet/x/term v0.2.1/go.mod h1:oQ4enTYFV7QN4m0i9mzHrViD7TQKvNEEkHUMCmsxdUg=
220220
github.com/checkmarx/2ms v1.4.1-0.20250327145719-b78804cb08c7 h1:COsC3skOJeJaSoCPuhLZ0byRGKm+ZHlyw5qm9ydlab0=
221221
github.com/checkmarx/2ms v1.4.1-0.20250327145719-b78804cb08c7/go.mod h1:Bnd2YSh8LQSc4fHAFN0BKz8LYThB6qHg3Wn/+H+WZ4I=
222-
github.com/checkmarx/2ms/v3 v3.20.0 h1:dr3vSVUoYXwS40DUGR5ueXaPROKTkMs+9xAij2/vzUA=
223-
github.com/checkmarx/2ms/v3 v3.20.0/go.mod h1:f5ZwVFEDBr8WRa/9aXluPnufi2wuq6tGWCROcW3CdbA=
222+
github.com/checkmarx/2ms/v3 v3.21.0 h1:EcabeDypNMsSidISQbziZ062HjMZQ+Hm/uOJ5AOxK8o=
223+
github.com/checkmarx/2ms/v3 v3.21.0/go.mod h1:e8f4F94MZ+iCetR/G3aw7nXdPe6TgPI92Zzk/NG1l0o=
224224
github.com/chromedp/cdproto v0.0.0-20230802225258-3cf4e6d46a89/go.mod h1:GKljq0VrfU4D5yc+2qA6OVr8pmO/MBbPEWqWQ/oqGEs=
225225
github.com/chromedp/chromedp v0.9.2/go.mod h1:LkSXJKONWTCHAfQasKFUZI+mxqS4tZqhmtGzzhLsnLs=
226226
github.com/chromedp/sysutil v1.0.0/go.mod h1:kgWmDdq8fTzXYcKIBqIYvRRTnYb9aNS9moAV0xufSww=

internal/commands/scan.go

Lines changed: 13 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -529,33 +529,30 @@ func scanContainersRealtimeSubCommand(realtimeScannerWrapper wrappers.RealtimeSc
529529
return scanContainersRealtimeCmd
530530
}
531531

532-
func scanSecretsRealtimeSubCommand(jwtWrapper wrappers.JWTWrapper, featureFlagsWrapper wrappers.FeatureFlagsWrapper) *cobra.Command {
532+
func scanSecretsRealtimeSubCommand(
533+
jwtWrapper wrappers.JWTWrapper,
534+
featureFlagsWrapper wrappers.FeatureFlagsWrapper,
535+
) *cobra.Command {
533536
scanSecretsRealtimeCmd := &cobra.Command{
534537
Hidden: true,
535538
Use: "secrets-realtime",
536539
Short: "Run a Secrets-Realtime scan",
537540
Long: "Running a Secrets-Realtime scan is a fast and efficient way to identify exposed secrets in a file.",
538-
Example: heredoc.Doc(
539-
`
540-
$ cx scan secrets-realtime -s <path to file separated>
541-
`,
542-
),
541+
Example: heredoc.Doc(`
542+
$ cx scan secrets-realtime -s <path to file>
543+
$ cx scan secrets-realtime -s <path to file> --ignored-file-path <path to ignored secrets file>
544+
`),
543545
Annotations: map[string]string{
544-
"command:doc": heredoc.Doc(
545-
`
546+
"command:doc": heredoc.Doc(`
546547
https://docs.checkmarx.com/en/34965-68625-checkmarx-one-cli-commands.html
547-
`,
548-
),
548+
`),
549549
},
550550
RunE: RunScanSecretsRealtimeCommand(jwtWrapper, featureFlagsWrapper),
551551
}
552552

553-
scanSecretsRealtimeCmd.PersistentFlags().StringP(
554-
commonParams.SourcesFlag,
555-
commonParams.SourcesFlagSh,
556-
"",
557-
"The file source should be the path to a single file or multiple files separated by commas",
558-
)
553+
scanSecretsRealtimeCmd.Flags().StringP(commonParams.SourcesFlag, "s", "", "Path to the file to scan")
554+
scanSecretsRealtimeCmd.Flags().String(commonParams.IgnoredFilePathFlag, "", "Path to ignored secrets file")
555+
559556
return scanSecretsRealtimeCmd
560557
}
561558

internal/commands/secrets-realtime.go

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -11,21 +11,26 @@ import (
1111

1212
func RunScanSecretsRealtimeCommand(
1313
jwtWrapper wrappers.JWTWrapper,
14-
featureFlagWrapper wrappers.FeatureFlagsWrapper) func(cmd *cobra.Command, args []string) error {
14+
featureFlagWrapper wrappers.FeatureFlagsWrapper,
15+
) func(cmd *cobra.Command, args []string) error {
1516
return func(cmd *cobra.Command, _ []string) error {
1617
fileSourceFlag, _ := cmd.Flags().GetString(commonParams.SourcesFlag)
1718
if fileSourceFlag == "" {
1819
return errorconstants.NewRealtimeEngineError(errorconstants.RealtimeEngineFilePathRequired).Error()
1920
}
21+
22+
ignoredFilePathFlag, _ := cmd.Flags().GetString(commonParams.IgnoredFilePathFlag)
23+
2024
secretsRealtimeService := secretsrealtime.NewSecretsRealtimeService(jwtWrapper, featureFlagWrapper)
2125

22-
results, err := secretsRealtimeService.RunSecretsRealtimeScan(fileSourceFlag)
26+
results, err := secretsRealtimeService.RunSecretsRealtimeScan(fileSourceFlag, ignoredFilePathFlag)
2327
if err != nil {
2428
return err
2529
}
30+
2631
err = printer.Print(cmd.OutOrStdout(), results, printer.FormatJSON)
2732
if err != nil {
28-
return errorconstants.NewRealtimeEngineError("failed to return packages").Error()
33+
return errorconstants.NewRealtimeEngineError("failed to return secrets").Error()
2934
}
3035

3136
return nil

internal/commands/secrets-realtime_test.go

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ func TestRunScanSecretsRealtimeCommand_TxtFile_ScanSuccess(t *testing.T) {
1313
mock.Flag = wrappers.FeatureFlagResponseModel{Name: wrappers.OssRealtimeEnabled, Status: true}
1414
execCmdNilAssertion(
1515
t,
16-
"scan", "secrets-realtime", "-s", "data/secret-exposed.txt",
16+
"scan", "secrets-realtime", "-s", "data/secret-exposed.txt", "--ignored-file-path", "",
1717
)
1818
}
1919

@@ -22,7 +22,7 @@ func TestRunScanSecretsRealtimeCommand_EmptyFilePath_ScanFailed(t *testing.T) {
2222
mock.Flag = wrappers.FeatureFlagResponseModel{Name: wrappers.OssRealtimeEnabled, Status: true}
2323
err := execCmdNotNilAssertion(
2424
t,
25-
"scan", "secrets-realtime", "-s", "",
25+
"scan", "secrets-realtime", "-s", "", "--ignored-file-path", "",
2626
)
2727
assert.NotNil(t, err)
2828
}
@@ -32,7 +32,7 @@ func TestRunScanSecretsRealtimeCommand_FFDisable_ScanFailed(t *testing.T) {
3232
mock.Flag = wrappers.FeatureFlagResponseModel{Name: wrappers.OssRealtimeEnabled, Status: false}
3333
err := execCmdNotNilAssertion(
3434
t,
35-
"scan", "secrets-realtime", "-s", "data/secret-exposed.txt",
35+
"scan", "secrets-realtime", "-s", "data/secret-exposed.txt", "--ignored-file-path", "",
3636
)
3737
assert.NotNil(t, err)
3838
}

internal/services/realtimeengine/secretsrealtime/config.go

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,3 +9,9 @@ type SecretsRealtimeResult struct {
99
Severity string `json:"Severity"`
1010
Locations []realtimeengine.Location `json:"Locations"`
1111
}
12+
13+
type IgnoredSecret struct {
14+
Title string `json:"Title"`
15+
FilePath string `json:"FilePath"`
16+
Line int `json:"Line"`
17+
}

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

Lines changed: 54 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,16 @@
11
package secretsrealtime
22

33
import (
4+
"encoding/json"
45
"fmt"
6+
errorconstants "github.com/checkmarx/ast-cli/internal/constants/errors"
7+
"github.com/checkmarx/ast-cli/internal/logger"
58
"os"
69

710
"github.com/checkmarx/2ms/v3/lib/reporting"
811
"github.com/checkmarx/2ms/v3/lib/secrets"
912
scanner "github.com/checkmarx/2ms/v3/pkg"
1013

11-
errorconstants "github.com/checkmarx/ast-cli/internal/constants/errors"
12-
"github.com/checkmarx/ast-cli/internal/logger"
1314
"github.com/checkmarx/ast-cli/internal/services/realtimeengine"
1415
"github.com/checkmarx/ast-cli/internal/wrappers"
1516
)
@@ -39,7 +40,44 @@ func NewSecretsRealtimeService(
3940
}
4041
}
4142

42-
func (s *SecretsRealtimeService) RunSecretsRealtimeScan(filePath string) ([]SecretsRealtimeResult, error) {
43+
func filterIgnoredSecrets(results []SecretsRealtimeResult, ignoreMap map[string]bool) []SecretsRealtimeResult {
44+
filtered := make([]SecretsRealtimeResult, 0, len(results))
45+
for _, r := range results {
46+
if len(r.Locations) == 0 {
47+
filtered = append(filtered, r)
48+
continue
49+
}
50+
key := fmt.Sprintf("%s_%s_%d", r.Title, r.FilePath, r.Locations[0].Line)
51+
if !ignoreMap[key] {
52+
filtered = append(filtered, r)
53+
}
54+
}
55+
return filtered
56+
}
57+
58+
func buildIgnoreMap(ignored []IgnoredSecret) map[string]bool {
59+
m := make(map[string]bool)
60+
for _, s := range ignored {
61+
key := fmt.Sprintf("%s_%s_%d", s.Title, s.FilePath, s.Line)
62+
m[key] = true
63+
}
64+
return m
65+
}
66+
67+
func loadIgnoredSecrets(path string) ([]IgnoredSecret, error) {
68+
data, err := os.ReadFile(path)
69+
if err != nil {
70+
return nil, err
71+
}
72+
var ignored []IgnoredSecret
73+
err = json.Unmarshal(data, &ignored)
74+
if err != nil {
75+
return nil, err
76+
}
77+
return ignored, nil
78+
}
79+
80+
func (s *SecretsRealtimeService) RunSecretsRealtimeScan(filePath, ignoredFilePath string) ([]SecretsRealtimeResult, error) {
4381
if filePath == "" {
4482
return nil, errorconstants.NewRealtimeEngineError(errorconstants.RealtimeEngineFilePathRequired).Error()
4583
}
@@ -66,7 +104,18 @@ func (s *SecretsRealtimeService) RunSecretsRealtimeScan(filePath string) ([]Secr
66104
return nil, errorconstants.NewRealtimeEngineError("failed to run secrets scan").Error()
67105
}
68106

69-
return convertToSecretsRealtimeResult(report), nil
107+
results := convertToSecretsRealtimeResult(report)
108+
109+
if ignoredFilePath == "" {
110+
return results, nil
111+
}
112+
ignoredSecrets, err := loadIgnoredSecrets(ignoredFilePath)
113+
if err != nil {
114+
return nil, errorconstants.NewRealtimeEngineError("failed to load ignored secrets").Error()
115+
}
116+
ignoreMap := buildIgnoreMap(ignoredSecrets)
117+
results = filterIgnoredSecrets(results, ignoreMap)
118+
return results, nil
70119
}
71120

72121
func readFile(filePath string) (string, error) {
@@ -78,6 +127,7 @@ func readFile(filePath string) (string, error) {
78127
}
79128

80129
func runScan(source, content string) (*reporting.Report, error) {
130+
81131
item := scanner.ScanItem{
82132
Content: &content,
83133
Source: source,

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

Lines changed: 35 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package secretsrealtime
22

33
import (
4+
"encoding/json"
45
"os"
56
"path/filepath"
67
"testing"
@@ -29,7 +30,7 @@ func TestRunSecretsRealtimeScan_EmptyFilePath_ReturnsError(t *testing.T) {
2930
FeatureFlagWrapper: &mock.FeatureFlagsMockWrapper{},
3031
}
3132

32-
results, err := service.RunSecretsRealtimeScan("")
33+
results, err := service.RunSecretsRealtimeScan("", "")
3334

3435
assert.Nil(t, results)
3536
assert.NotNil(t, err)
@@ -44,7 +45,7 @@ func TestRunSecretsRealtimeScan_FeatureFlagDisabled_ReturnsError(t *testing.T) {
4445
FeatureFlagWrapper: &mock.FeatureFlagsMockWrapper{},
4546
}
4647

47-
results, err := service.RunSecretsRealtimeScan("test.txt")
48+
results, err := service.RunSecretsRealtimeScan("test.txt", "")
4849

4950
assert.Nil(t, results)
5051
assert.NotNil(t, err)
@@ -59,13 +60,43 @@ func TestRunSecretsRealtimeScan_FileNotFound_ReturnsError(t *testing.T) {
5960
FeatureFlagWrapper: &mock.FeatureFlagsMockWrapper{},
6061
}
6162

62-
results, err := service.RunSecretsRealtimeScan("nonexistent-file.txt")
63+
results, err := service.RunSecretsRealtimeScan("nonexistent-file.txt", "")
6364

6465
assert.Nil(t, results)
6566
assert.NotNil(t, err)
6667
assert.Contains(t, err.Error(), "failed to read file")
6768
}
6869

70+
func TestRunSecretsRealtimeScan_WithIgnoreFile_FiltersResult(t *testing.T) {
71+
mock.Flag = wrappers.FeatureFlagResponseModel{Name: wrappers.OssRealtimeEnabled, Status: true}
72+
73+
tempDir := t.TempDir()
74+
75+
testFile := filepath.Join(tempDir, "test.txt")
76+
testContent := "aws_access_key_id = AKIAIOSFODNN7EXAMPLE\ngithub_token = ghp_XXXXXXXXXXXXXXXXXXXX"
77+
assert.NoError(t, os.WriteFile(testFile, []byte(testContent), 0644))
78+
79+
ignoreFile := filepath.Join(tempDir, "ignored.json")
80+
ignored := []IgnoredSecret{
81+
{Title: "github-token", FilePath: "test.txt", Line: 2},
82+
}
83+
data, _ := json.Marshal(ignored)
84+
assert.NoError(t, os.WriteFile(ignoreFile, data, 0644))
85+
86+
service := &SecretsRealtimeService{
87+
JwtWrapper: &mock.JWTMockWrapper{},
88+
FeatureFlagWrapper: &mock.FeatureFlagsMockWrapper{},
89+
}
90+
91+
results, err := service.RunSecretsRealtimeScan(testFile, ignoreFile)
92+
assert.NoError(t, err)
93+
assert.NotNil(t, results)
94+
95+
for _, r := range results {
96+
assert.NotEqual(t, "github-token", r.Title)
97+
}
98+
}
99+
69100
func TestRunSecretsRealtimeScan_ValidFile_Success(t *testing.T) {
70101
mock.Flag = wrappers.FeatureFlagResponseModel{Name: wrappers.OssRealtimeEnabled, Status: true}
71102

@@ -81,7 +112,7 @@ func TestRunSecretsRealtimeScan_ValidFile_Success(t *testing.T) {
81112
FeatureFlagWrapper: &mock.FeatureFlagsMockWrapper{},
82113
}
83114

84-
results, err := service.RunSecretsRealtimeScan(tempFile)
115+
results, err := service.RunSecretsRealtimeScan(tempFile, "")
85116

86117
assert.NoError(t, err)
87118
assert.NotNil(t, results)

0 commit comments

Comments
 (0)