Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
27 commits
Select commit Hold shift + click to select a range
32dc1fb
add IncludeDirs option to Xray Bom Lib
attiasas Feb 12, 2026
1a1a659
prepare to pass working dirs
attiasas Feb 12, 2026
26955ad
format
attiasas Feb 12, 2026
b004474
use isSingleTarget, start deprecate old JAS interface to remove apps-…
attiasas Feb 12, 2026
c33f179
Merge remote-tracking branch 'upstream/dev' into pass_wd_to_xray_lib
attiasas Feb 12, 2026
d641985
deprecate JAS apps config module, use scan target
attiasas Feb 12, 2026
12005ea
new scan target detection logic
attiasas Feb 13, 2026
abc25bb
start impl new flow in Secrets
attiasas Feb 13, 2026
5fb9622
update xray lib to 0.0.3-47
attiasas Feb 16, 2026
1bff793
fix tests
attiasas Feb 16, 2026
1d4fd00
Merge remote-tracking branch 'upstream/dev' into pass_wd_to_xray_lib
attiasas Feb 17, 2026
8eac512
fix static tests
attiasas Feb 17, 2026
1ec4aeb
Merge remote-tracking branch 'upstream/dev' into pass_wd_to_xray_lib
attiasas Feb 17, 2026
4711afb
Fix target creation and JAS results parsing
attiasas Feb 19, 2026
d0f5aed
pass target to applicable, fix invocations
attiasas Feb 19, 2026
803b115
fix get cwd as path in old flow and tech aggregator for target
attiasas Feb 19, 2026
1c8f55d
fix wd in sarif
attiasas Feb 19, 2026
c1d2f08
fix get module for old flow
attiasas Feb 19, 2026
f6fb891
make sure sarif sca invocation also include the included wd
attiasas Feb 19, 2026
4f2aa4b
move configs to ScanTarget. refactor and fix exclude for target and s…
attiasas Feb 21, 2026
8b4f728
fix some tests
attiasas Feb 22, 2026
7385416
fix static
attiasas Feb 23, 2026
721a304
Merge remote-tracking branch 'upstream/dev' into pass_wd_to_xray_lib
attiasas Feb 24, 2026
f107544
Merge remote-tracking branch 'upstream/dev' into pass_wd_to_xray_lib
attiasas Feb 25, 2026
7cc338b
Fix apps config
attiasas Feb 25, 2026
3540e40
remove uneeded comment
attiasas Feb 25, 2026
18e78fd
Merge remote-tracking branch 'upstream/dev' into pass_wd_to_xray_lib
attiasas Mar 10, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
191 changes: 135 additions & 56 deletions commands/audit/audit.go

Large diffs are not rendered by default.

218 changes: 218 additions & 0 deletions commands/audit/audit_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -190,10 +190,221 @@ func TestDetectScansToPerform(t *testing.T) {
},
},
},
{
name: "Non-recursive scan on directory with descriptor at top level",
wd: dir,
params: func() *AuditParams {
param := NewAuditParams().SetWorkingDirs([]string{filepath.Join(dir, "dir", "npm")})
param.SetIsRecursiveScan(false)
return param
},
expected: []*results.TargetResults{
{
ScanTarget: results.ScanTarget{
Technology: techutils.Npm,
Target: filepath.Join(dir, "dir", "npm"),
},
JasResults: &results.JasScansResults{JasVulnerabilities: results.JasScanResults{}, JasViolations: results.JasScanResults{}},
ScaResults: &results.ScaScanResults{
Descriptors: []string{filepath.Join(dir, "dir", "npm", "package.json")},
},
},
},
},
{
name: "Single technology (npm only)",
wd: dir,
params: func() *AuditParams {
param := NewAuditParams().SetWorkingDirs([]string{dir})
param.SetTechnologies([]string{"npm"}).SetIsRecursiveScan(true)
return param
},
expected: []*results.TargetResults{
{
ScanTarget: results.ScanTarget{
Technology: techutils.Npm,
Target: filepath.Join(dir, "dir", "npm"),
},
JasResults: &results.JasScansResults{JasVulnerabilities: results.JasScanResults{}, JasViolations: results.JasScanResults{}},
ScaResults: &results.ScaScanResults{
Descriptors: []string{filepath.Join(dir, "dir", "npm", "package.json")},
},
},
{
// Requested tech npm had no other descriptors at root; add JAS-only target for requested directory
ScanTarget: results.ScanTarget{
Target: dir,
},
JasResults: &results.JasScansResults{JasVulnerabilities: results.JasScanResults{}, JasViolations: results.JasScanResults{}},
},
},
},
{
name: "Multiple working dirs (subset - dir and yarn only, no Nuget)",
wd: dir,
params: func() *AuditParams {
param := NewAuditParams().SetWorkingDirs([]string{filepath.Join(dir, "dir"), filepath.Join(dir, "yarn")})
param.SetIsRecursiveScan(true)
return param
},
expected: []*results.TargetResults{
{
ScanTarget: results.ScanTarget{
Technology: techutils.Go,
Target: filepath.Join(dir, "dir", "go"),
},
JasResults: &results.JasScansResults{JasVulnerabilities: results.JasScanResults{}, JasViolations: results.JasScanResults{}},
ScaResults: &results.ScaScanResults{
Descriptors: []string{filepath.Join(dir, "dir", "go", "go.mod")},
},
},
{
ScanTarget: results.ScanTarget{
Technology: techutils.Maven,
Target: filepath.Join(dir, "dir", "maven"),
},
JasResults: &results.JasScansResults{JasVulnerabilities: results.JasScanResults{}, JasViolations: results.JasScanResults{}},
ScaResults: &results.ScaScanResults{
Descriptors: []string{
filepath.Join(dir, "dir", "maven", "maven-sub", "pom.xml"),
filepath.Join(dir, "dir", "maven", "maven-sub2", "pom.xml"),
filepath.Join(dir, "dir", "maven", "pom.xml"),
},
},
},
{
ScanTarget: results.ScanTarget{
Technology: techutils.Npm,
Target: filepath.Join(dir, "dir", "npm"),
},
JasResults: &results.JasScansResults{JasVulnerabilities: results.JasScanResults{}, JasViolations: results.JasScanResults{}},
ScaResults: &results.ScaScanResults{
Descriptors: []string{filepath.Join(dir, "dir", "npm", "package.json")},
},
},
{
ScanTarget: results.ScanTarget{
Technology: techutils.Pip,
Target: filepath.Join(dir, "yarn", "Pip"),
},
JasResults: &results.JasScansResults{JasVulnerabilities: results.JasScanResults{}, JasViolations: results.JasScanResults{}},
ScaResults: &results.ScaScanResults{
Descriptors: []string{filepath.Join(dir, "yarn", "Pip", "requirements.txt")},
},
},
{
ScanTarget: results.ScanTarget{
Technology: techutils.Pipenv,
Target: filepath.Join(dir, "yarn", "Pipenv"),
},
JasResults: &results.JasScansResults{JasVulnerabilities: results.JasScanResults{}, JasViolations: results.JasScanResults{}},
ScaResults: &results.ScaScanResults{
Descriptors: []string{filepath.Join(dir, "yarn", "Pipenv", "Pipfile")},
},
},
{
ScanTarget: results.ScanTarget{
Technology: techutils.Yarn,
Target: filepath.Join(dir, "yarn"),
},
JasResults: &results.JasScansResults{JasVulnerabilities: results.JasScanResults{}, JasViolations: results.JasScanResults{}},
ScaResults: &results.ScaScanResults{
Descriptors: []string{filepath.Join(dir, "yarn", "package.json")},
},
},
},
},
{
name: "Single technology (maven only)",
wd: dir,
params: func() *AuditParams {
param := NewAuditParams().SetWorkingDirs([]string{filepath.Join(dir, "dir", "maven")})
param.SetIsRecursiveScan(true)
return param
},
expected: []*results.TargetResults{
{
ScanTarget: results.ScanTarget{
Technology: techutils.Maven,
Target: filepath.Join(dir, "dir", "maven"),
},
JasResults: &results.JasScansResults{JasVulnerabilities: results.JasScanResults{}, JasViolations: results.JasScanResults{}},
ScaResults: &results.ScaScanResults{
Descriptors: []string{
filepath.Join(dir, "dir", "maven", "maven-sub", "pom.xml"),
filepath.Join(dir, "dir", "maven", "maven-sub2", "pom.xml"),
filepath.Join(dir, "dir", "maven", "pom.xml"),
},
},
},
},
},
{
name: "Non-recursive on go directory",
wd: dir,
params: func() *AuditParams {
param := NewAuditParams().SetWorkingDirs([]string{filepath.Join(dir, "dir", "go")})
param.SetIsRecursiveScan(false)
return param
},
expected: []*results.TargetResults{
{
ScanTarget: results.ScanTarget{
Technology: techutils.Go,
Target: filepath.Join(dir, "dir", "go"),
},
JasResults: &results.JasScansResults{JasVulnerabilities: results.JasScanResults{}, JasViolations: results.JasScanResults{}},
ScaResults: &results.ScaScanResults{
Descriptors: []string{filepath.Join(dir, "dir", "go", "go.mod")},
},
},
},
},
{
name: "Single target with one working dir (npm)",
wd: dir,
params: func() *AuditParams {
param := NewAuditParams().SetWorkingDirs([]string{filepath.Join(dir, "dir", "npm")})
param.SetIsSingleTarget(true).SetIsRecursiveScan(false)
return param
},
expected: []*results.TargetResults{
{
ScanTarget: results.ScanTarget{
Target: dir,
Include: []string{filepath.Join(dir, "dir", "npm")},
Technology: techutils.Npm,
},
JasResults: &results.JasScansResults{JasVulnerabilities: results.JasScanResults{}, JasViolations: results.JasScanResults{}},
},
},
},
{
name: "Single target with one working dir (maven)",
wd: dir,
params: func() *AuditParams {
param := NewAuditParams().SetWorkingDirs([]string{filepath.Join(dir, "dir", "maven")})
param.SetIsSingleTarget(true).SetIsRecursiveScan(false)
return param
},
expected: []*results.TargetResults{
{
ScanTarget: results.ScanTarget{
Target: dir,
Include: []string{filepath.Join(dir, "dir", "maven")},
Technology: techutils.Maven,
},
JasResults: &results.JasScansResults{JasVulnerabilities: results.JasScanResults{}, JasViolations: results.JasScanResults{}},
},
},
},
}

for _, test := range tests {
t.Run(test.name, func(t *testing.T) {
if test.wd != "" {
defer securityTestUtils.ChangeWDWithCallback(t, test.wd)()
}
results := results.NewCommandResults(utils.SourceCode).SetEntitledForJas(true).SetSecretValidation(true)
detectScanTargets(results, test.params())
if assert.Len(t, results.Targets, len(test.expected)) {
Expand All @@ -210,6 +421,13 @@ func TestDetectScansToPerform(t *testing.T) {
if test.expected[i].ScaResults != nil {
sort.Strings(test.expected[i].ScaResults.Descriptors)
}
// Normalize for comparison: DeprecatedAppsConfigModule varies by working dir and is not under test
results.Targets[i].DeprecatedAppsConfigModule = nil
// Normalize single-target expected to actual cwd (path can differ e.g. /var vs /private/var on macOS)
if len(results.Targets) == 1 && len(results.Targets[i].Include) > 0 {
test.expected[i].Target = results.Targets[i].Target
test.expected[i].Include = results.Targets[i].Include
}
}
}
assert.ElementsMatch(t, test.expected, results.Targets)
Expand Down
26 changes: 24 additions & 2 deletions commands/audit/auditparams.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package audit
import (
"time"

jfrogappsconfig "github.com/jfrog/jfrog-apps-config/go"
"github.com/jfrog/jfrog-client-go/xray/services"
xscServices "github.com/jfrog/jfrog-client-go/xsc/services"

Expand All @@ -18,10 +19,13 @@ import (
)

type AuditParams struct {
// Where to scan
appsConfig *jfrogappsconfig.JFrogAppsConfig
workingDirs []string
isSingleTarget bool
// Common params to all scan routines
resultsContext results.ResultContext
gitContext *xscServices.XscGitInfoContext
workingDirs []string
installFunc func(tech string) error
fixableOnly bool
minSeverityFilter severityutils.Severity
Expand Down Expand Up @@ -192,6 +196,15 @@ func (params *AuditParams) SetScansResultsOutputDir(outputDir string) *AuditPara
return params
}

func (params *AuditParams) SetIsSingleTarget(isSingleTarget bool) *AuditParams {
params.isSingleTarget = isSingleTarget
return params
}

func (params *AuditParams) IsSingleTarget() bool {
return params.isSingleTarget
}

func (params *AuditParams) createXrayGraphScanParams() *services.XrayGraphScanParams {
return &services.XrayGraphScanParams{
RepoPath: params.resultsContext.RepoPath,
Expand All @@ -212,7 +225,7 @@ func (params *AuditParams) ToBuildInfoBomGenParams() (bomParams technologies.Bui
bomParams = technologies.BuildInfoBomGeneratorParams{
XrayVersion: params.GetXrayVersion(),
Progress: params.Progress(),
ExclusionPattern: technologies.GetExcludePattern(params.GetConfigProfile(), params.IsRecursiveScan(), params.Exclusions()...),
ExclusionPattern: technologies.GetScaExcludePattern(params.GetConfigProfile(), params.IsRecursiveScan(), params.Exclusions()...),
AllowPartialResults: params.AllowPartialResults(),
// Artifactory repository info
ServerDetails: serverDetails,
Expand Down Expand Up @@ -263,6 +276,15 @@ func (params *AuditParams) SetFilesToScan(filesToScan []string) *AuditParams {
return params
}

func (params *AuditParams) SetDeprecatedAppsConfig(appsConfig *jfrogappsconfig.JFrogAppsConfig) *AuditParams {
params.appsConfig = appsConfig
return params
}

func (params *AuditParams) DeprecatedAppsConfig() *jfrogappsconfig.JFrogAppsConfig {
return params.appsConfig
}

func (params *AuditParams) FilesToScan() []string {
return params.filesToScan
}
Expand Down
2 changes: 1 addition & 1 deletion commands/curation/curationaudit.go
Original file line number Diff line number Diff line change
Expand Up @@ -430,7 +430,7 @@ func (ca *CurationAuditCommand) getBuildInfoParamsByTech() (technologies.BuildIn
serverDetails, err := ca.ServerDetails()
return technologies.BuildInfoBomGeneratorParams{
XrayVersion: ca.GetXrayVersion(),
ExclusionPattern: technologies.GetExcludePattern(ca.GetConfigProfile(), ca.IsRecursiveScan(), ca.Exclusions()...),
ExclusionPattern: technologies.GetScaExcludePattern(ca.GetConfigProfile(), ca.IsRecursiveScan(), ca.Exclusions()...),
Progress: ca.Progress(),
// Artifactory Repository params
ServerDetails: serverDetails,
Expand Down
8 changes: 4 additions & 4 deletions commands/scan/scan.go
Original file line number Diff line number Diff line change
Expand Up @@ -565,10 +565,11 @@ func (scanCmd *ScanCommand) getXrayScanGraphParams(msi string) *scangraph.ScanGr

func (scanCmd *ScanCommand) RunBinaryJasScans(cmdType utils.CommandType, msi string, secretValidation bool, targetResults *results.TargetResults, targetCompId string, graphScanResults *services.ScanResponse, jasFileProducerConsumer *utils.SecurityParallelRunner, scanThreadId int) (err error) {
scanLogPrefix := clientutils.GetLogMsgPrefix(scanThreadId, false)
module, err := getJasModule(targetResults)
deprecatedAppsConfigModule, err := getJasDeprecatedAppsConfigModule(targetResults.Target)
if err != nil {
return targetResults.AddTargetError(fmt.Errorf(scanLogPrefix+"jas scanning failed with error: %s", err.Error()), false)
}
targetResults.DeprecatedAppsConfigModule = &deprecatedAppsConfigModule
// Prepare Jas scans
scannerOptions := []jas.JasScannerOption{
jas.WithEnvVars(
Expand Down Expand Up @@ -604,7 +605,6 @@ func (scanCmd *ScanCommand) RunBinaryJasScans(cmdType utils.CommandType, msi str
Runner: jasFileProducerConsumer,
ServerDetails: scanCmd.serverDetails,
Scanner: scanner,
Module: module,
TargetOutputDir: scanCmd.outputDir,
ScansToPerform: scanCmd.scansToPerform,
CvesProvider: func() (directCves []string, indirectCves []string) {
Expand Down Expand Up @@ -646,8 +646,8 @@ func isDockerBinary(cmdType utils.CommandType, targetResults *results.TargetResu
return cmdType == utils.DockerImage || targetResults.Technology == techutils.Docker || targetResults.Technology == techutils.Oci
}

func getJasModule(targetResults *results.TargetResults) (jfrogappsconfig.Module, error) {
jfrogAppsConfig, err := jas.CreateJFrogAppsConfig([]string{targetResults.Target})
func getJasDeprecatedAppsConfigModule(target string) (jfrogappsconfig.Module, error) {
jfrogAppsConfig, err := jas.CreateJFrogAppsConfig([]string{target})
if err != nil {
return jfrogappsconfig.Module{}, err
}
Expand Down
Loading
Loading