Skip to content
Draft
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
97643d2
- Initial Scan config triggered
cx-anjali-deore Mar 18, 2026
9f3d5d2
added aisc summary output
cx-sumit-morchhale Mar 18, 2026
f02279a
Upgrade Containers Resolver V1.0.33 (AST-133418) (#1441)
cx-adar-zandberg Mar 6, 2026
8461e53
Add notification step for Checkmarx scan results
cx-anurag-dalke Mar 10, 2026
3626dfd
Support DA_MIGRATION and configuration for direct association of appl…
cx-anjali-deore Mar 12, 2026
ef4bedb
added aisc summary output
cx-sumit-morchhale Mar 18, 2026
cde6455
Merge remote-tracking branch 'origin/feature/AST-140663-aisc-summaryC…
cx-sumit-morchhale Mar 18, 2026
130fd57
Added check for AISC
cx-sumit-morchhale Mar 18, 2026
af074f6
- Added resubmit config
cx-anjali-deore Mar 18, 2026
82375e0
Merge branch 'main' of https://github.com/Checkmarx/ast-cli into feat…
cx-anjali-deore Mar 18, 2026
9b85876
Support DA_MIGRATION and configuration for direct association of appl…
cx-anjali-deore Mar 12, 2026
e622037
added aisc summary output
cx-sumit-morchhale Mar 18, 2026
d1ac382
Added check for AISC
cx-sumit-morchhale Mar 18, 2026
f49d092
Merge remote-tracking branch 'origin/feature/AST-140663-aisc-summaryC…
cx-sumit-morchhale Mar 18, 2026
c2a8619
- Removed logger
cx-anjali-deore Mar 18, 2026
77a5678
interchnage the order
cx-sumit-morchhale Mar 18, 2026
5e2debc
fix unit and integration test comilatipon error
cx-sumit-morchhale Mar 18, 2026
4da360c
Added unit test cases
cx-sumit-morchhale Mar 18, 2026
bba1b08
Added Integration Test
cx-sumit-morchhale Mar 27, 2026
c10d5cb
- Added unit tests for aisc scan type
cx-anjali-deore Apr 1, 2026
fd02cfc
Merge branch 'feature/AST-140663-aisc-summaryCount' of https://github…
cx-anjali-deore Apr 2, 2026
a7438ab
- go mod
cx-anjali-deore Apr 2, 2026
2646a1f
Merge branch 'main' into feature/ai-supply-chain-scan
cx-anjali-deore Apr 2, 2026
0825d3c
- Added aiSupplyChainGAEnabled FLAG checked
cx-anjali-deore Apr 2, 2026
a5ddf0a
Merge branch 'feature/ai-supply-chain-scan' of https://github.com/Che…
cx-anjali-deore Apr 2, 2026
bbdc576
- Upgraded Go git version
cx-anjali-deore Apr 2, 2026
b2c75c6
fix bom error
cx-sumit-morchhale Apr 2, 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
2 changes: 2 additions & 0 deletions cmd/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,7 @@ func main() {
risksOverviewWrapper := wrappers.NewHTTPRisksOverviewWrapper(risksOverview, apiSecurityResult)
riskManagementWrapper := wrappers.NewHTTPRiskManagementWrapper(riskManagement)
scsScanOverviewWrapper := wrappers.NewHTTPScanOverviewWrapper(scsScanOverview)
scanSummaryWrapper := wrappers.NewHTTPScanSummaryWrapper(scanSummary)
resultsWrapper := wrappers.NewHTTPResultsWrapper(results, scanSummary)
authWrapper := wrappers.NewAuthHTTPWrapper()
resultsPredicatesWrapper := wrappers.NewResultsPredicatesHTTPWrapper()
Expand Down Expand Up @@ -115,6 +116,7 @@ func main() {
risksOverviewWrapper,
riskManagementWrapper,
scsScanOverviewWrapper,
scanSummaryWrapper,
authWrapper,
logsWrapper,
groupsWrapper,
Expand Down
4 changes: 2 additions & 2 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -141,8 +141,8 @@ require (
github.com/gitleaks/go-gitdiff v0.9.1 // indirect
github.com/go-errors/errors v1.5.1 // indirect
github.com/go-git/gcfg v1.5.1-0.20230307220236-3a3c6141e376 // indirect
github.com/go-git/go-billy/v5 v5.6.2 // indirect
github.com/go-git/go-git/v5 v5.16.5 // indirect
github.com/go-git/go-billy/v5 v5.8.0 // indirect
github.com/go-git/go-git/v5 v5.17.1 // indirect
github.com/go-gorp/gorp/v3 v3.1.0 // indirect
github.com/go-logr/logr v1.4.3 // indirect
github.com/go-logr/stdr v1.2.2 // indirect
Expand Down
8 changes: 4 additions & 4 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -386,12 +386,12 @@ github.com/go-errors/errors v1.5.1 h1:ZwEMSLRCapFLflTpT7NKaAc7ukJ8ZPEjzlxt8rPN8b
github.com/go-errors/errors v1.5.1/go.mod h1:sIVyrIiJhuEF+Pj9Ebtd6P/rEYROXFi3BopGUQ5a5Og=
github.com/go-git/gcfg v1.5.1-0.20230307220236-3a3c6141e376 h1:+zs/tPmkDkHx3U66DAb0lQFJrpS6731Oaa12ikc+DiI=
github.com/go-git/gcfg v1.5.1-0.20230307220236-3a3c6141e376/go.mod h1:an3vInlBmSxCcxctByoQdvwPiA7DTK7jaaFDBTtu0ic=
github.com/go-git/go-billy/v5 v5.6.2 h1:6Q86EsPXMa7c3YZ3aLAQsMA0VlWmy43r6FHqa/UNbRM=
github.com/go-git/go-billy/v5 v5.6.2/go.mod h1:rcFC2rAsp/erv7CMz9GczHcuD0D32fWzH+MJAU+jaUU=
github.com/go-git/go-billy/v5 v5.8.0 h1:I8hjc3LbBlXTtVuFNJuwYuMiHvQJDq1AT6u4DwDzZG0=
github.com/go-git/go-billy/v5 v5.8.0/go.mod h1:RpvI/rw4Vr5QA+Z60c6d6LXH0rYJo0uD5SqfmrrheCY=
github.com/go-git/go-git-fixtures/v4 v4.3.2-0.20231010084843-55a94097c399 h1:eMje31YglSBqCdIqdhKBW8lokaMrL3uTkpGYlE2OOT4=
github.com/go-git/go-git-fixtures/v4 v4.3.2-0.20231010084843-55a94097c399/go.mod h1:1OCfN199q1Jm3HZlxleg+Dw/mwps2Wbk9frAWm+4FII=
github.com/go-git/go-git/v5 v5.16.5 h1:mdkuqblwr57kVfXri5TTH+nMFLNUxIj9Z7F5ykFbw5s=
github.com/go-git/go-git/v5 v5.16.5/go.mod h1:QOMLpNf1qxuSY4StA/ArOdfFR2TrKEjJiye2kel2m+M=
github.com/go-git/go-git/v5 v5.17.1 h1:WnljyxIzSj9BRRUlnmAU35ohDsjRK0EKmL0evDqi5Jk=
github.com/go-git/go-git/v5 v5.17.1/go.mod h1:pW/VmeqkanRFqR6AljLcs7EA7FbZaN5MQqO7oZADXpo=
github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU=
github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8=
github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8=
Expand Down
59 changes: 55 additions & 4 deletions internal/commands/result.go
Original file line number Diff line number Diff line change
Expand Up @@ -187,6 +187,7 @@ func NewResultsCommand(
risksOverviewWrapper wrappers.RisksOverviewWrapper,
riskManagementWrapper wrappers.RiskManagementWrapper,
scsScanOverviewWrapper wrappers.ScanOverviewWrapper,
scanSummaryWrapper wrappers.ScanSummaryWrapper,
policyWrapper wrappers.PolicyWrapper,
featureFlagsWrapper wrappers.FeatureFlagsWrapper,
jwtWrapper wrappers.JWTWrapper,
Expand All @@ -203,7 +204,7 @@ func NewResultsCommand(
},
}
showResultCmd := resultShowSubCommand(resultsWrapper, scanWrapper, exportWrapper, resultsPdfReportsWrapper, resultsJSONReportsWrapper,
risksOverviewWrapper, scsScanOverviewWrapper, policyWrapper, featureFlagsWrapper, jwtWrapper)
risksOverviewWrapper, scsScanOverviewWrapper, scanSummaryWrapper, policyWrapper, featureFlagsWrapper, jwtWrapper)
codeBashingCmd := resultCodeBashing(codeBashingWrapper)
bflResultCmd := resultBflSubCommand(bflWrapper)
exitCodeSubcommand := exitCodeSubCommand(scanWrapper)
Expand Down Expand Up @@ -263,6 +264,7 @@ func resultShowSubCommand(
resultsJSONReportsWrapper wrappers.ResultsJSONWrapper,
risksOverviewWrapper wrappers.RisksOverviewWrapper,
scsScanOverviewWrapper wrappers.ScanOverviewWrapper,
scanSummaryWrapper wrappers.ScanSummaryWrapper,
policyWrapper wrappers.PolicyWrapper,
featureFlagsWrapper wrappers.FeatureFlagsWrapper,
jwtWrapper wrappers.JWTWrapper,
Expand All @@ -276,7 +278,7 @@ func resultShowSubCommand(
$ cx results show --scan-id <scan Id>
`,
),
RunE: runGetResultCommand(resultsWrapper, scanWrapper, exportWrapper, resultsPdfReportsWrapper, resultsJSONReportsWrapper, risksOverviewWrapper, scsScanOverviewWrapper, policyWrapper, featureFlagsWrapper, jwtWrapper),
RunE: runGetResultCommand(resultsWrapper, scanWrapper, exportWrapper, resultsPdfReportsWrapper, resultsJSONReportsWrapper, risksOverviewWrapper, scsScanOverviewWrapper, scanSummaryWrapper, policyWrapper, featureFlagsWrapper, jwtWrapper),
}
addScanIDFlag(resultShowCmd, "ID to report on")
addResultFormatFlag(
Expand Down Expand Up @@ -691,6 +693,7 @@ func summaryReport(
policies *wrappers.PolicyResponseModel,
risksOverviewWrapper wrappers.RisksOverviewWrapper,
scsScanOverviewWrapper wrappers.ScanOverviewWrapper,
scanSummaryWrapper wrappers.ScanSummaryWrapper,
featureFlagsWrapper wrappers.FeatureFlagsWrapper,
results *wrappers.ScanResultsCollection,
resultsParams map[string]string,
Expand Down Expand Up @@ -720,6 +723,15 @@ func summaryReport(
summary.SCSOverview = SCSOverview
}

if summary.HasAISC() {
// Getting AISC information from scan-summary API
aiscInfo, err := getAISCInfoFromScanSummary(scanSummaryWrapper, summary.ScanID)
if err != nil {
return nil, err
}
summary.AISCInfo = aiscInfo
}

if policies != nil {
summary.Policies = filterViolatedRules(*policies)
}
Expand Down Expand Up @@ -888,6 +900,10 @@ func writeConsoleSummary(summary *wrappers.ResultSummary, featureFlagsWrapper wr
printSCSSummary(summary.SCSOverview.MicroEngineOverviews, featureFlagsWrapper)
}

if summary.HasAISC() {
printAISCSummary(summary)
}

fmt.Printf(" Checkmarx One - Scan Summary & Details: %s\n", summary.BaseURI)
} else {
fmt.Printf("Scan executed in asynchronous mode or still running. Hence, no results generated.\n")
Expand Down Expand Up @@ -977,6 +993,15 @@ func printSCSTableRow(microEngineOverview *wrappers.MicroEngineOverview, feature
}
}

func printAISCSummary(summary *wrappers.ResultSummary) {
fmt.Printf(" AI SUPPLY CHAIN ENGINE SUMMARY\n")
fmt.Printf(" --------------------------------------------------------------------- \n")
fmt.Printf(" | %-32s %30s |\n", "Category", "Count")
fmt.Printf(" | %-32s %30d |\n", "Total Assets", summary.AISCAssetsValue())
fmt.Printf(" | %-32s %30d |\n", "Total Asset Types", summary.AISCAssetTypesValue())
fmt.Printf(" --------------------------------------------------------------------- \n\n")
}

func getCountValue(count int) interface{} {
if count < 0 {
return disabledString
Expand Down Expand Up @@ -1027,6 +1052,7 @@ func runGetResultCommand(
resultsJSONReportsWrapper wrappers.ResultsJSONWrapper,
risksOverviewWrapper wrappers.RisksOverviewWrapper,
scsScanOverviewWrapper wrappers.ScanOverviewWrapper,
scanSummaryWrapper wrappers.ScanSummaryWrapper,
policyWrapper wrappers.PolicyWrapper,
featureFlagsWrapper wrappers.FeatureFlagsWrapper,
jwtWrapper wrappers.JWTWrapper,
Expand Down Expand Up @@ -1093,7 +1119,7 @@ func runGetResultCommand(
resultsParams[commonParams.SastRedundancyFlag] = ""
}

_, err = CreateScanReport(resultsWrapper, risksOverviewWrapper, scsScanOverviewWrapper, exportWrapper,
_, err = CreateScanReport(resultsWrapper, risksOverviewWrapper, scsScanOverviewWrapper, scanSummaryWrapper, exportWrapper,
policyResponseModel, resultsPdfReportsWrapper, resultsJSONReportsWrapper, scan, format, formatPdfToEmail, formatPdfOptions,
formatSbomOptions, targetFile, targetPath, agent, resultsParams, featureFlagsWrapper, ignorePolicyFlagOmit)
return err
Expand Down Expand Up @@ -1183,6 +1209,7 @@ func CreateScanReport(
resultsWrapper wrappers.ResultsWrapper,
risksOverviewWrapper wrappers.RisksOverviewWrapper,
scsScanOverviewWrapper wrappers.ScanOverviewWrapper,
scanSummaryWrapper wrappers.ScanSummaryWrapper,
exportWrapper wrappers.ExportWrapper,
policyResponseModel *wrappers.PolicyResponseModel,
resultsPdfReportsWrapper wrappers.ResultsPdfWrapper,
Expand Down Expand Up @@ -1220,7 +1247,7 @@ func CreateScanReport(
}
isSummaryNeeded := verifyFormatsByReportList(reportList, summaryFormats...)
if isSummaryNeeded && !scanPending {
summary, err = summaryReport(summary, policyResponseModel, risksOverviewWrapper, scsScanOverviewWrapper, featureFlagsWrapper, results, resultsParams)
summary, err = summaryReport(summary, policyResponseModel, risksOverviewWrapper, scsScanOverviewWrapper, scanSummaryWrapper, featureFlagsWrapper, results, resultsParams)
if err != nil {
return nil, err
}
Expand Down Expand Up @@ -1376,6 +1403,30 @@ func getScanOverviewForSCSScanner(
return nil, nil
}

func getAISCInfoFromScanSummary(
scanSummaryWrapper wrappers.ScanSummaryWrapper,
scanID string,
) (*wrappers.AISCInfo, error) {
var scanSummaryModel *wrappers.ScanSummariesModel
var errorModel *wrappers.WebError

scanSummaryModel, errorModel, err := scanSummaryWrapper.GetScanSummaryByScanID(scanID)
if err != nil {
return nil, errors.Wrapf(err, "AISC: %s", failedListingResults)
}
if errorModel != nil {
return nil, errors.Errorf("AISC: %s: CODE: %d, %s", failedListingResults, errorModel.Code, errorModel.Message)
}
if scanSummaryModel != nil && len(scanSummaryModel.ScansSummaries) > 0 {
aiscCounters := scanSummaryModel.ScansSummaries[0].AiscCounters
return &wrappers.AISCInfo{
TotalAssets: aiscCounters.AssetsCounter, // Map from API response
TotalAssetTypes: aiscCounters.AssetTypesCounter, // Map from API response
}, nil
}
return nil, nil
}

func isScanPending(scanStatus string) bool {
return !(strings.EqualFold(scanStatus, "Completed") || strings.EqualFold(
scanStatus,
Expand Down
139 changes: 139 additions & 0 deletions internal/commands/result_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
"github.com/checkmarx/ast-cli/internal/params"
"github.com/checkmarx/ast-cli/internal/wrappers"
"github.com/checkmarx/ast-cli/internal/wrappers/mock"
"github.com/pkg/errors"
assertion "github.com/stretchr/testify/assert"
"golang.org/x/text/cases"
"golang.org/x/text/language"
Expand Down Expand Up @@ -1740,3 +1741,141 @@
}
}
}

func TestGetAISCInfoFromScanSummary_Success(t *testing.T) {
mockWrapper := &mock.ScanSummaryMockWrapper{}
scanID := "test-scan-id"

result, err := getAISCInfoFromScanSummary(mockWrapper, scanID)

assert.NilError(t, err)
assert.Assert(t, result != nil, "Expected non-nil result")
if result == nil {
return
}
assert.Equal(t, result.TotalAssets, 0, "Expected TotalAssets to be 0")
assert.Equal(t, result.TotalAssetTypes, 0, "Expected TotalAssetTypes to be 0")
}

func TestGetAISCInfoFromScanSummary_WithNonZeroValues(t *testing.T) {
// Create a custom mock wrapper with non-zero values
mockWrapper := &customScanSummaryMockWrapper{
assetsCounter: 10,
assetTypesCounter: 5,
}
scanID := "test-scan-id"

result, err := getAISCInfoFromScanSummary(mockWrapper, scanID)

assert.NilError(t, err)
assert.Assert(t, result != nil, "Expected non-nil result")
if result == nil {
return
}
assert.Equal(t, result.TotalAssets, 10, "Expected TotalAssets to be 10")
assert.Equal(t, result.TotalAssetTypes, 5, "Expected TotalAssetTypes to be 5")
}

func TestGetAISCInfoFromScanSummary_EmptyScansSummaries(t *testing.T) {
mockWrapper := &customScanSummaryMockWrapper{
emptySummaries: true,
}
scanID := "test-scan-id"

result, err := getAISCInfoFromScanSummary(mockWrapper, scanID)

assert.NilError(t, err)
assert.Assert(t, result == nil, "Expected nil result for empty summaries")
}

func TestGetAISCInfoFromScanSummary_NilScanSummaryModel(t *testing.T) {
mockWrapper := &customScanSummaryMockWrapper{
nilModel: true,
}
scanID := "test-scan-id"

result, err := getAISCInfoFromScanSummary(mockWrapper, scanID)

assert.NilError(t, err)
assert.Assert(t, result == nil, "Expected nil result for nil scan summary model")
}

func TestGetAISCInfoFromScanSummary_Error(t *testing.T) {
mockWrapper := &customScanSummaryMockWrapper{
returnError: true,
}
scanID := "test-scan-id"

result, err := getAISCInfoFromScanSummary(mockWrapper, scanID)

assert.Assert(t, err != nil, "Expected error")
assert.Assert(t, result == nil, "Expected nil result on error")
if err == nil {
return
}
assert.Assert(t, strings.Contains(err.Error(), "AISC"), "Expected error message to contain 'AISC'")
assert.Assert(t, strings.Contains(err.Error(), failedListingResults), "Expected error message to contain failedListingResults")
}

func TestGetAISCInfoFromScanSummary_WebError(t *testing.T) {
mockWrapper := &customScanSummaryMockWrapper{
returnWebError: true,
}
scanID := "test-scan-id"

result, err := getAISCInfoFromScanSummary(mockWrapper, scanID)

assert.Assert(t, err != nil, "Expected error")
assert.Assert(t, result == nil, "Expected nil result on web error")
if err == nil {
return
}
assert.Assert(t, strings.Contains(err.Error(), "AISC"), "Expected error message to contain 'AISC'")
assert.Assert(t, strings.Contains(err.Error(), failedListingResults), "Expected error message to contain failedListingResults")
assert.Assert(t, strings.Contains(err.Error(), "CODE: 400"), "Expected error message to contain error code")
assert.Assert(t, strings.Contains(err.Error(), "Bad Request"), "Expected error message to contain error message")
}

// Custom mock wrapper for testing different scenarios
type customScanSummaryMockWrapper struct {
assetsCounter int
assetTypesCounter int
emptySummaries bool
nilModel bool
returnError bool
returnWebError bool
}

func (m *customScanSummaryMockWrapper) GetScanSummaryByScanID(scanID string) (*wrappers.ScanSummariesModel, *wrappers.WebError, error) {
if m.returnError {
return nil, nil, errors.New("mock error from GetScanSummaryByScanID")
}
if m.returnWebError {
return nil, &wrappers.WebError{
Code: 400,
Message: "Bad Request",
}, nil
}
if m.nilModel {
return nil, nil, nil
}
if m.emptySummaries {
return &wrappers.ScanSummariesModel{
ScansSummaries: []wrappers.ScanSumaries{},
TotalCount: 0,
}, nil, nil
}
return &wrappers.ScanSummariesModel{
ScansSummaries: []wrappers.ScanSumaries{
{
ScanID: scanID,
AiscCounters: wrappers.AiscCounters{
AssetsCounter: m.assetsCounter,
AssetTypesCounter: m.assetTypesCounter,
},
},
},
TotalCount: 1,
}, nil, nil
}

Check failure on line 1881 in internal/commands/result_test.go

View workflow job for this annotation

GitHub Actions / lint

File is not properly formatted (gofmt)
3 changes: 3 additions & 0 deletions internal/commands/root.go
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ func NewAstCLI(
risksOverviewWrapper wrappers.RisksOverviewWrapper,
riskManagementWrapper wrappers.RiskManagementWrapper,
scsScanOverviewWrapper wrappers.ScanOverviewWrapper,
scanSummaryWrapper wrappers.ScanSummaryWrapper,
authWrapper wrappers.AuthWrapper,
logsWrapper wrappers.LogsWrapper,
groupsWrapper wrappers.GroupsWrapper,
Expand Down Expand Up @@ -189,6 +190,7 @@ func NewAstCLI(
groupsWrapper,
risksOverviewWrapper,
scsScanOverviewWrapper,
scanSummaryWrapper,
jwtWrapper,
scaRealTimeWrapper,
policyWrapper,
Expand All @@ -213,6 +215,7 @@ func NewAstCLI(
risksOverviewWrapper,
riskManagementWrapper,
scsScanOverviewWrapper,
scanSummaryWrapper,
policyWrapper,
featureFlagsWrapper,
jwtWrapper,
Expand Down
2 changes: 2 additions & 0 deletions internal/commands/root_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ func createASTTestCommand() *cobra.Command {
risksOverviewMockWrapper := &mock.RisksOverviewMockWrapper{}
riskManagementMockWrapper := &mock.RiskManagementMockWrapper{}
scsScanOverviewMockWrapper := &mock.ScanOverviewMockWrapper{}
scanSummaryMockWrapper := &mock.ScanSummaryMockWrapper{}
authWrapper := &mock.AuthMockWrapper{}
logsWrapper := &mock.LogsMockWrapper{}
codeBashingWrapper := &mock.CodeBashingMockWrapper{}
Expand Down Expand Up @@ -89,6 +90,7 @@ func createASTTestCommand() *cobra.Command {
risksOverviewMockWrapper,
riskManagementMockWrapper,
scsScanOverviewMockWrapper,
scanSummaryMockWrapper,
authWrapper,
logsWrapper,
groupsMockWrapper,
Expand Down
Loading
Loading