Skip to content

add IncludeDirs option to Xray Bom Lib#670

Open
attiasas wants to merge 40 commits intojfrog:devfrom
attiasas:pass_wd_to_xray_lib
Open

add IncludeDirs option to Xray Bom Lib#670
attiasas wants to merge 40 commits intojfrog:devfrom
attiasas:pass_wd_to_xray_lib

Conversation

@attiasas
Copy link
Copy Markdown
Collaborator

@attiasas attiasas commented Feb 12, 2026

Support multiple working dirs with single-target scan flow & deprecate jfrog-apps-config in new flow

Summary

Refactors the audit scan pipeline to support multiple working directories via a single scan target (--static-sca / Xray lib flow), and deprecates the jfrog-apps-config.yml module system for JAS scans in the new flow. Scan configuration (include/exclude patterns, central config modules) is now carried directly on ScanTarget instead of being resolved through jfrog-apps-config modules.

Depends on:

  • XRAY-135682 (bug: secrets/CA when multiple roots are passed)
  • XRAY-138915 (improvement: iac does not support multiple roots)

Analyzer-Manager minimum version: 1.33.0

Changes

  • ScanTarget extended – added Include, Exclude, DeprecatedAppsConfigModule, and CentralConfigModules fields; added methods IsScanRequestedByCentralConfig, GetCentralConfigExclusions, GetDeprecatedAppsConfigModuleExclusions.
  • New single-target detection (createSingleScanTarget) – when the new flow (Xray lib BOM generator) is active, a single ScanTarget is created with the working directories as include paths, instead of detecting one target per technology directory.
  • JAS scanners refactored – every scanner (Secrets, IaC, SAST, Applicability) now exposes two code paths: Run(target ScanTarget) (new flow, target-based) and DeprecatedRun(module, centralConfigExclusions) (old flow, module-based). Config file generation, exclude-pattern resolution, and SARIF result reading follow the same split.
  • jfrog-apps-config deprecated in new flowAppsConfigModule replaced by DeprecatedAppsConfigModule; config loading only happens in the old (graph-based) flow. A deprecation warning is emitted when the file is detected.
  • Exclude/include patterns moved to target levelScanTarget.Exclude is set during target detection and passed through to BOM generation (Xray lib IgnorePatterns + IncludeDirs) and all JAS scanner config files.
  • Central config profile support per-targetmatchCentralConfigModules assigns profile modules to targets; ShouldSkipScannerByConfigProfile checks enablement per scan type on the target.
  • SARIF invocation reworkfillMissingRequiredInvocationInformation now aggregates execution success and creates a single canonical invocation with include property bag for multi-root targets.
  • SBOM logging moved to bomgenerator – logging of component counts and duration is now in the shared GenerateSbomForTarget instead of duplicated in XrayLibBomGenerator.
  • Utility additionsGetFullPathsWorkingDirs, IsPathExcluded, ElementsEqual, CreateNewInvocation.
  • Tests – new unit tests in commands/audit/audit_test.go, jas/common_test.go, jas/secrets/secretsscanner_test.go, jas/iac/iacscanner_test.go, jas/applicability/applicabilitymanager_test.go, utils/results/results_test.go, utils/paths_test.go, utils/utils_test.go.

Testing

  • New and updated unit tests covering target detection, exclude-pattern resolution, central-config module matching, SARIF invocation creation, and scanner config-file generation.
  • Existing integration tests updated to match new signatures.

Notes

  • In the new flow, jfrog-apps-config.yml is deprecated – flags, env vars, or central JFrog Platform config should be used instead.
  • The old graph-based flow is untouched and still loads jfrog-apps-config as before.

@attiasas attiasas added the ignore for release Automatically generated release notes label Feb 12, 2026
@attiasas attiasas added the safe to test Approve running integration tests on a pull request label Feb 12, 2026
@github-actions github-actions Bot removed the safe to test Approve running integration tests on a pull request label Feb 12, 2026
@attiasas attiasas added the safe to test Approve running integration tests on a pull request label Feb 17, 2026
@github-actions github-actions Bot removed the safe to test Approve running integration tests on a pull request label Feb 17, 2026
@attiasas attiasas added the safe to test Approve running integration tests on a pull request label Feb 19, 2026
@github-actions github-actions Bot removed the safe to test Approve running integration tests on a pull request label Apr 13, 2026
@github-actions
Copy link
Copy Markdown

github-actions Bot commented May 4, 2026

👍 Frogbot scanned this pull request and did not find any new security issues.


Comment thread jas/common.go
return []string{target.Target}
}

func GetWorkingDirsFromTarget(target results.ScanTarget) []string {
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Unused func, delete

Comment thread jas/common.go

func (a *JasScanner) Run(scannerCmd ScannerCmd, module jfrogappsconfig.Module) (vulnerabilitiesSarifRuns []*sarif.Run, violationsSarifRuns []*sarif.Run, err error) {
func (a *JasScanner) DeprecatedRun(scannerCmd ScannerCmd, module jfrogappsconfig.Module, centralConfigExclusions []string) (vulnerabilitiesSarifRuns []*sarif.Run, violationsSarifRuns []*sarif.Run, err error) {
func() {
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we can remove the func() {...}() wrapper - it adds no value it wraps it and calls the func inside DeprecatedRun.

Comment thread utils/results/results.go
if len(st.Include) > 0 {
relativePaths := []string{}
for _, path := range st.Include {
relativePaths = append(relativePaths, utils.GetRelativePath(path, st.Target))
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

aren't they already relative paths here?

Comment thread utils/results/results.go
return false
}

func (st ScanTarget) String() (str string) {
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

  1. in line 267 do str += st.Name or you'll erase the previous step of the Target/Target + Include dirs
  2. The log can contain Target + Include dirs + Name + techs and it will look like that:
    {} [].
    maybe we should make it a bit more readable, like:
    : {} [technologies: ]

Comment thread utils/results/common.go
relative := utils.GetRelativePath(potential.Target, sourceBasePath)
log.Debug(fmt.Sprintf("Comparing target %s, relative: '%s'", potential.String(), relative))
if technology != techutils.NoTech && potential.Technology != technology {
if len(technologies) > 0 && !utils.ElementsEqual[techutils.Technology](potential.Technologies, technologies) {
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

maybe not something we want to address but maybe worth noting- if a new tech is added in a PR (new module or something) we will find no match. this is a edge case but maybe worth a comment

Comment thread utils/paths.go
return filepath.Join(curationFolder, "nuget"), nil
}

func GetFullPathsWorkingDirs(workingDirs []string) ([]string, error) {
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

can maybe be replaced with coreutils.GetFullPathsWorkingDirs

Comment thread commands/audit/audit.go
})
}
// Load deprecated apps config information for all targets
if params.DeprecatedAppsConfig() == nil && !isNewFlow(params.bomGenerator) {
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

shouldn't it be params.DeprecatedAppsConfig != nil ?

return
}

func runApplicabilityScan(applicabilityScanManager *ApplicabilityScanManager, params ContextualAnalysisScanParams) (vulnerabilitiesSarifRuns []*sarif.Run, err error) {
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why manager is passed as a param and it is not a method?

Comment thread jas/iac/iacscanner.go
return
}

func runIacScan(iacScanManager *IacScanManager, params IacScanParams) (vulnerabilitiesResults []*sarif.Run, violationsResults []*sarif.Run, err error) {
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why manager is passed as a param and it is not a method?

Comment thread jas/sast/sastscanner.go
return
}

func runSastScan(sastScanManager *SastScanManager, params SastScanParams) (vulnerabilitiesResults []*sarif.Run, violationsResults []*sarif.Run, err error) {
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why manager is passed as a param and it is not a method?

return
}

func runSecretsScan(secretScanManager *SecretScanManager, params SecretsScanParams) (vulnerabilitiesResults []*sarif.Run, violationsResults []*sarif.Run, err error) {
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why manager is passed as a param and it is not a method?

Comment thread jas/common.go
log.Debug(fmt.Sprintf("Skipping %s scan as requested by '%s' config profile...", jasType, configProfile.ProfileName))
return true
}
// validate target is excluded by config profile exclude patterns
Copy link
Copy Markdown
Contributor

@eranturgeman eranturgeman May 7, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

// validate IF target is excluded by config profile exclude patterns

Comment thread jas/common_test.go
require.Equal(t, "dir/file2", sarifutils.GetLocationFileName(result.Locations[0]))
}

func TestShouldSkipScannerByConfigProfile(t *testing.T) {
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

what about test for ShouldSkipScannerByModule

Comment thread sca/bom/bomgenerator.go

func GenerateSbomForTarget(generator SbomGenerator, params SbomGeneratorParams) {
startLog := "Generating SBOM"
if params.TotalTargets > 1 {
Copy link
Copy Markdown
Contributor

@eranturgeman eranturgeman May 7, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

just making sure - it TotalTarget > 1, do we have them all in params.Target.Target?.
Also change the log to " for targets: %s"

Comment thread sca/bom/bomgenerator.go
}
outLog := "SBOM generated"
if totalTargets > 1 {
outLog += fmt.Sprintf(" for target '%s'", target)
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

also here, it totalTargets > 1 we need to change the log to " for targets ..."

Comment thread sca/scan/scascan.go
log.Debug(fmt.Sprintf("%sSkipping SCA for %s as requested by input...", logPrefix, params.ScanResults.Target))
return false, nil
}
if params.ScanResults == nil {
Copy link
Copy Markdown
Contributor

@eranturgeman eranturgeman May 10, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I see this check existed before, but I dont think it is really a possible usecase. we can leave it for safety though

}

func TestPrepareSimpleJsonVulnerabilities_Technology(t *testing.T) {
testCases := []struct {
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

maybe add another testcase with multi-rows and different technologies?

return
}
// Applicability scan does not produce violations.
vulnerabilitiesSarifRuns, _, err = applicabilityScanManager.scanner.DeprecatedRun(applicabilityScanManager, *params.Target.DeprecatedAppsConfigModule, params.Target.GetCentralConfigExclusions(utils.ContextualAnalysisScan))
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

please check that calling GetCentralConfigExclusions is the correct call here. Here we are at the Deprecated case but we are callign the new GetExclusions func (which doesnt include AppsConfig)

Comment thread jas/iac/iacscanner.go
if params.Target.DeprecatedAppsConfigModule == nil {
return iacScanManager.scanner.Run(iacScanManager, params.Target)
}
return iacScanManager.scanner.DeprecatedRun(iacScanManager, *params.Target.DeprecatedAppsConfigModule, params.Target.GetCentralConfigExclusions(utils.IacScan))
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

please check that calling GetCentralConfigExclusions is the correct call here. Here we are at the Deprecated case but we are callign the new GetExclusions func (which doesnt include AppsConfig)

Comment thread jas/sast/sastscanner.go
if params.Target.DeprecatedAppsConfigModule == nil {
return sastScanManager.scanner.Run(sastScanManager, params.Target)
}
return sastScanManager.scanner.DeprecatedRun(sastScanManager, *params.Target.DeprecatedAppsConfigModule, params.Target.GetCentralConfigExclusions(utils.SastScan))
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

please check that calling GetCentralConfigExclusions is the correct call here. Here we are at the Deprecated case but we are callign the new GetExclusions func (which doesnt include AppsConfig)

Comment thread utils/utils_test.go
slice1 []string
slice2 []string
expected bool
}{
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

please add testcases of:
slice1: {a, b, c}
slice2: (a, b, b)

slice1: {a,b,b}
slice2: {a,b,c}

Comment thread utils/utils.go
freq[v]++
}
for _, v := range slice2 {
freq[v]--
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

if v doesnt exist here wont we get a panic?
for example slice1 = {a,b,b}, slice2={a,c,b}
when we try doing freq["c"]-- I think we get a panic

Copy link
Copy Markdown
Contributor

@eranturgeman eranturgeman left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM! see my comments

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

ignore for release Automatically generated release notes

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants