Skip to content

Commit 70b8e6f

Browse files
authored
Malicious Code scan command (#704)
1 parent e00b60b commit 70b8e6f

6 files changed

Lines changed: 150 additions & 126 deletions

File tree

.github/workflows/test.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -311,7 +311,7 @@ jobs:
311311

312312
# Test
313313
- name: Run tests
314-
run: go test ${{ env.GO_COMMON_TEST_ARGS }} --test.curation --test.enrich --ci.runId=${{ runner.os }}-sec-test
314+
run: go test ${{ env.GO_COMMON_TEST_ARGS }} --test.curation --test.enrich --test.maliciousScan --ci.runId=${{ runner.os }}-sec-test
315315

316316
Git_Commands_Integration_Tests:
317317
name: "[${{ matrix.os }}] Git Commands Integration Tests"

cli/scancommands.go

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ import (
2323
auditSpecificDocs "github.com/jfrog/jfrog-cli-security/cli/docs/auditspecific"
2424
enrichDocs "github.com/jfrog/jfrog-cli-security/cli/docs/enrich"
2525

26-
// maliciousScanDocs "github.com/jfrog/jfrog-cli-security/cli/docs/maliciousscan"
26+
maliciousScanDocs "github.com/jfrog/jfrog-cli-security/cli/docs/maliciousscan"
2727
mcpDocs "github.com/jfrog/jfrog-cli-security/cli/docs/mcp"
2828
sastServerDocs "github.com/jfrog/jfrog-cli-security/cli/docs/sastserver"
2929
auditDocs "github.com/jfrog/jfrog-cli-security/cli/docs/scan/audit"
@@ -79,15 +79,15 @@ func getAuditAndScansCommands() []components.Command {
7979
Category: securityCategory,
8080
Action: EnrichCmd,
8181
},
82-
// {
83-
// Name: "malicious-scan",
84-
// Aliases: []string{"ms"},
85-
// Flags: flags.GetCommandFlags(flags.MaliciousScan),
86-
// Description: maliciousScanDocs.GetDescription(),
87-
// Arguments: maliciousScanDocs.GetArguments(),
88-
// Category: securityCategory,
89-
// Action: MaliciousScanCmd,
90-
// },
82+
{
83+
Name: "malicious-scan",
84+
Aliases: []string{"ms"},
85+
Flags: flags.GetCommandFlags(flags.MaliciousScan),
86+
Description: maliciousScanDocs.GetDescription(),
87+
Arguments: maliciousScanDocs.GetArguments(),
88+
Category: securityCategory,
89+
Action: MaliciousScanCmd,
90+
},
9191
{
9292
Name: "build-scan",
9393
Aliases: []string{"bs"},

commands/maliciousscan/maliciousscan.go

Lines changed: 19 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -16,10 +16,17 @@ import (
1616
"github.com/jfrog/jfrog-cli-security/utils/results"
1717
"github.com/jfrog/jfrog-cli-security/utils/results/output"
1818
"github.com/jfrog/jfrog-cli-security/utils/severityutils"
19-
"github.com/jfrog/jfrog-cli-security/utils/xray"
19+
xrayUtils "github.com/jfrog/jfrog-cli-security/utils/xray"
20+
clientUtils "github.com/jfrog/jfrog-client-go/utils"
2021
ioUtils "github.com/jfrog/jfrog-client-go/utils/io"
2122
"github.com/jfrog/jfrog-client-go/utils/io/fileutils"
2223
"github.com/jfrog/jfrog-client-go/utils/log"
24+
"github.com/jfrog/jfrog-client-go/xray"
25+
)
26+
27+
const (
28+
MaliciousScanFeatureId = "ai_catalog"
29+
MinimumXrayVersionForMaliciousScan = "3.132.0"
2330
)
2431

2532
type MaliciousScanCommand struct {
@@ -106,21 +113,20 @@ func (cmd *MaliciousScanCommand) Run() (err error) {
106113
}
107114

108115
func (cmd *MaliciousScanCommand) validateAndPrepare() (xrayVersion string, entitledForJas bool, workingDirs []string, err error) {
109-
xrayManager, xrayVersion, err := xray.CreateXrayServiceManagerAndGetVersion(cmd.serverDetails, xray.WithScopedProjectKey(cmd.project))
116+
xrayManager, xrayVersion, err := xrayUtils.CreateXrayServiceManagerAndGetVersion(cmd.serverDetails, xrayUtils.WithScopedProjectKey(cmd.project))
110117
if err != nil {
111118
return "", false, nil, err
112119
}
113-
114-
entitledForJas, err = jas.IsEntitledForJas(xrayManager, xrayVersion)
115-
if err != nil {
120+
if err = clientUtils.ValidateMinimumVersion(clientUtils.Xray, xrayVersion, MinimumXrayVersionForMaliciousScan); err != nil {
121+
return "", false, nil, err
122+
}
123+
log.Info("JFrog Xray version is:", xrayVersion)
124+
if entitledForJas, err = IsEntitledForMaliciousScan(xrayManager, xrayVersion); err != nil {
116125
return "", false, nil, err
117126
}
118127
if !entitledForJas {
119-
return "", false, nil, errors.New("JAS (Advanced Security) feature is not entitled")
128+
return "", false, nil, errors.New("malicious scan feature is not entitled")
120129
}
121-
122-
log.Info("JFrog Xray version is:", xrayVersion)
123-
124130
workingDirs, err = coreutils.GetFullPathsWorkingDirs(cmd.workingDirs)
125131
if err != nil {
126132
return "", false, nil, err
@@ -130,6 +136,10 @@ func (cmd *MaliciousScanCommand) validateAndPrepare() (xrayVersion string, entit
130136
return xrayVersion, entitledForJas, workingDirs, nil
131137
}
132138

139+
func IsEntitledForMaliciousScan(xrayManager *xray.XrayServicesManager, xrayVersion string) (entitled bool, err error) {
140+
return xrayUtils.IsEntitled(xrayManager, xrayVersion, MaliciousScanFeatureId)
141+
}
142+
133143
func (cmd *MaliciousScanCommand) initializeCommandResults(xrayVersion string, entitledForJas bool) *results.SecurityCommandResults {
134144
cmdResults := results.NewCommandResults(utils.SourceCode)
135145
cmdResults.SetXrayVersion(xrayVersion)

maliciousscan_test.go

Lines changed: 100 additions & 96 deletions
Original file line numberDiff line numberDiff line change
@@ -1,112 +1,116 @@
11
package main
22

33
import (
4-
// "strconv"
5-
// "strings"
6-
// "testing"
4+
"strconv"
5+
"strings"
6+
"testing"
77

8-
// "path/filepath"
8+
"path/filepath"
99

10-
// "github.com/stretchr/testify/assert"
11-
// securityTestUtils "github.com/jfrog/jfrog-cli-security/tests/utils"
12-
// "github.com/jfrog/jfrog-cli-security/tests/validations"
10+
"github.com/jfrog/jfrog-cli-security/commands/maliciousscan"
11+
securityTestUtils "github.com/jfrog/jfrog-cli-security/tests/utils"
12+
"github.com/jfrog/jfrog-cli-security/tests/validations"
13+
"github.com/stretchr/testify/assert"
1314

14-
// "github.com/jfrog/jfrog-cli-core/v2/common/format"
15-
// securityTests "github.com/jfrog/jfrog-cli-security/tests"
16-
// securityIntegrationTestUtils "github.com/jfrog/jfrog-cli-security/tests/utils/integration"
15+
"github.com/jfrog/jfrog-cli-core/v2/common/format"
16+
securityTests "github.com/jfrog/jfrog-cli-security/tests"
17+
securityIntegrationTestUtils "github.com/jfrog/jfrog-cli-security/tests/utils/integration"
1718
)
1819

19-
// type maliciousScanCommandTestParams struct {
20-
// WorkingDirsToScan []string
21-
// Format format.OutputFormat
22-
// Threads int
23-
// MinSeverity string
24-
// }
20+
type maliciousScanCommandTestParams struct {
21+
WorkingDirsToScan []string
22+
Format format.OutputFormat
23+
Threads int
24+
MinSeverity string
25+
}
2526

26-
// func getMaliciousScanCmdArgs(params maliciousScanCommandTestParams) (args []string) {
27-
// args = []string{"malicious-scan"}
28-
// if len(params.WorkingDirsToScan) > 0 {
29-
// args = append(args, "--working-dirs="+strings.Join(params.WorkingDirsToScan, ","))
30-
// }
31-
// if params.Format != "" {
32-
// args = append(args, "--format="+string(params.Format))
33-
// }
34-
// if params.Threads > 0 {
35-
// args = append(args, "--threads="+strconv.Itoa(params.Threads))
36-
// }
37-
// if params.MinSeverity != "" {
38-
// args = append(args, "--min-severity="+params.MinSeverity)
39-
// }
40-
// return args
41-
// }
27+
func getMaliciousScanCmdArgs(params maliciousScanCommandTestParams) (args []string) {
28+
args = []string{"malicious-scan"}
29+
if len(params.WorkingDirsToScan) > 0 {
30+
args = append(args, "--working-dirs="+strings.Join(params.WorkingDirsToScan, ","))
31+
}
32+
if params.Format != "" {
33+
args = append(args, "--format="+string(params.Format))
34+
}
35+
if params.Threads > 0 {
36+
args = append(args, "--threads="+strconv.Itoa(params.Threads))
37+
}
38+
if params.MinSeverity != "" {
39+
args = append(args, "--min-severity="+params.MinSeverity)
40+
}
41+
return args
42+
}
4243

43-
// func runMaliciousScan(t *testing.T, params maliciousScanCommandTestParams) (string, error) {
44-
// cleanUp := securityIntegrationTestUtils.UseTestHomeWithDefaultXrayConfig(t)
45-
// defer cleanUp()
46-
// return securityTests.PlatformCli.RunCliCmdWithOutputs(t, getMaliciousScanCmdArgs(params)...)
47-
// }
44+
func runMaliciousScan(t *testing.T, params maliciousScanCommandTestParams) (string, error) {
45+
cleanUp := securityIntegrationTestUtils.UseTestHomeWithDefaultXrayConfig(t)
46+
defer cleanUp()
47+
return securityTests.PlatformCli.RunCliCmdWithOutputs(t, getMaliciousScanCmdArgs(params)...)
48+
}
4849

49-
// func TestMaliciousScan(t *testing.T) {
50-
// testCases := []struct {
51-
// name string
52-
// format format.OutputFormat
53-
// projectPath string
54-
// expectedIssues int
55-
// }{
56-
// {
57-
// name: "Malicious scan with findings (Simple JSON)",
58-
// format: format.SimpleJson,
59-
// projectPath: filepath.Join("projects", "jas", "jas", "malicious"),
60-
// expectedIssues: 1,
61-
// },
62-
// {
63-
// name: "Malicious scan without findings (Simple JSON)",
64-
// format: format.SimpleJson,
65-
// projectPath: filepath.Join("projects", "empty_project", "python_project_with_no_deps"),
66-
// expectedIssues: 0,
67-
// },
68-
// }
69-
// for _, tc := range testCases {
70-
// t.Run(tc.name, func(t *testing.T) {
71-
// fullProjectPath := filepath.Join(filepath.FromSlash(securityTests.GetTestResourcesPath()), tc.projectPath)
72-
// _, cleanUp := securityTestUtils.CreateTestProjectEnvAndChdir(t, fullProjectPath)
73-
// defer cleanUp()
50+
func TestMaliciousScan(t *testing.T) {
51+
securityIntegrationTestUtils.InitMaliciousScanTest(t, maliciousscan.MinimumXrayVersionForMaliciousScan)
52+
testCases := []struct {
53+
name string
54+
format format.OutputFormat
55+
projectPath string
56+
expectedIssues int
57+
}{
58+
{
59+
name: "Malicious scan with findings (Simple JSON)",
60+
format: format.SimpleJson,
61+
projectPath: filepath.Join("projects", "jas", "jas", "malicious"),
62+
expectedIssues: 1,
63+
},
64+
{
65+
name: "Malicious scan without findings (Simple JSON)",
66+
format: format.SimpleJson,
67+
projectPath: filepath.Join("projects", "empty_project", "python_project_with_no_deps"),
68+
expectedIssues: 0,
69+
},
70+
}
71+
for _, tc := range testCases {
72+
t.Run(tc.name, func(t *testing.T) {
73+
fullProjectPath := filepath.Join(filepath.FromSlash(securityTests.GetTestResourcesPath()), tc.projectPath)
74+
_, cleanUp := securityTestUtils.CreateTestProjectEnvAndChdir(t, fullProjectPath)
75+
defer cleanUp()
7476

75-
// params := maliciousScanCommandTestParams{
76-
// Format: tc.format,
77-
// }
78-
// output, err := runMaliciousScan(t, params)
79-
// assert.NoError(t, err)
77+
params := maliciousScanCommandTestParams{
78+
Format: tc.format,
79+
}
80+
output, err := runMaliciousScan(t, params)
81+
assert.NoError(t, err)
8082

81-
// validationsParams := validations.ValidationParams{
82-
// Vulnerabilities: &validations.VulnerabilityCount{
83-
// ValidateScan: &validations.ScanCount{MaliciousCode: tc.expectedIssues},
84-
// },
85-
// }
86-
// if tc.expectedIssues == 0 {
87-
// validationsParams.ExactResultsMatch = true
88-
// }
89-
// validations.ValidateCommandOutput(t, output, tc.format, validationsParams)
90-
// })
91-
// }
92-
// }
83+
validationsParams := validations.ValidationParams{
84+
Vulnerabilities: &validations.VulnerabilityCount{
85+
ValidateScan: &validations.ScanCount{MaliciousCode: tc.expectedIssues},
86+
},
87+
}
88+
if tc.expectedIssues == 0 {
89+
validationsParams.ExactResultsMatch = true
90+
}
91+
validations.ValidateCommandOutput(t, output, tc.format, validationsParams)
92+
})
93+
}
94+
}
9395

94-
// func TestMaliciousScanWithWorkingDirs(t *testing.T) {
95-
// maliciousProjectPath := filepath.Join(filepath.FromSlash(securityTests.GetTestResourcesPath()), "projects", "jas", "jas", "malicious")
96-
// _, cleanUp := securityTestUtils.CreateTestProjectEnvAndChdir(t, maliciousProjectPath)
97-
// defer cleanUp()
96+
func TestMaliciousScanWithWorkingDirs(t *testing.T) {
97+
securityIntegrationTestUtils.InitMaliciousScanTest(t, maliciousscan.MinimumXrayVersionForMaliciousScan)
9898

99-
// params := maliciousScanCommandTestParams{
100-
// WorkingDirsToScan: []string{"."},
101-
// Format: format.SimpleJson,
102-
// }
103-
// output, err := runMaliciousScan(t, params)
104-
// assert.NoError(t, err)
99+
maliciousProjectPath := filepath.Join(filepath.FromSlash(securityTests.GetTestResourcesPath()), "projects", "jas", "jas", "malicious")
100+
_, cleanUp := securityTestUtils.CreateTestProjectEnvAndChdir(t, maliciousProjectPath)
101+
defer cleanUp()
105102

106-
// validationsParams := validations.ValidationParams{
107-
// Vulnerabilities: &validations.VulnerabilityCount{
108-
// ValidateScan: &validations.ScanCount{MaliciousCode: 1},
109-
// },
110-
// }
111-
// validations.ValidateCommandOutput(t, output, format.SimpleJson, validationsParams)
112-
// }
103+
params := maliciousScanCommandTestParams{
104+
WorkingDirsToScan: []string{"."},
105+
Format: format.SimpleJson,
106+
}
107+
output, err := runMaliciousScan(t, params)
108+
assert.NoError(t, err)
109+
110+
validationsParams := validations.ValidationParams{
111+
Vulnerabilities: &validations.VulnerabilityCount{
112+
ValidateScan: &validations.ScanCount{MaliciousCode: 1},
113+
},
114+
}
115+
validations.ValidateCommandOutput(t, output, format.SimpleJson, validationsParams)
116+
}

tests/config.go

Lines changed: 13 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -35,15 +35,16 @@ var (
3535

3636
// Test flags
3737
var (
38-
TestUnit *bool
39-
TestArtifactory *bool
40-
TestXray *bool
41-
TestXsc *bool
42-
TestScan *bool
43-
TestDockerScan *bool
44-
TestCuration *bool
45-
TestEnrich *bool
46-
TestGit *bool
38+
TestUnit *bool
39+
TestArtifactory *bool
40+
TestXray *bool
41+
TestXsc *bool
42+
TestScan *bool
43+
TestDockerScan *bool
44+
TestCuration *bool
45+
TestEnrich *bool
46+
TestMaliciousScan *bool
47+
TestGit *bool
4748

4849
TestAuditGeneral *bool
4950
TestAuditNewSca *bool
@@ -124,6 +125,7 @@ func init() {
124125
TestAuditPython = flag.Bool("test.audit.Python", false, "Run Python technologies (Pip, PipEnv, Poetry) audit integration tests")
125126
TestAuditCocoapods = flag.Bool("test.audit.Cocoapods", false, "Run Cocoapods technologies audit integration tests")
126127
TestAuditSwift = flag.Bool("test.audit.Swift", false, "Run Swift technologies audit integration tests")
128+
TestMaliciousScan = flag.Bool("test.maliciousScan", false, "Run Malicious scan command integration tests")
127129

128130
JfrogUrl = flag.String("jfrog.url", getTestUrlDefaultValue(), "JFrog platform url")
129131
JfrogUser = flag.String("jfrog.user", getTestUserDefaultValue(), "JFrog platform username")
@@ -140,7 +142,7 @@ func init() {
140142
func InitTestFlags() {
141143
flag.Parse()
142144
// If no test types flags were set, run all types
143-
shouldRunAllTests := !isAtLeastOneFlagSet(TestUnit, TestArtifactory, TestXray, TestXsc, TestAuditGeneral, TestAuditNewSca, TestAuditJas, TestAuditJavaScript, TestAuditJava, TestAuditCTypes, TestAuditGo, TestAuditPython, TestAuditCocoapods, TestAuditSwift, TestScan, TestDockerScan, TestCuration, TestEnrich, TestGit)
145+
shouldRunAllTests := !isAtLeastOneFlagSet(TestUnit, TestArtifactory, TestXray, TestXsc, TestAuditGeneral, TestAuditNewSca, TestAuditJas, TestAuditJavaScript, TestAuditJava, TestAuditCTypes, TestAuditGo, TestAuditPython, TestAuditCocoapods, TestAuditSwift, TestScan, TestDockerScan, TestCuration, TestEnrich, TestMaliciousScan, TestGit)
144146
if shouldRunAllTests {
145147
log.Info("Running all tests. To run only specific tests, please specify the desired test flags.")
146148
*TestUnit = true
@@ -161,6 +163,7 @@ func InitTestFlags() {
161163
*TestDockerScan = true
162164
*TestCuration = true
163165
*TestEnrich = true
166+
*TestMaliciousScan = true
164167
*TestGit = true
165168
}
166169
}

tests/utils/integration/test_integrationutils.go

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -201,6 +201,13 @@ func InitEnrichTest(t *testing.T, minVersion string) {
201201
testUtils.GetAndValidateXrayVersion(t, minVersion)
202202
}
203203

204+
func InitMaliciousScanTest(t *testing.T, minVersion string) {
205+
if !*configTests.TestMaliciousScan {
206+
t.Skip(getSkipTestMsg("Malicious scan command integration", "--test.maliciousScan"))
207+
}
208+
testUtils.GetAndValidateXrayVersion(t, minVersion)
209+
}
210+
204211
func InitGitTest(t *testing.T, minXrayVersion string) (string, string, func()) {
205212
if !*configTests.TestGit {
206213
t.Skip(getSkipTestMsg("Git commands integration", "--test.git"))

0 commit comments

Comments
 (0)