Skip to content

Commit 629efe7

Browse files
committed
Malicious code scanner
1 parent 8f5ee12 commit 629efe7

File tree

12 files changed

+150
-145
lines changed

12 files changed

+150
-145
lines changed

cli/docs/maliciousscan/help.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ import (
55
)
66

77
func GetDescription() string {
8-
return "Scan malicious models (pickle files, etc.) located in the working directory with AnalyzerManager."
8+
return "[Beta] Scan malicious models (pickle files, etc.) located in the working directory."
99
}
1010

1111
func GetArguments() []components.Argument {

commands/maliciousscan/maliciousscan.go

Lines changed: 78 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,8 @@ import (
77
"path/filepath"
88
"strings"
99

10+
clientutils "github.com/jfrog/jfrog-client-go/utils"
11+
1012
"github.com/jfrog/jfrog-cli-core/v2/common/format"
1113
"github.com/jfrog/jfrog-cli-core/v2/utils/config"
1214
"github.com/jfrog/jfrog-cli-core/v2/utils/coreutils"
@@ -90,72 +92,119 @@ func (cmd *MaliciousScanCommand) Run() (err error) {
9092
}
9193
}()
9294

93-
xrayManager, xrayVersion, err := xray.CreateXrayServiceManagerAndGetVersion(cmd.serverDetails)
95+
xrayVersion, entitledForJas, workingDirs, err := cmd.validateAndPrepare()
9496
if err != nil {
9597
return err
9698
}
9799

98-
entitledForJas, err := jas.IsEntitledForJas(xrayManager, xrayVersion)
100+
cmdResults := cmd.initializeCommandResults(xrayVersion, entitledForJas)
101+
populateScanTargets(cmdResults, workingDirs)
102+
103+
scanner, err := cmd.createJasScanner()
99104
if err != nil {
100105
return err
101106
}
107+
108+
if err = cmd.runMaliciousScans(cmdResults, scanner); err != nil {
109+
return err
110+
}
111+
112+
if cmd.progress != nil {
113+
if err = cmd.progress.Quit(); err != nil {
114+
return err
115+
}
116+
}
117+
118+
return cmd.outputResults(cmdResults)
119+
}
120+
121+
func (cmd *MaliciousScanCommand) validateAndPrepare() (xrayVersion string, entitledForJas bool, workingDirs []string, err error) {
122+
xrayManager, xrayVersion, err := xray.CreateXrayServiceManagerAndGetVersion(cmd.serverDetails)
123+
if err != nil {
124+
return "", false, nil, err
125+
}
126+
127+
entitledForJas, err = jas.IsEntitledForJas(xrayManager, xrayVersion)
128+
if err != nil {
129+
return "", false, nil, err
130+
}
102131
if !entitledForJas {
103-
return errors.New("JAS (Advanced Security) feature is not entitled")
132+
return "", false, nil, errors.New("JAS (Advanced Security) feature is not entitled")
104133
}
105134

106135
log.Info("JFrog Xray version is:", xrayVersion)
107136

108137
if err = jas.DownloadAnalyzerManagerIfNeeded(0); err != nil {
109-
return fmt.Errorf("failed to download Analyzer Manager: %w", err)
138+
return "", false, nil, fmt.Errorf("failed to download Analyzer Manager: %w", err)
110139
}
111140

112-
workingDirs, err := coreutils.GetFullPathsWorkingDirs(cmd.workingDirs)
141+
workingDirs, err = coreutils.GetFullPathsWorkingDirs(cmd.workingDirs)
113142
if err != nil {
114-
return err
143+
return "", false, nil, err
115144
}
116145
logScanPaths(workingDirs)
117146

147+
return xrayVersion, entitledForJas, workingDirs, nil
148+
}
149+
150+
func (cmd *MaliciousScanCommand) initializeCommandResults(xrayVersion string, entitledForJas bool) *results.SecurityCommandResults {
118151
cmdResults := results.NewCommandResults(utils.SourceCode)
119152
cmdResults.SetXrayVersion(xrayVersion)
120153
cmdResults.SetEntitledForJas(entitledForJas)
121154
cmdResults.SetResultsContext(results.ResultContext{
122155
IncludeVulnerabilities: true,
123156
})
157+
return cmdResults
158+
}
124159

125-
populateScanTargets(cmdResults, workingDirs)
126-
160+
func (cmd *MaliciousScanCommand) createJasScanner() (*jas.JasScanner, error) {
127161
scannerOptions := []jas.JasScannerOption{
128162
jas.WithEnvVars(
129-
false, // validateSecrets not relevant for malicious scan
163+
false,
130164
jas.NotDiffScanEnvValue,
131165
jas.GetAnalyzerManagerXscEnvVars(
132-
"", // msi
133-
"", // gitRepoUrl
134-
"", // projectKey
135-
nil, // watches
166+
"",
167+
"",
168+
"",
169+
nil,
136170
),
137171
),
138172
jas.WithMinSeverity(cmd.minSeverityFilter),
139173
}
140174

141175
scanner, err := jas.NewJasScanner(cmd.serverDetails, scannerOptions...)
142176
if err != nil {
143-
return fmt.Errorf("failed to create JAS scanner: %w", err)
177+
return nil, fmt.Errorf("failed to create JAS scanner: %w", err)
144178
}
145179
if scanner == nil {
146-
return errors.New("JAS scanner was not created")
180+
return nil, errors.New("JAS scanner was not created")
147181
}
148182

149-
if cmd.customAnalyzerManagerPath != "" {
150-
scanner.AnalyzerManager.AnalyzerManagerFullPath = cmd.customAnalyzerManagerPath
151-
} else {
152-
if scanner.AnalyzerManager.AnalyzerManagerFullPath, err = jas.GetAnalyzerManagerExecutable(); err != nil {
153-
return fmt.Errorf("failed to set analyzer manager executable path: %w", err)
154-
}
183+
if err = cmd.setAnalyzerManagerPath(scanner); err != nil {
184+
return nil, err
155185
}
156186

157187
log.Debug(fmt.Sprintf("Using analyzer manager executable at: %s", scanner.AnalyzerManager.AnalyzerManagerFullPath))
188+
return scanner, nil
189+
}
190+
191+
func (cmd *MaliciousScanCommand) setAnalyzerManagerPath(scanner *jas.JasScanner) error {
192+
if cmd.customAnalyzerManagerPath == "" {
193+
if err := jas.DownloadAnalyzerManagerIfNeeded(0); err != nil {
194+
return fmt.Errorf("failed to download analyzer manager: %s", err.Error())
195+
}
196+
var err error
197+
if scanner.AnalyzerManager.AnalyzerManagerFullPath, err = jas.GetAnalyzerManagerExecutable(); err != nil {
198+
return fmt.Errorf("failed to set analyzer manager executable path: %s", err.Error())
199+
}
200+
} else {
201+
scanner.AnalyzerManager.AnalyzerManagerFullPath = cmd.customAnalyzerManagerPath
202+
log.Debug(clientutils.GetLogMsgPrefix(0, false) + "using custom analyzer manager binary path")
203+
}
204+
return nil
205+
}
158206

207+
func (cmd *MaliciousScanCommand) runMaliciousScans(cmdResults *results.SecurityCommandResults, scanner *jas.JasScanner) error {
159208
jasScanProducerConsumer := utils.NewSecurityParallelRunner(cmd.threads)
160209

161210
serverDetails, err := cmd.ServerDetails()
@@ -199,14 +248,11 @@ func (cmd *MaliciousScanCommand) Run() (err error) {
199248
}
200249

201250
jasScanProducerConsumer.Start()
251+
return nil
252+
}
202253

203-
if cmd.progress != nil {
204-
if err = cmd.progress.Quit(); err != nil {
205-
return err
206-
}
207-
}
208-
209-
if err = output.NewResultsWriter(cmdResults).
254+
func (cmd *MaliciousScanCommand) outputResults(cmdResults *results.SecurityCommandResults) error {
255+
if err := output.NewResultsWriter(cmdResults).
210256
SetOutputFormat(cmd.outputFormat).
211257
SetPlatformUrl(cmd.serverDetails.Url).
212258
SetPrintExtendedTable(false).
@@ -216,7 +262,7 @@ func (cmd *MaliciousScanCommand) Run() (err error) {
216262
return errors.Join(err, cmdResults.GetErrors())
217263
}
218264

219-
if err = cmdResults.GetErrors(); err != nil {
265+
if err := cmdResults.GetErrors(); err != nil {
220266
return err
221267
}
222268

@@ -229,10 +275,10 @@ func logScanPaths(workingDirs []string) {
229275
return
230276
}
231277
if len(workingDirs) == 1 {
232-
log.Info("Scanning path:", workingDirs[0])
278+
log.Debug("Scanning path:", workingDirs[0])
233279
return
234280
}
235-
log.Info("Scanning paths:", strings.Join(workingDirs, ", "))
281+
log.Debug("Scanning paths:", strings.Join(workingDirs, ", "))
236282
}
237283

238284
func populateScanTargets(cmdResults *results.SecurityCommandResults, workingDirs []string) {
@@ -244,17 +290,8 @@ func populateScanTargets(cmdResults *results.SecurityCommandResults, workingDirs
244290
cmdResults.NewScanResults(results.ScanTarget{Target: requestedDirectory, Name: filepath.Base(requestedDirectory)})
245291
}
246292

247-
if len(workingDirs) == 0 {
248-
currentDir, err := coreutils.GetWorkingDirectory()
249-
if err != nil {
250-
cmdResults.AddGeneralError(fmt.Errorf("failed to get current working directory: %w", err), false)
251-
return
252-
}
253-
cmdResults.NewScanResults(results.ScanTarget{Target: currentDir, Name: filepath.Base(currentDir)})
254-
}
255-
256293
if len(cmdResults.Targets) == 0 {
257-
log.Warn("No scan targets were detected. Proceeding with empty scan...")
294+
log.Warn("No scan targets were detected.")
258295
return
259296
}
260297

go.mod

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -135,7 +135,7 @@ require (
135135
gopkg.in/warnings.v0 v0.1.2 // indirect
136136
)
137137

138-
replace github.com/jfrog/jfrog-client-go => github.com/barv-jfrog/jfrog-client-go v0.0.0-20251201141602-632626d6c959
138+
replace github.com/jfrog/jfrog-client-go => github.com/barv-jfrog/jfrog-client-go v0.0.0-20251215101028-5969e0b31b56
139139

140140
// replace github.com/jfrog/jfrog-cli-core/v2 => github.com/jfrog/jfrog-cli-core/v2 master
141141

go.sum

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -23,8 +23,8 @@ github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5 h1:0CwZNZbxp69SHPd
2323
github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5/go.mod h1:wHh0iHkYZB8zMSxRWpUBQtwG5a7fFgvEO+odwuTv2gs=
2424
github.com/barv-jfrog/jfrog-apps-config v0.0.0-20250128142442-6fd49006bb85 h1:kNdHaJdeD1QBQ0czgrfKqrcND3T+6dInSI8s23lW4Cw=
2525
github.com/barv-jfrog/jfrog-apps-config v0.0.0-20250128142442-6fd49006bb85/go.mod h1:8AIIr1oY9JuH5dylz2S6f8Ym2MaadPLR6noCBO4C22w=
26-
github.com/barv-jfrog/jfrog-client-go v0.0.0-20251201141602-632626d6c959 h1:Wr8RuVIeQVPyhxpT2oonIBaWZVuzP6zTqJ3ruys5ihs=
27-
github.com/barv-jfrog/jfrog-client-go v0.0.0-20251201141602-632626d6c959/go.mod h1:ureS+L3wNs0qYUBSwH8C9PjwnraTX9ibZu7JkaqjO/E=
26+
github.com/barv-jfrog/jfrog-client-go v0.0.0-20251215101028-5969e0b31b56 h1:Mz0F8nWUBTwzJ3ZXuitvXcYBrO7Q43RrofFdm8CBEyo=
27+
github.com/barv-jfrog/jfrog-client-go v0.0.0-20251215101028-5969e0b31b56/go.mod h1:WQ5Y+oKYyHFAlCbHN925bWhnShTd2ruxZ6YTpb76fpU=
2828
github.com/beevik/etree v1.6.0 h1:u8Kwy8pp9D9XeITj2Z0XtA5qqZEmtJtuXZRQi+j03eE=
2929
github.com/beevik/etree v1.6.0/go.mod h1:bh4zJxiIr62SOf9pRzN7UUYaEDa9HEKafK25+sLc0Gc=
3030
github.com/bradleyjkemp/cupaloy/v2 v2.8.0 h1:any4BmKE+jGIaMpnU8YgH/I2LPiLBufr6oMMlVBbn9M=
@@ -156,14 +156,10 @@ github.com/jfrog/froggit-go v1.20.6 h1:Xp7+LlEh0m1KGrQstb+u0aGfjRUtv1eh9xQBV3571
156156
github.com/jfrog/froggit-go v1.20.6/go.mod h1:obSG1SlsWjktkuqmKtpq7MNTTL63e0ot+ucTnlOMV88=
157157
github.com/jfrog/gofrog v1.7.6 h1:QmfAiRzVyaI7JYGsB7cxfAJePAZTzFz0gRWZSE27c6s=
158158
github.com/jfrog/gofrog v1.7.6/go.mod h1:ntr1txqNOZtHplmaNd7rS4f8jpA5Apx8em70oYEe7+4=
159-
github.com/jfrog/jfrog-apps-config v1.0.1 h1:mtv6k7g8A8BVhlHGlSveapqf4mJfonwvXYLipdsOFMY=
160-
github.com/jfrog/jfrog-apps-config v1.0.1/go.mod h1:8AIIr1oY9JuH5dylz2S6f8Ym2MaadPLR6noCBO4C22w=
161159
github.com/jfrog/jfrog-cli-artifactory v0.8.1-0.20251211075913-35ebcd308e93 h1:rpkJZN0TigpAGY/bfgmLO4nwhyhkr0gkBTLz/0B5zS8=
162160
github.com/jfrog/jfrog-cli-artifactory v0.8.1-0.20251211075913-35ebcd308e93/go.mod h1:7cCaRhXorlbyXZgiW5bplCExFxlnROaG21K12d8inpQ=
163161
github.com/jfrog/jfrog-cli-core/v2 v2.60.1-0.20251210085744-f8481d179ac5 h1:GYE67ubwl+ZRw3CcXFUi49EwwQp6k+qS8sX0QuHDHO8=
164162
github.com/jfrog/jfrog-cli-core/v2 v2.60.1-0.20251210085744-f8481d179ac5/go.mod h1:BMoGi2rG0udCCeaghqlNgiW3fTmT+TNnfTnBoWFYgcg=
165-
github.com/jfrog/jfrog-client-go v1.55.1-0.20251211124639-306f15dbcf29 h1:u+FMai2cImOJExJ1Ehe8JsrpAXmPyRaDXwM60wV3bPA=
166-
github.com/jfrog/jfrog-client-go v1.55.1-0.20251211124639-306f15dbcf29/go.mod h1:WQ5Y+oKYyHFAlCbHN925bWhnShTd2ruxZ6YTpb76fpU=
167163
github.com/jhump/protoreflect v1.15.1 h1:HUMERORf3I3ZdX05WaQ6MIpd/NJ434hTp5YiKgfCL6c=
168164
github.com/jhump/protoreflect v1.15.1/go.mod h1:jD/2GMKKE6OqX8qTjhADU1e6DShO+gavG9e0Q693nKo=
169165
github.com/k0kubun/colorstring v0.0.0-20150214042306-9440f1994b88/go.mod h1:3w7q1U84EfirKl04SVQ/s7nPm1ZPhiXd34z40TNz36k=

jas/maliciouscode/maliciouscodescanner.go

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ import (
1515

1616
const (
1717
maliciousScanCommand = "mal"
18+
malDocsUrlSuffix = ""
1819

1920
MaliciousScannerType MaliciousScanType = "malicious-scan" // #nosec
2021
)
@@ -73,7 +74,7 @@ func (mal *MaliciousScanManager) Run(module jfrogappsconfig.Module) (vulnerabili
7374
if err = mal.runAnalyzerManager(); err != nil {
7475
return
7576
}
76-
return jas.ReadJasScanRunsFromFile(mal.resultsFileName, module.SourceRoot, "", mal.scanner.MinSeverity)
77+
return jas.ReadJasScanRunsFromFile(mal.resultsFileName, module.SourceRoot, malDocsUrlSuffix, mal.scanner.MinSeverity)
7778
}
7879

7980
type maliciousScanConfig struct {

jas/maliciouscode/maliciouscodescanner_test.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -101,7 +101,7 @@ func TestParseResults_EmptyResults(t *testing.T) {
101101
maliciousScanManager.resultsFileName = filepath.Join(jas.GetTestDataPath(), "malicious-scan", "no-malicious.sarif")
102102

103103
// Act
104-
vulnerabilitiesResults, _, err := jas.ReadJasScanRunsFromFile(maliciousScanManager.resultsFileName, jfrogAppsConfigForTest.Modules[0].SourceRoot, "", scanner.MinSeverity)
104+
vulnerabilitiesResults, _, err := jas.ReadJasScanRunsFromFile(maliciousScanManager.resultsFileName, jfrogAppsConfigForTest.Modules[0].SourceRoot, malDocsUrlSuffix, scanner.MinSeverity)
105105

106106
// Assert
107107
if assert.NoError(t, err) && assert.NotNil(t, vulnerabilitiesResults) {
@@ -122,7 +122,7 @@ func TestParseResults_ResultsContainMalicious(t *testing.T) {
122122
maliciousScanManager.resultsFileName = filepath.Join(jas.GetTestDataPath(), "malicious-scan", "contain-malicious.sarif")
123123

124124
// Act
125-
vulnerabilitiesResults, _, err := jas.ReadJasScanRunsFromFile(maliciousScanManager.resultsFileName, jfrogAppsConfigForTest.Modules[0].SourceRoot, "", severityutils.Medium)
125+
vulnerabilitiesResults, _, err := jas.ReadJasScanRunsFromFile(maliciousScanManager.resultsFileName, jfrogAppsConfigForTest.Modules[0].SourceRoot, malDocsUrlSuffix, severityutils.Medium)
126126

127127
// Assert
128128
if assert.NoError(t, err) && assert.NotNil(t, vulnerabilitiesResults) {

jas/runner/jasrunner.go

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -73,9 +73,11 @@ func AddJasScannersTasks(params JasRunnerParams) error {
7373
errorsCollection = errors.Join(errorsCollection, generalError)
7474
}
7575

76-
if generalError := addJasScanTaskForModuleIfNeeded(params, utils.MaliciousCodeScan, runMaliciousScan(&params)); generalError != nil {
77-
// Scan task addition failure should not impact the other scanners tasks addition, therefore we accumulate the errors and return the overall error at the end.
78-
errorsCollection = errors.Join(errorsCollection, generalError)
76+
if slices.Contains(params.ScansToPerform, utils.MaliciousCodeScan) {
77+
if generalError := addJasScanTaskForModuleIfNeeded(params, utils.MaliciousCodeScan, runMaliciousScan(&params)); generalError != nil {
78+
// Scan task addition failure should not impact the other scanners tasks addition, therefore we accumulate the errors and return the overall error at the end.
79+
errorsCollection = errors.Join(errorsCollection, generalError)
80+
}
7981
}
8082

8183
if !runAllScanners {

0 commit comments

Comments
 (0)