From e30a441fc17a62b878d9111a09257a7f3430964b Mon Sep 17 00:00:00 2001 From: Atish Jadhav <141334503+cx-atish-jadhav@users.noreply.github.com> Date: Tue, 26 May 2026 14:01:21 +0530 Subject: [PATCH 01/27] Fix KICS container shutdown race condition and add OneAssist license support - Create kicsshutdown package with thread-safe container name management - Update signal handler to read container name from kicsshutdown instead of viper - Prevents race conditions during SIGTERM cleanup - Add support for OneAssist license in addition to Developer Assist - Update GetUniqueID() to check both license types --- cmd/main.go | 12 +++++---- internal/commands/scan.go | 5 +++- internal/kicsshutdown/container_name.go | 25 +++++++++++++++++++ .../iacrealtime/container-manager.go | 2 ++ .../iacrealtime/container-manager_test.go | 14 +++++++++++ internal/wrappers/jwt-helper.go | 11 ++++++-- internal/wrappers/jwt-helper_test.go | 4 +-- 7 files changed, 63 insertions(+), 10 deletions(-) create mode 100644 internal/kicsshutdown/container_name.go diff --git a/cmd/main.go b/cmd/main.go index 53d2ae664..ae5d46ceb 100644 --- a/cmd/main.go +++ b/cmd/main.go @@ -9,6 +9,7 @@ import ( "syscall" "github.com/checkmarx/ast-cli/internal/commands" + "github.com/checkmarx/ast-cli/internal/kicsshutdown" "github.com/checkmarx/ast-cli/internal/logger" "github.com/checkmarx/ast-cli/internal/params" "github.com/checkmarx/ast-cli/internal/wrappers" @@ -191,10 +192,6 @@ func exitListener() { } func signalHandler(signalChanel chan os.Signal) { - kicsRunArgs := []string{ - killCommand, - viper.GetString(params.KicsContainerNameKey), - } for { s := <-signalChanel switch s { @@ -204,7 +201,12 @@ func signalHandler(signalChanel chan os.Signal) { os.Exit(failureExitCode) } logger.PrintIfVerbose(string(out)) - if strings.Contains(string(out), viper.GetString(params.KicsContainerNameKey)) { + kicsContainerName := kicsshutdown.GetKicsContainerName() + if kicsContainerName != "" && strings.Contains(string(out), kicsContainerName) { + kicsRunArgs := []string{ + killCommand, + kicsContainerName, + } out, err = exec.Command("docker", kicsRunArgs...).CombinedOutput() logger.PrintIfVerbose(string(out)) if err != nil { diff --git a/internal/commands/scan.go b/internal/commands/scan.go index b0d346a6d..777632c6a 100644 --- a/internal/commands/scan.go +++ b/internal/commands/scan.go @@ -35,6 +35,7 @@ import ( "github.com/pkg/errors" "github.com/MakeNowJust/heredoc" + "github.com/checkmarx/ast-cli/internal/kicsshutdown" commonParams "github.com/checkmarx/ast-cli/internal/params" "github.com/checkmarx/ast-cli/internal/wrappers" "github.com/mssola/user_agent" @@ -279,7 +280,9 @@ func NewScanCommand( func scanRealtimeSubCommand() *cobra.Command { kicsContainerID := uuid.New() - viper.Set(commonParams.KicsContainerNameKey, kicsContainerPrefixName+kicsContainerID.String()) + kicsName := kicsContainerPrefixName + kicsContainerID.String() + viper.Set(commonParams.KicsContainerNameKey, kicsName) + kicsshutdown.SetKicsContainerName(kicsName) realtimeScanCmd := &cobra.Command{ Use: "kics-realtime", Short: "Create and run kics scan", diff --git a/internal/kicsshutdown/container_name.go b/internal/kicsshutdown/container_name.go new file mode 100644 index 000000000..274858b64 --- /dev/null +++ b/internal/kicsshutdown/container_name.go @@ -0,0 +1,25 @@ +// Package kicsshutdown holds the current KICS Docker container name for SIGTERM cleanup. +// It is updated alongside viper wherever KicsContainerNameKey is set so the signal handler +// can read the latest name without concurrent access to viper. +package kicsshutdown + +import "sync" + +var ( + mu sync.RWMutex + name string +) + +// SetKicsContainerName records the container name used for shutdown handling. +func SetKicsContainerName(n string) { + mu.Lock() + defer mu.Unlock() + name = n +} + +// GetKicsContainerName returns the last recorded container name. +func GetKicsContainerName() string { + mu.RLock() + defer mu.RUnlock() + return name +} diff --git a/internal/services/realtimeengine/iacrealtime/container-manager.go b/internal/services/realtimeengine/iacrealtime/container-manager.go index 77a833b8b..0a8fcae62 100644 --- a/internal/services/realtimeengine/iacrealtime/container-manager.go +++ b/internal/services/realtimeengine/iacrealtime/container-manager.go @@ -7,6 +7,7 @@ import ( "strings" "github.com/checkmarx/ast-cli/internal/commands/util" + "github.com/checkmarx/ast-cli/internal/kicsshutdown" "github.com/checkmarx/ast-cli/internal/logger" commonParams "github.com/checkmarx/ast-cli/internal/params" "github.com/google/uuid" @@ -32,6 +33,7 @@ func (dm *ContainerManager) GenerateContainerID() string { containerID := uuid.New().String() containerName := KicsContainerPrefix + containerID viper.Set(commonParams.KicsContainerNameKey, containerName) + kicsshutdown.SetKicsContainerName(containerName) return containerName } diff --git a/internal/services/realtimeengine/iacrealtime/container-manager_test.go b/internal/services/realtimeengine/iacrealtime/container-manager_test.go index 2a2261121..7f19ac42c 100644 --- a/internal/services/realtimeengine/iacrealtime/container-manager_test.go +++ b/internal/services/realtimeengine/iacrealtime/container-manager_test.go @@ -7,6 +7,7 @@ import ( "strings" "testing" + "github.com/checkmarx/ast-cli/internal/kicsshutdown" commonParams "github.com/checkmarx/ast-cli/internal/params" "github.com/google/uuid" "github.com/spf13/viper" @@ -46,6 +47,7 @@ func (m *MockContainerManager) GenerateContainerID() string { containerName := KicsContainerPrefix + containerID m.GeneratedContainerIDs = append(m.GeneratedContainerIDs, containerName) viper.Set(commonParams.KicsContainerNameKey, containerName) + kicsshutdown.SetKicsContainerName(containerName) return containerName } @@ -102,6 +104,7 @@ func TestMockContainerManager_GenerateContainerID(t *testing.T) { // Clear any existing value viper.Set(commonParams.KicsContainerNameKey, "") + kicsshutdown.SetKicsContainerName("") containerName := dm.GenerateContainerID() @@ -125,6 +128,9 @@ func TestMockContainerManager_GenerateContainerID(t *testing.T) { if viperValue != containerName { t.Errorf("Viper should be set to '%s', got '%s'", containerName, viperValue) } + if kicsshutdown.GetKicsContainerName() != containerName { + t.Errorf("kicsshutdown should be set to '%s', got '%s'", containerName, kicsshutdown.GetKicsContainerName()) + } // Test that mock recorded the generated ID if len(dm.GeneratedContainerIDs) != 1 { @@ -164,6 +170,7 @@ func TestMockContainerManager_RunKicsContainer(t *testing.T) { // Set up test parameters containerName := "test-container" viper.Set(commonParams.KicsContainerNameKey, containerName) + kicsshutdown.SetKicsContainerName(containerName) tests := []struct { name string @@ -263,6 +270,9 @@ func TestMockContainerManager_Integration(t *testing.T) { if viper.GetString(commonParams.KicsContainerNameKey) != containerName { t.Error("Container name should be set in viper after generation") } + if kicsshutdown.GetKicsContainerName() != containerName { + t.Error("Container name should be set in kicsshutdown after generation") + } // Test running container err := dm.RunKicsContainer("docker", "/tmp:/path") @@ -379,6 +389,7 @@ func TestContainerManager_GenerateContainerID(t *testing.T) { // Clear any existing value viper.Set(commonParams.KicsContainerNameKey, "") + kicsshutdown.SetKicsContainerName("") containerName := cm.GenerateContainerID() @@ -402,6 +413,9 @@ func TestContainerManager_GenerateContainerID(t *testing.T) { if viperValue != containerName { t.Errorf("Viper should be set to '%s', got '%s'", containerName, viperValue) } + if kicsshutdown.GetKicsContainerName() != containerName { + t.Errorf("kicsshutdown should be set to '%s', got '%s'", containerName, kicsshutdown.GetKicsContainerName()) + } // Test that subsequent calls generate different IDs containerName2 := cm.GenerateContainerID() diff --git a/internal/wrappers/jwt-helper.go b/internal/wrappers/jwt-helper.go index 63b1defb5..8393c6b43 100644 --- a/internal/wrappers/jwt-helper.go +++ b/internal/wrappers/jwt-helper.go @@ -203,12 +203,19 @@ func GetUniqueID() string { var uniqueID string // Check License first jwtWrapper := NewJwtWrapper() - isAllowed, err := jwtWrapper.IsAllowedEngine(commonParams.CheckmarxDevAssistType) + devAssistAllowed, err := jwtWrapper.IsAllowedEngine(commonParams.CheckmarxDevAssistType) if err != nil { logger.PrintIfVerbose("Failed to check engine allowance: " + err.Error()) return "" } - if !isAllowed { + + oneAssistAllowed, err := jwtWrapper.IsAllowedEngine(commonParams.CheckmarxOneAssistType) + if err != nil { + logger.PrintIfVerbose("Failed to check engine allowance: " + err.Error()) + return "" + } + + if !devAssistAllowed && !oneAssistAllowed { return "" } diff --git a/internal/wrappers/jwt-helper_test.go b/internal/wrappers/jwt-helper_test.go index ea01fb041..9356921ef 100644 --- a/internal/wrappers/jwt-helper_test.go +++ b/internal/wrappers/jwt-helper_test.go @@ -90,7 +90,7 @@ func TestGetUniqueID(t *testing.T) { if result != "" { assert.Equal(t, existingID, result) } else { - t.Skip("Requires valid auth and 'Checkmarx Developer Assist' license") + t.Skip("Requires valid auth and 'Checkmarx Developer Assist' or 'Checkmarx OneAssist' license") } }) @@ -101,7 +101,7 @@ func TestGetUniqueID(t *testing.T) { result := GetUniqueID() if result == "" { - t.Skip("Requires valid auth and 'Checkmarx Developer Assist' license") + t.Skip("Requires valid auth and 'Checkmarx Developer Assist' or 'Checkmarx OneAssist' license") return } From e7356a7af90c0432d6c983af647e233e202142c0 Mon Sep 17 00:00:00 2001 From: Atish Jadhav <141334503+cx-atish-jadhav@users.noreply.github.com> Date: Tue, 26 May 2026 18:13:06 +0530 Subject: [PATCH 02/27] Integrate file updates: SARIF enhancements, filters expansion, and project/application management improvements - Add CodeFlow and ThreadFlow support to SARIF result structures with new types - Extend BaseIncludeFilters with 41 additional file type patterns - Enhance applications.go with project association polling and duplicate prevention - Update result.go with CodeFlow handling in SARIF serialization - Add IsInSource and CommitURL fields to SarifResultProperties - Fix projects.go verifyApplicationAssociationDone and UpsertProjectGroups functions - Change IaCS and KICS filter flags from String to StringSlice in scan.go Co-Authored-By: Claude Haiku 4.5 --- internal/commands/result.go | 5901 ++++++++++---------- internal/commands/scan.go | 4 +- internal/params/filters.go | 41 + internal/services/applications.go | 18 +- internal/services/applications_test.go | 10 +- internal/services/projects.go | 1 - internal/wrappers/mock/application-mock.go | 4 +- internal/wrappers/results-sarif.go | 13 + 8 files changed, 3035 insertions(+), 2957 deletions(-) diff --git a/internal/commands/result.go b/internal/commands/result.go index f37c5e46b..34320193c 100644 --- a/internal/commands/result.go +++ b/internal/commands/result.go @@ -1,2942 +1,2959 @@ -package commands - -import ( - "encoding/json" - "fmt" - "html" - "log" - "net/url" - "os" - "path/filepath" - "regexp" - "slices" - "strconv" - "strings" - "text/template" - "time" - - "github.com/MakeNowJust/heredoc" - "github.com/checkmarx/ast-cli/internal/commands/util" - "github.com/checkmarx/ast-cli/internal/commands/util/printer" - errorConstants "github.com/checkmarx/ast-cli/internal/constants/errors" - "github.com/checkmarx/ast-cli/internal/logger" - "github.com/checkmarx/ast-cli/internal/services" - "github.com/checkmarx/ast-cli/internal/wrappers" - "github.com/checkmarx/ast-cli/internal/wrappers/utils" - "golang.org/x/text/cases" - "golang.org/x/text/language" - - commonParams "github.com/checkmarx/ast-cli/internal/params" - - "github.com/pkg/errors" - "github.com/spf13/cobra" -) - -const ( - failedCreatingSummary = "Failed creating summary" - failedGettingScan = "Failed getting scan" - failedListingResults = "Failed listing results" - failedListingCodeBashing = "Failed codebashing link" - mediumLabel = "medium" - criticalLabel = "critical" - highLabel = "high" - lowLabel = "low" - infoLabel = "info" - sonarTypeLabel = "_sonar" - glSastTypeLabel = ".gl-sast-report" - glScaTypeLabel = ".gl-sca-report" - directoryPermission = 0700 - infoSonar = "INFO" - lowSonar = "LOW" - mediumSonar = "MEDIUM" - highSonar = "HIGH" - criticalSonar = "BLOCKER" - infoLowSarif = "note" - mediumSarif = "warning" - highSarif = "error" - vulnerabilitySonar = "SECURITY" - cleanCodeAttribute = "FORMATTED" - infoCx = "INFO" - lowCx = "LOW" - mediumCx = "MEDIUM" - highCx = "HIGH" - criticalCx = "CRITICAL" - tableResultsFormat = " | %-10s %6v %5d %6d %5d %4d %-9s |\n" - stringTableResultsFormat = " | %-10s %5s %6s %6s %5s %4s %5s |\n" - TableTitleFormat = " | %-11s %4s %4s %6s %4s %4s %6s |\n" - twoNewLines = "\n\n" - tableLine = " --------------------------------------------------------------------- " - codeBashingKey = "cb-url" - failedGettingBfl = "Failed getting BFL" - notAvailableString = "-" - disabledString = "N/A" - scanFailedString = "Failed " - scanCanceledString = "Canceled" - scanSuccessString = "Completed" - scanPartialString = "Partial" - scsScanUnavailableString = "" - notAvailableNumber = -1 - scanFailedNumber = -2 - scanCanceledNumber = -3 - scanPartialNumber = -4 - defaultPaddingSize = -13 - scanPendingMessage = "Scan triggered in asynchronous mode or still running. Click more details to get the full status." - directDependencyType = "Direct Dependency" - indirectDependencyType = "Transitive Dependency" - startedStatus = "started" - requestedStatus = "requested" - completedStatus = "completed" - pdfToEmailFlagDescription = "Send the PDF report to the specified email address." + - " Use \",\" as the delimiter for multiple emails" - pdfOptionsFlagDescription = "Sections to generate PDF report. Available options: Iac-Security,Sast,Sca," + - defaultPdfOptionsDataSections - sbomReportFlagDescription = "Sections to generate SBOM report. Available options: CycloneDxJson,CycloneDxXml,SpdxJson" - reportNameScanReport = "scan-report" - reportNameImprovedScanReport = "improved-scan-report" - reportTypeEmail = "email" - defaultPdfOptionsDataSections = "ScanSummary,ExecutiveSummary,ScanResults" - exploitablePathFlagDescription = "Enable or disable exploitable path in scan. Available options: true,false" - scaLastScanTimeFlagDescription = "SCA last scan time. Available options: integer above 1" - projectPrivatePackageFlagDescription = "Enable or disable project private package. Available options: true,false" - scaPrivatePackageVersionFlagDescription = "SCA project private package version. Example: 0.1.1" - scaHideDevAndTestDepFlagDescription = "Filter SCA results to exclude dev and test dependencies" - policeManagementNoneStatus = "none" - apiDocumentationFlagDescription = "Swagger folder/file filter for API-Security scan. Example: ./swagger.json" - summaryCreatedAtLayout = "2006-01-02, 15:04:05" - glTimeFormat = "2006-01-02T15:04:05" - sarifNodeFileLength = 2 - fixLabel = "fix" - redundantLabel = "redundant" - delayValueForReport = 10 - fixLinkPrefix = "https://devhub.checkmarx.com/cve-details/" - ScaDevAndTestExclusionParam = "DEV_AND_TEST" - ScaExcludeResultTypesParam = "exclude-result-types" - noFileForScorecardResultString = "Issue Found in your GitHub repository" - CliType = "cli" - artifactLocationURIString = "This alert has no associated file" -) - -var ( - summaryFormats = []string{ - printer.FormatSummaryConsole, - printer.FormatSummary, - printer.FormatSummaryJSON, - printer.FormatPDF, - printer.FormatSummaryMarkdown, - printer.FormatSbom, - printer.FormatGLSast, - printer.FormatGLSca, - printer.FormatSonar, - } - - filterResultsListFlagUsage = fmt.Sprintf( - "Filter the list of results. Use ';' as the delimiter for arrays. Available filters are: %s", - strings.Join( - []string{ - commonParams.ScanIDQueryParam, - commonParams.LimitQueryParam, - commonParams.OffsetQueryParam, - commonParams.SortQueryParam, - commonParams.IncludeNodesQueryParam, - commonParams.NodeIDsQueryParam, - commonParams.QueryQueryParam, - commonParams.GroupQueryParam, - commonParams.StatusQueryParam, - commonParams.SeverityQueryParam, - commonParams.StateQueryParam, - }, ",", - ), - ) - - // Follows: over 9.0 is critical, 7.0 to 8.9 is high, 4.0 to 6.9 is medium and 3.9 or less is low. - securities = map[string]string{ - infoCx: "1.0", - lowCx: "2.0", - mediumCx: "4.0", - highCx: "7.0", - criticalCx: "9.0", - } - - // Match cx severity with sonar severity - sonarSeverities = map[string]string{ - infoCx: infoSonar, - lowCx: lowSonar, - mediumCx: mediumSonar, - highCx: highSonar, - criticalCx: criticalSonar, - } - - containerEngineUnsupportedAgents = []string{ - commonParams.JetbrainsAgent, commonParams.VSCodeAgent, commonParams.VisualStudioAgent, commonParams.EclipseAgent, - } - - sscsEngineToOverviewEngineMap = map[string]string{ - commonParams.SCSScorecardType: commonParams.SCSScorecardOverviewType, - commonParams.SCSSecretDetectionType: commonParams.SCSSecretDetectionOverviewType, - } -) - -func NewResultsCommand( - resultsWrapper wrappers.ResultsWrapper, - scanWrapper wrappers.ScansWrapper, - exportWrapper wrappers.ExportWrapper, - resultsPdfReportsWrapper wrappers.ResultsPdfWrapper, - resultsJSONReportsWrapper wrappers.ResultsJSONWrapper, - codeBashingWrapper wrappers.CodeBashingWrapper, - bflWrapper wrappers.BflWrapper, - risksOverviewWrapper wrappers.RisksOverviewWrapper, - riskManagementWrapper wrappers.RiskManagementWrapper, - scsScanOverviewWrapper wrappers.ScanOverviewWrapper, - policyWrapper wrappers.PolicyWrapper, - featureFlagsWrapper wrappers.FeatureFlagsWrapper, - jwtWrapper wrappers.JWTWrapper, -) *cobra.Command { - resultCmd := &cobra.Command{ - Use: "results", - Short: "Retrieve results", - Annotations: map[string]string{ - "command:doc": heredoc.Doc( - ` - https://checkmarx.com/resource/documents/en/34965-68640-results.html - `, - ), - }, - } - showResultCmd := resultShowSubCommand(resultsWrapper, scanWrapper, exportWrapper, resultsPdfReportsWrapper, resultsJSONReportsWrapper, - risksOverviewWrapper, scsScanOverviewWrapper, policyWrapper, featureFlagsWrapper, jwtWrapper) - codeBashingCmd := resultCodeBashing(codeBashingWrapper) - bflResultCmd := resultBflSubCommand(bflWrapper) - exitCodeSubcommand := exitCodeSubCommand(scanWrapper) - riskManagementSubCommand := riskManagementSubCommand(riskManagementWrapper, featureFlagsWrapper) - resultCmd.AddCommand( - showResultCmd, bflResultCmd, codeBashingCmd, exitCodeSubcommand, riskManagementSubCommand, - ) - return resultCmd -} - -func exitCodeSubCommand(scanWrapper wrappers.ScansWrapper) *cobra.Command { - exitCodeCmd := &cobra.Command{ - Use: "exit-code", - Short: "Get exit code and details of a scan", - Long: "The exit-code command enables you to get the exit code and failure details of a requested scan in Checkmarx One", - Example: heredoc.Doc( - ` - $ cx results exit-code --scan-id --scan-types - `, - ), - RunE: runGetExitCodeCommand(scanWrapper), - } - - exitCodeCmd.PersistentFlags().String(commonParams.ScanIDFlag, "", "Scan ID") - exitCodeCmd.PersistentFlags().String(commonParams.ScanTypes, "", "Scan types") - - return exitCodeCmd -} -func riskManagementSubCommand(riskManagement wrappers.RiskManagementWrapper, featureFlagsWrapper wrappers.FeatureFlagsWrapper, -) *cobra.Command { - riskManagementCmd := &cobra.Command{ - Use: "risk-management", - Short: "Show risk-management results of a project", - Long: "The risk-management command displays risk management results for a specific project in Checkmarx One", - Example: heredoc.Doc( - ` - $ cx results risk-management --project-id --scan-id --limit (1-50, default: 50) - `, - ), - RunE: runRiskManagementCommand(riskManagement, featureFlagsWrapper), - } - - riskManagementCmd.PersistentFlags().String(commonParams.ProjectIDFlag, "", "Project ID") - riskManagementCmd.PersistentFlags().String(commonParams.ScanIDFlag, "", "Scan ID") - riskManagementCmd.PersistentFlags().Int(commonParams.LimitFlag, -1, "Limit") - - addFormatFlag(riskManagementCmd, printer.FormatJSON, printer.FormatTable, printer.FormatList) - - return riskManagementCmd -} - -func resultShowSubCommand( - resultsWrapper wrappers.ResultsWrapper, - scanWrapper wrappers.ScansWrapper, - exportWrapper wrappers.ExportWrapper, - resultsPdfReportsWrapper wrappers.ResultsPdfWrapper, - resultsJSONReportsWrapper wrappers.ResultsJSONWrapper, - risksOverviewWrapper wrappers.RisksOverviewWrapper, - scsScanOverviewWrapper wrappers.ScanOverviewWrapper, - policyWrapper wrappers.PolicyWrapper, - featureFlagsWrapper wrappers.FeatureFlagsWrapper, - jwtWrapper wrappers.JWTWrapper, -) *cobra.Command { - resultShowCmd := &cobra.Command{ - Use: "show", - Short: "Show results of a scan", - Long: "The show command enables the ability to show results about a requested scan in Checkmarx One", - Example: heredoc.Doc( - ` - $ cx results show --scan-id - `, - ), - RunE: runGetResultCommand(resultsWrapper, scanWrapper, exportWrapper, resultsPdfReportsWrapper, resultsJSONReportsWrapper, risksOverviewWrapper, scsScanOverviewWrapper, policyWrapper, featureFlagsWrapper, jwtWrapper), - } - addScanIDFlag(resultShowCmd, "ID to report on") - addResultFormatFlag( - resultShowCmd, - printer.FormatJSON, - printer.FormatJSONv2, - printer.FormatSummary, - printer.FormatSummaryConsole, - printer.FormatSarif, - printer.FormatSummaryJSON, - printer.FormatSbom, - printer.FormatPDF, - printer.FormatSummaryMarkdown, - printer.FormatGLSast, - printer.FormatGLSca, - printer.FormatSonar, - ) - resultShowCmd.PersistentFlags().String(commonParams.ReportFormatPdfToEmailFlag, "", pdfToEmailFlagDescription) - resultShowCmd.PersistentFlags().String(commonParams.ReportSbomFormatFlag, services.DefaultSbomOption, sbomReportFlagDescription) - resultShowCmd.PersistentFlags().String(commonParams.ReportFormatPdfOptionsFlag, defaultPdfOptionsDataSections, pdfOptionsFlagDescription) - resultShowCmd.PersistentFlags().String(commonParams.TargetFlag, "cx_result", "Output file") - resultShowCmd.PersistentFlags().String(commonParams.TargetPathFlag, ".", "Output Path") - resultShowCmd.PersistentFlags().StringSlice(commonParams.FilterFlag, []string{}, filterResultsListFlagUsage) - - resultShowCmd.PersistentFlags().IntP( - commonParams.WaitDelayFlag, - "", - commonParams.WaitDelayDefault, - "Polling wait time in seconds", - ) - resultShowCmd.PersistentFlags().Int( - commonParams.PolicyTimeoutFlag, - commonParams.ResultPolicyDefaultTimeout, - "Cancel the policy evaluation and fail after the timeout in minutes", - ) - resultShowCmd.PersistentFlags().Bool(commonParams.IgnorePolicyFlag, false, "Skip policy evaluation. Requires override-policy-management permission.") - resultShowCmd.PersistentFlags().Bool(commonParams.SastRedundancyFlag, false, - "Populate SAST results 'data.redundancy' with values '"+fixLabel+"' (to fix) or '"+redundantLabel+"' (no need to fix)") - resultShowCmd.PersistentFlags().Bool(commonParams.ScaHideDevAndTestDepFlag, false, scaHideDevAndTestDepFlagDescription) - - return resultShowCmd -} - -func resultBflSubCommand(bflWrapper wrappers.BflWrapper) *cobra.Command { - resultBflCmd := &cobra.Command{ - Use: "bfl", - Short: "Show best fix location for a query id within the scan result", - Long: "The bfl command enables the ability to show best fix location for a querid within the scan result", - Example: heredoc.Doc( - ` - $ cx results bfl --scan-id --query-id - `, - ), - RunE: runGetBestFixLocationCommand(bflWrapper), - } - addScanIDFlag(resultBflCmd, "ID to report on") - addQueryIDFlag(resultBflCmd, "Query Id from the result") - addFormatFlag(resultBflCmd, printer.FormatList, printer.FormatJSON) - - markFlagAsRequired(resultBflCmd, commonParams.ScanIDFlag) - markFlagAsRequired(resultBflCmd, commonParams.QueryIDFlag) - - return resultBflCmd -} - -func runGetExitCodeCommand(scanWrapper wrappers.ScansWrapper) func(cmd *cobra.Command, args []string) error { - return func(cmd *cobra.Command, args []string) error { - scanID, _ := cmd.Flags().GetString(commonParams.ScanIDFlag) - if scanID == "" { - return errors.New(errorConstants.ScanIDRequired) - } - scanTypesFlagValue, _ := cmd.Flags().GetString(commonParams.ScanTypes) - results, err := GetScannerResults(scanWrapper, scanID, scanTypesFlagValue) - if err != nil { - return err - } - - if len(results) == 0 { - return nil - } - - return printer.Print(cmd.OutOrStdout(), results, printer.FormatIndentedJSON) - } -} - -func runRiskManagementCommand(riskManagement wrappers.RiskManagementWrapper, featureFlagsWrapper wrappers.FeatureFlagsWrapper, -) func(cmd *cobra.Command, args []string) error { - return func(cmd *cobra.Command, args []string) error { - projectID, _ := cmd.Flags().GetString(commonParams.ProjectIDFlag) - scanID, _ := cmd.Flags().GetString(commonParams.ScanIDFlag) - - limit, _ := cmd.Flags().GetInt(commonParams.LimitFlag) - - flagResponse, _ := wrappers.GetSpecificFeatureFlag(featureFlagsWrapper, wrappers.RiskManagementEnabled) - ASPMEnabled := flagResponse.Status - if !ASPMEnabled { - return errors.Errorf("%s", "Risk management results are currently unavailable for your tenant.") - } - results, err := getRiskManagementResults(riskManagement, projectID, scanID) - if err != nil { - return err - } - results.Results = utils.LimitSlice(results.Results, limit) - err = printByFormat(cmd, results) - return err - } -} - -func getRiskManagementResults(riskManagement wrappers.RiskManagementWrapper, projectID, scanID string) (*wrappers.ASPMResult, error) { - ASPMResult, errorModel, err := riskManagement.GetTopVulnerabilitiesByProjectID(projectID, scanID) - if err != nil { - return nil, errors.Wrapf(err, "%s", failedListingResults) - } - if errorModel != nil { - return nil, errors.Errorf("%s: CODE: %d, %s", failedListingResults, errorModel.Code, errorModel.Message) - } - return ASPMResult, nil -} - -func GetScannerResults(scanWrapper wrappers.ScansWrapper, scanID, scanTypesFlagValue string) ([]ScannerResponse, error) { - scanResponseModel, errorModel, err := scanWrapper.GetByID(scanID) - if err != nil { - return nil, errors.Wrapf(err, "%s", failedGetting) - } - if errorModel != nil { - return nil, errors.Errorf("%s: CODE: %d, %s", failedGettingScan, errorModel.Code, errorModel.Message) - } - results := getScannerResponse(scanTypesFlagValue, scanResponseModel) - return results, nil -} - -func getScannerResponse(scanTypesFlagValue string, scanResponseModel *wrappers.ScanResponseModel) []ScannerResponse { - var results []ScannerResponse - - if scanResponseModel.Status == wrappers.ScanCanceled || - scanResponseModel.Status == wrappers.ScanRunning || - scanResponseModel.Status == wrappers.ScanQueued || - scanResponseModel.Status == wrappers.ScanPartial || - scanResponseModel.Status == wrappers.ScanCompleted { - result := ScannerResponse{ - ScanID: scanResponseModel.ID, - Status: string(scanResponseModel.Status), - } - results = append(results, result) - return results - } - - if scanTypesFlagValue == "" { - results = createAllFailedScannersResponse(scanResponseModel) - } else { - scanTypes := sanitizeScannerNames(scanTypesFlagValue) - results = createRequestedScannersResponse(scanTypes, scanResponseModel) - } - - return results -} - -func createRequestedScannersResponse(scanTypes map[string]string, scanResponseModel *wrappers.ScanResponseModel) []ScannerResponse { - var results []ScannerResponse - for i := range scanResponseModel.StatusDetails { - if _, ok := scanTypes[scanResponseModel.StatusDetails[i].Name]; ok { - results = append(results, createScannerResponse(&scanResponseModel.StatusDetails[i])) - } - } - return results -} - -func createAllFailedScannersResponse(scanResponseModel *wrappers.ScanResponseModel) []ScannerResponse { - var results []ScannerResponse - for i := range scanResponseModel.StatusDetails { - if scanResponseModel.StatusDetails[i].Status == wrappers.ScanFailed { - results = append(results, createScannerResponse(&scanResponseModel.StatusDetails[i])) - } - } - return results -} - -func sanitizeScannerNames(scanTypes string) map[string]string { - scanTypeSlice := strings.Split(scanTypes, ",") - scanTypeMap := make(map[string]string) - for i := range scanTypeSlice { - lowered := strings.ToLower(scanTypeSlice[i]) - scanTypeMap[lowered] = lowered - } - - return scanTypeMap -} - -func createScannerResponse(statusDetails *wrappers.StatusInfo) ScannerResponse { - return ScannerResponse{ - Name: statusDetails.Name, - Status: statusDetails.Status, - Details: statusDetails.Details, - ErrorCode: stringifyErrorCode(statusDetails.ErrorCode), - } -} - -func stringifyErrorCode(errorCode int) string { - if errorCode == 0 { - return "" - } - return strconv.Itoa(errorCode) -} - -func runGetBestFixLocationCommand(bflWrapper wrappers.BflWrapper) func(cmd *cobra.Command, args []string) error { - return func(cmd *cobra.Command, args []string) error { - var bflResponseModel *wrappers.BFLResponseModel - var errorModel *wrappers.WebError - var err error - - scanID, _ := cmd.Flags().GetString(commonParams.ScanIDFlag) - queryID, _ := cmd.Flags().GetString(commonParams.QueryIDFlag) - - scanIds := strings.Split(scanID, ",") - if len(scanIds) > 1 { - return errors.Errorf("%s", "Multiple scan-ids are not allowed.") - } - queryIds := strings.Split(queryID, ",") - if len(queryIds) > 1 { - return errors.Errorf("%s", "Multiple query-ids are not allowed.") - } - - params := make(map[string]string) - params[commonParams.ScanIDQueryParam] = scanID - params[commonParams.QueryIDQueryParam] = queryID - - bflResponseModel, errorModel, err = bflWrapper.GetBflByScanIDAndQueryID(params) - - if err != nil { - return errors.Wrapf(err, "%s", failedGettingBfl) - } - - // Checking the response - if errorModel != nil { - return errors.Errorf("%s: CODE: %d, %s", failedGettingBfl, errorModel.Code, errorModel.Message) - } else if bflResponseModel != nil { - err = printByFormat(cmd, toBflView(*bflResponseModel)) - if err != nil { - return err - } - } - - return nil - } -} - -func toBflView(bflResponseModel wrappers.BFLResponseModel) []wrappers.ScanResultNode { - if (bflResponseModel.TotalCount) > 0 { - views := make([]wrappers.ScanResultNode, bflResponseModel.TotalCount) - - for i := 0; i < bflResponseModel.TotalCount; i++ { - views[i] = wrappers.ScanResultNode{ - Name: bflResponseModel.Trees[i].BFL.Name, - FileName: bflResponseModel.Trees[i].BFL.FileName, - FullName: bflResponseModel.Trees[i].BFL.FullName, - Column: bflResponseModel.Trees[i].BFL.Column, - Length: bflResponseModel.Trees[i].BFL.Length, - Line: bflResponseModel.Trees[i].BFL.Line, - MethodLine: bflResponseModel.Trees[i].BFL.MethodLine, - Method: bflResponseModel.Trees[i].BFL.Method, - DomType: bflResponseModel.Trees[i].BFL.DomType, - } - } - return views - } - views := make([]wrappers.ScanResultNode, 0) - return views -} - -func resultCodeBashing(codeBashingWrapper wrappers.CodeBashingWrapper) *cobra.Command { - // Create a codeBashing wrapper - resultCmd := &cobra.Command{ - Use: "codebashing", - Short: "Get codebashing lesson link", - Long: "The codebashing command enables the ability to retrieve the link about a specific vulnerability", - Example: heredoc.Doc( - ` - $ cx results codebashing --language --vulnerability-type --cwe-id --format - `, - ), - RunE: runGetCodeBashingCommand(codeBashingWrapper), - } - resultCmd.PersistentFlags().String(commonParams.LanguageFlag, "", "Language of the vulnerability") - err := resultCmd.MarkPersistentFlagRequired(commonParams.LanguageFlag) - if err != nil { - log.Fatal(err) - } - resultCmd.PersistentFlags().String(commonParams.VulnerabilityTypeFlag, "", "Vulnerability type") - err = resultCmd.MarkPersistentFlagRequired(commonParams.VulnerabilityTypeFlag) - if err != nil { - log.Fatal(err) - } - resultCmd.PersistentFlags().String(commonParams.CweIDFlag, "", "CWE ID for the vulnerability") - err = resultCmd.MarkPersistentFlagRequired(commonParams.CweIDFlag) - if err != nil { - log.Fatal(err) - } - addFormatFlag(resultCmd, printer.FormatJSON, printer.FormatTable, printer.FormatList) - return resultCmd -} - -func convertScanToResultsSummary(scanInfo *wrappers.ScanResponseModel, resultsWrapper wrappers.ResultsWrapper) (*wrappers.ResultSummary, error) { - if scanInfo == nil { - return nil, errors.New(failedCreatingSummary) - } - - scanInfo.ReplaceMicroEnginesWithSCS() - - sastIssues := 0 - scaIssues := 0 - kicsIssues := 0 - var containersIssues *int - var scsIssues *int - enginesStatusCode := map[string]int{ - commonParams.SastType: 0, - commonParams.ScaType: 0, - commonParams.KicsType: 0, - commonParams.APISecType: 0, - commonParams.ScsType: 0, - commonParams.ContainersType: 0, - } - if wrappers.IsContainersEnabled { - containersIssues = new(int) - *containersIssues = 0 - enginesStatusCode[commonParams.ContainersType] = 0 - } - - scsIssues = new(int) - *scsIssues = 0 - enginesStatusCode[commonParams.ScsType] = 0 - - if len(scanInfo.StatusDetails) > 0 { - for _, statusDetailItem := range scanInfo.StatusDetails { - if statusDetailItem.Status == wrappers.ScanFailed || statusDetailItem.Status == wrappers.ScanCanceled { - if statusDetailItem.Name == commonParams.SastType { - sastIssues = notAvailableNumber - } else if statusDetailItem.Name == commonParams.ScaType { - scaIssues = notAvailableNumber - } else if statusDetailItem.Name == commonParams.KicsType { - kicsIssues = notAvailableNumber - } else if statusDetailItem.Name == commonParams.ScsType { - *scsIssues = notAvailableNumber - } else if statusDetailItem.Name == commonParams.ContainersType && wrappers.IsContainersEnabled { - *containersIssues = notAvailableNumber - } - } - switch statusDetailItem.Status { - case wrappers.ScanFailed: - handleScanStatus(statusDetailItem, enginesStatusCode, scanFailedNumber) - case wrappers.ScanCanceled: - handleScanStatus(statusDetailItem, enginesStatusCode, scanCanceledNumber) - } - } - } - summary := &wrappers.ResultSummary{ - ScanID: scanInfo.ID, - Status: string(scanInfo.Status), - CreatedAt: scanInfo.CreatedAt.Format("2006-01-02, 15:04:05"), - ProjectID: scanInfo.ProjectID, - RiskStyle: "", - RiskMsg: "", - CriticalIssues: 0, - HighIssues: 0, - MediumIssues: 0, - LowIssues: 0, - InfoIssues: 0, - SastIssues: sastIssues, - KicsIssues: kicsIssues, - ScaIssues: scaIssues, - ScsIssues: scsIssues, - ContainersIssues: containersIssues, - Tags: scanInfo.Tags, - ProjectName: scanInfo.ProjectName, - BranchName: scanInfo.Branch, - EnginesEnabled: scanInfo.Engines, - EnginesResult: map[string]*wrappers.EngineResultSummary{ - commonParams.SastType: {StatusCode: enginesStatusCode[commonParams.SastType]}, - commonParams.ScaType: {StatusCode: enginesStatusCode[commonParams.ScaType]}, - commonParams.KicsType: {StatusCode: enginesStatusCode[commonParams.KicsType]}, - commonParams.APISecType: {StatusCode: enginesStatusCode[commonParams.APISecType]}, - commonParams.ContainersType: {StatusCode: enginesStatusCode[commonParams.ContainersType]}, - }, - } - if wrappers.IsContainersEnabled { - summary.EnginesResult[commonParams.ContainersType] = &wrappers.EngineResultSummary{StatusCode: enginesStatusCode[commonParams.ContainersType]} - } - - summary.EnginesResult[commonParams.ScsType] = &wrappers.EngineResultSummary{StatusCode: enginesStatusCode[commonParams.ScsType]} - - baseURI, err := resultsWrapper.GetResultsURL(summary.ProjectID) - if err != nil { - return nil, err - } - - summary.BaseURI = baseURI - summary.BaseURI = generateScanSummaryURL(summary) - if isScanPending(summary.Status) { - summary.ScanInfoMessage = scanPendingMessage - } - - return summary, nil -} - -func handleScanStatus(statusDetailItem wrappers.StatusInfo, targetTypes map[string]int, statusCode int) { - if _, ok := targetTypes[statusDetailItem.Name]; ok { - targetTypes[statusDetailItem.Name] = statusCode - } -} - -func summaryReport( - summary *wrappers.ResultSummary, - policies *wrappers.PolicyResponseModel, - risksOverviewWrapper wrappers.RisksOverviewWrapper, - scsScanOverviewWrapper wrappers.ScanOverviewWrapper, - featureFlagsWrapper wrappers.FeatureFlagsWrapper, - results *wrappers.ScanResultsCollection, - resultsParams map[string]string, -) (*wrappers.ResultSummary, error) { - if summary.HasAPISecurity() { - apiSecFilterRisks, err := getFilterResultsForAPISecScanner(risksOverviewWrapper, summary.ScanID, resultsParams) - if err != nil { - return nil, err - } - if apiSecFilterRisks != nil { - summary.APISecurity = *apiSecFilterRisks - } - apiSecRisks, err := getResultsForAPISecScanner(risksOverviewWrapper, summary.ScanID) - if err != nil { - return nil, err - } - if apiSecRisks != nil { - summary.APISecurity.APICount = apiSecRisks.APICount - } - } - if summary.HasSCS() { - // Getting the base SCS overview. Results counts are overwritten in enhanceWithScanSummary->countResult - SCSOverview, err := getScanOverviewForSCSScanner(scsScanOverviewWrapper, summary.ScanID) - if err != nil { - return nil, err - } - summary.SCSOverview = SCSOverview - } - - if policies != nil { - summary.Policies = filterViolatedRules(*policies) - } - - enhanceWithScanSummary(summary, results, featureFlagsWrapper) - - setNotAvailableNumberIfZero(summary, &summary.SastIssues, commonParams.SastType) - setNotAvailableNumberIfZero(summary, &summary.ScaIssues, commonParams.ScaType) - setNotAvailableNumberIfZero(summary, &summary.KicsIssues, commonParams.KicsType) - setNotAvailableNumberIfZero(summary, summary.ScsIssues, commonParams.ScsType) - - if wrappers.IsContainersEnabled { - setNotAvailableNumberIfZero(summary, summary.ContainersIssues, commonParams.ContainersType) - } - - setRiskMsgAndStyle(summary) - setNotAvailableEnginesStatusCode(summary) - - return summary, nil -} - -func setNotAvailableEnginesStatusCode(summary *wrappers.ResultSummary) { - for engineName, engineResult := range summary.EnginesResult { - setNotAvailableNumberIfZero(summary, &engineResult.StatusCode, engineName) - } -} - -func setRiskMsgAndStyle(summary *wrappers.ResultSummary) { - if summary.CriticalIssues > 0 { - summary.RiskStyle = criticalLabel - summary.RiskMsg = "Critical Risk" - } else if summary.HighIssues > 0 { - summary.RiskStyle = highLabel - summary.RiskMsg = "High Risk" - } else if summary.MediumIssues > 0 { - summary.RiskStyle = mediumLabel - summary.RiskMsg = "Medium Risk" - } else if summary.LowIssues > 0 { - summary.RiskStyle = lowLabel - summary.RiskMsg = "Low Risk" - } else if summary.TotalIssues == 0 { - summary.RiskMsg = "No Risk" - } -} - -func setNotAvailableNumberIfZero(summary *wrappers.ResultSummary, counter *int, engineType string) { - if *counter == 0 && !contains(summary.EnginesEnabled, engineType) { - *counter = notAvailableNumber - } -} - -func enhanceWithScanSummary(summary *wrappers.ResultSummary, results *wrappers.ScanResultsCollection, featureFlagsWrapper wrappers.FeatureFlagsWrapper) { - for _, result := range results.Results { - countResult(summary, result) - } - // Set critical count for a specific engine if critical is disabled - flagResponse, _ := wrappers.GetSpecificFeatureFlag(featureFlagsWrapper, wrappers.CVSSV3Enabled) - criticalEnabled := flagResponse.Status - if summary.HasAPISecurity() { - summary.EnginesResult[commonParams.APISecType].Low = summary.APISecurity.SeverityCount["low"] - summary.EnginesResult[commonParams.APISecType].Medium = summary.APISecurity.SeverityCount["medium"] - summary.EnginesResult[commonParams.APISecType].High = summary.APISecurity.SeverityCount["high"] - if !criticalEnabled { - summary.EnginesResult[commonParams.APISecType].Critical = notAvailableNumber - } else { - summary.EnginesResult[commonParams.APISecType].Critical = summary.APISecurity.SeverityCount["critical"] - } - } - - summary.TotalIssues = summary.SastIssues + summary.ScaIssues + summary.KicsIssues + summary.GetAPISecurityDocumentationTotal() - - if summary.HasSCS() { - // Special case for SCS where status is partial if any microengines failed - if summary.SCSOverview.Status == scanPartialString { - summary.EnginesResult[commonParams.ScsType].StatusCode = scanPartialNumber - } - if !criticalEnabled { - summary.EnginesResult[commonParams.ScsType].Critical = notAvailableNumber - removeCriticalFromSCSOverview(summary) - } - if *summary.ScsIssues >= 0 { - summary.TotalIssues += *summary.ScsIssues - } - } - if wrappers.IsContainersEnabled { - if *summary.ContainersIssues >= 0 { - summary.TotalIssues += *summary.ContainersIssues - } - } - if !criticalEnabled { - summary.EnginesResult[commonParams.SastType].Critical = notAvailableNumber - summary.EnginesResult[commonParams.KicsType].Critical = notAvailableNumber - summary.EnginesResult[commonParams.ScaType].Critical = notAvailableNumber - summary.EnginesResult[commonParams.ContainersType].Critical = notAvailableNumber - } -} - -func removeCriticalFromSCSOverview(summary *wrappers.ResultSummary) { - criticalCount := summary.SCSOverview.RiskSummary[criticalLabel] - summary.SCSOverview.TotalRisksCount -= criticalCount - summary.SCSOverview.RiskSummary[criticalLabel] = notAvailableNumber - for _, microEngineOverview := range summary.SCSOverview.MicroEngineOverviews { - if microEngineOverview.RiskSummary != nil && microEngineOverview.RiskSummary[criticalLabel] != nil { - engineCriticalCount := microEngineOverview.RiskSummary[criticalLabel] - microEngineOverview.TotalRisks -= engineCriticalCount.(int) - microEngineOverview.RiskSummary[criticalLabel] = disabledString - } - } -} - -func writeHTMLSummary(targetFile string, summary *wrappers.ResultSummary) error { - log.Println("Creating Summary Report: ", targetFile) - summaryTemp, err := template.New("summaryTemplate").Parse(wrappers.SummaryTemplate(isScanPending(summary.Status))) - if err == nil { - f, err := os.Create(targetFile) - if err == nil { - _ = summaryTemp.ExecuteTemplate(f, "SummaryTemplate", summary) - _ = f.Close() - } - return err - } - return nil -} -func writeMarkdownSummary(targetFile string, data *wrappers.ResultSummary) error { - log.Println("Creating Markdown Summary Report: ", targetFile) - tmpl, err := template.New(printer.FormatSummaryMarkdown).Parse(wrappers.SummaryMarkdownTemplate(isScanPending(data.Status))) - if err != nil { - return err - } - file, err := os.Create(targetFile) - if err != nil { - return err - } - defer file.Close() - - err = tmpl.Execute(file, &data) - if err != nil { - return err - } - return nil -} - -// nolint: whitespace -func writeConsoleSummary(summary *wrappers.ResultSummary, featureFlagsWrapper wrappers.FeatureFlagsWrapper, ignorePolicyFlagOmit bool) error { - if !isScanPending(summary.Status) { - fmt.Printf(" Scan Summary: \n") - fmt.Printf(" Created At: %s\n", summary.CreatedAt) - fmt.Printf(" Project Name: %s \n", summary.ProjectName) - fmt.Printf(" Scan ID: %s \n\n", summary.ScanID) - fmt.Printf(" Results Summary: \n") - fmt.Printf( - " Risk Level: %s \n", - summary.RiskMsg, - ) - if summary.Policies != nil && !strings.EqualFold(summary.Policies.Status, policeManagementNoneStatus) { - printPoliciesSummary(summary, ignorePolicyFlagOmit) - } - - printResultsSummaryTable(summary) - - if summary.HasAPISecurity() { - printAPIsSecuritySummary(summary) - } - - if summary.HasSCS() { - printSCSSummary(summary.SCSOverview.MicroEngineOverviews, featureFlagsWrapper) - } - - 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") - fmt.Printf("For more information: %s\n", summary.BaseURI) - } - return nil -} - -func printPoliciesSummary(summary *wrappers.ResultSummary, ignorePolicyFlagOmit bool) { - hasViolations := false - for _, policy := range summary.Policies.Policies { - if len(policy.RulesViolated) > 0 { - hasViolations = true - break - } - } - if hasViolations { - fmt.Printf(tableLine + "\n") - if ignorePolicyFlagOmit { - printWarningIfIgnorePolicyOmiited() - } - if summary.Policies.BreakBuild { - fmt.Printf(" Policy Management Violation - Break Build Enabled: \n") - } else { - fmt.Printf(" Policy Management Violation: \n") - } - for _, police := range summary.Policies.Policies { - if len(police.RulesViolated) > 0 { - fmt.Printf(" Policy: %s | Break Build: %t | Violated Rules: ", police.Name, police.BreakBuild) - for _, violatedRule := range police.RulesViolated { - fmt.Printf("%s;", violatedRule) - } - } - fmt.Printf("\n") - } - fmt.Printf("\n") - } -} - -func printAPIsSecuritySummary(summary *wrappers.ResultSummary) { - fmt.Printf(" API Security - Total Detected APIs: %d \n", summary.APISecurity.APICount) - fmt.Printf(" APIS WITH RISK: %*d \n", defaultPaddingSize, summary.APISecurity.TotalRisksCount) - if summary.HasAPISecurityDocumentation() { - fmt.Printf(" APIS DOCUMENTATION: %*d \n", defaultPaddingSize, summary.GetAPISecurityDocumentationTotal()) - } - fmt.Printf(tableLine + twoNewLines) -} - -func printTableRow(title string, counts *wrappers.EngineResultSummary, statusNumber int) { - switch statusNumber { - case notAvailableNumber: - fmt.Printf(stringTableResultsFormat, title, notAvailableString, notAvailableString, notAvailableString, notAvailableString, notAvailableString, notAvailableString) - case scanFailedNumber: - fmt.Printf(tableResultsFormat, title, getCountValue(counts.Critical), counts.High, counts.Medium, counts.Low, counts.Info, scanFailedString) - case scanCanceledNumber: - fmt.Printf(tableResultsFormat, title, getCountValue(counts.Critical), counts.High, counts.Medium, counts.Low, counts.Info, scanCanceledString) - case scanPartialNumber: - fmt.Printf(tableResultsFormat, title, getCountValue(counts.Critical), counts.High, counts.Medium, counts.Low, counts.Info, scanPartialString) - default: - fmt.Printf(tableResultsFormat, title, getCountValue(counts.Critical), counts.High, counts.Medium, counts.Low, counts.Info, scanSuccessString) - } -} - -func printSCSSummary(microEngineOverviews []*wrappers.MicroEngineOverview, featureFlagsWrapper wrappers.FeatureFlagsWrapper) { - fmt.Printf(" Supply Chain Security Results\n") - fmt.Printf(" -------------------------------------------------------------------------- \n") - fmt.Println(" | Critical High Medium Low Info Status |") - for _, microEngineOverview := range microEngineOverviews { - printSCSTableRow(microEngineOverview, featureFlagsWrapper) - } - fmt.Printf(" -------------------------------------------------------------------------- \n\n") -} - -func printSCSTableRow(microEngineOverview *wrappers.MicroEngineOverview, featureFlagsWrapper wrappers.FeatureFlagsWrapper) { - formatString := " | %-20s %4v %4v %6v %4v %4v %-9s |\n" - notAvailableFormatString := " | %-20s %4v %4s %6s %4s %4s %5s |\n" - - riskSummary := microEngineOverview.RiskSummary - microEngineName := microEngineOverview.FullName - - switch microEngineOverview.Status { - case scsScanUnavailableString: - fmt.Printf(notAvailableFormatString, microEngineName, notAvailableString, notAvailableString, notAvailableString, notAvailableString, notAvailableString, notAvailableString) - default: - fmt.Printf(formatString, microEngineName, riskSummary[criticalLabel], riskSummary[highLabel], riskSummary[mediumLabel], riskSummary[lowLabel], - riskSummary[infoLabel], microEngineOverview.Status) - } -} - -func getCountValue(count int) interface{} { - if count < 0 { - return disabledString - } - return count -} - -func printResultsSummaryTable(summary *wrappers.ResultSummary) { - totalCriticalIssues := summary.EnginesResult.GetCriticalIssues() - totalHighIssues := summary.EnginesResult.GetHighIssues() - totalMediumIssues := summary.EnginesResult.GetMediumIssues() - totalLowIssues := summary.EnginesResult.GetLowIssues() - totalInfoIssues := summary.EnginesResult.GetInfoIssues() - fmt.Printf(tableLine + twoNewLines) - fmt.Printf(" Total Results: %d (Total Results includes only API documentation vulnerabilities\n and does not include API code vulnerabilities.)\n", summary.TotalIssues) - fmt.Println(tableLine) - fmt.Printf(TableTitleFormat, " ", "Critical", "High", "Medium", "Low", "Info", "Status") - - printTableRow("APIs", summary.EnginesResult[commonParams.APISecType], summary.EnginesResult[commonParams.APISecType].StatusCode) - printTableRow("IAC", summary.EnginesResult[commonParams.KicsType], summary.EnginesResult[commonParams.KicsType].StatusCode) - printTableRow("SAST", summary.EnginesResult[commonParams.SastType], summary.EnginesResult[commonParams.SastType].StatusCode) - printTableRow("SCA", summary.EnginesResult[commonParams.ScaType], summary.EnginesResult[commonParams.ScaType].StatusCode) - printTableRow("SCS", summary.EnginesResult[commonParams.ScsType], summary.EnginesResult[commonParams.ScsType].StatusCode) - - if wrappers.IsContainersEnabled { - printTableRow("CONTAINERS", summary.EnginesResult[commonParams.ContainersType], summary.EnginesResult[commonParams.ContainersType].StatusCode) - } - - fmt.Println(tableLine) - fmt.Printf(tableResultsFormat, - "TOTAL", getCountValue(totalCriticalIssues), totalHighIssues, totalMediumIssues, totalLowIssues, totalInfoIssues, summary.Status) - fmt.Printf(tableLine + twoNewLines) -} - -func generateScanSummaryURL(summary *wrappers.ResultSummary) string { - summaryURL := fmt.Sprintf( - strings.Replace(summary.BaseURI, "overview", "scans?id=%s&branch=%s", 1), - summary.ScanID, url.QueryEscape(summary.BranchName), - ) - return summaryURL -} - -func runGetResultCommand( - resultsWrapper wrappers.ResultsWrapper, - scanWrapper wrappers.ScansWrapper, - exportWrapper wrappers.ExportWrapper, - resultsPdfReportsWrapper wrappers.ResultsPdfWrapper, - resultsJSONReportsWrapper wrappers.ResultsJSONWrapper, - risksOverviewWrapper wrappers.RisksOverviewWrapper, - scsScanOverviewWrapper wrappers.ScanOverviewWrapper, - policyWrapper wrappers.PolicyWrapper, - featureFlagsWrapper wrappers.FeatureFlagsWrapper, - jwtWrapper wrappers.JWTWrapper, -) func(cmd *cobra.Command, args []string) error { - return func(cmd *cobra.Command, args []string) error { - targetFile, _ := cmd.Flags().GetString(commonParams.TargetFlag) - targetPath, _ := cmd.Flags().GetString(commonParams.TargetPathFlag) - format, _ := cmd.Flags().GetString(commonParams.TargetFormatFlag) - formatPdfToEmail, _ := cmd.Flags().GetString(commonParams.ReportFormatPdfToEmailFlag) - formatPdfOptions, _ := cmd.Flags().GetString(commonParams.ReportFormatPdfOptionsFlag) - formatSbomOptions, _ := cmd.Flags().GetString(commonParams.ReportSbomFormatFlag) - sastRedundancy, _ := cmd.Flags().GetBool(commonParams.SastRedundancyFlag) - agent, _ := cmd.Flags().GetString(commonParams.AgentFlag) - scaHideDevAndTestDep, _ := cmd.Flags().GetBool(commonParams.ScaHideDevAndTestDepFlag) - ignorePolicy, _ := cmd.Flags().GetBool(commonParams.IgnorePolicyFlag) - // Check if the user has permission to override policy management if --ignore-policy is set - ignorePolicyFlagOmit := false - if ignorePolicy { - overridePolicyManagementPer, err := jwtWrapper.CheckPermissionByAccessToken(OverridePolicyManagement) - if err != nil { - return err - } - if !overridePolicyManagementPer { - ignorePolicyFlagOmit = true - ignorePolicy = false - } - } - waitDelay, _ := cmd.Flags().GetInt(commonParams.WaitDelayFlag) - policyTimeout, _ := cmd.Flags().GetInt(commonParams.PolicyTimeoutFlag) - - scanID, _ := cmd.Flags().GetString(commonParams.ScanIDFlag) - if scanID == "" { - return errors.Errorf("%s: Please provide a scan ID", failedListingResults) - } - - resultsParams, err := getFilters(cmd) - if err != nil { - return errors.Wrapf(err, "%s", failedListingResults) - } - - if scaHideDevAndTestDep { - resultsParams[ScaExcludeResultTypesParam] = ScaDevAndTestExclusionParam - } - - scan, errorModel, scanErr := scanWrapper.GetByID(scanID) - if scanErr != nil { - return errors.Wrapf(scanErr, "%s", failedGetting) - } - if errorModel != nil { - return errors.Errorf("%s: CODE: %d, %s", failedGettingScan, errorModel.Code, errorModel.Message) - } - - var policyResponseModel *wrappers.PolicyResponseModel - if !isScanPending(string(scan.Status)) { - policyResponseModel, err = services.HandlePolicyEvaluation(cmd, policyWrapper, scan, ignorePolicy, agent, waitDelay, policyTimeout) - if err != nil { - return err - } - } else { - logger.PrintIfVerbose("Policy violations aren't returned in the pipeline for scans run in async mode.") - } - - if sastRedundancy { - resultsParams[commonParams.SastRedundancyFlag] = "" - } - - _, err = CreateScanReport(resultsWrapper, risksOverviewWrapper, scsScanOverviewWrapper, exportWrapper, - policyResponseModel, resultsPdfReportsWrapper, resultsJSONReportsWrapper, scan, format, formatPdfToEmail, formatPdfOptions, - formatSbomOptions, targetFile, targetPath, agent, resultsParams, featureFlagsWrapper, ignorePolicyFlagOmit) - return err - } -} - -func runGetCodeBashingCommand( - codeBashingWrapper wrappers.CodeBashingWrapper, -) func(cmd *cobra.Command, args []string) error { - return func(cmd *cobra.Command, args []string) error { - language, _ := cmd.Flags().GetString(commonParams.LanguageFlag) - cwe, _ := cmd.Flags().GetString(commonParams.CweIDFlag) - vulType, _ := cmd.Flags().GetString(commonParams.VulnerabilityTypeFlag) - params, err := codeBashingWrapper.BuildCodeBashingParams( - []wrappers.CodeBashingParamsCollection{ - { - CweID: "CWE-" + cwe, - Language: language, - CxQueryName: strings.ReplaceAll(vulType, " ", "_"), - }, - }, - ) - if err != nil { - return err - } - // Fetch the cached token or a new one to obtain the codebashing URL incoded in the jwt token - codeBashingURL, err := codeBashingWrapper.GetCodeBashingURL(codeBashingKey) - if err != nil { - return err - } - // Make the request to the api to obtain the codebashing link and send the codebashing url to enrich the path - CodeBashingModel, webError, err := codeBashingWrapper.GetCodeBashingLinks(params, codeBashingURL) - if err != nil { - return err - } - if webError != nil { - return errors.New(webError.Message) - } - err = printByFormat(cmd, *CodeBashingModel) - if err != nil { - return errors.Wrapf(err, "%s", failedListingCodeBashing) - } - return nil - } -} - -func setIsContainersEnabled(agent string) { - wrappers.IsContainersEnabled = !containsIgnoreCase(containerEngineUnsupportedAgents, agent) -} - -func filterResultsByType(results *wrappers.ScanResultsCollection, excludedTypes map[string]struct{}) *wrappers.ScanResultsCollection { - var filteredResults []*wrappers.ScanResult - - for _, result := range results.Results { - if _, shouldExclude := excludedTypes[result.Type]; shouldExclude { - results.TotalCount-- - } else { - filteredResults = append(filteredResults, result) - } - } - results.Results = filteredResults - return results -} - -func filterScsResultsByAgent(results *wrappers.ScanResultsCollection, agent string) *wrappers.ScanResultsCollection { - unsupportedTypesByAgent := map[string][]string{ - commonParams.VSCodeAgent: {commonParams.SCSScorecardType}, - commonParams.JetbrainsAgent: {commonParams.SCSScorecardType}, - commonParams.EclipseAgent: {commonParams.SCSScorecardType, commonParams.SCSSecretDetectionType}, - commonParams.VisualStudioAgent: {commonParams.SCSScorecardType}, - } - - excludedTypes := make(map[string]struct{}) - - if typesToExclude, exists := unsupportedTypesByAgent[agent]; exists { - for _, excludeType := range typesToExclude { - excludedTypes[excludeType] = struct{}{} - } - } - - results = filterResultsByType(results, excludedTypes) - - return results -} - -func CreateScanReport( - resultsWrapper wrappers.ResultsWrapper, - risksOverviewWrapper wrappers.RisksOverviewWrapper, - scsScanOverviewWrapper wrappers.ScanOverviewWrapper, - exportWrapper wrappers.ExportWrapper, - policyResponseModel *wrappers.PolicyResponseModel, - resultsPdfReportsWrapper wrappers.ResultsPdfWrapper, - resultsJSONReportsWrapper wrappers.ResultsJSONWrapper, - scan *wrappers.ScanResponseModel, - reportTypes, - formatPdfToEmail, - formatPdfOptions, - formatSbomOptions, - targetFile, - targetPath string, - agent string, - resultsParams map[string]string, - featureFlagsWrapper wrappers.FeatureFlagsWrapper, - ignorePolicyFlagOmit bool, -) (*wrappers.ScanResultsCollection, error) { - reportList := strings.Split(reportTypes, ",") - results := &wrappers.ScanResultsCollection{} - setIsContainersEnabled(agent) - summary, err := convertScanToResultsSummary(scan, resultsWrapper) - if err != nil { - return nil, err - } - scanPending := isScanPending(summary.Status) - - err = createDirectory(targetPath) - if err != nil { - return nil, err - } - if !scanPending { - results, err = ReadResults(resultsWrapper, exportWrapper, scan, resultsParams, agent, featureFlagsWrapper) - if err != nil { - return nil, err - } - } - isSummaryNeeded := verifyFormatsByReportList(reportList, summaryFormats...) - if isSummaryNeeded && !scanPending { - summary, err = summaryReport(summary, policyResponseModel, risksOverviewWrapper, scsScanOverviewWrapper, featureFlagsWrapper, results, resultsParams) - if err != nil { - return nil, err - } - } - for _, reportType := range reportList { - err = createReport(reportType, formatPdfToEmail, formatPdfOptions, formatSbomOptions, targetFile, - targetPath, results, summary, exportWrapper, resultsPdfReportsWrapper, resultsJSONReportsWrapper, featureFlagsWrapper, ignorePolicyFlagOmit) - if err != nil { - return nil, err - } - } - return results, nil -} - -func countResult(summary *wrappers.ResultSummary, result *wrappers.ScanResult) { - engineType := strings.TrimSpace(result.Type) - severity := strings.ToLower(result.Severity) - if contains(summary.EnginesEnabled, engineType) && isExploitable(result.State) { - if engineType == commonParams.SastType { - summary.SastIssues++ - summary.TotalIssues++ - } else if engineType == commonParams.ScaType { - summary.ScaIssues++ - summary.TotalIssues++ - } else if engineType == commonParams.KicsType { - summary.KicsIssues++ - summary.TotalIssues++ - } else if engineType == commonParams.ContainersType { - if wrappers.IsContainersEnabled { - *summary.ContainersIssues++ - summary.TotalIssues++ - } else { - return - } - } else if strings.HasPrefix(engineType, commonParams.SscsType) { - addResultToSCSOverview(summary, result) - engineType = commonParams.ScsType - *summary.ScsIssues++ - summary.TotalIssues++ - } else { - return - } - - switch severity { - case criticalLabel: - summary.CriticalIssues++ - case highLabel: - summary.HighIssues++ - case mediumLabel: - summary.MediumIssues++ - case lowLabel: - summary.LowIssues++ - case infoLabel: - summary.InfoIssues++ - } - - summary.UpdateEngineResultSummary(engineType, severity) - } -} - -func addResultToSCSOverview(summary *wrappers.ResultSummary, result *wrappers.ScanResult) { - if engineOverviewName, engineExists := sscsEngineToOverviewEngineMap[result.Type]; engineExists { - for _, microEngineOverview := range summary.SCSOverview.MicroEngineOverviews { - if microEngineOverview.Name == engineOverviewName { - if microEngineOverview.RiskSummary != nil { - severity := strings.ToLower(result.Severity) - if severityCount, exists := microEngineOverview.RiskSummary[severity]; exists { - summary.SCSOverview.RiskSummary[severity]++ - microEngineOverview.TotalRisks++ - summary.SCSOverview.TotalRisksCount++ - microEngineOverview.RiskSummary[severity] = severityCount.(int) + 1 - } - } - } - } - } -} - -func verifyFormatsByReportList(reportFormats []string, formats ...string) bool { - for _, reportFormat := range reportFormats { - for _, format := range formats { - if printer.IsFormat(reportFormat, format) { - return true - } - } - } - return false -} - -func validateEmails(emailString string) ([]string, error) { - re := regexp.MustCompile(`^[a-zA-Z0-9_.+-]+@[a-zA-Z0-9-]+\.[a-zA-Z0-9-.]+$`) - emails := strings.Split(emailString, ",") - var validEmails []string - for _, emailStr := range emails { - email := strings.TrimSpace(emailStr) - if re.MatchString(email) { - validEmails = append(validEmails, email) - } else { - return nil, errors.Errorf("report not sent, invalid email address: %s", email) - } - } - return validEmails, nil -} - -func getResultsForAPISecScanner( - risksOverviewWrapper wrappers.RisksOverviewWrapper, - scanID string, -) (results *wrappers.APISecResult, err error) { - var apiSecResultsModel *wrappers.APISecResult - var errorModel *wrappers.WebError - - apiSecResultsModel, errorModel, err = risksOverviewWrapper.GetAllAPISecRisksByScanID(scanID) - if err != nil { - return nil, errors.Wrapf(err, "%s", failedListingResults) - } - if errorModel != nil { - return nil, errors.Errorf("%s: CODE: %d, %s", failedListingResults, errorModel.Code, errorModel.Message) - } else if apiSecResultsModel != nil { - return apiSecResultsModel, nil - } - return nil, nil -} - -func getScanOverviewForSCSScanner( - scsScanOverviewWrapper wrappers.ScanOverviewWrapper, - scanID string, -) (results *wrappers.SCSOverview, err error) { - var scsOverview *wrappers.SCSOverview - var errorModel *wrappers.WebError - - scsOverview, errorModel, err = scsScanOverviewWrapper.GetSCSOverviewByScanID(scanID) - if err != nil { - return nil, errors.Wrapf(err, "SCS: %s", failedListingResults) - } - if errorModel != nil { - return nil, errors.Errorf("SCS: %s: CODE: %d, %s", failedListingResults, errorModel.Code, errorModel.Message) - } else if scsOverview != nil { - // Setting all counts to 0. Results are recounted in enhanceWithScanSummary->countResult - scsOverview.TotalRisksCount = 0 - for key := range scsOverview.RiskSummary { - scsOverview.RiskSummary[key] = 0 - } - for _, microEngineOverview := range scsOverview.MicroEngineOverviews { - microEngineOverview.TotalRisks = 0 - if microEngineOverview.RiskSummary != nil { - for severity := range microEngineOverview.RiskSummary { - microEngineOverview.RiskSummary[severity] = 0 - } - } - } - return scsOverview, nil - } - return nil, nil -} - -func isScanPending(scanStatus string) bool { - return !(strings.EqualFold(scanStatus, "Completed") || strings.EqualFold( - scanStatus, - "Partial", - ) || strings.EqualFold(scanStatus, "Failed")) -} - -func isValidScanStatus(status, format string) bool { - if isScanPending(status) { - log.Printf("Result format file %s not create because scan status is %s", format, status) - return false - } - return true -} - -func createReport(format, - formatPdfToEmail, - formatPdfOptions, - formatSbomOptions, - targetFile, - targetPath string, - results *wrappers.ScanResultsCollection, - summary *wrappers.ResultSummary, - exportWrapper wrappers.ExportWrapper, - resultsPdfReportsWrapper wrappers.ResultsPdfWrapper, - resultsJSONReportsWrapper wrappers.ResultsJSONWrapper, - featureFlagsWrapper wrappers.FeatureFlagsWrapper, - ignorePolicyFlagOmit bool) error { - if printer.IsFormat(format, printer.FormatIndentedJSON) { - return nil - } - if printer.IsFormat(format, printer.FormatSarif) && isValidScanStatus(summary.Status, printer.FormatSarif) { - sarifRpt := createTargetName(targetFile, targetPath, printer.FormatSarif) - return exportSarifResults(sarifRpt, results) - } - if printer.IsFormat(format, printer.FormatSonar) && isValidScanStatus(summary.Status, printer.FormatSonar) { - sonarRpt := createTargetName(fmt.Sprintf("%s%s", targetFile, sonarTypeLabel), targetPath, printer.FormatJSON) - return exportSonarResults(sonarRpt, results) - } - if printer.IsFormat(format, printer.FormatJSON) && isValidScanStatus(summary.Status, printer.FormatJSON) { - jsonRpt := createTargetName(targetFile, targetPath, printer.FormatJSON) - return exportJSONResults(jsonRpt, results) - } - if printer.IsFormat(format, printer.FormatJSONv2) && isValidScanStatus(summary.Status, printer.FormatJSONv2) { - summaryRpt := createTargetName(targetFile, targetPath, printer.FormatJSON) - return exportJSONReportResults(resultsJSONReportsWrapper, summary, summaryRpt, featureFlagsWrapper) - } - if printer.IsFormat(format, printer.FormatGLSast) { - jsonRpt := createTargetName(fmt.Sprintf("%s%s", targetFile, glSastTypeLabel), targetPath, printer.FormatJSON) - return exportGlSastResults(jsonRpt, results, summary) - } - if printer.IsFormat(format, printer.FormatGLSca) { - jsonRpt := createTargetName(fmt.Sprintf("%s%s", targetFile, glScaTypeLabel), targetPath, printer.FormatJSON) - return exportGlScaResults(jsonRpt, results, summary) - } - - if printer.IsFormat(format, printer.FormatSummaryConsole) { - return writeConsoleSummary(summary, featureFlagsWrapper, ignorePolicyFlagOmit) - } - if printer.IsFormat(format, printer.FormatSummary) { - summaryRpt := createTargetName(targetFile, targetPath, printer.FormatHTML) - convertNotAvailableNumberToZero(summary) - return writeHTMLSummary(summaryRpt, summary) - } - if printer.IsFormat(format, printer.FormatSummaryJSON) { - summaryRpt := createTargetName(targetFile, targetPath, printer.FormatJSON) - convertNotAvailableNumberToZero(summary) - return exportJSONSummaryResults(summaryRpt, summary) - } - if printer.IsFormat(format, printer.FormatPDF) && isValidScanStatus(summary.Status, printer.FormatPDF) { - summaryRpt := createTargetName(targetFile, targetPath, printer.FormatPDF) - return exportPdfResults(resultsPdfReportsWrapper, summary, summaryRpt, formatPdfToEmail, formatPdfOptions, featureFlagsWrapper) - } - if printer.IsFormat(format, printer.FormatSummaryMarkdown) { - summaryRpt := createTargetName(targetFile, targetPath, "md") - convertNotAvailableNumberToZero(summary) - return writeMarkdownSummary(summaryRpt, summary) - } - if printer.IsFormat(format, printer.FormatSbom) && isValidScanStatus(summary.Status, printer.FormatSbom) { - targetType := printer.FormatJSON - if strings.Contains(strings.ToLower(formatSbomOptions), printer.FormatXML) { - targetType = printer.FormatXML - } - summaryRpt := createTargetName(fmt.Sprintf("%s_%s", targetFile, printer.FormatSbom), targetPath, targetType) - convertNotAvailableNumberToZero(summary) - - if !contains(summary.EnginesEnabled, commonParams.ScaType) { - return fmt.Errorf("unable to generate %s report - SCA engine must be enabled on scan summary", printer.FormatSbom) - } - - if summary.ScaIssues == notAvailableNumber { - return fmt.Errorf("unable to generate %s report - SCA engine did not complete successfully", printer.FormatSbom) - } - - return services.ExportSbomResults(exportWrapper, summaryRpt, summary, formatSbomOptions) - } - return fmt.Errorf("bad report format %s", format) -} - -func createTargetName(targetFile, targetPath, targetType string) string { - return filepath.Join(targetPath, targetFile+"."+targetType) -} - -func createDirectory(targetPath string) error { - if _, err := os.Stat(targetPath); os.IsNotExist(err) { - log.Printf("\nOutput path not found: %s\n", targetPath) - log.Printf("Creating directory: %s\n", targetPath) - err = os.Mkdir(targetPath, directoryPermission) - if err != nil { - return err - } - } - return nil -} - -func ReadResults( - resultsWrapper wrappers.ResultsWrapper, - exportWrapper wrappers.ExportWrapper, - scan *wrappers.ScanResponseModel, - resultsParams map[string]string, - agent string, featureflagsWrappers wrappers.FeatureFlagsWrapper) (results *wrappers.ScanResultsCollection, err error) { - var resultsModel *wrappers.ScanResultsCollection - var errorModel *wrappers.WebError - - resultsParams[commonParams.ScanIDQueryParam] = scan.ID - _, sastRedundancy := resultsParams[commonParams.SastRedundancyFlag] - - scaHideDevAndTestDep := resultsParams[ScaExcludeResultTypesParam] == ScaDevAndTestExclusionParam - - resultsModel, errorModel, err = resultsWrapper.GetAllResultsByScanID(resultsParams) - - if err != nil { - return nil, errors.Wrapf(err, "%s", failedListingResults) - } - if errorModel != nil { - return nil, errors.Errorf("%s: CODE: %d, %s", failedListingResults, errorModel.Code, errorModel.Message) - } - - if resultsModel != nil { - if slices.Contains(scan.Engines, commonParams.SastType) && sastRedundancy { - // Compute SAST results redundancy - resultsModel = ComputeRedundantSastResults(resultsModel) - } - resultsModel, err = enrichScaResults(exportWrapper, scan, resultsModel, scaHideDevAndTestDep, featureflagsWrappers) - if err != nil { - return nil, err - } - - if slices.Contains(scan.Engines, commonParams.ScsType) { - resultsModel = filterScsResultsByAgent(resultsModel, agent) - } - - resultsModel.ScanID = scan.ID - return resultsModel, nil - } - return nil, nil -} - -func enrichScaResults( - exportWrapper wrappers.ExportWrapper, - scan *wrappers.ScanResponseModel, - resultsModel *wrappers.ScanResultsCollection, - scaHideDevAndTestDep bool, featureflagWrapper wrappers.FeatureFlagsWrapper) (*wrappers.ScanResultsCollection, error) { - if slices.Contains(scan.Engines, commonParams.ScaType) { - scaExportDetails, err := services.GetExportPackage(exportWrapper, scan.ID, scaHideDevAndTestDep, featureflagWrapper) - if err != nil { - return nil, errors.Wrapf(err, "%s", failedListingResults) - } - scaPackageModel := parseScaExportPackage(scaExportDetails.Packages) - scaTypeModel := parseExportScaVulnerability(scaExportDetails.ScaTypes) - if scaPackageModel != nil { - resultsModel = addPackageInformation(resultsModel, scaPackageModel, scaTypeModel) - } - } - if slices.Contains(scan.Engines, commonParams.ContainersType) && !wrappers.IsContainersEnabled { - resultsModel = removeResultsByType(resultsModel, commonParams.ContainersType) - } - return resultsModel, nil -} - -func parseExportScaVulnerability(types []wrappers.ScaType) *[]wrappers.ScaTypeCollection { - var scaTypes []wrappers.ScaTypeCollection - for _, t := range types { - scaTypes = append(scaTypes, wrappers.ScaTypeCollection(t)) - } - return &scaTypes -} - -func parseScaExportPackage(packages []wrappers.ScaPackage) *[]wrappers.ScaPackageCollection { - var scaPackages []wrappers.ScaPackageCollection - for _, pkg := range packages { - pkg := pkg - scaPackages = append(scaPackages, wrappers.ScaPackageCollection{ - ID: pkg.ID, - Locations: pkg.Locations, - DependencyPathArray: parsePackagePathToDependencyPath(&pkg), - Outdated: pkg.Outdated, - IsDirectDependency: pkg.IsDirectDependency, - IsDevelopmentDependency: pkg.IsDevelopmentDependency, - IsTestDependency: pkg.IsTestDependency, - }) - } - return &scaPackages -} - -func parsePackagePathToDependencyPath(pkg *wrappers.ScaPackage) [][]wrappers.DependencyPath { - var dependencyPathArray [][]wrappers.DependencyPath - for _, path := range pkg.PackagePathArray { - var dependencyPath []wrappers.DependencyPath - for _, dep := range path { - dependencyPath = append(dependencyPath, wrappers.DependencyPath{ - ID: dep.ID, - Name: dep.Name, - Version: dep.Version, - }) - } - dependencyPathArray = append(dependencyPathArray, dependencyPath) - } - - // We are doing this to maintain the same structure that was in risk-management api response - // in risk-management, if the length of the dependency path array is 1, it will be the main package - // in export service, if there are no dependencies, the package path array will be empty - if len(dependencyPathArray) == 0 { - appendMainPackageToDependencyPath(&dependencyPathArray, pkg) - } - return dependencyPathArray -} - -func appendMainPackageToDependencyPath(dependencyPathArray *[][]wrappers.DependencyPath, pkg *wrappers.ScaPackage) { - *dependencyPathArray = append(*dependencyPathArray, []wrappers.DependencyPath{{ - ID: pkg.ID, - Locations: pkg.Locations, - Name: pkg.Name, - IsDevelopment: pkg.IsDevelopmentDependency, - }}) -} - -func removeResultsByType(model *wrappers.ScanResultsCollection, resultType string) *wrappers.ScanResultsCollection { - var newResults []*wrappers.ScanResult - for _, result := range model.Results { - isResultType := result.Type == resultType - if resultType == commonParams.SscsType { - isResultType = strings.HasPrefix(result.Type, resultType) - } - if !isResultType { - newResults = append(newResults, result) - } - } - model.Results = newResults - model.TotalCount = uint(len(newResults)) - return model -} - -func exportSarifResults(targetFile string, results *wrappers.ScanResultsCollection) error { - var err error - var resultsJSON []byte - log.Println("Creating SARIF Report: ", targetFile) - var sarifResults = convertCxResultsToSarif(results) - resultsJSON, err = json.Marshal(sarifResults) - if err != nil { - return errors.Wrapf(err, "%s: failed to serialize results response ", failedGettingAll) - } - f, err := os.Create(targetFile) - if err != nil { - return errors.Wrapf(err, "%s: failed to create target file ", failedGettingAll) - } - _, _ = fmt.Fprintln(f, string(resultsJSON)) - _ = f.Close() - return nil -} -func exportGlSastResults(targetFile string, results *wrappers.ScanResultsCollection, summary *wrappers.ResultSummary) error { - log.Println("Creating gl-sast Report: ", targetFile) - var glSast = new(wrappers.GlSastResultsCollection) - glSast.Vulnerabilities = []wrappers.GlVulnerabilities{} - err := addScanToGlSastReport(summary, glSast) - if err != nil { - return errors.Wrapf(err, "%s: failed to add scan to gl-sast report", failedListingResults) - } - convertCxResultToGlSastVulnerability(results, glSast, summary) - resultsJSON, err := json.Marshal(glSast) - if err != nil { - return errors.Wrapf(err, "%s: failed to serialize gl-sast report ", failedListingResults) - } - f, err := os.Create(targetFile) - if err != nil { - return errors.Wrapf(err, "%s: failed to create target file ", failedListingResults) - } - defer f.Close() - _, _ = fmt.Fprintln(f, string(resultsJSON)) - return nil -} - -func exportGlScaResults(targetFile string, results *wrappers.ScanResultsCollection, summary *wrappers.ResultSummary) error { - log.Println("Creating Gl-sca Report: ", targetFile) - glScaResult := &wrappers.GlScaResultsCollection{ - Vulnerabilities: []wrappers.GlScaDepVulnerabilities{}, // Initialize arrays to prevent GitLab schema validation errors. - ScaDependencyFiles: []wrappers.ScaDependencyFile{}, - } - err := addScanToGlScaReport(summary, glScaResult) - if err != nil { - return errors.Wrapf(err, "%s: failed to denerate GL-Sca report ", failedListingResults) - } - convertCxResultToGlScaVulnerability(results, glScaResult) - convertCxResultToGlScaFiles(results, glScaResult) - resultsJSON, err := json.Marshal(glScaResult) - if err != nil { - return errors.Wrapf(err, "%s: failed to serialize GL-Sca report ", failedListingResults) - } - f, err := os.Create(targetFile) - if err != nil { - return errors.Wrapf(err, "%s: failed to create target file ", failedListingResults) - } - _, _ = fmt.Fprintln(f, string(resultsJSON)) - defer f.Close() - - return nil -} - -func addScanToGlScaReport(summary *wrappers.ResultSummary, glScaResult *wrappers.GlScaResultsCollection) error { - createdAt, err := time.Parse(summaryCreatedAtLayout, summary.CreatedAt) - if err != nil { - return err - } - - glScaResult.Schema = wrappers.ScaSchema - glScaResult.Version = wrappers.SchemaVersion - glScaResult.Scan.Analyzer.VendorGlSCA.VendorGlname = wrappers.AnalyzerScaID - glScaResult.Scan.Analyzer.Name = wrappers.AnalyzerScaID - glScaResult.Scan.Analyzer.Name = wrappers.AnalyzerScaID - glScaResult.Scan.Analyzer.ID = wrappers.ScannerID - glScaResult.Scan.Scanner.ID = wrappers.ScannerID - glScaResult.Scan.Scanner.Name = wrappers.AnalyzerScaID - glScaResult.Scan.Scanner.VendorGlSCA.VendorGlname = wrappers.AnalyzerScaID - glScaResult.Scan.Status = commonParams.Success - glScaResult.Scan.Type = wrappers.ScannerType - glScaResult.Scan.StartTime = createdAt.Format(glTimeFormat) - glScaResult.Scan.EndTime = createdAt.Format(glTimeFormat) - glScaResult.Scan.Scanner.Name = wrappers.AnalyzerScaID - glScaResult.Scan.Scanner.VersionGlSca = commonParams.Version - glScaResult.Scan.Analyzer.VersionGlSca = commonParams.Version - - return nil -} - -func addScanToGlSastReport(summary *wrappers.ResultSummary, glSast *wrappers.GlSastResultsCollection) error { - createdAt, err := time.Parse(summaryCreatedAtLayout, summary.CreatedAt) - if err != nil { - return err - } - - glSast.Scan = wrappers.ScanGlReport{} - glSast.Schema = wrappers.SastSchema - glSast.Version = wrappers.SastSchemaVersion - glSast.Scan.Analyzer.URL = wrappers.AnalyzerURL - glSast.Scan.Analyzer.Name = wrappers.VendorName - glSast.Scan.Analyzer.Vendor.Name = wrappers.VendorName - glSast.Scan.Analyzer.ID = wrappers.AnalyzerID - glSast.Scan.Scanner.ID = wrappers.AnalyzerID - glSast.Scan.Scanner.Name = wrappers.VendorName - glSast.Scan.Status = commonParams.Success - glSast.Scan.Type = commonParams.SastType - glSast.Scan.StartTime = createdAt.Format(glTimeFormat) - glSast.Scan.EndTime = createdAt.Format(glTimeFormat) - glSast.Scan.Scanner.Vendor.Name = wrappers.VendorName - glSast.Scan.Scanner.Version = commonParams.Version - glSast.Scan.Analyzer.Version = commonParams.Version - - return nil -} -func exportSonarResults(targetFile string, results *wrappers.ScanResultsCollection) error { - var err error - var resultsJSON []byte - log.Println("Creating SONAR Report: ", targetFile) - var sonarResults = convertCxResultsToSonar(results) - resultsJSON, err = json.Marshal(sonarResults) - if err != nil { - return errors.Wrapf(err, "%s: failed to serialize results response ", failedGettingAll) - } - f, err := os.Create(targetFile) - if err != nil { - return errors.Wrapf(err, "%s: failed to create target file ", failedGettingAll) - } - _, _ = fmt.Fprintln(f, string(resultsJSON)) - _ = f.Close() - return nil -} - -// Function to decode HTML entities in the ScanResultsCollection -func decodeHTMLEntitiesInResults(results *wrappers.ScanResultsCollection) { - for _, result := range results.Results { - result.Description = html.UnescapeString(result.Description) - result.DescriptionHTML = html.UnescapeString(result.DescriptionHTML) - for _, node := range result.ScanResultData.Nodes { - node.FullName = html.UnescapeString(node.FullName) - node.Name = html.UnescapeString(node.Name) - } - } -} - -func exportJSONResults(targetFile string, results *wrappers.ScanResultsCollection) error { - decodeHTMLEntitiesInResults(results) - var err error - var resultsJSON []byte - log.Println("Creating JSON Report: ", targetFile) - resultsJSON, err = json.Marshal(results) - if err != nil { - return errors.Wrapf(err, "%s: failed to serialize results response ", failedGettingAll) - } - f, err := os.Create(targetFile) - if err != nil { - return errors.Wrapf(err, "%s: failed to create target file ", failedGettingAll) - } - _, _ = fmt.Fprintln(f, string(resultsJSON)) - _ = f.Close() - return nil -} - -func exportJSONReportResults(jsonWrapper wrappers.ResultsJSONWrapper, summary *wrappers.ResultSummary, summaryRpt string, featureFlagsWrapper wrappers.FeatureFlagsWrapper) error { - jsonReportsPayload := &wrappers.JSONReportsPayload{} - pollingResp := &wrappers.JSONPollingResponse{} - jsonReportsPayload.ReportName = reportNameImprovedScanReport - - jsonOptionsSections, jsonOptionsEngines := parseJSONOptions(summary.EnginesEnabled, jsonReportsPayload.ReportName) - - jsonReportsPayload.ReportType = CliType - jsonReportsPayload.FileFormat = printer.FormatJSON - jsonReportsPayload.Data.ScanID = summary.ScanID - jsonReportsPayload.Data.ProjectID = summary.ProjectID - jsonReportsPayload.Data.BranchName = summary.BranchName - jsonReportsPayload.Data.Scanners = jsonOptionsEngines - jsonReportsPayload.Data.Sections = jsonOptionsSections - - jsonReportID, webErr, err := jsonWrapper.GenerateJSONReport(jsonReportsPayload) - if webErr != nil { - return errors.Errorf("Error generating JSON report - %s", webErr.Message) - } - if err != nil { - return errors.Errorf("Error generating JSON report - %s", err.Error()) - } - log.Println("Generating JSON report") - pollingResp.Status = startedStatus - for pollingResp.Status == startedStatus || pollingResp.Status == requestedStatus { - pollingResp, webErr, err = jsonWrapper.CheckJSONReportStatus(jsonReportID.ReportID) - if err != nil || webErr != nil { - return errors.Wrapf(err, "%v", webErr) - } - logger.PrintfIfVerbose("JSON report status: %s", pollingResp.Status) - time.Sleep(delayValueForReport * time.Millisecond) - } - if pollingResp.Status != completedStatus { - return errors.Errorf("JSON generating failed - Current status: %s", pollingResp.Status) - } - - minioEnabled, _ := wrappers.GetSpecificFeatureFlag(featureFlagsWrapper, wrappers.MinioEnabled) - infoPathType := "" - if minioEnabled.Status { - infoPathType = jsonReportID.ReportID - } else { - infoPathType = pollingResp.URL - } - err = jsonWrapper.DownloadJSONReport(infoPathType, summaryRpt, minioEnabled.Status) - if err != nil { - return errors.Wrapf(err, "%s", "Failed downloading JSON report") - } - return nil -} - -func parseJSONOptions(enabledEngines []string, reportName string) (jsonOptionsSections, jsonOptionsEngines []string) { - jsonOptionsSections = []string{ - "ScanSummary", - "ExecutiveSummary", - "ScanResults", - } - - var jsonOptionsEnginesMap = map[string]string{ - commonParams.ScaType: "SCA", - commonParams.SastType: "SAST", - commonParams.KicsType: "KICS", - commonParams.IacType: "KICS", - commonParams.ContainersType: "Containers", - commonParams.ScsType: "Microengines", - } - if jsonOptionsEngines == nil { - for _, engine := range enabledEngines { - if jsonOptionsEnginesMap[engine] != "" { - jsonOptionsEngines = append(jsonOptionsEngines, jsonOptionsEnginesMap[engine]) - } - } - } - - if reportName == reportNameImprovedScanReport { - jsonOptionsSections = translateReportSectionsForImproved(jsonOptionsSections) - } - - return jsonOptionsSections, jsonOptionsEngines -} - -func exportJSONSummaryResults(targetFile string, results *wrappers.ResultSummary) error { - var err error - var resultsJSON []byte - log.Println("Creating summary JSON Report: ", targetFile) - resultsJSON, err = json.Marshal(results) - if err != nil { - return errors.Wrapf(err, "%s: failed to serialize results response ", failedGettingAll) - } - f, err := os.Create(targetFile) - if err != nil { - return errors.Wrapf(err, "%s: failed to create target file ", failedGettingAll) - } - _, _ = fmt.Fprintln(f, string(resultsJSON)) - _ = f.Close() - return nil -} - -func exportPdfResults(pdfWrapper wrappers.ResultsPdfWrapper, summary *wrappers.ResultSummary, summaryRpt, formatPdfToEmail, - pdfOptions string, featureFlagsWrapper wrappers.FeatureFlagsWrapper) error { - pdfReportsPayload := &wrappers.PdfReportsPayload{} - pollingResp := &wrappers.PdfPollingResponse{} - pdfReportsPayload.ReportName = reportNameImprovedScanReport - pdfOptionsSections, pdfOptionsEngines, err := parsePDFOptions(pdfOptions, summary.EnginesEnabled, pdfReportsPayload.ReportName) - if err != nil { - return err - } - pdfReportsPayload.ReportType = CliType - pdfReportsPayload.FileFormat = printer.FormatPDF - pdfReportsPayload.Data.ScanID = summary.ScanID - pdfReportsPayload.Data.ProjectID = summary.ProjectID - pdfReportsPayload.Data.BranchName = summary.BranchName - pdfReportsPayload.Data.Scanners = pdfOptionsEngines - pdfReportsPayload.Data.Sections = pdfOptionsSections - - // will generate pdf report and send it to the email list - // instead of saving it to the file system - if len(formatPdfToEmail) > 0 { - emailList, validateErr := validateEmails(formatPdfToEmail) - if validateErr != nil { - return validateErr - } - pdfReportsPayload.ReportType = reportTypeEmail - pdfReportsPayload.Data.Email = emailList - } - pdfReportID, webErr, err := pdfWrapper.GeneratePdfReport(pdfReportsPayload) - if webErr != nil { - return errors.Errorf("Error generating PDF report - %s", webErr.Message) - } - if err != nil { - return errors.Errorf("Error generating PDF report - %s", err.Error()) - } - if pdfReportsPayload.ReportType == reportTypeEmail { - log.Println("Sending PDF report to: ", pdfReportsPayload.Data.Email) - return nil - } - log.Println("Generating PDF report") - pollingResp.Status = startedStatus - for pollingResp.Status == startedStatus || pollingResp.Status == requestedStatus { - pollingResp, webErr, err = pdfWrapper.CheckPdfReportStatus(pdfReportID.ReportID) - if err != nil || webErr != nil { - return errors.Wrapf(err, "%v", webErr) - } - logger.PrintfIfVerbose("PDF report status: %s", pollingResp.Status) - time.Sleep(delayValueForReport * time.Millisecond) - } - if pollingResp.Status != completedStatus { - return errors.Errorf("PDF generating failed - Current status: %s", pollingResp.Status) - } - - minioEnabled, _ := wrappers.GetSpecificFeatureFlag(featureFlagsWrapper, wrappers.MinioEnabled) - infoPathType := "" - if minioEnabled.Status { - infoPathType = pdfReportID.ReportID - } else { - infoPathType = pollingResp.URL - } - err = pdfWrapper.DownloadPdfReport(infoPathType, summaryRpt, minioEnabled.Status) - if err != nil { - return errors.Wrapf(err, "%s", "Failed downloading PDF report") - } - return nil -} - -func parsePDFOptions(pdfOptions string, enabledEngines []string, reportName string) (pdfOptionsSections, pdfOptionsEngines []string, err error) { - var pdfOptionsSectionsMap = map[string]string{ - "scansummary": "ScanSummary", - "executivesummary": "ExecutiveSummary", - "scanresults": "ScanResults", - } - - var pdfOptionsEnginesMap = map[string]string{ - commonParams.ScaType: "SCA", - commonParams.SastType: "SAST", - commonParams.KicsType: "KICS", - commonParams.IacType: "KICS", - } - - pdfOptions = strings.ToLower(strings.ReplaceAll(pdfOptions, " ", "")) - options := strings.Split(strings.ReplaceAll(pdfOptions, "\n", ""), ",") - for _, s := range options { - if pdfOptionsEnginesMap[s] != "" { - pdfOptionsEngines = append(pdfOptionsEngines, pdfOptionsEnginesMap[s]) - } else if pdfOptionsSectionsMap[s] != "" { - pdfOptionsSections = append(pdfOptionsSections, pdfOptionsSectionsMap[s]) - } else { - return nil, nil, errors.Errorf("report option \"%s\" unavailable", s) - } - } - if pdfOptionsEngines == nil { - for _, engine := range enabledEngines { - if pdfOptionsEnginesMap[engine] != "" { - pdfOptionsEngines = append(pdfOptionsEngines, pdfOptionsEnginesMap[engine]) - } - } - } - - if reportName == reportNameImprovedScanReport { - pdfOptionsSections = translateReportSectionsForImproved(pdfOptionsSections) - } - - return pdfOptionsSections, pdfOptionsEngines, nil -} - -func translateReportSectionsForImproved(sections []string) []string { - var resultSections = make([]string, 0) - - var pdfOptionsSectionsImprovedTranslation = map[string][]string{ - "ScanSummary": {"scan-information"}, - "ExecutiveSummary": {"results-overview"}, - "ScanResults": {"scan-results", "categories", "resolved-results", "vulnerability-details"}, - } - - for _, section := range sections { - if translatedSections := pdfOptionsSectionsImprovedTranslation[section]; translatedSections != nil { - resultSections = append(resultSections, translatedSections...) - } - } - - return resultSections -} - -func convertCxResultsToSarif(results *wrappers.ScanResultsCollection) *wrappers.SarifResultsCollection { - var sarif = new(wrappers.SarifResultsCollection) - sarif.Schema = "https://raw.githubusercontent.com/oasis-tcs/sarif-spec/master/Schemata/sarif-schema-2.1.0.json" - sarif.Version = "2.1.0" - sarif.Runs = []wrappers.SarifRun{} - sarif.Runs = append(sarif.Runs, createSarifRun(results)) - return sarif -} - -func convertCxResultToGlSastVulnerability(results *wrappers.ScanResultsCollection, glSast *wrappers.GlSastResultsCollection, summary *wrappers.ResultSummary) { - for _, result := range results.Results { - if strings.TrimSpace(result.Type) == commonParams.SastType { - glSast = parseGlSastVulnerability(result, glSast, summary) - } - } -} - -func convertCxResultToGlScaVulnerability(results *wrappers.ScanResultsCollection, glScaResult *wrappers.GlScaResultsCollection) { - for _, result := range results.Results { - if strings.TrimSpace(result.Type) == commonParams.ScaType { - glScaResult = parseGlscaVulnerability(result, glScaResult) - } - } -} - -func convertCxResultToGlScaFiles(results *wrappers.ScanResultsCollection, glScaResult *wrappers.GlScaResultsCollection) { - for _, result := range results.Results { - if strings.TrimSpace(result.Type) == commonParams.ScaType { - glScaResult = parseGlScaFiles(result, glScaResult) - } - } -} -func parseGlSastVulnerability(result *wrappers.ScanResult, glSast *wrappers.GlSastResultsCollection, summary *wrappers.ResultSummary) *wrappers.GlSastResultsCollection { - hostName := parseURI(summary.BaseURI) - - queryName := result.ScanResultData.QueryName - fileName := result.ScanResultData.Nodes[0].FileName - lineNumber := strconv.FormatUint(uint64(result.ScanResultData.Nodes[0].Line), 10) - startLine := result.ScanResultData.Nodes[0].Line - endLine := result.ScanResultData.Nodes[0].Line + result.ScanResultData.Nodes[0].Length - ID := fmt.Sprintf("%s:%s:%s", queryName, fileName, lineNumber) - category := fmt.Sprintf("%s-%s", wrappers.VendorName, result.Type) - message := fmt.Sprintf("%s@%s:%s", queryName, fileName, lineNumber) - QueryDescriptionLink := fmt.Sprintf("%s/results/%s/%s/sast/description/%s/%s", hostName, summary.ScanID, summary.ProjectID, result.VulnerabilityDetails.CweID, result.ScanResultData.QueryID) - - glSast.Vulnerabilities = append(glSast.Vulnerabilities, wrappers.GlVulnerabilities{ - ID: ID, - Category: category, - Name: queryName, - Message: message, - Description: result.Description + " \n" + QueryDescriptionLink, - CVE: ID, - Severity: cases.Title(language.English).String(result.Severity), - Confidence: cases.Title(language.English).String(result.Severity), - Solution: "", - - Scanner: wrappers.GlScanner{ - ID: category, - Name: category, - }, - Identifiers: []wrappers.Identifier{ - { - Type: "cxOneScan", - Name: "CxOne Scan", - URL: summary.BaseURI, - Value: result.ID, - }, - }, - Links: make([]string, 0), - Tracking: wrappers.Tracking{ - Type: "source", - Items: []wrappers.Item{ - { - Signatures: []wrappers.Signature{{Algorithm: result.Type + "-Algorithm ", Value: "NA"}}, - File: fileName, - EndLine: endLine, - StartLine: startLine, - }, - }, - }, - Flags: make([]wrappers.Flag, 0), - Location: wrappers.Location{ - File: fileName, - StartLine: startLine, - EndLine: endLine, - }, - }) - return glSast -} -func parseGlscaVulnerability(result *wrappers.ScanResult, glDependencyResult *wrappers.GlScaResultsCollection) *wrappers.GlScaResultsCollection { - if result.ScanResultData.ScaPackageCollection != nil { - glDependencyResult.Vulnerabilities = append(glDependencyResult.Vulnerabilities, wrappers.GlScaDepVulnerabilities{ - ID: result.ID, - Name: result.VulnerabilityDetails.CveName, - Description: result.Description, - Severity: cases.Title(language.English).String(result.Severity), - Solution: result.ScanResultData.RecommendedVersion, - Identifiers: collectScaPackageData(result), - Links: collectScaPackageLinks(result), - TrackingDep: wrappers.TrackingDep{ - Items: collectScaPackageItemsDep(result), - }, - Flags: make([]string, 0), - LocationDep: wrappers.GlScaDepVulnerabilityLocation{ - File: parseGlDependencyLocation(result), - Dependency: wrappers.ScaDependencyLocation{ - Package: wrappers.PackageName{Name: result.ScanResultData.PackageIdentifier}, - ScaDependencyLocationVersion: "", - Direct: result.ScanResultData.ScaPackageCollection.IsDirectDependency, - ScaDependencyPath: result.ScanResultData.Line, - }, - }, - }) - } - return glDependencyResult -} -func parseGlDependencyLocation(result *wrappers.ScanResult) string { - var location string - if result != nil && result.ScanResultData.ScaPackageCollection != nil && result.ScanResultData.ScaPackageCollection.Locations != nil { - location = *result.ScanResultData.ScaPackageCollection.Locations[0] - } else { - location = "" - } - return location -} -func parseGlScaFiles(result *wrappers.ScanResult, glScaResult *wrappers.GlScaResultsCollection) *wrappers.GlScaResultsCollection { - if result.ScanResultData.ScaPackageCollection != nil && result.ScanResultData.ScaPackageCollection.Locations != nil { - glScaResult.ScaDependencyFiles = append(glScaResult.ScaDependencyFiles, wrappers.ScaDependencyFile{ - Path: *result.ScanResultData.ScaPackageCollection.Locations[0], - PackageManager: result.ScanResultData.ScaPackageCollection.ID, - Dependencies: collectScaFileLocations(result), - }) - } - return glScaResult -} -func collectScaFileLocations(result *wrappers.ScanResult) []wrappers.ScaDependencyLocation { - allScaIdentifierLocations := []wrappers.ScaDependencyLocation{} - for _, packageInfo := range result.ScanResultData.PackageData { - allScaIdentifierLocations = append(allScaIdentifierLocations, wrappers.ScaDependencyLocation{ - Package: wrappers.PackageName{ - Name: packageInfo.Type, - }, - ScaDependencyLocationVersion: packageInfo.URL, - Direct: true, - ScaDependencyPath: result.ScanResultData.Line, - }) - } - return allScaIdentifierLocations -} -func collectScaPackageItemsDep(result *wrappers.ScanResult) []wrappers.ItemDep { - allScaPackageItemDep := []wrappers.ItemDep{} - allScaPackageItemDep = append(allScaPackageItemDep, wrappers.ItemDep{ - Signature: []wrappers.SignatureDep{{Algorithm: "SCA-Algorithm ", Value: "NA"}}, - File: result.VulnerabilityDetails.CveName, - EndLine: 0, - StartLine: 0, - }) - return allScaPackageItemDep -} -func collectScaPackageLinks(result *wrappers.ScanResult) []wrappers.LinkDep { - allScaPackageLinks := []wrappers.LinkDep{} - for _, packageInfo := range result.ScanResultData.PackageData { - allScaPackageLinks = append(allScaPackageLinks, wrappers.LinkDep{ - Name: packageInfo.Type, - URL: packageInfo.URL, - }) - } - return allScaPackageLinks -} -func collectScaPackageData(result *wrappers.ScanResult) []wrappers.IdentifierDep { - allIdentifierDep := []wrappers.IdentifierDep{} - for _, packageInfo := range result.ScanResultData.PackageData { - allIdentifierDep = append(allIdentifierDep, wrappers.IdentifierDep{ - Type: packageInfo.Type, - Value: packageInfo.URL, - Name: packageInfo.URL, - }) - } - return allIdentifierDep -} - -func convertCxResultsToSonar(results *wrappers.ScanResultsCollection) *wrappers.ScanResultsSonar { - var sonar = new(wrappers.ScanResultsSonar) - sonar.Issues, sonar.Rules = parseSonar(results) - return sonar -} - -func createSarifRun(results *wrappers.ScanResultsCollection) wrappers.SarifRun { - var sarifRun wrappers.SarifRun - sarifRun.Tool.Driver.Name = wrappers.SarifName - sarifRun.Tool.Driver.Version = wrappers.SarifVersion - sarifRun.Tool.Driver.InformationURI = wrappers.SarifInformationURI - sarifRun.Tool.Driver.Rules, sarifRun.Results = parseResults(results) - return sarifRun -} - -func parseResults(results *wrappers.ScanResultsCollection) ([]wrappers.SarifDriverRule, []wrappers.SarifScanResult) { - var sarifRules = make([]wrappers.SarifDriverRule, 0) - var sarifResults = make([]wrappers.SarifScanResult, 0) - if results != nil { - ruleIds := map[interface{}]bool{} - for _, result := range results.Results { - if rule := findRule(ruleIds, result); rule != nil { - sarifRules = append(sarifRules, *rule) - } - if sarifResult := findResult(result); sarifResult != nil { - sarifResults = append(sarifResults, sarifResult...) - } - } - } - return sarifRules, sarifResults -} - -func parseSonar(results *wrappers.ScanResultsCollection) ([]wrappers.SonarIssues, []wrappers.SonarRules) { - var sonarIssues []wrappers.SonarIssues - var sonarRules []wrappers.SonarRules - seenRuleIDs := make(map[string]bool) // Track already added rule IDs - - if results != nil { - for _, result := range results.Results { - var auxRules = initSonarRules(result) - var auxIssue = initSonarIssue(result) - - if !seenRuleIDs[auxRules.ID] { - sonarRules = append(sonarRules, auxRules) - seenRuleIDs[auxRules.ID] = true - } - - engineType := strings.TrimSpace(result.Type) - - if engineType == commonParams.SastType { - auxIssue.PrimaryLocation = parseSonarPrimaryLocation(result) - auxIssue.SecondaryLocations = parseSonarSecondaryLocations(result) - sonarIssues = append(sonarIssues, auxIssue) - } else if engineType == commonParams.KicsType { - auxIssue.PrimaryLocation = parseLocationKics(result) - sonarIssues = append(sonarIssues, auxIssue) - } else if engineType == commonParams.ScaType { - sonarIssuesByLocation := parseScaSonarLocations(result) - sonarIssues = append(sonarIssues, sonarIssuesByLocation...) - } else if wrappers.IsContainersEnabled && engineType == commonParams.ContainersType { - auxIssue.PrimaryLocation = parseContainersSonar(result) - sonarIssues = append(sonarIssues, auxIssue) - } else if strings.HasPrefix(engineType, commonParams.SscsType) { - sscsSonarIssue := parseSscsSonar(result, &auxIssue) - sonarIssues = append(sonarIssues, sscsSonarIssue) - } - } - } - return sonarIssues, sonarRules -} - -func parseContainersSonar(result *wrappers.ScanResult) wrappers.SonarLocation { - var auxLocation wrappers.SonarLocation - auxLocation.FilePath = result.ScanResultData.ImageFilePath - auxLocation.Message = html.UnescapeString(result.Description) - var textRange wrappers.SonarTextRange - textRange.StartColumn = 1 - textRange.EndColumn = 2 - textRange.StartLine = 1 - textRange.EndLine = 2 - auxLocation.TextRange = textRange - return auxLocation -} - -func parseSscsSonar(result *wrappers.ScanResult, sonarIssue *wrappers.SonarIssues) wrappers.SonarIssues { - sonarIssue.PrimaryLocation.FilePath = result.ScanResultData.Filename - - sonarIssue.PrimaryLocation.Message = html.UnescapeString(result.ScanResultData.Remediation) - var textRange wrappers.SonarTextRange - textRange.StartColumn = 1 - textRange.EndColumn = 2 - textRange.StartLine = result.ScanResultData.Line - sonarIssue.PrimaryLocation.TextRange = textRange - return *sonarIssue -} - -func initSonarIssue(result *wrappers.ScanResult) wrappers.SonarIssues { - var sonarIssue wrappers.SonarIssues - engineType := strings.TrimSpace(result.Type) - if engineType == commonParams.SastType { - sonarIssue.RuleID = result.ScanResultData.LanguageName + " - " + result.ScanResultData.QueryName - } else if engineType == commonParams.KicsType { - sonarIssue.RuleID = result.ScanResultData.QueryName - } else if engineType == commonParams.ScaType { - sonarIssue.RuleID = result.ID - } else if wrappers.IsContainersEnabled && engineType == commonParams.ContainersType { - sonarIssue.RuleID = result.ID - } else if strings.HasPrefix(engineType, commonParams.SscsType) { - sonarIssue.RuleID = result.ID - } - - sonarIssue.PrimaryLocation.Message = html.UnescapeString(result.Description) - sonarIssue.EffortMinutes = 0 - - return sonarIssue -} - -func initSonarRules(result *wrappers.ScanResult) wrappers.SonarRules { - var sonarRules wrappers.SonarRules - var sonarImpacts wrappers.SonarImpacts - - sonarImpacts.Severity = sonarSeverities[result.Severity] - sonarImpacts.SoftwareQuality = vulnerabilitySonar - - sonarRules.EngineID = result.Type - sonarRules.CleanCodeAttribute = cleanCodeAttribute - - engineType := strings.TrimSpace(result.Type) - if engineType == commonParams.SastType { - sonarRules.Name = result.ScanResultData.QueryName - sonarRules.Description = html.UnescapeString(result.Description) - sonarRules.ID = result.ScanResultData.LanguageName + " - " + result.ScanResultData.QueryName - } else if engineType == commonParams.KicsType { - sonarRules.Name = result.ScanResultData.QueryName - sonarRules.Description = html.UnescapeString(result.Description) - sonarRules.ID = result.ScanResultData.QueryName - } else if engineType == commonParams.ScaType { - sonarRules.Name = result.ScanResultData.PackageIdentifier - sonarRules.Description = html.UnescapeString(result.Description) - sonarRules.ID = result.ID - } else if wrappers.IsContainersEnabled && engineType == commonParams.ContainersType { - sonarRules.Name = result.ScanResultData.ImageTag - sonarRules.Description = html.UnescapeString(result.Description) - sonarRules.ID = result.ID - } else if strings.HasPrefix(engineType, commonParams.SscsType) { - sonarRules.Name = result.ScanResultData.RuleName - sonarRules.Description = html.UnescapeString(result.ScanResultData.RuleDescription) - sonarRules.ID = result.ID - } - - sonarRules.Impacts = []wrappers.SonarImpacts{sonarImpacts} - - return sonarRules -} - -func parseScaSonarLocations(result *wrappers.ScanResult) []wrappers.SonarIssues { - if result == nil || result.ScanResultData.ScaPackageCollection == nil || result.ScanResultData.ScaPackageCollection.Locations == nil { - return []wrappers.SonarIssues{} - } - - var issuesByLocation []wrappers.SonarIssues - - for _, location := range result.ScanResultData.ScaPackageCollection.Locations { - issueByLocation := initSonarIssue(result) - - var primaryLocation wrappers.SonarLocation - - primaryLocation.FilePath = *location - _, _, primaryLocation.Message = findRuleID(result) - - var textRange wrappers.SonarTextRange - textRange.StartColumn = 1 - textRange.EndColumn = 2 - textRange.StartLine = 1 - textRange.EndLine = 2 - - primaryLocation.TextRange = textRange - - issueByLocation.PrimaryLocation = primaryLocation - - issuesByLocation = append(issuesByLocation, issueByLocation) - } - - return issuesByLocation -} - -func parseLocationKics(results *wrappers.ScanResult) wrappers.SonarLocation { - var auxLocation wrappers.SonarLocation - auxLocation.FilePath = strings.TrimLeft(results.ScanResultData.Filename, "/") - auxLocation.Message = html.UnescapeString(results.ScanResultData.Value) - var auxTextRange wrappers.SonarTextRange - auxTextRange.StartLine = results.ScanResultData.Line - auxTextRange.StartColumn = 0 - auxTextRange.EndColumn = 1 - auxLocation.TextRange = auxTextRange - return auxLocation -} - -func parseSonarPrimaryLocation(results *wrappers.ScanResult) wrappers.SonarLocation { - var auxLocation wrappers.SonarLocation - // fill the details in the primary Location - if len(results.ScanResultData.Nodes) > 0 { - auxLocation.FilePath = strings.TrimLeft(results.ScanResultData.Nodes[0].FileName, "/") - auxLocation.Message = html.UnescapeString(strings.ReplaceAll(results.ScanResultData.QueryName, "_", " ")) - auxLocation.TextRange = parseSonarTextRange(results.ScanResultData.Nodes[0]) - } - return auxLocation -} - -func parseSonarSecondaryLocations(results *wrappers.ScanResult) []wrappers.SonarLocation { - var auxSecondaryLocations []wrappers.SonarLocation - // Traverse all the rest of the scan result nodes into secondary location of sonar - if len(results.ScanResultData.Nodes) >= 1 { - for _, node := range results.ScanResultData.Nodes[1:] { - var auxSecondaryLocation wrappers.SonarLocation - auxSecondaryLocation.FilePath = strings.TrimLeft(node.FileName, "/") - auxSecondaryLocation.Message = html.UnescapeString(strings.ReplaceAll(results.ScanResultData.QueryName, "_", " ")) - auxSecondaryLocation.TextRange = parseSonarTextRange(node) - auxSecondaryLocations = append(auxSecondaryLocations, auxSecondaryLocation) - } - } - return auxSecondaryLocations -} - -func parseSonarTextRange(results *wrappers.ScanResultNode) wrappers.SonarTextRange { - var auxTextRange wrappers.SonarTextRange - auxTextRange.StartLine = results.Line - startColumn := getSastStartColumn(results.Column) - - auxTextRange.StartColumn = startColumn - auxTextRange.EndColumn = startColumn + results.Length - - if auxTextRange.StartColumn == auxTextRange.EndColumn { - auxTextRange.EndColumn++ - } - - return auxTextRange -} - -func findRule(ruleIds map[interface{}]bool, result *wrappers.ScanResult) *wrappers.SarifDriverRule { - var sarifRule wrappers.SarifDriverRule - sarifRule.ID, sarifRule.Name, _ = findRuleID(result) - sarifRule.FullDescription = findFullDescription(result) - sarifRule.Help = findHelp(result) - sarifRule.HelpURI = findHelpURI(result) - sarifRule.Properties = findProperties(result) - - if !ruleIds[sarifRule.ID] { - ruleIds[sarifRule.ID] = true - return &sarifRule - } - - return nil -} - -func getSastStartColumn(column uint) uint { - if column == 0 { - return 0 - } - return column - 1 -} - -func findRuleID(result *wrappers.ScanResult) (ruleID, ruleName, shortMessage string) { - caser := cases.Title(language.English) - - if result.ScanResultData.QueryID == nil && result.ScanResultData.RuleID == nil { - return fmt.Sprintf("%s (%s)", result.ID, result.Type), - caser.String(strings.ToLower(strings.ReplaceAll(result.ID, "-", ""))), - html.UnescapeString(fmt.Sprintf("%s (%s)", result.ScanResultData.PackageIdentifier, result.ID)) - } - - if result.ScanResultData.RuleID != nil { - ruleName = strings.ReplaceAll(result.ScanResultData.RuleName, "_", " ") - return fmt.Sprintf("%s - %s (%s)", ruleName, *result.ScanResultData.RuleID, result.Type), - ruleName, - ruleName - } - - ruleName = strings.ReplaceAll(result.ScanResultData.QueryName, "_", " ") - return fmt.Sprintf("%v - %s (%s)", ruleName, result.ScanResultData.QueryID, result.Type), - ruleName, - ruleName -} - -func findFullDescription(result *wrappers.ScanResult) wrappers.SarifDescription { - var sarifDescription wrappers.SarifDescription - sarifDescription.Text = findDescriptionText(result) - return sarifDescription -} - -func findHelp(result *wrappers.ScanResult) wrappers.SarifHelp { - var sarifHelp wrappers.SarifHelp - sarifHelp.Text = findHelpText(result) - sarifHelp.Markdown = findHelpMarkdownText(result) - - return sarifHelp -} - -func findHelpURI(result *wrappers.ScanResult) string { - if strings.HasPrefix(result.Type, commonParams.SscsType) { - if result.ScanResultData.RemediationLink != "" { - return result.ScanResultData.RemediationLink - } - } - - return wrappers.SarifInformationURI -} - -func findDescriptionText(result *wrappers.ScanResult) string { - if result.Type == commonParams.KicsType { - return fmt.Sprintf( - "%s Value: %s Excepted value: %s", - result.Description, result.ScanResultData.Value, result.ScanResultData.ExpectedValue, - ) - } else if strings.HasPrefix(result.Type, commonParams.SscsType) { - return result.ScanResultData.RuleDescription - } - - return result.Description -} - -func findHelpText(result *wrappers.ScanResult) string { - if strings.HasPrefix(result.Type, commonParams.SscsType) { - return findHelpMarkdownText(result) - } - - return findDescriptionText(result) -} - -func findHelpMarkdownText(result *wrappers.ScanResult) string { - if result.Type == commonParams.KicsType { - return fmt.Sprintf( - "%s

Value: %s
Excepted value: %s", - result.Description, result.ScanResultData.Value, result.ScanResultData.ExpectedValue, - ) - } else if strings.HasPrefix(result.Type, commonParams.SscsType) { - return result.ScanResultData.Remediation - } - - return result.Description -} - -func findProperties(result *wrappers.ScanResult) wrappers.SarifProperties { - var sarifProperties wrappers.SarifProperties - sarifProperties.ID, sarifProperties.Name, _ = findRuleID(result) - sarifProperties.Description = findDescriptionText(result) - sarifProperties.SecuritySeverity = securities[result.Severity] - sarifProperties.Tags = []string{"security", "checkmarx", result.Type} - return sarifProperties -} - -func findSarifLevel(result *wrappers.ScanResult) string { - level := map[string]string{ - infoCx: infoLowSarif, - lowCx: infoLowSarif, - mediumCx: mediumSarif, - highCx: highSarif, - criticalCx: highSarif, - } - return level[result.Severity] -} - -func initSarifResult(result *wrappers.ScanResult) wrappers.SarifScanResult { - var scanResult wrappers.SarifScanResult - scanResult.RuleID, _, scanResult.Message.Text = findRuleID(result) - scanResult.Level = findSarifLevel(result) - scanResult.Locations = []wrappers.SarifLocation{} - - return scanResult -} - -func findResult(result *wrappers.ScanResult) []wrappers.SarifScanResult { - var scanResults []wrappers.SarifScanResult - - if len(result.ScanResultData.Nodes) > 0 { - scanResults = parseSarifResultSast(result, scanResults) - } else if result.Type == commonParams.KicsType { - scanResults = parseSarifResultKics(result, scanResults) - } else if result.Type == commonParams.ScaType { - scanResults = parseSarifResultsSca(result, scanResults) - } else if result.Type == commonParams.ContainersType && wrappers.IsContainersEnabled { - scanResults = parseSarifResultsContainers(result, scanResults) - } else if strings.HasPrefix(result.Type, commonParams.SscsType) { - scanResults = parseSarifResultsSscs(result, scanResults) - } - - if len(scanResults) > 0 { - return scanResults - } - return nil -} - -func parseSarifResultsContainers(result *wrappers.ScanResult, scanResults []wrappers.SarifScanResult) []wrappers.SarifScanResult { - var scanResult = initSarifResult(result) - var scanLocation wrappers.SarifLocation - - scanLocation.PhysicalLocation.ArtifactLocation.URI = result.ScanResultData.ImageFilePath - scanLocation.PhysicalLocation.Region = &wrappers.SarifRegion{} - scanLocation.PhysicalLocation.Region.StartLine = 1 - scanLocation.PhysicalLocation.Region.StartColumn = 1 - scanLocation.PhysicalLocation.Region.EndColumn = 2 - scanResult.Locations = append(scanResult.Locations, scanLocation) - - scanResults = append(scanResults, scanResult) - return scanResults -} - -func parseSarifResultsSca(result *wrappers.ScanResult, scanResults []wrappers.SarifScanResult) []wrappers.SarifScanResult { - if result == nil || result.ScanResultData.ScaPackageCollection == nil || result.ScanResultData.ScaPackageCollection.Locations == nil { - return scanResults - } - for _, location := range result.ScanResultData.ScaPackageCollection.Locations { - var scanResult = initSarifResult(result) - - var scanLocation wrappers.SarifLocation - scanLocation.PhysicalLocation.ArtifactLocation.URI = *location - scanLocation.PhysicalLocation.Region = &wrappers.SarifRegion{} - scanLocation.PhysicalLocation.Region.StartLine = 1 - scanLocation.PhysicalLocation.Region.StartColumn = 1 - scanLocation.PhysicalLocation.Region.EndColumn = 2 - scanResult.Locations = append(scanResult.Locations, scanLocation) - - scanResults = append(scanResults, scanResult) - } - return scanResults -} - -func parseSarifResultKics(result *wrappers.ScanResult, scanResults []wrappers.SarifScanResult) []wrappers.SarifScanResult { - var scanResult = initSarifResult(result) - var scanLocation wrappers.SarifLocation - - scanLocation.PhysicalLocation.ArtifactLocation.URI = strings.Replace( - result.ScanResultData.Filename, - "/", - "", - 1, - ) - scanLocation.PhysicalLocation.Region = &wrappers.SarifRegion{} - scanLocation.PhysicalLocation.Region.StartLine = result.ScanResultData.Line - scanLocation.PhysicalLocation.Region.StartColumn = 1 - scanLocation.PhysicalLocation.Region.EndColumn = 2 - scanResult.Locations = append(scanResult.Locations, scanLocation) - - scanResults = append(scanResults, scanResult) - return scanResults -} - -func parseSarifResultSast(result *wrappers.ScanResult, scanResults []wrappers.SarifScanResult) []wrappers.SarifScanResult { - if result == nil || result.ScanResultData.Nodes == nil { - return scanResults - } - var scanResult = initSarifResult(result) - - for _, node := range result.ScanResultData.Nodes { - var scanLocation wrappers.SarifLocation - if len(node.FileName) >= sarifNodeFileLength { - scanLocation.PhysicalLocation.ArtifactLocation.URI = node.FileName[1:] - if node.Line <= 0 { - continue - } - scanLocation.PhysicalLocation.Region = &wrappers.SarifRegion{} - scanLocation.PhysicalLocation.Region.StartLine = node.Line - column := node.Column - length := node.Length - scanLocation.PhysicalLocation.Region.StartColumn = column - scanLocation.PhysicalLocation.Region.EndColumn = column + length - - scanResult.Locations = append(scanResult.Locations, scanLocation) - } - } - - scanResults = append(scanResults, scanResult) - return scanResults -} - -func parseSarifResultsSscs(result *wrappers.ScanResult, scanResults []wrappers.SarifScanResult) []wrappers.SarifScanResult { - var scanResult = initSarifResult(result) - scanResult.Message.Text = result.Description - - var scanLocation wrappers.SarifLocation - - trimOsSeparatorFromFileName(result) - if result.Type == commonParams.SCSScorecardType && result.ScanResultData.Filename == noFileForScorecardResultString { - scanLocation.PhysicalLocation.ArtifactLocation.URI = artifactLocationURIString - scanLocation.PhysicalLocation.ArtifactLocation.Description = &wrappers.SarifMessage{} - scanLocation.PhysicalLocation.ArtifactLocation.Description.Text = result.ScanResultData.Filename - } else { - scanLocation.PhysicalLocation.ArtifactLocation.URI = result.ScanResultData.Filename - } - - scanLocation.PhysicalLocation.Region = &wrappers.SarifRegion{} - scanLocation.PhysicalLocation.Region.StartLine = result.ScanResultData.Line - scanLocation.PhysicalLocation.Region.StartColumn = 1 - scanLocation.PhysicalLocation.Region.EndColumn = 2 - if result.ScanResultData.Snippet != "" { - scanLocation.PhysicalLocation.Region.Snippet = &wrappers.SarifSnippet{} - scanLocation.PhysicalLocation.Region.Snippet.Text = result.ScanResultData.Snippet - } - - scanResult.Locations = append(scanResult.Locations, scanLocation) - - var properties wrappers.SarifResultProperties - properties.Severity = result.Severity - properties.Validity = result.ScanResultData.Validity - properties.IsInSource = result.ScanResultData.IsInSource - properties.CommitURL = result.ScanResultData.CommitURL - scanResult.Properties = &properties - - scanResults = append(scanResults, scanResult) - return scanResults -} - -func convertNotAvailableNumberToZero(summary *wrappers.ResultSummary) { - if summary.KicsIssues == notAvailableNumber { - summary.KicsIssues = 0 - } else if summary.SastIssues == notAvailableNumber { - summary.SastIssues = 0 - } else if summary.ScaIssues == notAvailableNumber { - summary.ScaIssues = 0 - } else if wrappers.IsContainersEnabled && *summary.ContainersIssues == notAvailableNumber { - *summary.ContainersIssues = 0 - } -} - -func buildAuxiliaryScaMaps(resultsModel *wrappers.ScanResultsCollection, scaPackageModel *[]wrappers.ScaPackageCollection, - scaTypeModel *[]wrappers.ScaTypeCollection) (locationsByID map[string][]*string, typesByCVE map[string]wrappers.ScaTypeCollection) { - locationsByID = make(map[string][]*string) - typesByCVE = make(map[string]wrappers.ScaTypeCollection) - // Create map to be used to populate locations for each package path - for _, result := range resultsModel.Results { - if result.Type == commonParams.ScaType { - for _, packages := range *scaPackageModel { - currentPackage := packages - locationsByID[packages.ID] = currentPackage.Locations - } - for _, types := range *scaTypeModel { - identifier := fmt.Sprintf("%s:%s", types.ID, types.PackageID) - typesByCVE[identifier] = types - } - } - } - return locationsByID, typesByCVE -} - -func buildScaType(typesByCVE map[string]wrappers.ScaTypeCollection, result *wrappers.ScanResult) string { - identifier := buildVulnerabilityIdentifier(result) - types, ok := typesByCVE[identifier] - if ok && types.Type == "SupplyChain" { - return "Supply Chain" - } - return "Vulnerability" -} - -func buildScaState(typesByCVE map[string]wrappers.ScaTypeCollection, result *wrappers.ScanResult) string { - identifier := buildVulnerabilityIdentifier(result) - types, ok := typesByCVE[identifier] - if ok && types.IsIgnored { - return notExploitable - } - return result.State -} - -func buildVulnerabilityIdentifier(result *wrappers.ScanResult) string { - return fmt.Sprintf("%s:%s", result.ID, result.ScanResultData.PackageIdentifier) -} - -func addPackageInformation( - resultsModel *wrappers.ScanResultsCollection, - scaPackageModel *[]wrappers.ScaPackageCollection, - scaTypeModel *[]wrappers.ScaTypeCollection, -) *wrappers.ScanResultsCollection { - locationsByID, typesByCVE := buildAuxiliaryScaMaps(resultsModel, scaPackageModel, scaTypeModel) - scaPackageMap := buildScaPackageMap(*scaPackageModel) - - for _, result := range resultsModel.Results { - if result.Type == commonParams.ScaType { - processResult(result, locationsByID, typesByCVE, scaPackageMap) - } - } - - return resultsModel -} - -func processResult( - result *wrappers.ScanResult, - locationsByID map[string][]*string, - typesByCVE map[string]wrappers.ScaTypeCollection, - scaPackageMap map[string]wrappers.ScaPackageCollection, // Updated parameter -) { - const precision = 1 - - currentID := result.ScanResultData.PackageIdentifier - result.VulnerabilityDetails.CvssScore = util.RoundFloat(result.VulnerabilityDetails.CvssScore, precision) - result.ScaType = buildScaType(typesByCVE, result) - result.State = buildScaState(typesByCVE, result) - - updatePackages(result, scaPackageMap, locationsByID, currentID) -} - -func updatePackages( - result *wrappers.ScanResult, - scaPackageMap map[string]wrappers.ScaPackageCollection, - locationsByID map[string][]*string, - currentID string, -) { - packages, found := scaPackageMap[currentID] - if !found { - return - } - - updateDependencyPaths(packages.DependencyPathArray, locationsByID) - if !packages.SupportsQuickFix { - packages.SupportsQuickFix = hasQuickFix(packages.DependencyPathArray) - } - - if packages.IsDirectDependency { - packages.TypeOfDependency = directDependencyType - } else { - packages.TypeOfDependency = indirectDependencyType - } - - packages.FixLink = buildFixLink(result) - result.ScanResultData.ScaPackageCollection = &packages -} - -func hasQuickFix(dependencyPaths [][]wrappers.DependencyPath) bool { - for i := range dependencyPaths { - head := &dependencyPaths[i][0] - if head.SupportsQuickFix { - return true - } - } - return false -} - -func buildScaPackageMap(scaPackageModel []wrappers.ScaPackageCollection) map[string]wrappers.ScaPackageCollection { - scaPackageMap := make(map[string]wrappers.ScaPackageCollection) - for i := range scaPackageModel { - scaPackageMap[scaPackageModel[i].ID] = scaPackageModel[i] - } - return scaPackageMap -} - -func updateDependencyPaths(dependencyPaths [][]wrappers.DependencyPath, locationsByID map[string][]*string) { - for i := range dependencyPaths { - head := &dependencyPaths[i][0] - head.Locations = locationsByID[head.ID] - head.SupportsQuickFix = len(dependencyPaths[i]) == 1 - - for _, location := range locationsByID[head.ID] { - head.SupportsQuickFix = head.SupportsQuickFix && util.IsPackageFileSupported(*location) - } - } -} - -func buildFixLink(result *wrappers.ScanResult) string { - if result.ID != "" { - return fmt.Sprint(fixLinkPrefix, result.ID) - } - return "" -} - -func filterViolatedRules(policyModel wrappers.PolicyResponseModel) *wrappers.PolicyResponseModel { - i := 0 - for _, policy := range policyModel.Policies { - if len(policy.RulesViolated) > 0 { - policyModel.Policies[i] = policy - i++ - } - } - policyModel.Policies = policyModel.Policies[:i] - return &policyModel -} - -func trimOsSeparatorFromFileName(result *wrappers.ScanResult) { - if result.ScanResultData.Filename != "" { - result.ScanResultData.Filename = strings.TrimPrefix(result.ScanResultData.Filename, "/") - result.ScanResultData.Filename = strings.TrimPrefix(result.ScanResultData.Filename, "\\") - } -} - -type ScannerResponse struct { - ScanID string `json:"ScanID,omitempty"` - Name string `json:"Name,omitempty"` - Status string `json:"Status,omitempty"` - Details string `json:"Details,omitempty"` - ErrorCode string `json:"ErrorCode,omitempty"` -} - -func parseURI(summaryBaseURI string) (hostName string) { - parsedURL, err := url.Parse(summaryBaseURI) - if err != nil { - return "" - } - hostName = fmt.Sprintf("%s://%s", parsedURL.Scheme, parsedURL.Host) - - return hostName -} - -func printWarningIfIgnorePolicyOmiited() { - fmt.Printf("\n Warning: The --ignore-policy flag was not implemented because you don’t have the required permission.\n Only users with 'override-policy-management' permission can use this flag. \n\n") -} - -func getFilterResultsForAPISecScanner(risksOverviewWrapper wrappers.RisksOverviewWrapper, scanID string, resultsParams map[string]string) (aPISecSeveritySummary *wrappers.APISecFilteredResult, err error) { - var apiSecRiskEntriesResult wrappers.APISecRiskEntriesResult - var errorModel *wrappers.WebError - - apiSecRiskEntriesResult, errorModel, err = risksOverviewWrapper.GetFilterResultForAPISecByScanID(scanID, resultsParams) - if err != nil { - return nil, errors.Wrapf(err, "%s", failedListingResults) - } - if errorModel != nil { - return nil, errors.Errorf("%s: CODE: %d, %s", failedListingResults, errorModel.Code, errorModel.Message) - } - if len(apiSecRiskEntriesResult.Entries) > 0 { - entries := apiSecRiskEntriesResult.Entries - severityCount := make(map[string]int) - originCount := make(map[string]int) - totalRecords := 0 - for i := range entries { - entry := &entries[i] - if !isExploitable(entry.State) { - continue - } - sev := strings.ToLower(entry.Severity) - severityCount[sev]++ - orig := strings.ToLower(entry.Origin) - originCount[orig]++ - totalRecords++ - } - var riskDistribution []wrappers.RiskDistributionEntry - if originCount["code"] > 0 { - riskDistribution = append(riskDistribution, wrappers.RiskDistributionEntry{Origin: "code", Total: originCount["code"]}) - } - if originCount["documentation"] > 0 { - riskDistribution = append(riskDistribution, wrappers.RiskDistributionEntry{Origin: "documentation", Total: originCount["documentation"]}) - } - return &wrappers.APISecFilteredResult{ - SeverityCount: severityCount, - RiskDistribution: riskDistribution, - TotalRisksCount: totalRecords, - }, nil - } - return nil, nil -} +package commands + +import ( + "encoding/json" + "fmt" + "html" + "log" + "net/url" + "os" + "path/filepath" + "regexp" + "slices" + "strconv" + "strings" + "text/template" + "time" + + "github.com/MakeNowJust/heredoc" + "github.com/checkmarx/ast-cli/internal/commands/util" + "github.com/checkmarx/ast-cli/internal/commands/util/printer" + errorConstants "github.com/checkmarx/ast-cli/internal/constants/errors" + "github.com/checkmarx/ast-cli/internal/logger" + "github.com/checkmarx/ast-cli/internal/services" + "github.com/checkmarx/ast-cli/internal/wrappers" + "github.com/checkmarx/ast-cli/internal/wrappers/utils" + "golang.org/x/text/cases" + "golang.org/x/text/language" + + commonParams "github.com/checkmarx/ast-cli/internal/params" + + "github.com/pkg/errors" + "github.com/spf13/cobra" +) + +const ( + failedCreatingSummary = "Failed creating summary" + failedGettingScan = "Failed getting scan" + failedListingResults = "Failed listing results" + failedListingCodeBashing = "Failed codebashing link" + mediumLabel = "medium" + criticalLabel = "critical" + highLabel = "high" + lowLabel = "low" + infoLabel = "info" + sonarTypeLabel = "_sonar" + glSastTypeLabel = ".gl-sast-report" + glScaTypeLabel = ".gl-sca-report" + directoryPermission = 0700 + infoSonar = "INFO" + lowSonar = "LOW" + mediumSonar = "MEDIUM" + highSonar = "HIGH" + criticalSonar = "BLOCKER" + infoLowSarif = "note" + mediumSarif = "warning" + highSarif = "error" + vulnerabilitySonar = "SECURITY" + cleanCodeAttribute = "FORMATTED" + infoCx = "INFO" + lowCx = "LOW" + mediumCx = "MEDIUM" + highCx = "HIGH" + criticalCx = "CRITICAL" + tableResultsFormat = " | %-10s %6v %5d %6d %5d %4d %-9s |\n" + stringTableResultsFormat = " | %-10s %5s %6s %6s %5s %4s %5s |\n" + TableTitleFormat = " | %-11s %4s %4s %6s %4s %4s %6s |\n" + twoNewLines = "\n\n" + tableLine = " --------------------------------------------------------------------- " + codeBashingKey = "cb-url" + failedGettingBfl = "Failed getting BFL" + notAvailableString = "-" + disabledString = "N/A" + scanFailedString = "Failed " + scanCanceledString = "Canceled" + scanSuccessString = "Completed" + scanPartialString = "Partial" + scsScanUnavailableString = "" + notAvailableNumber = -1 + scanFailedNumber = -2 + scanCanceledNumber = -3 + scanPartialNumber = -4 + defaultPaddingSize = -13 + scanPendingMessage = "Scan triggered in asynchronous mode or still running. Click more details to get the full status." + directDependencyType = "Direct Dependency" + indirectDependencyType = "Transitive Dependency" + startedStatus = "started" + requestedStatus = "requested" + completedStatus = "completed" + pdfToEmailFlagDescription = "Send the PDF report to the specified email address." + + " Use \",\" as the delimiter for multiple emails" + pdfOptionsFlagDescription = "Sections to generate PDF report. Available options: Iac-Security,Sast,Sca," + + defaultPdfOptionsDataSections + sbomReportFlagDescription = "Sections to generate SBOM report. Available options: CycloneDxJson,CycloneDxXml,SpdxJson" + reportNameScanReport = "scan-report" + reportNameImprovedScanReport = "improved-scan-report" + reportTypeEmail = "email" + defaultPdfOptionsDataSections = "ScanSummary,ExecutiveSummary,ScanResults" + exploitablePathFlagDescription = "Enable or disable exploitable path in scan. Available options: true,false" + scaLastScanTimeFlagDescription = "SCA last scan time. Available options: integer above 1" + projectPrivatePackageFlagDescription = "Enable or disable project private package. Available options: true,false" + scaPrivatePackageVersionFlagDescription = "SCA project private package version. Example: 0.1.1" + scaHideDevAndTestDepFlagDescription = "Filter SCA results to exclude dev and test dependencies" + policeManagementNoneStatus = "none" + apiDocumentationFlagDescription = "Swagger folder/file filter for API-Security scan. Example: ./swagger.json" + summaryCreatedAtLayout = "2006-01-02, 15:04:05" + glTimeFormat = "2006-01-02T15:04:05" + sarifNodeFileLength = 2 + fixLabel = "fix" + redundantLabel = "redundant" + delayValueForReport = 10 + fixLinkPrefix = "https://devhub.checkmarx.com/cve-details/" + ScaDevAndTestExclusionParam = "DEV_AND_TEST" + ScaExcludeResultTypesParam = "exclude-result-types" + noFileForScorecardResultString = "Issue Found in your GitHub repository" + CliType = "cli" + artifactLocationURIString = "This alert has no associated file" +) + +var ( + summaryFormats = []string{ + printer.FormatSummaryConsole, + printer.FormatSummary, + printer.FormatSummaryJSON, + printer.FormatPDF, + printer.FormatSummaryMarkdown, + printer.FormatSbom, + printer.FormatGLSast, + printer.FormatGLSca, + printer.FormatSonar, + } + + filterResultsListFlagUsage = fmt.Sprintf( + "Filter the list of results. Use ';' as the delimiter for arrays. Available filters are: %s", + strings.Join( + []string{ + commonParams.ScanIDQueryParam, + commonParams.LimitQueryParam, + commonParams.OffsetQueryParam, + commonParams.SortQueryParam, + commonParams.IncludeNodesQueryParam, + commonParams.NodeIDsQueryParam, + commonParams.QueryQueryParam, + commonParams.GroupQueryParam, + commonParams.StatusQueryParam, + commonParams.SeverityQueryParam, + commonParams.StateQueryParam, + }, ",", + ), + ) + + // Follows: over 9.0 is critical, 7.0 to 8.9 is high, 4.0 to 6.9 is medium and 3.9 or less is low. + securities = map[string]string{ + infoCx: "1.0", + lowCx: "2.0", + mediumCx: "4.0", + highCx: "7.0", + criticalCx: "9.0", + } + + // Match cx severity with sonar severity + sonarSeverities = map[string]string{ + infoCx: infoSonar, + lowCx: lowSonar, + mediumCx: mediumSonar, + highCx: highSonar, + criticalCx: criticalSonar, + } + + containerEngineUnsupportedAgents = []string{ + commonParams.JetbrainsAgent, commonParams.VSCodeAgent, commonParams.VisualStudioAgent, commonParams.EclipseAgent, + } + + sscsEngineToOverviewEngineMap = map[string]string{ + commonParams.SCSScorecardType: commonParams.SCSScorecardOverviewType, + commonParams.SCSSecretDetectionType: commonParams.SCSSecretDetectionOverviewType, + } +) + +func NewResultsCommand( + resultsWrapper wrappers.ResultsWrapper, + scanWrapper wrappers.ScansWrapper, + exportWrapper wrappers.ExportWrapper, + resultsPdfReportsWrapper wrappers.ResultsPdfWrapper, + resultsJSONReportsWrapper wrappers.ResultsJSONWrapper, + codeBashingWrapper wrappers.CodeBashingWrapper, + bflWrapper wrappers.BflWrapper, + risksOverviewWrapper wrappers.RisksOverviewWrapper, + riskManagementWrapper wrappers.RiskManagementWrapper, + scsScanOverviewWrapper wrappers.ScanOverviewWrapper, + policyWrapper wrappers.PolicyWrapper, + featureFlagsWrapper wrappers.FeatureFlagsWrapper, + jwtWrapper wrappers.JWTWrapper, +) *cobra.Command { + resultCmd := &cobra.Command{ + Use: "results", + Short: "Retrieve results", + Annotations: map[string]string{ + "command:doc": heredoc.Doc( + ` + https://checkmarx.com/resource/documents/en/34965-68640-results.html + `, + ), + }, + } + showResultCmd := resultShowSubCommand(resultsWrapper, scanWrapper, exportWrapper, resultsPdfReportsWrapper, resultsJSONReportsWrapper, + risksOverviewWrapper, scsScanOverviewWrapper, policyWrapper, featureFlagsWrapper, jwtWrapper) + codeBashingCmd := resultCodeBashing(codeBashingWrapper) + bflResultCmd := resultBflSubCommand(bflWrapper) + exitCodeSubcommand := exitCodeSubCommand(scanWrapper) + riskManagementSubCommand := riskManagementSubCommand(riskManagementWrapper, featureFlagsWrapper) + resultCmd.AddCommand( + showResultCmd, bflResultCmd, codeBashingCmd, exitCodeSubcommand, riskManagementSubCommand, + ) + return resultCmd +} + +func exitCodeSubCommand(scanWrapper wrappers.ScansWrapper) *cobra.Command { + exitCodeCmd := &cobra.Command{ + Use: "exit-code", + Short: "Get exit code and details of a scan", + Long: "The exit-code command enables you to get the exit code and failure details of a requested scan in Checkmarx One", + Example: heredoc.Doc( + ` + $ cx results exit-code --scan-id --scan-types + `, + ), + RunE: runGetExitCodeCommand(scanWrapper), + } + + exitCodeCmd.PersistentFlags().String(commonParams.ScanIDFlag, "", "Scan ID") + exitCodeCmd.PersistentFlags().String(commonParams.ScanTypes, "", "Scan types") + + return exitCodeCmd +} +func riskManagementSubCommand(riskManagement wrappers.RiskManagementWrapper, featureFlagsWrapper wrappers.FeatureFlagsWrapper, +) *cobra.Command { + riskManagementCmd := &cobra.Command{ + Use: "risk-management", + Short: "Show risk-management results of a project", + Long: "The risk-management command displays risk management results for a specific project in Checkmarx One", + Example: heredoc.Doc( + ` + $ cx results risk-management --project-id --scan-id --limit (1-50, default: 50) + `, + ), + RunE: runRiskManagementCommand(riskManagement, featureFlagsWrapper), + } + + riskManagementCmd.PersistentFlags().String(commonParams.ProjectIDFlag, "", "Project ID") + riskManagementCmd.PersistentFlags().String(commonParams.ScanIDFlag, "", "Scan ID") + riskManagementCmd.PersistentFlags().Int(commonParams.LimitFlag, -1, "Limit") + + addFormatFlag(riskManagementCmd, printer.FormatJSON, printer.FormatTable, printer.FormatList) + + return riskManagementCmd +} + +func resultShowSubCommand( + resultsWrapper wrappers.ResultsWrapper, + scanWrapper wrappers.ScansWrapper, + exportWrapper wrappers.ExportWrapper, + resultsPdfReportsWrapper wrappers.ResultsPdfWrapper, + resultsJSONReportsWrapper wrappers.ResultsJSONWrapper, + risksOverviewWrapper wrappers.RisksOverviewWrapper, + scsScanOverviewWrapper wrappers.ScanOverviewWrapper, + policyWrapper wrappers.PolicyWrapper, + featureFlagsWrapper wrappers.FeatureFlagsWrapper, + jwtWrapper wrappers.JWTWrapper, +) *cobra.Command { + resultShowCmd := &cobra.Command{ + Use: "show", + Short: "Show results of a scan", + Long: "The show command enables the ability to show results about a requested scan in Checkmarx One", + Example: heredoc.Doc( + ` + $ cx results show --scan-id + `, + ), + RunE: runGetResultCommand(resultsWrapper, scanWrapper, exportWrapper, resultsPdfReportsWrapper, resultsJSONReportsWrapper, risksOverviewWrapper, scsScanOverviewWrapper, policyWrapper, featureFlagsWrapper, jwtWrapper), + } + addScanIDFlag(resultShowCmd, "ID to report on") + addResultFormatFlag( + resultShowCmd, + printer.FormatJSON, + printer.FormatJSONv2, + printer.FormatSummary, + printer.FormatSummaryConsole, + printer.FormatSarif, + printer.FormatSummaryJSON, + printer.FormatSbom, + printer.FormatPDF, + printer.FormatSummaryMarkdown, + printer.FormatGLSast, + printer.FormatGLSca, + printer.FormatSonar, + ) + resultShowCmd.PersistentFlags().String(commonParams.ReportFormatPdfToEmailFlag, "", pdfToEmailFlagDescription) + resultShowCmd.PersistentFlags().String(commonParams.ReportSbomFormatFlag, services.DefaultSbomOption, sbomReportFlagDescription) + resultShowCmd.PersistentFlags().String(commonParams.ReportFormatPdfOptionsFlag, defaultPdfOptionsDataSections, pdfOptionsFlagDescription) + resultShowCmd.PersistentFlags().String(commonParams.TargetFlag, "cx_result", "Output file") + resultShowCmd.PersistentFlags().String(commonParams.TargetPathFlag, ".", "Output Path") + resultShowCmd.PersistentFlags().StringSlice(commonParams.FilterFlag, []string{}, filterResultsListFlagUsage) + + resultShowCmd.PersistentFlags().IntP( + commonParams.WaitDelayFlag, + "", + commonParams.WaitDelayDefault, + "Polling wait time in seconds", + ) + resultShowCmd.PersistentFlags().Int( + commonParams.PolicyTimeoutFlag, + commonParams.ResultPolicyDefaultTimeout, + "Cancel the policy evaluation and fail after the timeout in minutes", + ) + resultShowCmd.PersistentFlags().Bool(commonParams.IgnorePolicyFlag, false, "Skip policy evaluation. Requires override-policy-management permission.") + resultShowCmd.PersistentFlags().Bool(commonParams.SastRedundancyFlag, false, + "Populate SAST results 'data.redundancy' with values '"+fixLabel+"' (to fix) or '"+redundantLabel+"' (no need to fix)") + resultShowCmd.PersistentFlags().Bool(commonParams.ScaHideDevAndTestDepFlag, false, scaHideDevAndTestDepFlagDescription) + + return resultShowCmd +} + +func resultBflSubCommand(bflWrapper wrappers.BflWrapper) *cobra.Command { + resultBflCmd := &cobra.Command{ + Use: "bfl", + Short: "Show best fix location for a query id within the scan result", + Long: "The bfl command enables the ability to show best fix location for a querid within the scan result", + Example: heredoc.Doc( + ` + $ cx results bfl --scan-id --query-id + `, + ), + RunE: runGetBestFixLocationCommand(bflWrapper), + } + addScanIDFlag(resultBflCmd, "ID to report on") + addQueryIDFlag(resultBflCmd, "Query Id from the result") + addFormatFlag(resultBflCmd, printer.FormatList, printer.FormatJSON) + + markFlagAsRequired(resultBflCmd, commonParams.ScanIDFlag) + markFlagAsRequired(resultBflCmd, commonParams.QueryIDFlag) + + return resultBflCmd +} + +func runGetExitCodeCommand(scanWrapper wrappers.ScansWrapper) func(cmd *cobra.Command, args []string) error { + return func(cmd *cobra.Command, args []string) error { + scanID, _ := cmd.Flags().GetString(commonParams.ScanIDFlag) + if scanID == "" { + return errors.New(errorConstants.ScanIDRequired) + } + scanTypesFlagValue, _ := cmd.Flags().GetString(commonParams.ScanTypes) + results, err := GetScannerResults(scanWrapper, scanID, scanTypesFlagValue) + if err != nil { + return err + } + + if len(results) == 0 { + return nil + } + + return printer.Print(cmd.OutOrStdout(), results, printer.FormatIndentedJSON) + } +} + +func runRiskManagementCommand(riskManagement wrappers.RiskManagementWrapper, featureFlagsWrapper wrappers.FeatureFlagsWrapper, +) func(cmd *cobra.Command, args []string) error { + return func(cmd *cobra.Command, args []string) error { + projectID, _ := cmd.Flags().GetString(commonParams.ProjectIDFlag) + scanID, _ := cmd.Flags().GetString(commonParams.ScanIDFlag) + + limit, _ := cmd.Flags().GetInt(commonParams.LimitFlag) + + flagResponse, _ := wrappers.GetSpecificFeatureFlag(featureFlagsWrapper, wrappers.RiskManagementEnabled) + ASPMEnabled := flagResponse.Status + if !ASPMEnabled { + return errors.Errorf("%s", "Risk management results are currently unavailable for your tenant.") + } + results, err := getRiskManagementResults(riskManagement, projectID, scanID) + if err != nil { + return err + } + results.Results = utils.LimitSlice(results.Results, limit) + err = printByFormat(cmd, results) + return err + } +} + +func getRiskManagementResults(riskManagement wrappers.RiskManagementWrapper, projectID, scanID string) (*wrappers.ASPMResult, error) { + ASPMResult, errorModel, err := riskManagement.GetTopVulnerabilitiesByProjectID(projectID, scanID) + if err != nil { + return nil, errors.Wrapf(err, "%s", failedListingResults) + } + if errorModel != nil { + return nil, errors.Errorf("%s: CODE: %d, %s", failedListingResults, errorModel.Code, errorModel.Message) + } + return ASPMResult, nil +} + +func GetScannerResults(scanWrapper wrappers.ScansWrapper, scanID, scanTypesFlagValue string) ([]ScannerResponse, error) { + scanResponseModel, errorModel, err := scanWrapper.GetByID(scanID) + if err != nil { + return nil, errors.Wrapf(err, "%s", failedGetting) + } + if errorModel != nil { + return nil, errors.Errorf("%s: CODE: %d, %s", failedGettingScan, errorModel.Code, errorModel.Message) + } + results := getScannerResponse(scanTypesFlagValue, scanResponseModel) + return results, nil +} + +func getScannerResponse(scanTypesFlagValue string, scanResponseModel *wrappers.ScanResponseModel) []ScannerResponse { + var results []ScannerResponse + + if scanResponseModel.Status == wrappers.ScanCanceled || + scanResponseModel.Status == wrappers.ScanRunning || + scanResponseModel.Status == wrappers.ScanQueued || + scanResponseModel.Status == wrappers.ScanPartial || + scanResponseModel.Status == wrappers.ScanCompleted { + result := ScannerResponse{ + ScanID: scanResponseModel.ID, + Status: string(scanResponseModel.Status), + } + results = append(results, result) + return results + } + + if scanTypesFlagValue == "" { + results = createAllFailedScannersResponse(scanResponseModel) + } else { + scanTypes := sanitizeScannerNames(scanTypesFlagValue) + results = createRequestedScannersResponse(scanTypes, scanResponseModel) + } + + return results +} + +func createRequestedScannersResponse(scanTypes map[string]string, scanResponseModel *wrappers.ScanResponseModel) []ScannerResponse { + var results []ScannerResponse + for i := range scanResponseModel.StatusDetails { + if _, ok := scanTypes[scanResponseModel.StatusDetails[i].Name]; ok { + results = append(results, createScannerResponse(&scanResponseModel.StatusDetails[i])) + } + } + return results +} + +func createAllFailedScannersResponse(scanResponseModel *wrappers.ScanResponseModel) []ScannerResponse { + var results []ScannerResponse + for i := range scanResponseModel.StatusDetails { + if scanResponseModel.StatusDetails[i].Status == wrappers.ScanFailed { + results = append(results, createScannerResponse(&scanResponseModel.StatusDetails[i])) + } + } + return results +} + +func sanitizeScannerNames(scanTypes string) map[string]string { + scanTypeSlice := strings.Split(scanTypes, ",") + scanTypeMap := make(map[string]string) + for i := range scanTypeSlice { + lowered := strings.ToLower(scanTypeSlice[i]) + scanTypeMap[lowered] = lowered + } + + return scanTypeMap +} + +func createScannerResponse(statusDetails *wrappers.StatusInfo) ScannerResponse { + return ScannerResponse{ + Name: statusDetails.Name, + Status: statusDetails.Status, + Details: statusDetails.Details, + ErrorCode: stringifyErrorCode(statusDetails.ErrorCode), + } +} + +func stringifyErrorCode(errorCode int) string { + if errorCode == 0 { + return "" + } + return strconv.Itoa(errorCode) +} + +func runGetBestFixLocationCommand(bflWrapper wrappers.BflWrapper) func(cmd *cobra.Command, args []string) error { + return func(cmd *cobra.Command, args []string) error { + var bflResponseModel *wrappers.BFLResponseModel + var errorModel *wrappers.WebError + var err error + + scanID, _ := cmd.Flags().GetString(commonParams.ScanIDFlag) + queryID, _ := cmd.Flags().GetString(commonParams.QueryIDFlag) + + scanIds := strings.Split(scanID, ",") + if len(scanIds) > 1 { + return errors.Errorf("%s", "Multiple scan-ids are not allowed.") + } + queryIds := strings.Split(queryID, ",") + if len(queryIds) > 1 { + return errors.Errorf("%s", "Multiple query-ids are not allowed.") + } + + params := make(map[string]string) + params[commonParams.ScanIDQueryParam] = scanID + params[commonParams.QueryIDQueryParam] = queryID + + bflResponseModel, errorModel, err = bflWrapper.GetBflByScanIDAndQueryID(params) + + if err != nil { + return errors.Wrapf(err, "%s", failedGettingBfl) + } + + // Checking the response + if errorModel != nil { + return errors.Errorf("%s: CODE: %d, %s", failedGettingBfl, errorModel.Code, errorModel.Message) + } else if bflResponseModel != nil { + err = printByFormat(cmd, toBflView(*bflResponseModel)) + if err != nil { + return err + } + } + + return nil + } +} + +func toBflView(bflResponseModel wrappers.BFLResponseModel) []wrappers.ScanResultNode { + if (bflResponseModel.TotalCount) > 0 { + views := make([]wrappers.ScanResultNode, bflResponseModel.TotalCount) + + for i := 0; i < bflResponseModel.TotalCount; i++ { + views[i] = wrappers.ScanResultNode{ + Name: bflResponseModel.Trees[i].BFL.Name, + FileName: bflResponseModel.Trees[i].BFL.FileName, + FullName: bflResponseModel.Trees[i].BFL.FullName, + Column: bflResponseModel.Trees[i].BFL.Column, + Length: bflResponseModel.Trees[i].BFL.Length, + Line: bflResponseModel.Trees[i].BFL.Line, + MethodLine: bflResponseModel.Trees[i].BFL.MethodLine, + Method: bflResponseModel.Trees[i].BFL.Method, + DomType: bflResponseModel.Trees[i].BFL.DomType, + } + } + return views + } + views := make([]wrappers.ScanResultNode, 0) + return views +} + +func resultCodeBashing(codeBashingWrapper wrappers.CodeBashingWrapper) *cobra.Command { + // Create a codeBashing wrapper + resultCmd := &cobra.Command{ + Use: "codebashing", + Short: "Get codebashing lesson link", + Long: "The codebashing command enables the ability to retrieve the link about a specific vulnerability", + Example: heredoc.Doc( + ` + $ cx results codebashing --language --vulnerability-type --cwe-id --format + `, + ), + RunE: runGetCodeBashingCommand(codeBashingWrapper), + } + resultCmd.PersistentFlags().String(commonParams.LanguageFlag, "", "Language of the vulnerability") + err := resultCmd.MarkPersistentFlagRequired(commonParams.LanguageFlag) + if err != nil { + log.Fatal(err) + } + resultCmd.PersistentFlags().String(commonParams.VulnerabilityTypeFlag, "", "Vulnerability type") + err = resultCmd.MarkPersistentFlagRequired(commonParams.VulnerabilityTypeFlag) + if err != nil { + log.Fatal(err) + } + resultCmd.PersistentFlags().String(commonParams.CweIDFlag, "", "CWE ID for the vulnerability") + err = resultCmd.MarkPersistentFlagRequired(commonParams.CweIDFlag) + if err != nil { + log.Fatal(err) + } + addFormatFlag(resultCmd, printer.FormatJSON, printer.FormatTable, printer.FormatList) + return resultCmd +} + +func convertScanToResultsSummary(scanInfo *wrappers.ScanResponseModel, resultsWrapper wrappers.ResultsWrapper) (*wrappers.ResultSummary, error) { + if scanInfo == nil { + return nil, errors.New(failedCreatingSummary) + } + + scanInfo.ReplaceMicroEnginesWithSCS() + + sastIssues := 0 + scaIssues := 0 + kicsIssues := 0 + var containersIssues *int + var scsIssues *int + enginesStatusCode := map[string]int{ + commonParams.SastType: 0, + commonParams.ScaType: 0, + commonParams.KicsType: 0, + commonParams.APISecType: 0, + commonParams.ScsType: 0, + commonParams.ContainersType: 0, + } + if wrappers.IsContainersEnabled { + containersIssues = new(int) + *containersIssues = 0 + enginesStatusCode[commonParams.ContainersType] = 0 + } + + scsIssues = new(int) + *scsIssues = 0 + enginesStatusCode[commonParams.ScsType] = 0 + + if len(scanInfo.StatusDetails) > 0 { + for _, statusDetailItem := range scanInfo.StatusDetails { + if statusDetailItem.Status == wrappers.ScanFailed || statusDetailItem.Status == wrappers.ScanCanceled { + if statusDetailItem.Name == commonParams.SastType { + sastIssues = notAvailableNumber + } else if statusDetailItem.Name == commonParams.ScaType { + scaIssues = notAvailableNumber + } else if statusDetailItem.Name == commonParams.KicsType { + kicsIssues = notAvailableNumber + } else if statusDetailItem.Name == commonParams.ScsType { + *scsIssues = notAvailableNumber + } else if statusDetailItem.Name == commonParams.ContainersType && wrappers.IsContainersEnabled { + *containersIssues = notAvailableNumber + } + } + switch statusDetailItem.Status { + case wrappers.ScanFailed: + handleScanStatus(statusDetailItem, enginesStatusCode, scanFailedNumber) + case wrappers.ScanCanceled: + handleScanStatus(statusDetailItem, enginesStatusCode, scanCanceledNumber) + } + } + } + summary := &wrappers.ResultSummary{ + ScanID: scanInfo.ID, + Status: string(scanInfo.Status), + CreatedAt: scanInfo.CreatedAt.Format("2006-01-02, 15:04:05"), + ProjectID: scanInfo.ProjectID, + RiskStyle: "", + RiskMsg: "", + CriticalIssues: 0, + HighIssues: 0, + MediumIssues: 0, + LowIssues: 0, + InfoIssues: 0, + SastIssues: sastIssues, + KicsIssues: kicsIssues, + ScaIssues: scaIssues, + ScsIssues: scsIssues, + ContainersIssues: containersIssues, + Tags: scanInfo.Tags, + ProjectName: scanInfo.ProjectName, + BranchName: scanInfo.Branch, + EnginesEnabled: scanInfo.Engines, + EnginesResult: map[string]*wrappers.EngineResultSummary{ + commonParams.SastType: {StatusCode: enginesStatusCode[commonParams.SastType]}, + commonParams.ScaType: {StatusCode: enginesStatusCode[commonParams.ScaType]}, + commonParams.KicsType: {StatusCode: enginesStatusCode[commonParams.KicsType]}, + commonParams.APISecType: {StatusCode: enginesStatusCode[commonParams.APISecType]}, + commonParams.ContainersType: {StatusCode: enginesStatusCode[commonParams.ContainersType]}, + }, + } + if wrappers.IsContainersEnabled { + summary.EnginesResult[commonParams.ContainersType] = &wrappers.EngineResultSummary{StatusCode: enginesStatusCode[commonParams.ContainersType]} + } + + summary.EnginesResult[commonParams.ScsType] = &wrappers.EngineResultSummary{StatusCode: enginesStatusCode[commonParams.ScsType]} + + baseURI, err := resultsWrapper.GetResultsURL(summary.ProjectID) + if err != nil { + return nil, err + } + + summary.BaseURI = baseURI + summary.BaseURI = generateScanSummaryURL(summary) + if isScanPending(summary.Status) { + summary.ScanInfoMessage = scanPendingMessage + } + + return summary, nil +} + +func handleScanStatus(statusDetailItem wrappers.StatusInfo, targetTypes map[string]int, statusCode int) { + if _, ok := targetTypes[statusDetailItem.Name]; ok { + targetTypes[statusDetailItem.Name] = statusCode + } +} + +func summaryReport( + summary *wrappers.ResultSummary, + policies *wrappers.PolicyResponseModel, + risksOverviewWrapper wrappers.RisksOverviewWrapper, + scsScanOverviewWrapper wrappers.ScanOverviewWrapper, + featureFlagsWrapper wrappers.FeatureFlagsWrapper, + results *wrappers.ScanResultsCollection, + resultsParams map[string]string, +) (*wrappers.ResultSummary, error) { + if summary.HasAPISecurity() { + apiSecFilterRisks, err := getFilterResultsForAPISecScanner(risksOverviewWrapper, summary.ScanID, resultsParams) + if err != nil { + return nil, err + } + if apiSecFilterRisks != nil { + summary.APISecurity = *apiSecFilterRisks + } + apiSecRisks, err := getResultsForAPISecScanner(risksOverviewWrapper, summary.ScanID) + if err != nil { + return nil, err + } + if apiSecRisks != nil { + summary.APISecurity.APICount = apiSecRisks.APICount + } + } + if summary.HasSCS() { + // Getting the base SCS overview. Results counts are overwritten in enhanceWithScanSummary->countResult + SCSOverview, err := getScanOverviewForSCSScanner(scsScanOverviewWrapper, summary.ScanID) + if err != nil { + return nil, err + } + summary.SCSOverview = SCSOverview + } + + if policies != nil { + summary.Policies = filterViolatedRules(*policies) + } + + enhanceWithScanSummary(summary, results, featureFlagsWrapper) + + setNotAvailableNumberIfZero(summary, &summary.SastIssues, commonParams.SastType) + setNotAvailableNumberIfZero(summary, &summary.ScaIssues, commonParams.ScaType) + setNotAvailableNumberIfZero(summary, &summary.KicsIssues, commonParams.KicsType) + setNotAvailableNumberIfZero(summary, summary.ScsIssues, commonParams.ScsType) + + if wrappers.IsContainersEnabled { + setNotAvailableNumberIfZero(summary, summary.ContainersIssues, commonParams.ContainersType) + } + + setRiskMsgAndStyle(summary) + setNotAvailableEnginesStatusCode(summary) + + return summary, nil +} + +func setNotAvailableEnginesStatusCode(summary *wrappers.ResultSummary) { + for engineName, engineResult := range summary.EnginesResult { + setNotAvailableNumberIfZero(summary, &engineResult.StatusCode, engineName) + } +} + +func setRiskMsgAndStyle(summary *wrappers.ResultSummary) { + if summary.CriticalIssues > 0 { + summary.RiskStyle = criticalLabel + summary.RiskMsg = "Critical Risk" + } else if summary.HighIssues > 0 { + summary.RiskStyle = highLabel + summary.RiskMsg = "High Risk" + } else if summary.MediumIssues > 0 { + summary.RiskStyle = mediumLabel + summary.RiskMsg = "Medium Risk" + } else if summary.LowIssues > 0 { + summary.RiskStyle = lowLabel + summary.RiskMsg = "Low Risk" + } else if summary.TotalIssues == 0 { + summary.RiskMsg = "No Risk" + } +} + +func setNotAvailableNumberIfZero(summary *wrappers.ResultSummary, counter *int, engineType string) { + if *counter == 0 && !contains(summary.EnginesEnabled, engineType) { + *counter = notAvailableNumber + } +} + +func enhanceWithScanSummary(summary *wrappers.ResultSummary, results *wrappers.ScanResultsCollection, featureFlagsWrapper wrappers.FeatureFlagsWrapper) { + for _, result := range results.Results { + countResult(summary, result) + } + // Set critical count for a specific engine if critical is disabled + flagResponse, _ := wrappers.GetSpecificFeatureFlag(featureFlagsWrapper, wrappers.CVSSV3Enabled) + criticalEnabled := flagResponse.Status + if summary.HasAPISecurity() { + summary.EnginesResult[commonParams.APISecType].Low = summary.APISecurity.SeverityCount["low"] + summary.EnginesResult[commonParams.APISecType].Medium = summary.APISecurity.SeverityCount["medium"] + summary.EnginesResult[commonParams.APISecType].High = summary.APISecurity.SeverityCount["high"] + if !criticalEnabled { + summary.EnginesResult[commonParams.APISecType].Critical = notAvailableNumber + } else { + summary.EnginesResult[commonParams.APISecType].Critical = summary.APISecurity.SeverityCount["critical"] + } + } + + summary.TotalIssues = summary.SastIssues + summary.ScaIssues + summary.KicsIssues + summary.GetAPISecurityDocumentationTotal() + + if summary.HasSCS() { + // Special case for SCS where status is partial if any microengines failed + if summary.SCSOverview.Status == scanPartialString { + summary.EnginesResult[commonParams.ScsType].StatusCode = scanPartialNumber + } + if !criticalEnabled { + summary.EnginesResult[commonParams.ScsType].Critical = notAvailableNumber + removeCriticalFromSCSOverview(summary) + } + if *summary.ScsIssues >= 0 { + summary.TotalIssues += *summary.ScsIssues + } + } + if wrappers.IsContainersEnabled { + if *summary.ContainersIssues >= 0 { + summary.TotalIssues += *summary.ContainersIssues + } + } + if !criticalEnabled { + summary.EnginesResult[commonParams.SastType].Critical = notAvailableNumber + summary.EnginesResult[commonParams.KicsType].Critical = notAvailableNumber + summary.EnginesResult[commonParams.ScaType].Critical = notAvailableNumber + summary.EnginesResult[commonParams.ContainersType].Critical = notAvailableNumber + } +} + +func removeCriticalFromSCSOverview(summary *wrappers.ResultSummary) { + criticalCount := summary.SCSOverview.RiskSummary[criticalLabel] + summary.SCSOverview.TotalRisksCount -= criticalCount + summary.SCSOverview.RiskSummary[criticalLabel] = notAvailableNumber + for _, microEngineOverview := range summary.SCSOverview.MicroEngineOverviews { + if microEngineOverview.RiskSummary != nil && microEngineOverview.RiskSummary[criticalLabel] != nil { + engineCriticalCount := microEngineOverview.RiskSummary[criticalLabel] + microEngineOverview.TotalRisks -= engineCriticalCount.(int) + microEngineOverview.RiskSummary[criticalLabel] = disabledString + } + } +} + +func writeHTMLSummary(targetFile string, summary *wrappers.ResultSummary) error { + log.Println("Creating Summary Report: ", targetFile) + summaryTemp, err := template.New("summaryTemplate").Parse(wrappers.SummaryTemplate(isScanPending(summary.Status))) + if err == nil { + f, err := os.Create(targetFile) + if err == nil { + _ = summaryTemp.ExecuteTemplate(f, "SummaryTemplate", summary) + _ = f.Close() + } + return err + } + return nil +} +func writeMarkdownSummary(targetFile string, data *wrappers.ResultSummary) error { + log.Println("Creating Markdown Summary Report: ", targetFile) + tmpl, err := template.New(printer.FormatSummaryMarkdown).Parse(wrappers.SummaryMarkdownTemplate(isScanPending(data.Status))) + if err != nil { + return err + } + file, err := os.Create(targetFile) + if err != nil { + return err + } + defer file.Close() + + err = tmpl.Execute(file, &data) + if err != nil { + return err + } + return nil +} + +// nolint: whitespace +func writeConsoleSummary(summary *wrappers.ResultSummary, featureFlagsWrapper wrappers.FeatureFlagsWrapper, ignorePolicyFlagOmit bool) error { + if !isScanPending(summary.Status) { + fmt.Printf(" Scan Summary: \n") + fmt.Printf(" Created At: %s\n", summary.CreatedAt) + fmt.Printf(" Project Name: %s \n", summary.ProjectName) + fmt.Printf(" Scan ID: %s \n\n", summary.ScanID) + fmt.Printf(" Results Summary: \n") + fmt.Printf( + " Risk Level: %s \n", + summary.RiskMsg, + ) + if summary.Policies != nil && !strings.EqualFold(summary.Policies.Status, policeManagementNoneStatus) { + printPoliciesSummary(summary, ignorePolicyFlagOmit) + } + + printResultsSummaryTable(summary) + + if summary.HasAPISecurity() { + printAPIsSecuritySummary(summary) + } + + if summary.HasSCS() { + printSCSSummary(summary.SCSOverview.MicroEngineOverviews, featureFlagsWrapper) + } + + 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") + fmt.Printf("For more information: %s\n", summary.BaseURI) + } + return nil +} + +func printPoliciesSummary(summary *wrappers.ResultSummary, ignorePolicyFlagOmit bool) { + hasViolations := false + for _, policy := range summary.Policies.Policies { + if len(policy.RulesViolated) > 0 { + hasViolations = true + break + } + } + if hasViolations { + fmt.Printf(tableLine + "\n") + if ignorePolicyFlagOmit { + printWarningIfIgnorePolicyOmiited() + } + if summary.Policies.BreakBuild { + fmt.Printf(" Policy Management Violation - Break Build Enabled: \n") + } else { + fmt.Printf(" Policy Management Violation: \n") + } + for _, police := range summary.Policies.Policies { + if len(police.RulesViolated) > 0 { + fmt.Printf(" Policy: %s | Break Build: %t | Violated Rules: ", police.Name, police.BreakBuild) + for _, violatedRule := range police.RulesViolated { + fmt.Printf("%s;", violatedRule) + } + } + fmt.Printf("\n") + } + fmt.Printf("\n") + } +} + +func printAPIsSecuritySummary(summary *wrappers.ResultSummary) { + fmt.Printf(" API Security - Total Detected APIs: %d \n", summary.APISecurity.APICount) + fmt.Printf(" APIS WITH RISK: %*d \n", defaultPaddingSize, summary.APISecurity.TotalRisksCount) + if summary.HasAPISecurityDocumentation() { + fmt.Printf(" APIS DOCUMENTATION: %*d \n", defaultPaddingSize, summary.GetAPISecurityDocumentationTotal()) + } + fmt.Printf(tableLine + twoNewLines) +} + +func printTableRow(title string, counts *wrappers.EngineResultSummary, statusNumber int) { + switch statusNumber { + case notAvailableNumber: + fmt.Printf(stringTableResultsFormat, title, notAvailableString, notAvailableString, notAvailableString, notAvailableString, notAvailableString, notAvailableString) + case scanFailedNumber: + fmt.Printf(tableResultsFormat, title, getCountValue(counts.Critical), counts.High, counts.Medium, counts.Low, counts.Info, scanFailedString) + case scanCanceledNumber: + fmt.Printf(tableResultsFormat, title, getCountValue(counts.Critical), counts.High, counts.Medium, counts.Low, counts.Info, scanCanceledString) + case scanPartialNumber: + fmt.Printf(tableResultsFormat, title, getCountValue(counts.Critical), counts.High, counts.Medium, counts.Low, counts.Info, scanPartialString) + default: + fmt.Printf(tableResultsFormat, title, getCountValue(counts.Critical), counts.High, counts.Medium, counts.Low, counts.Info, scanSuccessString) + } +} + +func printSCSSummary(microEngineOverviews []*wrappers.MicroEngineOverview, featureFlagsWrapper wrappers.FeatureFlagsWrapper) { + fmt.Printf(" Supply Chain Security Results\n") + fmt.Printf(" -------------------------------------------------------------------------- \n") + fmt.Println(" | Critical High Medium Low Info Status |") + for _, microEngineOverview := range microEngineOverviews { + printSCSTableRow(microEngineOverview, featureFlagsWrapper) + } + fmt.Printf(" -------------------------------------------------------------------------- \n\n") +} + +func printSCSTableRow(microEngineOverview *wrappers.MicroEngineOverview, featureFlagsWrapper wrappers.FeatureFlagsWrapper) { + formatString := " | %-20s %4v %4v %6v %4v %4v %-9s |\n" + notAvailableFormatString := " | %-20s %4v %4s %6s %4s %4s %5s |\n" + + riskSummary := microEngineOverview.RiskSummary + microEngineName := microEngineOverview.FullName + + switch microEngineOverview.Status { + case scsScanUnavailableString: + fmt.Printf(notAvailableFormatString, microEngineName, notAvailableString, notAvailableString, notAvailableString, notAvailableString, notAvailableString, notAvailableString) + default: + fmt.Printf(formatString, microEngineName, riskSummary[criticalLabel], riskSummary[highLabel], riskSummary[mediumLabel], riskSummary[lowLabel], + riskSummary[infoLabel], microEngineOverview.Status) + } +} + +func getCountValue(count int) interface{} { + if count < 0 { + return disabledString + } + return count +} + +func printResultsSummaryTable(summary *wrappers.ResultSummary) { + totalCriticalIssues := summary.EnginesResult.GetCriticalIssues() + totalHighIssues := summary.EnginesResult.GetHighIssues() + totalMediumIssues := summary.EnginesResult.GetMediumIssues() + totalLowIssues := summary.EnginesResult.GetLowIssues() + totalInfoIssues := summary.EnginesResult.GetInfoIssues() + fmt.Printf(tableLine + twoNewLines) + fmt.Printf(" Total Results: %d (Total Results includes only API documentation vulnerabilities\n and does not include API code vulnerabilities.)\n", summary.TotalIssues) + fmt.Println(tableLine) + fmt.Printf(TableTitleFormat, " ", "Critical", "High", "Medium", "Low", "Info", "Status") + + printTableRow("APIs", summary.EnginesResult[commonParams.APISecType], summary.EnginesResult[commonParams.APISecType].StatusCode) + printTableRow("IAC", summary.EnginesResult[commonParams.KicsType], summary.EnginesResult[commonParams.KicsType].StatusCode) + printTableRow("SAST", summary.EnginesResult[commonParams.SastType], summary.EnginesResult[commonParams.SastType].StatusCode) + printTableRow("SCA", summary.EnginesResult[commonParams.ScaType], summary.EnginesResult[commonParams.ScaType].StatusCode) + printTableRow("SCS", summary.EnginesResult[commonParams.ScsType], summary.EnginesResult[commonParams.ScsType].StatusCode) + + if wrappers.IsContainersEnabled { + printTableRow("CONTAINERS", summary.EnginesResult[commonParams.ContainersType], summary.EnginesResult[commonParams.ContainersType].StatusCode) + } + + fmt.Println(tableLine) + fmt.Printf(tableResultsFormat, + "TOTAL", getCountValue(totalCriticalIssues), totalHighIssues, totalMediumIssues, totalLowIssues, totalInfoIssues, summary.Status) + fmt.Printf(tableLine + twoNewLines) +} + +func generateScanSummaryURL(summary *wrappers.ResultSummary) string { + summaryURL := fmt.Sprintf( + strings.Replace(summary.BaseURI, "overview", "scans?id=%s&branch=%s", 1), + summary.ScanID, url.QueryEscape(summary.BranchName), + ) + return summaryURL +} + +func runGetResultCommand( + resultsWrapper wrappers.ResultsWrapper, + scanWrapper wrappers.ScansWrapper, + exportWrapper wrappers.ExportWrapper, + resultsPdfReportsWrapper wrappers.ResultsPdfWrapper, + resultsJSONReportsWrapper wrappers.ResultsJSONWrapper, + risksOverviewWrapper wrappers.RisksOverviewWrapper, + scsScanOverviewWrapper wrappers.ScanOverviewWrapper, + policyWrapper wrappers.PolicyWrapper, + featureFlagsWrapper wrappers.FeatureFlagsWrapper, + jwtWrapper wrappers.JWTWrapper, +) func(cmd *cobra.Command, args []string) error { + return func(cmd *cobra.Command, args []string) error { + targetFile, _ := cmd.Flags().GetString(commonParams.TargetFlag) + targetPath, _ := cmd.Flags().GetString(commonParams.TargetPathFlag) + format, _ := cmd.Flags().GetString(commonParams.TargetFormatFlag) + formatPdfToEmail, _ := cmd.Flags().GetString(commonParams.ReportFormatPdfToEmailFlag) + formatPdfOptions, _ := cmd.Flags().GetString(commonParams.ReportFormatPdfOptionsFlag) + formatSbomOptions, _ := cmd.Flags().GetString(commonParams.ReportSbomFormatFlag) + sastRedundancy, _ := cmd.Flags().GetBool(commonParams.SastRedundancyFlag) + agent, _ := cmd.Flags().GetString(commonParams.AgentFlag) + scaHideDevAndTestDep, _ := cmd.Flags().GetBool(commonParams.ScaHideDevAndTestDepFlag) + ignorePolicy, _ := cmd.Flags().GetBool(commonParams.IgnorePolicyFlag) + // Check if the user has permission to override policy management if --ignore-policy is set + ignorePolicyFlagOmit := false + if ignorePolicy { + overridePolicyManagementPer, err := jwtWrapper.CheckPermissionByAccessToken(OverridePolicyManagement) + if err != nil { + return err + } + if !overridePolicyManagementPer { + ignorePolicyFlagOmit = true + ignorePolicy = false + } + } + waitDelay, _ := cmd.Flags().GetInt(commonParams.WaitDelayFlag) + policyTimeout, _ := cmd.Flags().GetInt(commonParams.PolicyTimeoutFlag) + + scanID, _ := cmd.Flags().GetString(commonParams.ScanIDFlag) + if scanID == "" { + return errors.Errorf("%s: Please provide a scan ID", failedListingResults) + } + + resultsParams, err := getFilters(cmd) + if err != nil { + return errors.Wrapf(err, "%s", failedListingResults) + } + + if scaHideDevAndTestDep { + resultsParams[ScaExcludeResultTypesParam] = ScaDevAndTestExclusionParam + } + + scan, errorModel, scanErr := scanWrapper.GetByID(scanID) + if scanErr != nil { + return errors.Wrapf(scanErr, "%s", failedGetting) + } + if errorModel != nil { + return errors.Errorf("%s: CODE: %d, %s", failedGettingScan, errorModel.Code, errorModel.Message) + } + + var policyResponseModel *wrappers.PolicyResponseModel + if !isScanPending(string(scan.Status)) { + policyResponseModel, err = services.HandlePolicyEvaluation(cmd, policyWrapper, scan, ignorePolicy, agent, waitDelay, policyTimeout) + if err != nil { + return err + } + } else { + logger.PrintIfVerbose("Policy violations aren't returned in the pipeline for scans run in async mode.") + } + + if sastRedundancy { + resultsParams[commonParams.SastRedundancyFlag] = "" + } + + _, err = CreateScanReport(resultsWrapper, risksOverviewWrapper, scsScanOverviewWrapper, exportWrapper, + policyResponseModel, resultsPdfReportsWrapper, resultsJSONReportsWrapper, scan, format, formatPdfToEmail, formatPdfOptions, + formatSbomOptions, targetFile, targetPath, agent, resultsParams, featureFlagsWrapper, ignorePolicyFlagOmit) + return err + } +} + +func runGetCodeBashingCommand( + codeBashingWrapper wrappers.CodeBashingWrapper, +) func(cmd *cobra.Command, args []string) error { + return func(cmd *cobra.Command, args []string) error { + language, _ := cmd.Flags().GetString(commonParams.LanguageFlag) + cwe, _ := cmd.Flags().GetString(commonParams.CweIDFlag) + vulType, _ := cmd.Flags().GetString(commonParams.VulnerabilityTypeFlag) + params, err := codeBashingWrapper.BuildCodeBashingParams( + []wrappers.CodeBashingParamsCollection{ + { + CweID: "CWE-" + cwe, + Language: language, + CxQueryName: strings.ReplaceAll(vulType, " ", "_"), + }, + }, + ) + if err != nil { + return err + } + // Fetch the cached token or a new one to obtain the codebashing URL incoded in the jwt token + codeBashingURL, err := codeBashingWrapper.GetCodeBashingURL(codeBashingKey) + if err != nil { + return err + } + // Make the request to the api to obtain the codebashing link and send the codebashing url to enrich the path + CodeBashingModel, webError, err := codeBashingWrapper.GetCodeBashingLinks(params, codeBashingURL) + if err != nil { + return err + } + if webError != nil { + return errors.New(webError.Message) + } + err = printByFormat(cmd, *CodeBashingModel) + if err != nil { + return errors.Wrapf(err, "%s", failedListingCodeBashing) + } + return nil + } +} + +func setIsContainersEnabled(agent string) { + wrappers.IsContainersEnabled = !containsIgnoreCase(containerEngineUnsupportedAgents, agent) +} + +func filterResultsByType(results *wrappers.ScanResultsCollection, excludedTypes map[string]struct{}) *wrappers.ScanResultsCollection { + var filteredResults []*wrappers.ScanResult + + for _, result := range results.Results { + if _, shouldExclude := excludedTypes[result.Type]; shouldExclude { + results.TotalCount-- + } else { + filteredResults = append(filteredResults, result) + } + } + results.Results = filteredResults + return results +} + +func filterScsResultsByAgent(results *wrappers.ScanResultsCollection, agent string) *wrappers.ScanResultsCollection { + unsupportedTypesByAgent := map[string][]string{ + commonParams.VSCodeAgent: {commonParams.SCSScorecardType}, + commonParams.JetbrainsAgent: {commonParams.SCSScorecardType}, + commonParams.EclipseAgent: {commonParams.SCSScorecardType, commonParams.SCSSecretDetectionType}, + commonParams.VisualStudioAgent: {commonParams.SCSScorecardType}, + } + + excludedTypes := make(map[string]struct{}) + + if typesToExclude, exists := unsupportedTypesByAgent[agent]; exists { + for _, excludeType := range typesToExclude { + excludedTypes[excludeType] = struct{}{} + } + } + + results = filterResultsByType(results, excludedTypes) + + return results +} + +func CreateScanReport( + resultsWrapper wrappers.ResultsWrapper, + risksOverviewWrapper wrappers.RisksOverviewWrapper, + scsScanOverviewWrapper wrappers.ScanOverviewWrapper, + exportWrapper wrappers.ExportWrapper, + policyResponseModel *wrappers.PolicyResponseModel, + resultsPdfReportsWrapper wrappers.ResultsPdfWrapper, + resultsJSONReportsWrapper wrappers.ResultsJSONWrapper, + scan *wrappers.ScanResponseModel, + reportTypes, + formatPdfToEmail, + formatPdfOptions, + formatSbomOptions, + targetFile, + targetPath string, + agent string, + resultsParams map[string]string, + featureFlagsWrapper wrappers.FeatureFlagsWrapper, + ignorePolicyFlagOmit bool, +) (*wrappers.ScanResultsCollection, error) { + reportList := strings.Split(reportTypes, ",") + results := &wrappers.ScanResultsCollection{} + setIsContainersEnabled(agent) + summary, err := convertScanToResultsSummary(scan, resultsWrapper) + if err != nil { + return nil, err + } + scanPending := isScanPending(summary.Status) + + err = createDirectory(targetPath) + if err != nil { + return nil, err + } + if !scanPending { + results, err = ReadResults(resultsWrapper, exportWrapper, scan, resultsParams, agent, featureFlagsWrapper) + if err != nil { + return nil, err + } + } + isSummaryNeeded := verifyFormatsByReportList(reportList, summaryFormats...) + if isSummaryNeeded && !scanPending { + summary, err = summaryReport(summary, policyResponseModel, risksOverviewWrapper, scsScanOverviewWrapper, featureFlagsWrapper, results, resultsParams) + if err != nil { + return nil, err + } + } + for _, reportType := range reportList { + err = createReport(reportType, formatPdfToEmail, formatPdfOptions, formatSbomOptions, targetFile, + targetPath, results, summary, exportWrapper, resultsPdfReportsWrapper, resultsJSONReportsWrapper, featureFlagsWrapper, ignorePolicyFlagOmit) + if err != nil { + return nil, err + } + } + return results, nil +} + +func countResult(summary *wrappers.ResultSummary, result *wrappers.ScanResult) { + engineType := strings.TrimSpace(result.Type) + severity := strings.ToLower(result.Severity) + if contains(summary.EnginesEnabled, engineType) && isExploitable(result.State) { + if engineType == commonParams.SastType { + summary.SastIssues++ + summary.TotalIssues++ + } else if engineType == commonParams.ScaType { + summary.ScaIssues++ + summary.TotalIssues++ + } else if engineType == commonParams.KicsType { + summary.KicsIssues++ + summary.TotalIssues++ + } else if engineType == commonParams.ContainersType { + if wrappers.IsContainersEnabled { + *summary.ContainersIssues++ + summary.TotalIssues++ + } else { + return + } + } else if strings.HasPrefix(engineType, commonParams.SscsType) { + addResultToSCSOverview(summary, result) + engineType = commonParams.ScsType + *summary.ScsIssues++ + summary.TotalIssues++ + } else { + return + } + + switch severity { + case criticalLabel: + summary.CriticalIssues++ + case highLabel: + summary.HighIssues++ + case mediumLabel: + summary.MediumIssues++ + case lowLabel: + summary.LowIssues++ + case infoLabel: + summary.InfoIssues++ + } + + summary.UpdateEngineResultSummary(engineType, severity) + } +} + +func addResultToSCSOverview(summary *wrappers.ResultSummary, result *wrappers.ScanResult) { + if engineOverviewName, engineExists := sscsEngineToOverviewEngineMap[result.Type]; engineExists { + for _, microEngineOverview := range summary.SCSOverview.MicroEngineOverviews { + if microEngineOverview.Name == engineOverviewName { + if microEngineOverview.RiskSummary != nil { + severity := strings.ToLower(result.Severity) + if severityCount, exists := microEngineOverview.RiskSummary[severity]; exists { + summary.SCSOverview.RiskSummary[severity]++ + microEngineOverview.TotalRisks++ + summary.SCSOverview.TotalRisksCount++ + microEngineOverview.RiskSummary[severity] = severityCount.(int) + 1 + } + } + } + } + } +} + +func verifyFormatsByReportList(reportFormats []string, formats ...string) bool { + for _, reportFormat := range reportFormats { + for _, format := range formats { + if printer.IsFormat(reportFormat, format) { + return true + } + } + } + return false +} + +func validateEmails(emailString string) ([]string, error) { + re := regexp.MustCompile(`^[a-zA-Z0-9_.+-]+@[a-zA-Z0-9-]+\.[a-zA-Z0-9-.]+$`) + emails := strings.Split(emailString, ",") + var validEmails []string + for _, emailStr := range emails { + email := strings.TrimSpace(emailStr) + if re.MatchString(email) { + validEmails = append(validEmails, email) + } else { + return nil, errors.Errorf("report not sent, invalid email address: %s", email) + } + } + return validEmails, nil +} + +func getResultsForAPISecScanner( + risksOverviewWrapper wrappers.RisksOverviewWrapper, + scanID string, +) (results *wrappers.APISecResult, err error) { + var apiSecResultsModel *wrappers.APISecResult + var errorModel *wrappers.WebError + + apiSecResultsModel, errorModel, err = risksOverviewWrapper.GetAllAPISecRisksByScanID(scanID) + if err != nil { + return nil, errors.Wrapf(err, "%s", failedListingResults) + } + if errorModel != nil { + return nil, errors.Errorf("%s: CODE: %d, %s", failedListingResults, errorModel.Code, errorModel.Message) + } else if apiSecResultsModel != nil { + return apiSecResultsModel, nil + } + return nil, nil +} + +func getScanOverviewForSCSScanner( + scsScanOverviewWrapper wrappers.ScanOverviewWrapper, + scanID string, +) (results *wrappers.SCSOverview, err error) { + var scsOverview *wrappers.SCSOverview + var errorModel *wrappers.WebError + + scsOverview, errorModel, err = scsScanOverviewWrapper.GetSCSOverviewByScanID(scanID) + if err != nil { + return nil, errors.Wrapf(err, "SCS: %s", failedListingResults) + } + if errorModel != nil { + return nil, errors.Errorf("SCS: %s: CODE: %d, %s", failedListingResults, errorModel.Code, errorModel.Message) + } else if scsOverview != nil { + // Setting all counts to 0. Results are recounted in enhanceWithScanSummary->countResult + scsOverview.TotalRisksCount = 0 + for key := range scsOverview.RiskSummary { + scsOverview.RiskSummary[key] = 0 + } + for _, microEngineOverview := range scsOverview.MicroEngineOverviews { + microEngineOverview.TotalRisks = 0 + if microEngineOverview.RiskSummary != nil { + for severity := range microEngineOverview.RiskSummary { + microEngineOverview.RiskSummary[severity] = 0 + } + } + } + return scsOverview, nil + } + return nil, nil +} + +func isScanPending(scanStatus string) bool { + return !(strings.EqualFold(scanStatus, "Completed") || strings.EqualFold( + scanStatus, + "Partial", + ) || strings.EqualFold(scanStatus, "Failed")) +} + +func isValidScanStatus(status, format string) bool { + if isScanPending(status) { + log.Printf("Result format file %s not create because scan status is %s", format, status) + return false + } + return true +} + +func createReport(format, + formatPdfToEmail, + formatPdfOptions, + formatSbomOptions, + targetFile, + targetPath string, + results *wrappers.ScanResultsCollection, + summary *wrappers.ResultSummary, + exportWrapper wrappers.ExportWrapper, + resultsPdfReportsWrapper wrappers.ResultsPdfWrapper, + resultsJSONReportsWrapper wrappers.ResultsJSONWrapper, + featureFlagsWrapper wrappers.FeatureFlagsWrapper, + ignorePolicyFlagOmit bool) error { + if printer.IsFormat(format, printer.FormatIndentedJSON) { + return nil + } + if printer.IsFormat(format, printer.FormatSarif) && isValidScanStatus(summary.Status, printer.FormatSarif) { + sarifRpt := createTargetName(targetFile, targetPath, printer.FormatSarif) + return exportSarifResults(sarifRpt, results) + } + if printer.IsFormat(format, printer.FormatSonar) && isValidScanStatus(summary.Status, printer.FormatSonar) { + sonarRpt := createTargetName(fmt.Sprintf("%s%s", targetFile, sonarTypeLabel), targetPath, printer.FormatJSON) + return exportSonarResults(sonarRpt, results) + } + if printer.IsFormat(format, printer.FormatJSON) && isValidScanStatus(summary.Status, printer.FormatJSON) { + jsonRpt := createTargetName(targetFile, targetPath, printer.FormatJSON) + return exportJSONResults(jsonRpt, results) + } + if printer.IsFormat(format, printer.FormatJSONv2) && isValidScanStatus(summary.Status, printer.FormatJSONv2) { + summaryRpt := createTargetName(targetFile, targetPath, printer.FormatJSON) + return exportJSONReportResults(resultsJSONReportsWrapper, summary, summaryRpt, featureFlagsWrapper) + } + if printer.IsFormat(format, printer.FormatGLSast) { + jsonRpt := createTargetName(fmt.Sprintf("%s%s", targetFile, glSastTypeLabel), targetPath, printer.FormatJSON) + return exportGlSastResults(jsonRpt, results, summary) + } + if printer.IsFormat(format, printer.FormatGLSca) { + jsonRpt := createTargetName(fmt.Sprintf("%s%s", targetFile, glScaTypeLabel), targetPath, printer.FormatJSON) + return exportGlScaResults(jsonRpt, results, summary) + } + + if printer.IsFormat(format, printer.FormatSummaryConsole) { + return writeConsoleSummary(summary, featureFlagsWrapper, ignorePolicyFlagOmit) + } + if printer.IsFormat(format, printer.FormatSummary) { + summaryRpt := createTargetName(targetFile, targetPath, printer.FormatHTML) + convertNotAvailableNumberToZero(summary) + return writeHTMLSummary(summaryRpt, summary) + } + if printer.IsFormat(format, printer.FormatSummaryJSON) { + summaryRpt := createTargetName(targetFile, targetPath, printer.FormatJSON) + convertNotAvailableNumberToZero(summary) + return exportJSONSummaryResults(summaryRpt, summary) + } + if printer.IsFormat(format, printer.FormatPDF) && isValidScanStatus(summary.Status, printer.FormatPDF) { + summaryRpt := createTargetName(targetFile, targetPath, printer.FormatPDF) + return exportPdfResults(resultsPdfReportsWrapper, summary, summaryRpt, formatPdfToEmail, formatPdfOptions, featureFlagsWrapper) + } + if printer.IsFormat(format, printer.FormatSummaryMarkdown) { + summaryRpt := createTargetName(targetFile, targetPath, "md") + convertNotAvailableNumberToZero(summary) + return writeMarkdownSummary(summaryRpt, summary) + } + if printer.IsFormat(format, printer.FormatSbom) && isValidScanStatus(summary.Status, printer.FormatSbom) { + targetType := printer.FormatJSON + if strings.Contains(strings.ToLower(formatSbomOptions), printer.FormatXML) { + targetType = printer.FormatXML + } + summaryRpt := createTargetName(fmt.Sprintf("%s_%s", targetFile, printer.FormatSbom), targetPath, targetType) + convertNotAvailableNumberToZero(summary) + + if !contains(summary.EnginesEnabled, commonParams.ScaType) { + return fmt.Errorf("unable to generate %s report - SCA engine must be enabled on scan summary", printer.FormatSbom) + } + + if summary.ScaIssues == notAvailableNumber { + return fmt.Errorf("unable to generate %s report - SCA engine did not complete successfully", printer.FormatSbom) + } + + return services.ExportSbomResults(exportWrapper, summaryRpt, summary, formatSbomOptions) + } + return fmt.Errorf("bad report format %s", format) +} + +func createTargetName(targetFile, targetPath, targetType string) string { + return filepath.Join(targetPath, targetFile+"."+targetType) +} + +func createDirectory(targetPath string) error { + if _, err := os.Stat(targetPath); os.IsNotExist(err) { + log.Printf("\nOutput path not found: %s\n", targetPath) + log.Printf("Creating directory: %s\n", targetPath) + err = os.Mkdir(targetPath, directoryPermission) + if err != nil { + return err + } + } + return nil +} + +func ReadResults( + resultsWrapper wrappers.ResultsWrapper, + exportWrapper wrappers.ExportWrapper, + scan *wrappers.ScanResponseModel, + resultsParams map[string]string, + agent string, featureflagsWrappers wrappers.FeatureFlagsWrapper) (results *wrappers.ScanResultsCollection, err error) { + var resultsModel *wrappers.ScanResultsCollection + var errorModel *wrappers.WebError + + resultsParams[commonParams.ScanIDQueryParam] = scan.ID + _, sastRedundancy := resultsParams[commonParams.SastRedundancyFlag] + + scaHideDevAndTestDep := resultsParams[ScaExcludeResultTypesParam] == ScaDevAndTestExclusionParam + + resultsModel, errorModel, err = resultsWrapper.GetAllResultsByScanID(resultsParams) + + if err != nil { + return nil, errors.Wrapf(err, "%s", failedListingResults) + } + if errorModel != nil { + return nil, errors.Errorf("%s: CODE: %d, %s", failedListingResults, errorModel.Code, errorModel.Message) + } + + if resultsModel != nil { + if slices.Contains(scan.Engines, commonParams.SastType) && sastRedundancy { + // Compute SAST results redundancy + resultsModel = ComputeRedundantSastResults(resultsModel) + } + resultsModel, err = enrichScaResults(exportWrapper, scan, resultsModel, scaHideDevAndTestDep, featureflagsWrappers) + if err != nil { + return nil, err + } + + if slices.Contains(scan.Engines, commonParams.ScsType) { + resultsModel = filterScsResultsByAgent(resultsModel, agent) + } + + resultsModel.ScanID = scan.ID + return resultsModel, nil + } + return nil, nil +} + +func enrichScaResults( + exportWrapper wrappers.ExportWrapper, + scan *wrappers.ScanResponseModel, + resultsModel *wrappers.ScanResultsCollection, + scaHideDevAndTestDep bool, featureflagWrapper wrappers.FeatureFlagsWrapper) (*wrappers.ScanResultsCollection, error) { + if slices.Contains(scan.Engines, commonParams.ScaType) { + scaExportDetails, err := services.GetExportPackage(exportWrapper, scan.ID, scaHideDevAndTestDep, featureflagWrapper) + if err != nil { + return nil, errors.Wrapf(err, "%s", failedListingResults) + } + scaPackageModel := parseScaExportPackage(scaExportDetails.Packages) + scaTypeModel := parseExportScaVulnerability(scaExportDetails.ScaTypes) + if scaPackageModel != nil { + resultsModel = addPackageInformation(resultsModel, scaPackageModel, scaTypeModel) + } + } + if slices.Contains(scan.Engines, commonParams.ContainersType) && !wrappers.IsContainersEnabled { + resultsModel = removeResultsByType(resultsModel, commonParams.ContainersType) + } + return resultsModel, nil +} + +func parseExportScaVulnerability(types []wrappers.ScaType) *[]wrappers.ScaTypeCollection { + var scaTypes []wrappers.ScaTypeCollection + for _, t := range types { + scaTypes = append(scaTypes, wrappers.ScaTypeCollection(t)) + } + return &scaTypes +} + +func parseScaExportPackage(packages []wrappers.ScaPackage) *[]wrappers.ScaPackageCollection { + var scaPackages []wrappers.ScaPackageCollection + for _, pkg := range packages { + pkg := pkg + scaPackages = append(scaPackages, wrappers.ScaPackageCollection{ + ID: pkg.ID, + Locations: pkg.Locations, + DependencyPathArray: parsePackagePathToDependencyPath(&pkg), + Outdated: pkg.Outdated, + IsDirectDependency: pkg.IsDirectDependency, + IsDevelopmentDependency: pkg.IsDevelopmentDependency, + IsTestDependency: pkg.IsTestDependency, + }) + } + return &scaPackages +} + +func parsePackagePathToDependencyPath(pkg *wrappers.ScaPackage) [][]wrappers.DependencyPath { + var dependencyPathArray [][]wrappers.DependencyPath + for _, path := range pkg.PackagePathArray { + var dependencyPath []wrappers.DependencyPath + for _, dep := range path { + dependencyPath = append(dependencyPath, wrappers.DependencyPath{ + ID: dep.ID, + Name: dep.Name, + Version: dep.Version, + }) + } + dependencyPathArray = append(dependencyPathArray, dependencyPath) + } + + // We are doing this to maintain the same structure that was in risk-management api response + // in risk-management, if the length of the dependency path array is 1, it will be the main package + // in export service, if there are no dependencies, the package path array will be empty + if len(dependencyPathArray) == 0 { + appendMainPackageToDependencyPath(&dependencyPathArray, pkg) + } + return dependencyPathArray +} + +func appendMainPackageToDependencyPath(dependencyPathArray *[][]wrappers.DependencyPath, pkg *wrappers.ScaPackage) { + *dependencyPathArray = append(*dependencyPathArray, []wrappers.DependencyPath{{ + ID: pkg.ID, + Locations: pkg.Locations, + Name: pkg.Name, + IsDevelopment: pkg.IsDevelopmentDependency, + }}) +} + +func removeResultsByType(model *wrappers.ScanResultsCollection, resultType string) *wrappers.ScanResultsCollection { + var newResults []*wrappers.ScanResult + for _, result := range model.Results { + isResultType := result.Type == resultType + if resultType == commonParams.SscsType { + isResultType = strings.HasPrefix(result.Type, resultType) + } + if !isResultType { + newResults = append(newResults, result) + } + } + model.Results = newResults + model.TotalCount = uint(len(newResults)) + return model +} + +func exportSarifResults(targetFile string, results *wrappers.ScanResultsCollection) error { + var err error + var resultsJSON []byte + log.Println("Creating SARIF Report: ", targetFile) + var sarifResults = convertCxResultsToSarif(results) + resultsJSON, err = json.Marshal(sarifResults) + if err != nil { + return errors.Wrapf(err, "%s: failed to serialize results response ", failedGettingAll) + } + f, err := os.Create(targetFile) + if err != nil { + return errors.Wrapf(err, "%s: failed to create target file ", failedGettingAll) + } + _, _ = fmt.Fprintln(f, string(resultsJSON)) + _ = f.Close() + return nil +} +func exportGlSastResults(targetFile string, results *wrappers.ScanResultsCollection, summary *wrappers.ResultSummary) error { + log.Println("Creating gl-sast Report: ", targetFile) + var glSast = new(wrappers.GlSastResultsCollection) + glSast.Vulnerabilities = []wrappers.GlVulnerabilities{} + err := addScanToGlSastReport(summary, glSast) + if err != nil { + return errors.Wrapf(err, "%s: failed to add scan to gl-sast report", failedListingResults) + } + convertCxResultToGlSastVulnerability(results, glSast, summary) + resultsJSON, err := json.Marshal(glSast) + if err != nil { + return errors.Wrapf(err, "%s: failed to serialize gl-sast report ", failedListingResults) + } + f, err := os.Create(targetFile) + if err != nil { + return errors.Wrapf(err, "%s: failed to create target file ", failedListingResults) + } + defer f.Close() + _, _ = fmt.Fprintln(f, string(resultsJSON)) + return nil +} + +func exportGlScaResults(targetFile string, results *wrappers.ScanResultsCollection, summary *wrappers.ResultSummary) error { + log.Println("Creating Gl-sca Report: ", targetFile) + glScaResult := &wrappers.GlScaResultsCollection{ + Vulnerabilities: []wrappers.GlScaDepVulnerabilities{}, // Initialize arrays to prevent GitLab schema validation errors. + ScaDependencyFiles: []wrappers.ScaDependencyFile{}, + } + err := addScanToGlScaReport(summary, glScaResult) + if err != nil { + return errors.Wrapf(err, "%s: failed to denerate GL-Sca report ", failedListingResults) + } + convertCxResultToGlScaVulnerability(results, glScaResult) + convertCxResultToGlScaFiles(results, glScaResult) + resultsJSON, err := json.Marshal(glScaResult) + if err != nil { + return errors.Wrapf(err, "%s: failed to serialize GL-Sca report ", failedListingResults) + } + f, err := os.Create(targetFile) + if err != nil { + return errors.Wrapf(err, "%s: failed to create target file ", failedListingResults) + } + _, _ = fmt.Fprintln(f, string(resultsJSON)) + defer f.Close() + + return nil +} + +func addScanToGlScaReport(summary *wrappers.ResultSummary, glScaResult *wrappers.GlScaResultsCollection) error { + createdAt, err := time.Parse(summaryCreatedAtLayout, summary.CreatedAt) + if err != nil { + return err + } + + glScaResult.Schema = wrappers.ScaSchema + glScaResult.Version = wrappers.SchemaVersion + glScaResult.Scan.Analyzer.VendorGlSCA.VendorGlname = wrappers.AnalyzerScaID + glScaResult.Scan.Analyzer.Name = wrappers.AnalyzerScaID + glScaResult.Scan.Analyzer.Name = wrappers.AnalyzerScaID + glScaResult.Scan.Analyzer.ID = wrappers.ScannerID + glScaResult.Scan.Scanner.ID = wrappers.ScannerID + glScaResult.Scan.Scanner.Name = wrappers.AnalyzerScaID + glScaResult.Scan.Scanner.VendorGlSCA.VendorGlname = wrappers.AnalyzerScaID + glScaResult.Scan.Status = commonParams.Success + glScaResult.Scan.Type = wrappers.ScannerType + glScaResult.Scan.StartTime = createdAt.Format(glTimeFormat) + glScaResult.Scan.EndTime = createdAt.Format(glTimeFormat) + glScaResult.Scan.Scanner.Name = wrappers.AnalyzerScaID + glScaResult.Scan.Scanner.VersionGlSca = commonParams.Version + glScaResult.Scan.Analyzer.VersionGlSca = commonParams.Version + + return nil +} + +func addScanToGlSastReport(summary *wrappers.ResultSummary, glSast *wrappers.GlSastResultsCollection) error { + createdAt, err := time.Parse(summaryCreatedAtLayout, summary.CreatedAt) + if err != nil { + return err + } + + glSast.Scan = wrappers.ScanGlReport{} + glSast.Schema = wrappers.SastSchema + glSast.Version = wrappers.SastSchemaVersion + glSast.Scan.Analyzer.URL = wrappers.AnalyzerURL + glSast.Scan.Analyzer.Name = wrappers.VendorName + glSast.Scan.Analyzer.Vendor.Name = wrappers.VendorName + glSast.Scan.Analyzer.ID = wrappers.AnalyzerID + glSast.Scan.Scanner.ID = wrappers.AnalyzerID + glSast.Scan.Scanner.Name = wrappers.VendorName + glSast.Scan.Status = commonParams.Success + glSast.Scan.Type = commonParams.SastType + glSast.Scan.StartTime = createdAt.Format(glTimeFormat) + glSast.Scan.EndTime = createdAt.Format(glTimeFormat) + glSast.Scan.Scanner.Vendor.Name = wrappers.VendorName + glSast.Scan.Scanner.Version = commonParams.Version + glSast.Scan.Analyzer.Version = commonParams.Version + + return nil +} +func exportSonarResults(targetFile string, results *wrappers.ScanResultsCollection) error { + var err error + var resultsJSON []byte + log.Println("Creating SONAR Report: ", targetFile) + var sonarResults = convertCxResultsToSonar(results) + resultsJSON, err = json.Marshal(sonarResults) + if err != nil { + return errors.Wrapf(err, "%s: failed to serialize results response ", failedGettingAll) + } + f, err := os.Create(targetFile) + if err != nil { + return errors.Wrapf(err, "%s: failed to create target file ", failedGettingAll) + } + _, _ = fmt.Fprintln(f, string(resultsJSON)) + _ = f.Close() + return nil +} + +// Function to decode HTML entities in the ScanResultsCollection +func decodeHTMLEntitiesInResults(results *wrappers.ScanResultsCollection) { + for _, result := range results.Results { + result.Description = html.UnescapeString(result.Description) + result.DescriptionHTML = html.UnescapeString(result.DescriptionHTML) + for _, node := range result.ScanResultData.Nodes { + node.FullName = html.UnescapeString(node.FullName) + node.Name = html.UnescapeString(node.Name) + } + } +} + +func exportJSONResults(targetFile string, results *wrappers.ScanResultsCollection) error { + decodeHTMLEntitiesInResults(results) + var err error + var resultsJSON []byte + log.Println("Creating JSON Report: ", targetFile) + resultsJSON, err = json.Marshal(results) + if err != nil { + return errors.Wrapf(err, "%s: failed to serialize results response ", failedGettingAll) + } + f, err := os.Create(targetFile) + if err != nil { + return errors.Wrapf(err, "%s: failed to create target file ", failedGettingAll) + } + _, _ = fmt.Fprintln(f, string(resultsJSON)) + _ = f.Close() + return nil +} + +func exportJSONReportResults(jsonWrapper wrappers.ResultsJSONWrapper, summary *wrappers.ResultSummary, summaryRpt string, featureFlagsWrapper wrappers.FeatureFlagsWrapper) error { + jsonReportsPayload := &wrappers.JSONReportsPayload{} + pollingResp := &wrappers.JSONPollingResponse{} + jsonReportsPayload.ReportName = reportNameImprovedScanReport + + jsonOptionsSections, jsonOptionsEngines := parseJSONOptions(summary.EnginesEnabled, jsonReportsPayload.ReportName) + + jsonReportsPayload.ReportType = CliType + jsonReportsPayload.FileFormat = printer.FormatJSON + jsonReportsPayload.Data.ScanID = summary.ScanID + jsonReportsPayload.Data.ProjectID = summary.ProjectID + jsonReportsPayload.Data.BranchName = summary.BranchName + jsonReportsPayload.Data.Scanners = jsonOptionsEngines + jsonReportsPayload.Data.Sections = jsonOptionsSections + + jsonReportID, webErr, err := jsonWrapper.GenerateJSONReport(jsonReportsPayload) + if webErr != nil { + return errors.Errorf("Error generating JSON report - %s", webErr.Message) + } + if err != nil { + return errors.Errorf("Error generating JSON report - %s", err.Error()) + } + log.Println("Generating JSON report") + pollingResp.Status = startedStatus + for pollingResp.Status == startedStatus || pollingResp.Status == requestedStatus { + pollingResp, webErr, err = jsonWrapper.CheckJSONReportStatus(jsonReportID.ReportID) + if err != nil || webErr != nil { + return errors.Wrapf(err, "%v", webErr) + } + logger.PrintfIfVerbose("JSON report status: %s", pollingResp.Status) + time.Sleep(delayValueForReport * time.Millisecond) + } + if pollingResp.Status != completedStatus { + return errors.Errorf("JSON generating failed - Current status: %s", pollingResp.Status) + } + + minioEnabled, _ := wrappers.GetSpecificFeatureFlag(featureFlagsWrapper, wrappers.MinioEnabled) + infoPathType := "" + if minioEnabled.Status { + infoPathType = jsonReportID.ReportID + } else { + infoPathType = pollingResp.URL + } + err = jsonWrapper.DownloadJSONReport(infoPathType, summaryRpt, minioEnabled.Status) + if err != nil { + return errors.Wrapf(err, "%s", "Failed downloading JSON report") + } + return nil +} + +func parseJSONOptions(enabledEngines []string, reportName string) (jsonOptionsSections, jsonOptionsEngines []string) { + jsonOptionsSections = []string{ + "ScanSummary", + "ExecutiveSummary", + "ScanResults", + } + + var jsonOptionsEnginesMap = map[string]string{ + commonParams.ScaType: "SCA", + commonParams.SastType: "SAST", + commonParams.KicsType: "KICS", + commonParams.IacType: "KICS", + commonParams.ContainersType: "Containers", + commonParams.ScsType: "Microengines", + } + if jsonOptionsEngines == nil { + for _, engine := range enabledEngines { + if jsonOptionsEnginesMap[engine] != "" { + jsonOptionsEngines = append(jsonOptionsEngines, jsonOptionsEnginesMap[engine]) + } + } + } + + if reportName == reportNameImprovedScanReport { + jsonOptionsSections = translateReportSectionsForImproved(jsonOptionsSections) + } + + return jsonOptionsSections, jsonOptionsEngines +} + +func exportJSONSummaryResults(targetFile string, results *wrappers.ResultSummary) error { + var err error + var resultsJSON []byte + log.Println("Creating summary JSON Report: ", targetFile) + resultsJSON, err = json.Marshal(results) + if err != nil { + return errors.Wrapf(err, "%s: failed to serialize results response ", failedGettingAll) + } + f, err := os.Create(targetFile) + if err != nil { + return errors.Wrapf(err, "%s: failed to create target file ", failedGettingAll) + } + _, _ = fmt.Fprintln(f, string(resultsJSON)) + _ = f.Close() + return nil +} + +func exportPdfResults(pdfWrapper wrappers.ResultsPdfWrapper, summary *wrappers.ResultSummary, summaryRpt, formatPdfToEmail, + pdfOptions string, featureFlagsWrapper wrappers.FeatureFlagsWrapper) error { + pdfReportsPayload := &wrappers.PdfReportsPayload{} + pollingResp := &wrappers.PdfPollingResponse{} + pdfReportsPayload.ReportName = reportNameImprovedScanReport + pdfOptionsSections, pdfOptionsEngines, err := parsePDFOptions(pdfOptions, summary.EnginesEnabled, pdfReportsPayload.ReportName) + if err != nil { + return err + } + pdfReportsPayload.ReportType = CliType + pdfReportsPayload.FileFormat = printer.FormatPDF + pdfReportsPayload.Data.ScanID = summary.ScanID + pdfReportsPayload.Data.ProjectID = summary.ProjectID + pdfReportsPayload.Data.BranchName = summary.BranchName + pdfReportsPayload.Data.Scanners = pdfOptionsEngines + pdfReportsPayload.Data.Sections = pdfOptionsSections + + // will generate pdf report and send it to the email list + // instead of saving it to the file system + if len(formatPdfToEmail) > 0 { + emailList, validateErr := validateEmails(formatPdfToEmail) + if validateErr != nil { + return validateErr + } + pdfReportsPayload.ReportType = reportTypeEmail + pdfReportsPayload.Data.Email = emailList + } + pdfReportID, webErr, err := pdfWrapper.GeneratePdfReport(pdfReportsPayload) + if webErr != nil { + return errors.Errorf("Error generating PDF report - %s", webErr.Message) + } + if err != nil { + return errors.Errorf("Error generating PDF report - %s", err.Error()) + } + if pdfReportsPayload.ReportType == reportTypeEmail { + log.Println("Sending PDF report to: ", pdfReportsPayload.Data.Email) + return nil + } + log.Println("Generating PDF report") + pollingResp.Status = startedStatus + for pollingResp.Status == startedStatus || pollingResp.Status == requestedStatus { + pollingResp, webErr, err = pdfWrapper.CheckPdfReportStatus(pdfReportID.ReportID) + if err != nil || webErr != nil { + return errors.Wrapf(err, "%v", webErr) + } + logger.PrintfIfVerbose("PDF report status: %s", pollingResp.Status) + time.Sleep(delayValueForReport * time.Millisecond) + } + if pollingResp.Status != completedStatus { + return errors.Errorf("PDF generating failed - Current status: %s", pollingResp.Status) + } + + minioEnabled, _ := wrappers.GetSpecificFeatureFlag(featureFlagsWrapper, wrappers.MinioEnabled) + infoPathType := "" + if minioEnabled.Status { + infoPathType = pdfReportID.ReportID + } else { + infoPathType = pollingResp.URL + } + err = pdfWrapper.DownloadPdfReport(infoPathType, summaryRpt, minioEnabled.Status) + if err != nil { + return errors.Wrapf(err, "%s", "Failed downloading PDF report") + } + return nil +} + +func parsePDFOptions(pdfOptions string, enabledEngines []string, reportName string) (pdfOptionsSections, pdfOptionsEngines []string, err error) { + var pdfOptionsSectionsMap = map[string]string{ + "scansummary": "ScanSummary", + "executivesummary": "ExecutiveSummary", + "scanresults": "ScanResults", + } + + var pdfOptionsEnginesMap = map[string]string{ + commonParams.ScaType: "SCA", + commonParams.SastType: "SAST", + commonParams.KicsType: "KICS", + commonParams.IacType: "KICS", + } + + pdfOptions = strings.ToLower(strings.ReplaceAll(pdfOptions, " ", "")) + options := strings.Split(strings.ReplaceAll(pdfOptions, "\n", ""), ",") + for _, s := range options { + if pdfOptionsEnginesMap[s] != "" { + pdfOptionsEngines = append(pdfOptionsEngines, pdfOptionsEnginesMap[s]) + } else if pdfOptionsSectionsMap[s] != "" { + pdfOptionsSections = append(pdfOptionsSections, pdfOptionsSectionsMap[s]) + } else { + return nil, nil, errors.Errorf("report option \"%s\" unavailable", s) + } + } + if pdfOptionsEngines == nil { + for _, engine := range enabledEngines { + if pdfOptionsEnginesMap[engine] != "" { + pdfOptionsEngines = append(pdfOptionsEngines, pdfOptionsEnginesMap[engine]) + } + } + } + + if reportName == reportNameImprovedScanReport { + pdfOptionsSections = translateReportSectionsForImproved(pdfOptionsSections) + } + + return pdfOptionsSections, pdfOptionsEngines, nil +} + +func translateReportSectionsForImproved(sections []string) []string { + var resultSections = make([]string, 0) + + var pdfOptionsSectionsImprovedTranslation = map[string][]string{ + "ScanSummary": {"scan-information"}, + "ExecutiveSummary": {"results-overview"}, + "ScanResults": {"scan-results", "categories", "resolved-results", "vulnerability-details"}, + } + + for _, section := range sections { + if translatedSections := pdfOptionsSectionsImprovedTranslation[section]; translatedSections != nil { + resultSections = append(resultSections, translatedSections...) + } + } + + return resultSections +} + +func convertCxResultsToSarif(results *wrappers.ScanResultsCollection) *wrappers.SarifResultsCollection { + var sarif = new(wrappers.SarifResultsCollection) + sarif.Schema = "https://raw.githubusercontent.com/oasis-tcs/sarif-spec/master/Schemata/sarif-schema-2.1.0.json" + sarif.Version = "2.1.0" + sarif.Runs = []wrappers.SarifRun{} + sarif.Runs = append(sarif.Runs, createSarifRun(results)) + return sarif +} + +func convertCxResultToGlSastVulnerability(results *wrappers.ScanResultsCollection, glSast *wrappers.GlSastResultsCollection, summary *wrappers.ResultSummary) { + for _, result := range results.Results { + if strings.TrimSpace(result.Type) == commonParams.SastType { + glSast = parseGlSastVulnerability(result, glSast, summary) + } + } +} + +func convertCxResultToGlScaVulnerability(results *wrappers.ScanResultsCollection, glScaResult *wrappers.GlScaResultsCollection) { + for _, result := range results.Results { + if strings.TrimSpace(result.Type) == commonParams.ScaType { + glScaResult = parseGlscaVulnerability(result, glScaResult) + } + } +} + +func convertCxResultToGlScaFiles(results *wrappers.ScanResultsCollection, glScaResult *wrappers.GlScaResultsCollection) { + for _, result := range results.Results { + if strings.TrimSpace(result.Type) == commonParams.ScaType { + glScaResult = parseGlScaFiles(result, glScaResult) + } + } +} +func parseGlSastVulnerability(result *wrappers.ScanResult, glSast *wrappers.GlSastResultsCollection, summary *wrappers.ResultSummary) *wrappers.GlSastResultsCollection { + hostName := parseURI(summary.BaseURI) + + queryName := result.ScanResultData.QueryName + fileName := result.ScanResultData.Nodes[0].FileName + lineNumber := strconv.FormatUint(uint64(result.ScanResultData.Nodes[0].Line), 10) + startLine := result.ScanResultData.Nodes[0].Line + endLine := result.ScanResultData.Nodes[0].Line + result.ScanResultData.Nodes[0].Length + ID := fmt.Sprintf("%s:%s:%s", queryName, fileName, lineNumber) + category := fmt.Sprintf("%s-%s", wrappers.VendorName, result.Type) + message := fmt.Sprintf("%s@%s:%s", queryName, fileName, lineNumber) + QueryDescriptionLink := fmt.Sprintf("%s/results/%s/%s/sast/description/%s/%s", hostName, summary.ScanID, summary.ProjectID, result.VulnerabilityDetails.CweID, result.ScanResultData.QueryID) + + glSast.Vulnerabilities = append(glSast.Vulnerabilities, wrappers.GlVulnerabilities{ + ID: ID, + Category: category, + Name: queryName, + Message: message, + Description: result.Description + " \n" + QueryDescriptionLink, + CVE: ID, + Severity: cases.Title(language.English).String(result.Severity), + Confidence: cases.Title(language.English).String(result.Severity), + Solution: "", + + Scanner: wrappers.GlScanner{ + ID: category, + Name: category, + }, + Identifiers: []wrappers.Identifier{ + { + Type: "cxOneScan", + Name: "CxOne Scan", + URL: summary.BaseURI, + Value: result.ID, + }, + }, + Links: make([]string, 0), + Tracking: wrappers.Tracking{ + Type: "source", + Items: []wrappers.Item{ + { + Signatures: []wrappers.Signature{{Algorithm: result.Type + "-Algorithm ", Value: "NA"}}, + File: fileName, + EndLine: endLine, + StartLine: startLine, + }, + }, + }, + Flags: make([]wrappers.Flag, 0), + Location: wrappers.Location{ + File: fileName, + StartLine: startLine, + EndLine: endLine, + }, + }) + return glSast +} +func parseGlscaVulnerability(result *wrappers.ScanResult, glDependencyResult *wrappers.GlScaResultsCollection) *wrappers.GlScaResultsCollection { + if result.ScanResultData.ScaPackageCollection != nil { + glDependencyResult.Vulnerabilities = append(glDependencyResult.Vulnerabilities, wrappers.GlScaDepVulnerabilities{ + ID: result.ID, + Name: result.VulnerabilityDetails.CveName, + Description: result.Description, + Severity: cases.Title(language.English).String(result.Severity), + Solution: result.ScanResultData.RecommendedVersion, + Identifiers: collectScaPackageData(result), + Links: collectScaPackageLinks(result), + TrackingDep: wrappers.TrackingDep{ + Items: collectScaPackageItemsDep(result), + }, + Flags: make([]string, 0), + LocationDep: wrappers.GlScaDepVulnerabilityLocation{ + File: parseGlDependencyLocation(result), + Dependency: wrappers.ScaDependencyLocation{ + Package: wrappers.PackageName{Name: result.ScanResultData.PackageIdentifier}, + ScaDependencyLocationVersion: "", + Direct: result.ScanResultData.ScaPackageCollection.IsDirectDependency, + ScaDependencyPath: result.ScanResultData.Line, + }, + }, + }) + } + return glDependencyResult +} +func parseGlDependencyLocation(result *wrappers.ScanResult) string { + var location string + if result != nil && result.ScanResultData.ScaPackageCollection != nil && result.ScanResultData.ScaPackageCollection.Locations != nil { + location = *result.ScanResultData.ScaPackageCollection.Locations[0] + } else { + location = "" + } + return location +} +func parseGlScaFiles(result *wrappers.ScanResult, glScaResult *wrappers.GlScaResultsCollection) *wrappers.GlScaResultsCollection { + if result.ScanResultData.ScaPackageCollection != nil && result.ScanResultData.ScaPackageCollection.Locations != nil { + glScaResult.ScaDependencyFiles = append(glScaResult.ScaDependencyFiles, wrappers.ScaDependencyFile{ + Path: *result.ScanResultData.ScaPackageCollection.Locations[0], + PackageManager: result.ScanResultData.ScaPackageCollection.ID, + Dependencies: collectScaFileLocations(result), + }) + } + return glScaResult +} +func collectScaFileLocations(result *wrappers.ScanResult) []wrappers.ScaDependencyLocation { + allScaIdentifierLocations := []wrappers.ScaDependencyLocation{} + for _, packageInfo := range result.ScanResultData.PackageData { + allScaIdentifierLocations = append(allScaIdentifierLocations, wrappers.ScaDependencyLocation{ + Package: wrappers.PackageName{ + Name: packageInfo.Type, + }, + ScaDependencyLocationVersion: packageInfo.URL, + Direct: true, + ScaDependencyPath: result.ScanResultData.Line, + }) + } + return allScaIdentifierLocations +} +func collectScaPackageItemsDep(result *wrappers.ScanResult) []wrappers.ItemDep { + allScaPackageItemDep := []wrappers.ItemDep{} + allScaPackageItemDep = append(allScaPackageItemDep, wrappers.ItemDep{ + Signature: []wrappers.SignatureDep{{Algorithm: "SCA-Algorithm ", Value: "NA"}}, + File: result.VulnerabilityDetails.CveName, + EndLine: 0, + StartLine: 0, + }) + return allScaPackageItemDep +} +func collectScaPackageLinks(result *wrappers.ScanResult) []wrappers.LinkDep { + allScaPackageLinks := []wrappers.LinkDep{} + for _, packageInfo := range result.ScanResultData.PackageData { + allScaPackageLinks = append(allScaPackageLinks, wrappers.LinkDep{ + Name: packageInfo.Type, + URL: packageInfo.URL, + }) + } + return allScaPackageLinks +} +func collectScaPackageData(result *wrappers.ScanResult) []wrappers.IdentifierDep { + allIdentifierDep := []wrappers.IdentifierDep{} + for _, packageInfo := range result.ScanResultData.PackageData { + allIdentifierDep = append(allIdentifierDep, wrappers.IdentifierDep{ + Type: packageInfo.Type, + Value: packageInfo.URL, + Name: packageInfo.URL, + }) + } + return allIdentifierDep +} + +func convertCxResultsToSonar(results *wrappers.ScanResultsCollection) *wrappers.ScanResultsSonar { + var sonar = new(wrappers.ScanResultsSonar) + sonar.Issues, sonar.Rules = parseSonar(results) + return sonar +} + +func createSarifRun(results *wrappers.ScanResultsCollection) wrappers.SarifRun { + var sarifRun wrappers.SarifRun + sarifRun.Tool.Driver.Name = wrappers.SarifName + sarifRun.Tool.Driver.Version = wrappers.SarifVersion + sarifRun.Tool.Driver.InformationURI = wrappers.SarifInformationURI + sarifRun.Tool.Driver.Rules, sarifRun.Results = parseResults(results) + return sarifRun +} + +func parseResults(results *wrappers.ScanResultsCollection) ([]wrappers.SarifDriverRule, []wrappers.SarifScanResult) { + var sarifRules = make([]wrappers.SarifDriverRule, 0) + var sarifResults = make([]wrappers.SarifScanResult, 0) + if results != nil { + ruleIds := map[interface{}]bool{} + for _, result := range results.Results { + if rule := findRule(ruleIds, result); rule != nil { + sarifRules = append(sarifRules, *rule) + } + if sarifResult := findResult(result); sarifResult != nil { + sarifResults = append(sarifResults, sarifResult...) + } + } + } + return sarifRules, sarifResults +} + +func parseSonar(results *wrappers.ScanResultsCollection) ([]wrappers.SonarIssues, []wrappers.SonarRules) { + var sonarIssues []wrappers.SonarIssues + var sonarRules []wrappers.SonarRules + seenRuleIDs := make(map[string]bool) // Track already added rule IDs + + if results != nil { + for _, result := range results.Results { + var auxRules = initSonarRules(result) + var auxIssue = initSonarIssue(result) + + if !seenRuleIDs[auxRules.ID] { + sonarRules = append(sonarRules, auxRules) + seenRuleIDs[auxRules.ID] = true + } + + engineType := strings.TrimSpace(result.Type) + + if engineType == commonParams.SastType { + auxIssue.PrimaryLocation = parseSonarPrimaryLocation(result) + auxIssue.SecondaryLocations = parseSonarSecondaryLocations(result) + sonarIssues = append(sonarIssues, auxIssue) + } else if engineType == commonParams.KicsType { + auxIssue.PrimaryLocation = parseLocationKics(result) + sonarIssues = append(sonarIssues, auxIssue) + } else if engineType == commonParams.ScaType { + sonarIssuesByLocation := parseScaSonarLocations(result) + sonarIssues = append(sonarIssues, sonarIssuesByLocation...) + } else if wrappers.IsContainersEnabled && engineType == commonParams.ContainersType { + auxIssue.PrimaryLocation = parseContainersSonar(result) + sonarIssues = append(sonarIssues, auxIssue) + } else if strings.HasPrefix(engineType, commonParams.SscsType) { + sscsSonarIssue := parseSscsSonar(result, &auxIssue) + sonarIssues = append(sonarIssues, sscsSonarIssue) + } + } + } + return sonarIssues, sonarRules +} + +func parseContainersSonar(result *wrappers.ScanResult) wrappers.SonarLocation { + var auxLocation wrappers.SonarLocation + auxLocation.FilePath = result.ScanResultData.ImageFilePath + auxLocation.Message = html.UnescapeString(result.Description) + var textRange wrappers.SonarTextRange + textRange.StartColumn = 1 + textRange.EndColumn = 2 + textRange.StartLine = 1 + textRange.EndLine = 2 + auxLocation.TextRange = textRange + return auxLocation +} + +func parseSscsSonar(result *wrappers.ScanResult, sonarIssue *wrappers.SonarIssues) wrappers.SonarIssues { + sonarIssue.PrimaryLocation.FilePath = result.ScanResultData.Filename + + sonarIssue.PrimaryLocation.Message = html.UnescapeString(result.ScanResultData.Remediation) + var textRange wrappers.SonarTextRange + textRange.StartColumn = 1 + textRange.EndColumn = 2 + textRange.StartLine = result.ScanResultData.Line + sonarIssue.PrimaryLocation.TextRange = textRange + return *sonarIssue +} + +func initSonarIssue(result *wrappers.ScanResult) wrappers.SonarIssues { + var sonarIssue wrappers.SonarIssues + engineType := strings.TrimSpace(result.Type) + if engineType == commonParams.SastType { + sonarIssue.RuleID = result.ScanResultData.LanguageName + " - " + result.ScanResultData.QueryName + } else if engineType == commonParams.KicsType { + sonarIssue.RuleID = result.ScanResultData.QueryName + } else if engineType == commonParams.ScaType { + sonarIssue.RuleID = result.ID + } else if wrappers.IsContainersEnabled && engineType == commonParams.ContainersType { + sonarIssue.RuleID = result.ID + } else if strings.HasPrefix(engineType, commonParams.SscsType) { + sonarIssue.RuleID = result.ID + } + + sonarIssue.PrimaryLocation.Message = html.UnescapeString(result.Description) + sonarIssue.EffortMinutes = 0 + + return sonarIssue +} + +func initSonarRules(result *wrappers.ScanResult) wrappers.SonarRules { + var sonarRules wrappers.SonarRules + var sonarImpacts wrappers.SonarImpacts + + sonarImpacts.Severity = sonarSeverities[result.Severity] + sonarImpacts.SoftwareQuality = vulnerabilitySonar + + sonarRules.EngineID = result.Type + sonarRules.CleanCodeAttribute = cleanCodeAttribute + + engineType := strings.TrimSpace(result.Type) + if engineType == commonParams.SastType { + sonarRules.Name = result.ScanResultData.QueryName + sonarRules.Description = html.UnescapeString(result.Description) + sonarRules.ID = result.ScanResultData.LanguageName + " - " + result.ScanResultData.QueryName + } else if engineType == commonParams.KicsType { + sonarRules.Name = result.ScanResultData.QueryName + sonarRules.Description = html.UnescapeString(result.Description) + sonarRules.ID = result.ScanResultData.QueryName + } else if engineType == commonParams.ScaType { + sonarRules.Name = result.ScanResultData.PackageIdentifier + sonarRules.Description = html.UnescapeString(result.Description) + sonarRules.ID = result.ID + } else if wrappers.IsContainersEnabled && engineType == commonParams.ContainersType { + sonarRules.Name = result.ScanResultData.ImageTag + sonarRules.Description = html.UnescapeString(result.Description) + sonarRules.ID = result.ID + } else if strings.HasPrefix(engineType, commonParams.SscsType) { + sonarRules.Name = result.ScanResultData.RuleName + sonarRules.Description = html.UnescapeString(result.ScanResultData.RuleDescription) + sonarRules.ID = result.ID + } + + sonarRules.Impacts = []wrappers.SonarImpacts{sonarImpacts} + + return sonarRules +} + +func parseScaSonarLocations(result *wrappers.ScanResult) []wrappers.SonarIssues { + if result == nil || result.ScanResultData.ScaPackageCollection == nil || result.ScanResultData.ScaPackageCollection.Locations == nil { + return []wrappers.SonarIssues{} + } + + var issuesByLocation []wrappers.SonarIssues + + for _, location := range result.ScanResultData.ScaPackageCollection.Locations { + issueByLocation := initSonarIssue(result) + + var primaryLocation wrappers.SonarLocation + + primaryLocation.FilePath = *location + _, _, primaryLocation.Message = findRuleID(result) + + var textRange wrappers.SonarTextRange + textRange.StartColumn = 1 + textRange.EndColumn = 2 + textRange.StartLine = 1 + textRange.EndLine = 2 + + primaryLocation.TextRange = textRange + + issueByLocation.PrimaryLocation = primaryLocation + + issuesByLocation = append(issuesByLocation, issueByLocation) + } + + return issuesByLocation +} + +func parseLocationKics(results *wrappers.ScanResult) wrappers.SonarLocation { + var auxLocation wrappers.SonarLocation + auxLocation.FilePath = strings.TrimLeft(results.ScanResultData.Filename, "/") + auxLocation.Message = html.UnescapeString(results.ScanResultData.Value) + var auxTextRange wrappers.SonarTextRange + auxTextRange.StartLine = results.ScanResultData.Line + auxTextRange.StartColumn = 0 + auxTextRange.EndColumn = 1 + auxLocation.TextRange = auxTextRange + return auxLocation +} + +func parseSonarPrimaryLocation(results *wrappers.ScanResult) wrappers.SonarLocation { + var auxLocation wrappers.SonarLocation + // fill the details in the primary Location + if len(results.ScanResultData.Nodes) > 0 { + auxLocation.FilePath = strings.TrimLeft(results.ScanResultData.Nodes[0].FileName, "/") + auxLocation.Message = html.UnescapeString(strings.ReplaceAll(results.ScanResultData.QueryName, "_", " ")) + auxLocation.TextRange = parseSonarTextRange(results.ScanResultData.Nodes[0]) + } + return auxLocation +} + +func parseSonarSecondaryLocations(results *wrappers.ScanResult) []wrappers.SonarLocation { + var auxSecondaryLocations []wrappers.SonarLocation + // Traverse all the rest of the scan result nodes into secondary location of sonar + if len(results.ScanResultData.Nodes) >= 1 { + for _, node := range results.ScanResultData.Nodes[1:] { + var auxSecondaryLocation wrappers.SonarLocation + auxSecondaryLocation.FilePath = strings.TrimLeft(node.FileName, "/") + auxSecondaryLocation.Message = html.UnescapeString(strings.ReplaceAll(results.ScanResultData.QueryName, "_", " ")) + auxSecondaryLocation.TextRange = parseSonarTextRange(node) + auxSecondaryLocations = append(auxSecondaryLocations, auxSecondaryLocation) + } + } + return auxSecondaryLocations +} + +func parseSonarTextRange(results *wrappers.ScanResultNode) wrappers.SonarTextRange { + var auxTextRange wrappers.SonarTextRange + auxTextRange.StartLine = results.Line + startColumn := getSastStartColumn(results.Column) + + auxTextRange.StartColumn = startColumn + auxTextRange.EndColumn = startColumn + results.Length + + if auxTextRange.StartColumn == auxTextRange.EndColumn { + auxTextRange.EndColumn++ + } + + return auxTextRange +} + +func findRule(ruleIds map[interface{}]bool, result *wrappers.ScanResult) *wrappers.SarifDriverRule { + var sarifRule wrappers.SarifDriverRule + sarifRule.ID, sarifRule.Name, _ = findRuleID(result) + sarifRule.FullDescription = findFullDescription(result) + sarifRule.Help = findHelp(result) + sarifRule.HelpURI = findHelpURI(result) + sarifRule.Properties = findProperties(result) + + if !ruleIds[sarifRule.ID] { + ruleIds[sarifRule.ID] = true + return &sarifRule + } + + return nil +} + +func getSastStartColumn(column uint) uint { + if column == 0 { + return 0 + } + return column - 1 +} + +func findRuleID(result *wrappers.ScanResult) (ruleID, ruleName, shortMessage string) { + caser := cases.Title(language.English) + + if result.ScanResultData.QueryID == nil && result.ScanResultData.RuleID == nil { + return fmt.Sprintf("%s (%s)", result.ID, result.Type), + caser.String(strings.ToLower(strings.ReplaceAll(result.ID, "-", ""))), + html.UnescapeString(fmt.Sprintf("%s (%s)", result.ScanResultData.PackageIdentifier, result.ID)) + } + + if result.ScanResultData.RuleID != nil { + ruleName = strings.ReplaceAll(result.ScanResultData.RuleName, "_", " ") + return fmt.Sprintf("%s - %s (%s)", ruleName, *result.ScanResultData.RuleID, result.Type), + ruleName, + ruleName + } + + ruleName = strings.ReplaceAll(result.ScanResultData.QueryName, "_", " ") + return fmt.Sprintf("%v - %s (%s)", ruleName, result.ScanResultData.QueryID, result.Type), + ruleName, + ruleName +} + +func findFullDescription(result *wrappers.ScanResult) wrappers.SarifDescription { + var sarifDescription wrappers.SarifDescription + sarifDescription.Text = findDescriptionText(result) + return sarifDescription +} + +func findHelp(result *wrappers.ScanResult) wrappers.SarifHelp { + var sarifHelp wrappers.SarifHelp + sarifHelp.Text = findHelpText(result) + sarifHelp.Markdown = findHelpMarkdownText(result) + + return sarifHelp +} + +func findHelpURI(result *wrappers.ScanResult) string { + if strings.HasPrefix(result.Type, commonParams.SscsType) { + if result.ScanResultData.RemediationLink != "" { + return result.ScanResultData.RemediationLink + } + } + + return wrappers.SarifInformationURI +} + +func findDescriptionText(result *wrappers.ScanResult) string { + if result.Type == commonParams.KicsType { + return fmt.Sprintf( + "%s Value: %s Excepted value: %s", + result.Description, result.ScanResultData.Value, result.ScanResultData.ExpectedValue, + ) + } else if strings.HasPrefix(result.Type, commonParams.SscsType) { + return result.ScanResultData.RuleDescription + } + + return result.Description +} + +func findHelpText(result *wrappers.ScanResult) string { + if strings.HasPrefix(result.Type, commonParams.SscsType) { + return findHelpMarkdownText(result) + } + + return findDescriptionText(result) +} + +func findHelpMarkdownText(result *wrappers.ScanResult) string { + if result.Type == commonParams.KicsType { + return fmt.Sprintf( + "%s

Value: %s
Excepted value: %s", + result.Description, result.ScanResultData.Value, result.ScanResultData.ExpectedValue, + ) + } else if strings.HasPrefix(result.Type, commonParams.SscsType) { + return result.ScanResultData.Remediation + } + + return result.Description +} + +func findProperties(result *wrappers.ScanResult) wrappers.SarifProperties { + var sarifProperties wrappers.SarifProperties + sarifProperties.ID, sarifProperties.Name, _ = findRuleID(result) + sarifProperties.Description = findDescriptionText(result) + sarifProperties.SecuritySeverity = securities[result.Severity] + sarifProperties.Tags = []string{"security", "checkmarx", result.Type} + return sarifProperties +} + +func findSarifLevel(result *wrappers.ScanResult) string { + level := map[string]string{ + infoCx: infoLowSarif, + lowCx: infoLowSarif, + mediumCx: mediumSarif, + highCx: highSarif, + criticalCx: highSarif, + } + return level[result.Severity] +} + +func initSarifResult(result *wrappers.ScanResult) wrappers.SarifScanResult { + var scanResult wrappers.SarifScanResult + scanResult.RuleID, _, scanResult.Message.Text = findRuleID(result) + scanResult.Level = findSarifLevel(result) + scanResult.Locations = []wrappers.SarifLocation{} + + return scanResult +} + +func findResult(result *wrappers.ScanResult) []wrappers.SarifScanResult { + var scanResults []wrappers.SarifScanResult + + if len(result.ScanResultData.Nodes) > 0 { + scanResults = parseSarifResultSast(result, scanResults) + } else if result.Type == commonParams.KicsType { + scanResults = parseSarifResultKics(result, scanResults) + } else if result.Type == commonParams.ScaType { + scanResults = parseSarifResultsSca(result, scanResults) + } else if result.Type == commonParams.ContainersType && wrappers.IsContainersEnabled { + scanResults = parseSarifResultsContainers(result, scanResults) + } else if strings.HasPrefix(result.Type, commonParams.SscsType) { + scanResults = parseSarifResultsSscs(result, scanResults) + } + + if len(scanResults) > 0 { + return scanResults + } + return nil +} + +func parseSarifResultsContainers(result *wrappers.ScanResult, scanResults []wrappers.SarifScanResult) []wrappers.SarifScanResult { + var scanResult = initSarifResult(result) + var scanLocation wrappers.SarifLocation + + scanLocation.PhysicalLocation.ArtifactLocation.URI = result.ScanResultData.ImageFilePath + scanLocation.PhysicalLocation.Region = &wrappers.SarifRegion{} + scanLocation.PhysicalLocation.Region.StartLine = 1 + scanLocation.PhysicalLocation.Region.StartColumn = 1 + scanLocation.PhysicalLocation.Region.EndColumn = 2 + scanResult.Locations = append(scanResult.Locations, scanLocation) + + scanResults = append(scanResults, scanResult) + return scanResults +} + +func parseSarifResultsSca(result *wrappers.ScanResult, scanResults []wrappers.SarifScanResult) []wrappers.SarifScanResult { + if result == nil || result.ScanResultData.ScaPackageCollection == nil || result.ScanResultData.ScaPackageCollection.Locations == nil { + return scanResults + } + for _, location := range result.ScanResultData.ScaPackageCollection.Locations { + var scanResult = initSarifResult(result) + + var scanLocation wrappers.SarifLocation + scanLocation.PhysicalLocation.ArtifactLocation.URI = *location + scanLocation.PhysicalLocation.Region = &wrappers.SarifRegion{} + scanLocation.PhysicalLocation.Region.StartLine = 1 + scanLocation.PhysicalLocation.Region.StartColumn = 1 + scanLocation.PhysicalLocation.Region.EndColumn = 2 + scanResult.Locations = append(scanResult.Locations, scanLocation) + + scanResults = append(scanResults, scanResult) + } + return scanResults +} + +func parseSarifResultKics(result *wrappers.ScanResult, scanResults []wrappers.SarifScanResult) []wrappers.SarifScanResult { + var scanResult = initSarifResult(result) + var scanLocation wrappers.SarifLocation + + scanLocation.PhysicalLocation.ArtifactLocation.URI = strings.Replace( + result.ScanResultData.Filename, + "/", + "", + 1, + ) + scanLocation.PhysicalLocation.Region = &wrappers.SarifRegion{} + scanLocation.PhysicalLocation.Region.StartLine = result.ScanResultData.Line + scanLocation.PhysicalLocation.Region.StartColumn = 1 + scanLocation.PhysicalLocation.Region.EndColumn = 2 + scanResult.Locations = append(scanResult.Locations, scanLocation) + + scanResults = append(scanResults, scanResult) + return scanResults +} + +func parseSarifResultSast(result *wrappers.ScanResult, scanResults []wrappers.SarifScanResult) []wrappers.SarifScanResult { + if result == nil || result.ScanResultData.Nodes == nil { + return scanResults + } + var scanResult = initSarifResult(result) + + var allLocations []wrappers.SarifLocation + for _, node := range result.ScanResultData.Nodes { + var scanLocation wrappers.SarifLocation + if len(node.FileName) >= sarifNodeFileLength { + scanLocation.PhysicalLocation.ArtifactLocation.URI = node.FileName[1:] + if node.Line <= 0 { + continue + } + scanLocation.PhysicalLocation.Region = &wrappers.SarifRegion{} + scanLocation.PhysicalLocation.Region.StartLine = node.Line + column := node.Column + length := node.Length + scanLocation.PhysicalLocation.Region.StartColumn = column + scanLocation.PhysicalLocation.Region.EndColumn = column + length + + allLocations = append(allLocations, scanLocation) + } + } + + if len(allLocations) > 0 { + var threadFlowLocations []wrappers.SarifThreadFlowLocation + for _, loc := range allLocations { + threadFlowLocations = append(threadFlowLocations, wrappers.SarifThreadFlowLocation{Location: loc}) + } + scanResult.CodeFlows = []wrappers.SarifCodeFlow{ + { + ThreadFlows: []wrappers.SarifThreadFlow{ + { + Locations: threadFlowLocations, + }, + }, + }, + } + } + + scanResults = append(scanResults, scanResult) + return scanResults +} + +func parseSarifResultsSscs(result *wrappers.ScanResult, scanResults []wrappers.SarifScanResult) []wrappers.SarifScanResult { + var scanResult = initSarifResult(result) + scanResult.Message.Text = result.Description + + var scanLocation wrappers.SarifLocation + + trimOsSeparatorFromFileName(result) + if result.Type == commonParams.SCSScorecardType && result.ScanResultData.Filename == noFileForScorecardResultString { + scanLocation.PhysicalLocation.ArtifactLocation.URI = artifactLocationURIString + scanLocation.PhysicalLocation.ArtifactLocation.Description = &wrappers.SarifMessage{} + scanLocation.PhysicalLocation.ArtifactLocation.Description.Text = result.ScanResultData.Filename + } else { + scanLocation.PhysicalLocation.ArtifactLocation.URI = result.ScanResultData.Filename + } + + scanLocation.PhysicalLocation.Region = &wrappers.SarifRegion{} + scanLocation.PhysicalLocation.Region.StartLine = result.ScanResultData.Line + scanLocation.PhysicalLocation.Region.StartColumn = 1 + scanLocation.PhysicalLocation.Region.EndColumn = 2 + if result.ScanResultData.Snippet != "" { + scanLocation.PhysicalLocation.Region.Snippet = &wrappers.SarifSnippet{} + scanLocation.PhysicalLocation.Region.Snippet.Text = result.ScanResultData.Snippet + } + + scanResult.Locations = append(scanResult.Locations, scanLocation) + + var properties wrappers.SarifResultProperties + properties.Severity = result.Severity + properties.Validity = result.ScanResultData.Validity + properties.IsInSource = result.ScanResultData.IsInSource + properties.CommitURL = result.ScanResultData.CommitURL + scanResult.Properties = &properties + + scanResults = append(scanResults, scanResult) + return scanResults +} + +func convertNotAvailableNumberToZero(summary *wrappers.ResultSummary) { + if summary.KicsIssues == notAvailableNumber { + summary.KicsIssues = 0 + } else if summary.SastIssues == notAvailableNumber { + summary.SastIssues = 0 + } else if summary.ScaIssues == notAvailableNumber { + summary.ScaIssues = 0 + } else if wrappers.IsContainersEnabled && *summary.ContainersIssues == notAvailableNumber { + *summary.ContainersIssues = 0 + } +} + +func buildAuxiliaryScaMaps(resultsModel *wrappers.ScanResultsCollection, scaPackageModel *[]wrappers.ScaPackageCollection, + scaTypeModel *[]wrappers.ScaTypeCollection) (locationsByID map[string][]*string, typesByCVE map[string]wrappers.ScaTypeCollection) { + locationsByID = make(map[string][]*string) + typesByCVE = make(map[string]wrappers.ScaTypeCollection) + // Create map to be used to populate locations for each package path + for _, result := range resultsModel.Results { + if result.Type == commonParams.ScaType { + for _, packages := range *scaPackageModel { + currentPackage := packages + locationsByID[packages.ID] = currentPackage.Locations + } + for _, types := range *scaTypeModel { + identifier := fmt.Sprintf("%s:%s", types.ID, types.PackageID) + typesByCVE[identifier] = types + } + } + } + return locationsByID, typesByCVE +} + +func buildScaType(typesByCVE map[string]wrappers.ScaTypeCollection, result *wrappers.ScanResult) string { + identifier := buildVulnerabilityIdentifier(result) + types, ok := typesByCVE[identifier] + if ok && types.Type == "SupplyChain" { + return "Supply Chain" + } + return "Vulnerability" +} + +func buildScaState(typesByCVE map[string]wrappers.ScaTypeCollection, result *wrappers.ScanResult) string { + identifier := buildVulnerabilityIdentifier(result) + types, ok := typesByCVE[identifier] + if ok && types.IsIgnored { + return notExploitable + } + return result.State +} + +func buildVulnerabilityIdentifier(result *wrappers.ScanResult) string { + return fmt.Sprintf("%s:%s", result.ID, result.ScanResultData.PackageIdentifier) +} + +func addPackageInformation( + resultsModel *wrappers.ScanResultsCollection, + scaPackageModel *[]wrappers.ScaPackageCollection, + scaTypeModel *[]wrappers.ScaTypeCollection, +) *wrappers.ScanResultsCollection { + locationsByID, typesByCVE := buildAuxiliaryScaMaps(resultsModel, scaPackageModel, scaTypeModel) + scaPackageMap := buildScaPackageMap(*scaPackageModel) + + for _, result := range resultsModel.Results { + if result.Type == commonParams.ScaType { + processResult(result, locationsByID, typesByCVE, scaPackageMap) + } + } + + return resultsModel +} + +func processResult( + result *wrappers.ScanResult, + locationsByID map[string][]*string, + typesByCVE map[string]wrappers.ScaTypeCollection, + scaPackageMap map[string]wrappers.ScaPackageCollection, // Updated parameter +) { + const precision = 1 + + currentID := result.ScanResultData.PackageIdentifier + result.VulnerabilityDetails.CvssScore = util.RoundFloat(result.VulnerabilityDetails.CvssScore, precision) + result.ScaType = buildScaType(typesByCVE, result) + result.State = buildScaState(typesByCVE, result) + + updatePackages(result, scaPackageMap, locationsByID, currentID) +} + +func updatePackages( + result *wrappers.ScanResult, + scaPackageMap map[string]wrappers.ScaPackageCollection, + locationsByID map[string][]*string, + currentID string, +) { + packages, found := scaPackageMap[currentID] + if !found { + return + } + + updateDependencyPaths(packages.DependencyPathArray, locationsByID) + if !packages.SupportsQuickFix { + packages.SupportsQuickFix = hasQuickFix(packages.DependencyPathArray) + } + + if packages.IsDirectDependency { + packages.TypeOfDependency = directDependencyType + } else { + packages.TypeOfDependency = indirectDependencyType + } + + packages.FixLink = buildFixLink(result) + result.ScanResultData.ScaPackageCollection = &packages +} + +func hasQuickFix(dependencyPaths [][]wrappers.DependencyPath) bool { + for i := range dependencyPaths { + head := &dependencyPaths[i][0] + if head.SupportsQuickFix { + return true + } + } + return false +} + +func buildScaPackageMap(scaPackageModel []wrappers.ScaPackageCollection) map[string]wrappers.ScaPackageCollection { + scaPackageMap := make(map[string]wrappers.ScaPackageCollection) + for i := range scaPackageModel { + scaPackageMap[scaPackageModel[i].ID] = scaPackageModel[i] + } + return scaPackageMap +} + +func updateDependencyPaths(dependencyPaths [][]wrappers.DependencyPath, locationsByID map[string][]*string) { + for i := range dependencyPaths { + head := &dependencyPaths[i][0] + head.Locations = locationsByID[head.ID] + head.SupportsQuickFix = len(dependencyPaths[i]) == 1 + + for _, location := range locationsByID[head.ID] { + head.SupportsQuickFix = head.SupportsQuickFix && util.IsPackageFileSupported(*location) + } + } +} + +func buildFixLink(result *wrappers.ScanResult) string { + if result.ID != "" { + return fmt.Sprint(fixLinkPrefix, result.ID) + } + return "" +} + +func filterViolatedRules(policyModel wrappers.PolicyResponseModel) *wrappers.PolicyResponseModel { + i := 0 + for _, policy := range policyModel.Policies { + if len(policy.RulesViolated) > 0 { + policyModel.Policies[i] = policy + i++ + } + } + policyModel.Policies = policyModel.Policies[:i] + return &policyModel +} + +func trimOsSeparatorFromFileName(result *wrappers.ScanResult) { + if result.ScanResultData.Filename != "" { + result.ScanResultData.Filename = strings.TrimPrefix(result.ScanResultData.Filename, "/") + result.ScanResultData.Filename = strings.TrimPrefix(result.ScanResultData.Filename, "\\") + } +} + +type ScannerResponse struct { + ScanID string `json:"ScanID,omitempty"` + Name string `json:"Name,omitempty"` + Status string `json:"Status,omitempty"` + Details string `json:"Details,omitempty"` + ErrorCode string `json:"ErrorCode,omitempty"` +} + +func parseURI(summaryBaseURI string) (hostName string) { + parsedURL, err := url.Parse(summaryBaseURI) + if err != nil { + return "" + } + hostName = fmt.Sprintf("%s://%s", parsedURL.Scheme, parsedURL.Host) + + return hostName +} + +func printWarningIfIgnorePolicyOmiited() { + fmt.Printf("\n Warning: The --ignore-policy flag was not implemented because you don’t have the required permission.\n Only users with 'override-policy-management' permission can use this flag. \n\n") +} + +func getFilterResultsForAPISecScanner(risksOverviewWrapper wrappers.RisksOverviewWrapper, scanID string, resultsParams map[string]string) (aPISecSeveritySummary *wrappers.APISecFilteredResult, err error) { + var apiSecRiskEntriesResult wrappers.APISecRiskEntriesResult + var errorModel *wrappers.WebError + + apiSecRiskEntriesResult, errorModel, err = risksOverviewWrapper.GetFilterResultForAPISecByScanID(scanID, resultsParams) + if err != nil { + return nil, errors.Wrapf(err, "%s", failedListingResults) + } + if errorModel != nil { + return nil, errors.Errorf("%s: CODE: %d, %s", failedListingResults, errorModel.Code, errorModel.Message) + } + if len(apiSecRiskEntriesResult.Entries) > 0 { + entries := apiSecRiskEntriesResult.Entries + severityCount := make(map[string]int) + originCount := make(map[string]int) + totalRecords := 0 + for i := range entries { + entry := &entries[i] + if !isExploitable(entry.State) { + continue + } + sev := strings.ToLower(entry.Severity) + severityCount[sev]++ + orig := strings.ToLower(entry.Origin) + originCount[orig]++ + totalRecords++ + } + var riskDistribution []wrappers.RiskDistributionEntry + if originCount["code"] > 0 { + riskDistribution = append(riskDistribution, wrappers.RiskDistributionEntry{Origin: "code", Total: originCount["code"]}) + } + if originCount["documentation"] > 0 { + riskDistribution = append(riskDistribution, wrappers.RiskDistributionEntry{Origin: "documentation", Total: originCount["documentation"]}) + } + return &wrappers.APISecFilteredResult{ + SeverityCount: severityCount, + RiskDistribution: riskDistribution, + TotalRisksCount: totalRecords, + }, nil + } + return nil, nil +} diff --git a/internal/commands/scan.go b/internal/commands/scan.go index 777632c6a..1ea696e8f 100644 --- a/internal/commands/scan.go +++ b/internal/commands/scan.go @@ -791,8 +791,8 @@ func scanCreateSubCommand( commonParams.Branch, commonParams.BranchFlagUsage, ) createScanCmd.PersistentFlags().String(commonParams.SastFilterFlag, "", commonParams.SastFilterUsage) - createScanCmd.PersistentFlags().String(commonParams.IacsFilterFlag, "", commonParams.IacsFilterUsage) - createScanCmd.PersistentFlags().String(commonParams.KicsFilterFlag, "", commonParams.KicsFilterUsage) + createScanCmd.PersistentFlags().StringSlice(commonParams.IacsFilterFlag, []string{}, commonParams.IacsFilterUsage) + createScanCmd.PersistentFlags().StringSlice(commonParams.KicsFilterFlag, []string{}, commonParams.KicsFilterUsage) err = createScanCmd.PersistentFlags().MarkDeprecated(commonParams.KicsFilterFlag, "please use the replacement flag --iac-security-filter") if err != nil { diff --git a/internal/params/filters.go b/internal/params/filters.go index 7ed55271d..fae79903f 100644 --- a/internal/params/filters.go +++ b/internal/params/filters.go @@ -150,6 +150,47 @@ var BaseIncludeFilters = []string{ "*.html", "*.xhtml", "*.vm", + "*.ac", + "*.am", + "*.app", + "*.asax", + "*.cmake", + "*.dspf", + "*.env", + "*.evt", + "*.ftl", + "*.gsp", + "*.gtl", + "*.handlebars", + "*.ini", + "*.jade", + "*.jsf", + "*.latex", + "*.lock", + "*.master", + "*.mf", + "*.mustache", + "*.pc", + "*.ph", + "*.phk", + "*.pro", + "*.rpgle", + "*.rpg", + "*.rpg38", + "*.sqlrpg", + "*.sqlrpgle", + "*.tex", + "*.toml", + "*.tsql", + "*.txt", + "*.vue", + "*.xsaccess", + "*.xsapp", + "*.pug", + "*.lua", + "*.ec", + "*.csv", + "*.apxc", } var BaseExcludeFilters = []string{ diff --git a/internal/services/applications.go b/internal/services/applications.go index 19880f529..10292c32f 100644 --- a/internal/services/applications.go +++ b/internal/services/applications.go @@ -79,12 +79,20 @@ func findApplicationAndUpdate(applicationName string, applicationsWrapper wrappe return errors.Errorf("%s: %s", errorConstants.ApplicationNotFound, applicationName) } + // Check if project is already associated (prevents unnecessary API calls for both when flag enabled/disabled) + for _, id := range applicationResp.ProjectIds { + if id == projectID { + logger.PrintfIfVerbose("Project is already associated with the application. Skipping association") + return nil + } + } + isEnabled, err := checkDirectAssociationEnabled(featureFlagsWrapper, tenantWrapper) if err != nil { return errors.Wrap(err, "error while checking if direct association is enabled") } if isEnabled { - err = associateProjectToApplication(applicationResp.ID, projectID, applicationResp.ProjectIds, applicationsWrapper) + err = associateProjectToApplication(applicationResp.ID, projectID, applicationsWrapper) if err != nil { return err } @@ -139,13 +147,7 @@ func updateApplication(applicationModel *wrappers.ApplicationConfiguration, appl return handleApplicationUpdateResponse(errorModel, err) } -func associateProjectToApplication(applicationID, projectID string, associatedProjectIds []string, applicationsWrapper wrappers.ApplicationsWrapper) error { - for _, id := range associatedProjectIds { - if id == projectID { - logger.PrintfIfVerbose("Project is already associated with the application. Skipping association") - return nil - } - } +func associateProjectToApplication(applicationID, projectID string, applicationsWrapper wrappers.ApplicationsWrapper) error { associateProjectsModel := &wrappers.AssociateProjectModel{ ProjectIds: []string{projectID}, } diff --git a/internal/services/applications_test.go b/internal/services/applications_test.go index ca1398c3e..0af427a97 100644 --- a/internal/services/applications_test.go +++ b/internal/services/applications_test.go @@ -11,6 +11,11 @@ import ( "gotest.tools/assert" ) +const ( + mockApplicationName = "MOCK" + testProjectName = "test-project" +) + func Test_createApplicationIds(t *testing.T) { type args struct { applicationID []string @@ -59,7 +64,7 @@ func Test_ProjectAssociation_ToApplicationDirectly(t *testing.T) { for _, test := range tests { tt := test t.Run(tt.description, func(t *testing.T) { - err := associateProjectToApplication(tt.applicationName, tt.projectName, []string{}, applicationWrapper) + err := associateProjectToApplication(tt.applicationName, tt.projectName, applicationWrapper) assert.Assert(t, strings.Contains(err.Error(), tt.error), err.Error()) }) } @@ -91,9 +96,8 @@ func Test_ProjectAssociation_ToApplicationWithoutDirectAssociation(t *testing.T) func Test_AssociateProjectToApplication_ProjectAlreadyAssociated(t *testing.T) { projectID := "project-123" - associatedProjectIds := []string{"project-123", "project-456"} applicationName := "app-1" applicationWrapper := &mock.ApplicationsMockWrapper{} - err := associateProjectToApplication(applicationName, projectID, associatedProjectIds, applicationWrapper) + err := associateProjectToApplication(applicationName, projectID, applicationWrapper) assert.NilError(t, err) } diff --git a/internal/services/projects.go b/internal/services/projects.go index 4d65e1b68..875568746 100644 --- a/internal/services/projects.go +++ b/internal/services/projects.go @@ -219,7 +219,6 @@ func updateProject(project *wrappers.ProjectResponseModel, projModel.Name = projModelResp.Name projModel.Groups = projModelResp.Groups projModel.Tags = projModelResp.Tags - projModel.ApplicationIds = projModelResp.ApplicationIds if projectTags != "" { logger.PrintIfVerbose("Updating project tags") projModel.Tags = createTagMap(projectTags) diff --git a/internal/wrappers/mock/application-mock.go b/internal/wrappers/mock/application-mock.go index 9bbdd28ef..8a0271492 100644 --- a/internal/wrappers/mock/application-mock.go +++ b/internal/wrappers/mock/application-mock.go @@ -31,12 +31,14 @@ func (a ApplicationsMockWrapper) Get(params map[string]string) (*wrappers.Applic Name: "MOCK", Description: "This is a mock application", Criticality: 2, - ProjectIds: []string{"ProjectID1", "ProjectID2", "MOCK", "test_project", "ID-new-project-name", "ID-newProject"}, + ProjectIds: []string{"ProjectID1", "ProjectID2", "test_project", "ID-new-project-name"}, CreatedAt: time.Now(), } if params["name"] == ExistingApplication { mockApplication.Name = ExistingApplication mockApplication.ID = "ID-newProject" + // For ExistingApplication, include "ID-newProject" for polling tests + mockApplication.ProjectIds = []string{"ProjectID1", "ProjectID2", "test_project", "ID-new-project-name", "ID-newProject"} return &wrappers.ApplicationsResponseModel{ TotalCount: 1, Applications: []wrappers.Application{mockApplication}, diff --git a/internal/wrappers/results-sarif.go b/internal/wrappers/results-sarif.go index 93e4ff3b4..e73786532 100644 --- a/internal/wrappers/results-sarif.go +++ b/internal/wrappers/results-sarif.go @@ -59,9 +59,22 @@ type SarifScanResult struct { Message SarifMessage `json:"message"` PartialFingerprints *SarifResultFingerprint `json:"partialFingerprints,omitempty"` Locations []SarifLocation `json:"locations,omitempty"` + CodeFlows []SarifCodeFlow `json:"codeFlows,omitempty"` Properties *SarifResultProperties `json:"properties,omitempty"` } +type SarifCodeFlow struct { + ThreadFlows []SarifThreadFlow `json:"threadFlows"` +} + +type SarifThreadFlow struct { + Locations []SarifThreadFlowLocation `json:"locations"` +} + +type SarifThreadFlowLocation struct { + Location SarifLocation `json:"location"` +} + type SarifLocation struct { PhysicalLocation SarifPhysicalLocation `json:"physicalLocation"` } From b70b80a82f5df69d258aba89853c0f8bf8079f4a Mon Sep 17 00:00:00 2001 From: atishj99 <141334503+cx-atish-jadhav@users.noreply.github.com> Date: Wed, 27 May 2026 12:08:36 +0530 Subject: [PATCH 03/27] Fix SCA vulnerabilities: update dependencies to patched versions - Upgrade distribution/v3 to v3.0.1-0.20260120145532-40594bd98e6d (security patch) - Upgrade go-jose/v3 to v3.0.5 (CWE-345: Insufficient Verification) - Upgrade anchore/stereoscope to v0.2.0 - Upgrade google.golang.org/grpc to v1.80.0 - Upgrade gonum to v0.17.0 - Upgrade containerd/v2 to v2.3.1 - Upgrade go-git/go-git/v5 to v5.18.1-0.20260420130857-e5bbc088b774 (CVE-2026-45022) - Upgrade go-git/go-billy/v5 to v5.8.1-0.20260506061021-07f2a0bf50e4 (CVE-2026-44973) - Upgrade Go version to 1.26.3 Co-Authored-By: Claude Haiku 4.5 --- go.mod | 68 +++++++++++++++++++++--------------------- go.sum | 94 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++-- 2 files changed, 127 insertions(+), 35 deletions(-) diff --git a/go.mod b/go.mod index 5a93ebf35..2ac014f7f 100644 --- a/go.mod +++ b/go.mod @@ -1,6 +1,6 @@ module github.com/checkmarx/ast-cli -go 1.25.9 +go 1.26.3 require ( github.com/Checkmarx/containers-resolver v1.0.34 @@ -30,8 +30,8 @@ require ( golang.org/x/crypto v0.50.0 golang.org/x/sync v0.20.0 golang.org/x/text v0.36.0 - google.golang.org/grpc v1.79.3 - google.golang.org/protobuf v1.36.11 + google.golang.org/grpc v1.80.0 + google.golang.org/protobuf v1.36.12-0.20260120151049-f2248ac996af gopkg.in/yaml.v3 v3.0.1 gotest.tools v2.2.0+incompatible ) @@ -46,7 +46,7 @@ require ( cloud.google.com/go/monitoring v1.24.3 // indirect cloud.google.com/go/storage v1.61.3 // indirect cyphar.com/go-pathrs v0.2.1 // indirect - github.com/GoogleCloudPlatform/opentelemetry-operations-go/detectors/gcp v1.30.0 // indirect + github.com/GoogleCloudPlatform/opentelemetry-operations-go/detectors/gcp v1.31.0 // indirect github.com/GoogleCloudPlatform/opentelemetry-operations-go/exporter/metric v0.55.0 // indirect github.com/GoogleCloudPlatform/opentelemetry-operations-go/internal/resourcemapping v0.55.0 // indirect github.com/OneOfOne/xxhash v1.2.8 // indirect @@ -82,11 +82,13 @@ require ( github.com/clipperhouse/displaywidth v0.10.0 // indirect github.com/clipperhouse/uax29/v2 v2.6.0 // indirect github.com/cncf/xds/go v0.0.0-20251210132809-ee656c7534f5 // indirect - github.com/containerd/containerd/v2 v2.2.3 // indirect - github.com/containerd/plugin v1.0.0 // indirect + github.com/containerd/containerd/v2 v2.3.1 // indirect + github.com/containerd/plugin v1.1.0 // indirect github.com/diskfs/go-diskfs v1.7.0 // indirect + github.com/distribution/distribution/v3 v3.0.1-0.20260120145532-40594bd98e6d // indirect github.com/envoyproxy/go-control-plane/envoy v1.36.0 // indirect github.com/envoyproxy/protoc-gen-validate v1.3.0 // indirect + github.com/go-jose/go-jose/v3 v3.0.5 // indirect github.com/go-jose/go-jose/v4 v4.1.4 // indirect github.com/goccy/go-yaml v1.19.2 // indirect github.com/gohugoio/hashstructure v0.6.0 // indirect @@ -116,14 +118,14 @@ require ( github.com/sorairolake/lzip-go v0.3.8 // indirect github.com/spiffe/go-spiffe/v2 v2.6.0 // indirect go.opentelemetry.io/contrib/detectors/gcp v1.39.0 // indirect - go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.63.0 // indirect + go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.68.0 // indirect go.opentelemetry.io/otel/sdk v1.43.0 // indirect go.opentelemetry.io/otel/sdk/metric v1.43.0 // indirect go4.org v0.0.0-20230225012048-214862532bf5 // indirect - gonum.org/v1/gonum v0.16.0 // indirect + gonum.org/v1/gonum v0.17.0 // indirect google.golang.org/api v0.271.0 // indirect - google.golang.org/genproto/googleapis/api v0.0.0-20260203192932-546029d2fa20 // indirect - sigs.k8s.io/structured-merge-diff/v6 v6.3.0 // indirect + google.golang.org/genproto/googleapis/api v0.0.0-20260401024825-9d38bb4040a9 // indirect + sigs.k8s.io/structured-merge-diff/v6 v6.3.2 // indirect ) require ( @@ -139,8 +141,8 @@ require ( github.com/Masterminds/semver/v3 v3.4.0 // indirect github.com/Masterminds/sprig/v3 v3.3.0 // indirect github.com/Masterminds/squirrel v1.5.4 // indirect - github.com/Microsoft/go-winio v0.6.2 // indirect - github.com/Microsoft/hcsshim v0.14.1 // indirect + github.com/Microsoft/go-winio v0.6.3-0.20251027160822-ad3df93bed29 // indirect + github.com/Microsoft/hcsshim v0.15.0-rc.1 // indirect github.com/ProtonMail/go-crypto v1.4.0 // indirect github.com/acobaugh/osrelease v0.1.0 // indirect github.com/adrg/xdg v0.5.3 // indirect @@ -154,7 +156,7 @@ require ( github.com/anchore/go-struct-converter v0.1.0 // indirect github.com/anchore/go-version v1.2.2-0.20200701162849-18adb9c92b9b // indirect github.com/anchore/packageurl-go v0.2.0 // indirect - github.com/anchore/stereoscope v0.1.23 // indirect + github.com/anchore/stereoscope v0.2.0 // indirect github.com/anchore/syft v1.43.0 // indirect github.com/andybalholm/brotli v1.2.0 // indirect github.com/apparentlymart/go-textseg/v15 v15.0.0 // indirect @@ -174,23 +176,23 @@ require ( github.com/charmbracelet/x/cellbuf v0.0.15 // indirect github.com/charmbracelet/x/term v0.2.2 // indirect github.com/cloudflare/circl v1.6.3 // indirect - github.com/containerd/cgroups/v3 v3.1.2 // indirect + github.com/containerd/cgroups/v3 v3.1.3 // indirect github.com/containerd/containerd v1.7.30 // indirect - github.com/containerd/containerd/api v1.10.0 // indirect - github.com/containerd/continuity v0.4.5 // indirect + github.com/containerd/containerd/api v1.11.1 // indirect + github.com/containerd/continuity v0.5.0 // indirect github.com/containerd/errdefs v1.0.0 // indirect github.com/containerd/errdefs/pkg v0.3.0 // indirect github.com/containerd/fifo v1.1.0 // indirect github.com/containerd/log v0.1.0 // indirect github.com/containerd/platforms v1.0.0-rc.4 // indirect github.com/containerd/stargz-snapshotter/estargz v0.18.2 // indirect - github.com/containerd/ttrpc v1.2.7 // indirect + github.com/containerd/ttrpc v1.2.8 // indirect github.com/containerd/typeurl/v2 v2.2.3 // indirect github.com/cyphar/filepath-securejoin v0.6.1 // indirect github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect github.com/deitch/magic v0.0.0-20240306090643-c67ab88f10cb // indirect github.com/distribution/reference v0.6.0 // indirect - github.com/docker/cli v29.4.0+incompatible // indirect + github.com/docker/cli v29.4.3+incompatible // indirect github.com/docker/docker-credential-helpers v0.9.5 // indirect github.com/docker/go-connections v0.6.0 // indirect github.com/docker/go-units v0.5.0 // indirect @@ -213,8 +215,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.8.0 // indirect - github.com/go-git/go-git/v5 v5.18.0 // indirect + github.com/go-git/go-billy/v5 v5.8.1-0.20260506061021-07f2a0bf50e4 // indirect + github.com/go-git/go-git/v5 v5.18.1-0.20260420130857-e5bbc088b774 // 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 @@ -294,7 +296,7 @@ require ( github.com/opencontainers/selinux v1.13.1 // indirect github.com/pborman/indent v1.2.1 // indirect github.com/pelletier/go-toml v1.9.5 // indirect - github.com/pelletier/go-toml/v2 v2.2.4 // indirect + github.com/pelletier/go-toml/v2 v2.3.1 // indirect github.com/peterbourgon/diskv v2.0.1+incompatible // indirect github.com/pierrec/lz4/v4 v4.1.22 // indirect github.com/pjbgf/sha1cd v0.3.2 // indirect @@ -345,14 +347,14 @@ require ( github.com/zricethezav/gitleaks/v8 v8.18.2 // indirect go.opencensus.io v0.24.0 // indirect go.opentelemetry.io/auto/sdk v1.2.1 // indirect - go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.61.0 // indirect + go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.68.0 // indirect go.opentelemetry.io/otel v1.43.0 // indirect go.opentelemetry.io/otel/metric v1.43.0 // indirect go.opentelemetry.io/otel/trace v1.43.0 // indirect - go.uber.org/mock v0.5.2 // indirect + go.uber.org/mock v0.6.0 // indirect go.yaml.in/yaml/v2 v2.4.3 // indirect go.yaml.in/yaml/v3 v3.0.4 // indirect - golang.org/x/exp v0.0.0-20251023183803-a4bb9ffd2546 // indirect + golang.org/x/exp v0.0.0-20260410095643-746e56fc9e2f // indirect golang.org/x/mod v0.35.0 // indirect golang.org/x/net v0.53.0 // indirect golang.org/x/oauth2 v0.36.0 // indirect @@ -362,23 +364,23 @@ require ( golang.org/x/tools v0.44.0 // indirect golang.org/x/xerrors v0.0.0-20240903120638-7835f813f4da // indirect google.golang.org/genproto v0.0.0-20260128011058-8636f8732409 // indirect - google.golang.org/genproto/googleapis/rpc v0.0.0-20260226221140-a57be14db171 // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20260406210006-6f92a3bedf2d // indirect gopkg.in/evanphx/json-patch.v4 v4.13.0 // indirect gopkg.in/inf.v0 v0.9.1 // indirect gopkg.in/warnings.v0 v0.1.2 // indirect gopkg.in/yaml.v2 v2.4.0 // indirect helm.sh/helm/v3 v3.20.2 // indirect - k8s.io/api v0.35.1 // indirect + k8s.io/api v0.36.0 // indirect k8s.io/apiextensions-apiserver v0.35.1 // indirect - k8s.io/apimachinery v0.35.1 // indirect + k8s.io/apimachinery v0.36.0 // indirect k8s.io/apiserver v0.35.1 // indirect k8s.io/cli-runtime v0.35.1 // indirect - k8s.io/client-go v0.35.1 // indirect - k8s.io/component-base v0.35.1 // indirect - k8s.io/klog/v2 v2.130.1 // indirect - k8s.io/kube-openapi v0.0.0-20250910181357-589584f1c912 // indirect + k8s.io/client-go v0.36.0 // indirect + k8s.io/component-base v0.36.0 // indirect + k8s.io/klog/v2 v2.140.0 // indirect + k8s.io/kube-openapi v0.0.0-20260319004828-5883c5ee87b9 // indirect k8s.io/kubectl v0.35.1 // indirect - k8s.io/utils v0.0.0-20251002143259-bc988d571ff4 // indirect + k8s.io/utils v0.0.0-20260319190234-28399d86e0b5 // indirect modernc.org/libc v1.70.0 // indirect modernc.org/mathutil v1.7.1 // indirect modernc.org/memory v1.11.0 // indirect @@ -391,6 +393,6 @@ require ( sigs.k8s.io/yaml v1.6.0 // indirect ) -replace github.com/containerd/containerd => github.com/containerd/containerd v1.7.31 +replace github.com/containerd/containerd => github.com/containerd/containerd v1.7.32 replace github.com/opencontainers/selinux => github.com/opencontainers/selinux v1.13.0 diff --git a/go.sum b/go.sum index 705cd99ef..d46acad4d 100644 --- a/go.sum +++ b/go.sum @@ -110,6 +110,8 @@ github.com/DataDog/zstd v1.5.6 h1:LbEglqepa/ipmmQJUDnSsfvA8e8IStVcGaFWDuxvGOY= github.com/DataDog/zstd v1.5.6/go.mod h1:g4AWEaM3yOg3HYfnJ3YIawPnVdXJh9QME85blwSAmyw= github.com/GoogleCloudPlatform/opentelemetry-operations-go/detectors/gcp v1.30.0 h1:sBEjpZlNHzK1voKq9695PJSX2o5NEXl7/OL3coiIY0c= github.com/GoogleCloudPlatform/opentelemetry-operations-go/detectors/gcp v1.30.0/go.mod h1:P4WPRUkOhJC13W//jWpyfJNDAIpvRbAUIYLX/4jtlE0= +github.com/GoogleCloudPlatform/opentelemetry-operations-go/detectors/gcp v1.31.0 h1:DHa2U07rk8syqvCge0QIGMCE1WxGj9njT44GH7zNJLQ= +github.com/GoogleCloudPlatform/opentelemetry-operations-go/detectors/gcp v1.31.0/go.mod h1:P4WPRUkOhJC13W//jWpyfJNDAIpvRbAUIYLX/4jtlE0= github.com/GoogleCloudPlatform/opentelemetry-operations-go/exporter/metric v0.55.0 h1:UnDZ/zFfG1JhH/DqxIZYU/1CUAlTUScoXD/LcM2Ykk8= github.com/GoogleCloudPlatform/opentelemetry-operations-go/exporter/metric v0.55.0/go.mod h1:IA1C1U7jO/ENqm/vhi7V9YYpBsp+IMyqNrEN94N7tVc= github.com/GoogleCloudPlatform/opentelemetry-operations-go/internal/cloudmock v0.55.0 h1:7t/qx5Ost0s0wbA/VDrByOooURhp+ikYwv20i9Y07TQ= @@ -129,8 +131,12 @@ github.com/Masterminds/squirrel v1.5.4/go.mod h1:NNaOrjSoIDfDA40n7sr2tPNZRfjzjA4 github.com/Microsoft/go-winio v0.5.2/go.mod h1:WpS1mjBmmwHBEWmogvA2mj8546UReBk4v8QkMxJ6pZY= github.com/Microsoft/go-winio v0.6.2 h1:F2VQgta7ecxGYO8k3ZZz3RS8fVIXVxONVUPlNERoyfY= github.com/Microsoft/go-winio v0.6.2/go.mod h1:yd8OoFMLzJbo9gZq8j5qaps8bJ9aShtEA8Ipt1oGCvU= +github.com/Microsoft/go-winio v0.6.3-0.20251027160822-ad3df93bed29 h1:0kQAzHq8vLs7Pptv+7TxjdETLf/nIqJpIB4oC6Ba4vY= +github.com/Microsoft/go-winio v0.6.3-0.20251027160822-ad3df93bed29/go.mod h1:ZWa7ssZJT30CCDGJ7fk/2SBTq9BIQrrVjrcss0UW2s0= github.com/Microsoft/hcsshim v0.14.1 h1:CMuB3fqQVfPdhyXhUqYdUmPUIOhJkmghCx3dJet8Cqs= github.com/Microsoft/hcsshim v0.14.1/go.mod h1:VnzvPLyWUhxiPVsJ31P6XadxCcTogTguBFDy/1GR/OM= +github.com/Microsoft/hcsshim v0.15.0-rc.1 h1:FbbwtQmiD+BVHynGkx5S65JkLyhkEiiTP8nrpmg2SZw= +github.com/Microsoft/hcsshim v0.15.0-rc.1/go.mod h1:HWvvUPIy9HF6LotILj1G4VyS065rcLQ6tqj6tMUdOfI= github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU= github.com/OneOfOne/xxhash v1.2.8 h1:31czK/TI9sNkxIKfaUfGlU47BAxQ0ztGgd9vPyqimf8= github.com/OneOfOne/xxhash v1.2.8/go.mod h1:eZbhyaAYD41SGSSsnmcpxVoRiQ/MPUTjUdIIOT9Um7Q= @@ -176,6 +182,8 @@ github.com/anchore/packageurl-go v0.2.0 h1:CkrM4RMUwrEGAiE1OVlxaZNzWj0TuHRey7o4T github.com/anchore/packageurl-go v0.2.0/go.mod h1:2JCgOQMIsqZ7TmliXG4PnUthPJAKE3mWQbsW2XHjAOE= github.com/anchore/stereoscope v0.1.23 h1:q9i3CtbicTuSlcCnA+5pfoT9WDCEoSqvXDfHMH1hyWo= github.com/anchore/stereoscope v0.1.23/go.mod h1:JLnun49fkLkuv3ebU0ROvFl/0JiRmNmUtCzc6y4ollo= +github.com/anchore/stereoscope v0.2.0 h1:8haOu2ugLymmxvyfrZR7OTBFiRFRBh5LlNUtRrSRoxI= +github.com/anchore/stereoscope v0.2.0/go.mod h1:PYx3fD4lvBVsYoQ/fBdauhZ5hmkRrJgw1B73svKx7/U= github.com/anchore/syft v1.43.0 h1:m6BwN48vgD0j2U4uk/wwqkUCxVKp2On30ZnKWQGCjKI= github.com/anchore/syft v1.43.0/go.mod h1:6jC8wnvN5Jble2qrWrS7q9jVoR1K2DVMKGBookHZai0= github.com/andreyvit/diff v0.0.0-20170406064948-c7f18ee00883/go.mod h1:rCTlJbsFo29Kk6CurOXKm700vrz8f0KW0JNfpkRJY/8= @@ -331,14 +339,26 @@ github.com/cncf/xds/go v0.0.0-20251210132809-ee656c7534f5 h1:6xNmx7iTtyBRev0+D/T github.com/cncf/xds/go v0.0.0-20251210132809-ee656c7534f5/go.mod h1:KdCmV+x/BuvyMxRnYBlmVaq4OLiKW6iRQfvC62cvdkI= github.com/containerd/cgroups/v3 v3.1.2 h1:OSosXMtkhI6Qove637tg1XgK4q+DhR0mX8Wi8EhrHa4= github.com/containerd/cgroups/v3 v3.1.2/go.mod h1:PKZ2AcWmSBsY/tJUVhtS/rluX0b1uq1GmPO1ElCmbOw= -github.com/containerd/containerd v1.7.31 h1:jn3IMuTV4Bb1Uwb0MFPW2ASJAD3W1lh6QqqZHIZwDh4= -github.com/containerd/containerd v1.7.31/go.mod h1:jdwD6s/BhV4XVJGrvtziNPVA+83n66TwptVaPKprq4E= +github.com/containerd/cgroups/v3 v3.1.3 h1:eUNflyMddm18+yrDmZPn3jI7C5hJ9ahABE5q6dyLYXQ= +github.com/containerd/cgroups/v3 v3.1.3/go.mod h1:PKZ2AcWmSBsY/tJUVhtS/rluX0b1uq1GmPO1ElCmbOw= +github.com/containerd/containerd v1.7.32 h1:S54xuVcPxeLaYgaRABtpJ2VyVUVsy0IGf7qHBs+sbY8= +github.com/containerd/containerd v1.7.32/go.mod h1:jdwD6s/BhV4XVJGrvtziNPVA+83n66TwptVaPKprq4E= github.com/containerd/containerd/api v1.10.0 h1:5n0oHYVBwN4VhoX9fFykCV9dF1/BvAXeg2F8W6UYq1o= github.com/containerd/containerd/api v1.10.0/go.mod h1:NBm1OAk8ZL+LG8R0ceObGxT5hbUYj7CzTmR3xh0DlMM= +github.com/containerd/containerd/api v1.11.0 h1:smv4e74S/wwIx0Sj7lhwO1t3M/oi+mSzk2VXqHq8aO0= +github.com/containerd/containerd/api v1.11.0/go.mod h1:CaQFRu+N1MtbgL6JDOJLUB1hCKESU1lD6MuTJhgtdlw= +github.com/containerd/containerd/api v1.11.1 h1:h8nfoDW9+fNsC/9TwiAHj8B1GzXKtR4eFtkhi/X5RLU= +github.com/containerd/containerd/api v1.11.1/go.mod h1:CaQFRu+N1MtbgL6JDOJLUB1hCKESU1lD6MuTJhgtdlw= github.com/containerd/containerd/v2 v2.2.3 h1:mOBRLaHGvmgy0bRo1Sg6OD8ugMKZIvCoWWMeMMygliA= github.com/containerd/containerd/v2 v2.2.3/go.mod h1:ns24cwt+p36mRnuKE3hLRxVBpuSP+a/Y25AMki1t/RY= +github.com/containerd/containerd/v2 v2.3.0 h1:qpB5dyToxPqea1OdedyAiAnnor5wxTM+Py9nWt5CnWY= +github.com/containerd/containerd/v2 v2.3.0/go.mod h1:+chyhxLNeqUVOcTJGgaSu/IbDGX6p3+d8AJjAaerAS8= +github.com/containerd/containerd/v2 v2.3.1 h1:4dVXBdlvotRBlaP2TmNbY/EGc06KJrMDDUqQdxX/HOk= +github.com/containerd/containerd/v2 v2.3.1/go.mod h1:xVoxGPWZBwwph8DF2IbDhriLKdHfjdpO0b3wFP9wQ1I= github.com/containerd/continuity v0.4.5 h1:ZRoN1sXq9u7V6QoHMcVWGhOwDFqZ4B9i5H6un1Wh0x4= github.com/containerd/continuity v0.4.5/go.mod h1:/lNJvtJKUQStBzpVQ1+rasXO1LAWtUQssk28EZvJ3nE= +github.com/containerd/continuity v0.5.0 h1:7a85HZpCSs+1Zps0Ee3DPSuAWY+0SJM1JNM51nlEVDg= +github.com/containerd/continuity v0.5.0/go.mod h1:/lNJvtJKUQStBzpVQ1+rasXO1LAWtUQssk28EZvJ3nE= github.com/containerd/errdefs v1.0.0 h1:tg5yIfIlQIrxYtu9ajqY42W3lpS19XqdxRQeEwYG8PI= github.com/containerd/errdefs v1.0.0/go.mod h1:+YBYIdtsnF4Iw6nWZhJcqGSg/dwvV7tyJ/kCkyJ2k+M= github.com/containerd/errdefs/pkg v0.3.0 h1:9IKJ06FvyNlexW690DXuQNx2KA2cUJXx151Xdx3ZPPE= @@ -351,10 +371,14 @@ github.com/containerd/platforms v1.0.0-rc.4 h1:M42JrUT4zfZTqtkUwkr0GzmUWbfyO5VO0 github.com/containerd/platforms v1.0.0-rc.4/go.mod h1:lKlMXyLybmBedS/JJm11uDofzI8L2v0J2ZbYvNsbq1A= github.com/containerd/plugin v1.0.0 h1:c8Kf1TNl6+e2TtMHZt+39yAPDbouRH9WAToRjex483Y= github.com/containerd/plugin v1.0.0/go.mod h1:hQfJe5nmWfImiqT1q8Si3jLv3ynMUIBB47bQ+KexvO8= +github.com/containerd/plugin v1.1.0 h1:O+7lczNJVMy8rz0YNx3xGB8tTf5qY4i5abF041Ew19U= +github.com/containerd/plugin v1.1.0/go.mod h1:qBTum+A8lJ6lO44A19Eo7y1OlcLj4OWFH1DA/vnHmcc= github.com/containerd/stargz-snapshotter/estargz v0.18.2 h1:yXkZFYIzz3eoLwlTUZKz2iQ4MrckBxJjkmD16ynUTrw= github.com/containerd/stargz-snapshotter/estargz v0.18.2/go.mod h1:XyVU5tcJ3PRpkA9XS2T5us6Eg35yM0214Y+wvrZTBrY= github.com/containerd/ttrpc v1.2.7 h1:qIrroQvuOL9HQ1X6KHe2ohc7p+HP/0VE6XPU7elJRqQ= github.com/containerd/ttrpc v1.2.7/go.mod h1:YCXHsb32f+Sq5/72xHubdiJRQY9inL4a4ZQrAbN1q9o= +github.com/containerd/ttrpc v1.2.8 h1:xbVu6D4qF2jihdh9rDVOKqUMiFBQk6YctTdo1zk087Y= +github.com/containerd/ttrpc v1.2.8/go.mod h1:wyZW2K79t4Hfcxl+GUvkZqRBzJlqFFvgEeeWXa42tyE= github.com/containerd/typeurl/v2 v2.2.3 h1:yNA/94zxWdvYACdYO8zofhrTVuQY73fFU1y++dYSw40= github.com/containerd/typeurl/v2 v2.2.3/go.mod h1:95ljDnPfD3bAbDJRugOiShd/DlAAsxGtUBhJxIn7SCk= github.com/coreos/go-semver v0.3.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk= @@ -362,6 +386,7 @@ github.com/coreos/go-systemd/v22 v22.3.2/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSV github.com/coreos/go-systemd/v22 v22.5.0/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc= github.com/coreos/go-systemd/v22 v22.6.0 h1:aGVa/v8B7hpb0TKl0MWoAavPDmHvobFe5R5zn0bCJWo= github.com/coreos/go-systemd/v22 v22.6.0/go.mod h1:iG+pp635Fo7ZmV/j14KUcmEyWF+0X7Lua8rrTWzYgWU= +github.com/coreos/go-systemd/v22 v22.7.0 h1:LAEzFkke61DFROc7zNLX/WA2i5J8gYqe0rSj9KI28KA= github.com/cpuguy83/go-md2man/v2 v2.0.1/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= github.com/cpuguy83/go-md2man/v2 v2.0.6/go.mod h1:oOW0eioCTA6cOiMLiUPZOpcVxMig6NIQQ7OS05n1F4g= github.com/creack/pty v1.1.24 h1:bJrF4RRfyJnbTJqzRLHzcGaZK1NeM5kTC9jGgovnR1s= @@ -381,6 +406,8 @@ github.com/diskfs/go-diskfs v1.7.0 h1:vonWmt5CMowXwUc79jWyGrf2DIMeoOjkLlMnQYGVOs github.com/diskfs/go-diskfs v1.7.0/go.mod h1:LhQyXqOugWFRahYUSw47NyZJPezFzB9UELwhpszLP/k= github.com/distribution/distribution/v3 v3.0.1-0.20250403190400-dbca4995c83c h1:tFjIrcN2x16eg3aob8g8LPNJClLxtQbu1wqeUMydXRc= github.com/distribution/distribution/v3 v3.0.1-0.20250403190400-dbca4995c83c/go.mod h1:tRNuFoZsUdyRVegq8xGNeds4KLjwLCRin/tTo6i1DhU= +github.com/distribution/distribution/v3 v3.0.1-0.20260120145532-40594bd98e6d h1:c2HDaWKU1MalLXwrAek+Yks7n80p/salSR5u6alHPBo= +github.com/distribution/distribution/v3 v3.0.1-0.20260120145532-40594bd98e6d/go.mod h1:WiiB9B3TqqAPe7hPjI1P9OMtEW7Ub/HHGndi11SqeDA= github.com/distribution/reference v0.6.0 h1:0IXCQ5g4/QMHHkarYzh5l+u8T3t73zM5QvfrDyIgxBk= github.com/distribution/reference v0.6.0/go.mod h1:BbU0aIcezP1/5jX/8MP0YiH4SdvB5Y4f/wlDRiLyi3E= github.com/djherbis/times v1.6.0 h1:w2ctJ92J8fBvWPxugmXIv7Nz7Q3iDMKNx9v5ocVH20c= @@ -389,6 +416,8 @@ github.com/dlclark/regexp2 v1.11.0 h1:G/nrcoOa7ZXlpoa/91N3X7mM3r8eIlMBBJZvsz/mxK github.com/dlclark/regexp2 v1.11.0/go.mod h1:DHkYz0B9wPfa6wondMfaivmHpzrQ3v9q8cnmRbL6yW8= github.com/docker/cli v29.4.0+incompatible h1:+IjXULMetlvWJiuSI0Nbor36lcJ5BTcVpUmB21KBoVM= github.com/docker/cli v29.4.0+incompatible/go.mod h1:JLrzqnKDaYBop7H2jaqPtU4hHvMKP+vjCwu2uszcLI8= +github.com/docker/cli v29.4.3+incompatible h1:u+UliYm2J/rYrIh2FqHQg32neRG8GjbvNuwQRTzGspU= +github.com/docker/cli v29.4.3+incompatible/go.mod h1:JLrzqnKDaYBop7H2jaqPtU4hHvMKP+vjCwu2uszcLI8= github.com/docker/docker-credential-helpers v0.9.5 h1:EFNN8DHvaiK8zVqFA2DT6BjXE0GzfLOZ38ggPTKePkY= github.com/docker/docker-credential-helpers v0.9.5/go.mod h1:v1S+hepowrQXITkEfw6o4+BMbGot02wiKpzWhGUZK6c= github.com/docker/go-connections v0.6.0 h1:LlMG9azAe1TqfR7sO+NJttz1gy6KO7VJBh+pMmjSD94= @@ -486,15 +515,21 @@ github.com/go-git/gcfg v1.5.1-0.20230307220236-3a3c6141e376 h1:+zs/tPmkDkHx3U66D github.com/go-git/gcfg v1.5.1-0.20230307220236-3a3c6141e376/go.mod h1:an3vInlBmSxCcxctByoQdvwPiA7DTK7jaaFDBTtu0ic= 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-billy/v5 v5.8.1-0.20260506061021-07f2a0bf50e4 h1:XK6pelr1UQyrCSXsrqrJxr0jkrHXg7QCzfPH3UQMYp8= +github.com/go-git/go-billy/v5 v5.8.1-0.20260506061021-07f2a0bf50e4/go.mod h1:jCnQMLj9eUgGU7+ludSTYoZL/GGmii14RxKFj7ROgHw= 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.18.0 h1:O831KI+0PR51hM2kep6T8k+w0/LIAD490gvqMCvL5hM= github.com/go-git/go-git/v5 v5.18.0/go.mod h1:pW/VmeqkanRFqR6AljLcs7EA7FbZaN5MQqO7oZADXpo= +github.com/go-git/go-git/v5 v5.18.1-0.20260420130857-e5bbc088b774 h1:FED4o0JOD1z8x/dMcmM6IKkqoIz22xz7sWE81FEdXNQ= +github.com/go-git/go-git/v5 v5.18.1-0.20260420130857-e5bbc088b774/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= github.com/go-gorp/gorp/v3 v3.1.0 h1:ItKF/Vbuj31dmV4jxA1qblpSwkl9g1typ24xoe70IGs= github.com/go-gorp/gorp/v3 v3.1.0/go.mod h1:dLEjIyyRNiXvNZ8PSmzpt1GsWAUK8kjVhEpjH8TixEw= +github.com/go-jose/go-jose/v3 v3.0.5 h1:BLLJWbC4nMZOfuPVxoZIxeYsn6Nl2r1fITaJ78UQlVQ= +github.com/go-jose/go-jose/v3 v3.0.5/go.mod h1:5b+7YgP7ZICgJDBdfjZaIt+H/9L9T/YQrVfLAMboGkQ= github.com/go-jose/go-jose/v4 v4.1.4 h1:moDMcTHmvE6Groj34emNPLs/qtYXRVcd6S7NHbHz3kA= github.com/go-jose/go-jose/v4 v4.1.4/go.mod h1:x4oUasVrzR7071A4TnHLGSPpNOm2a21K9Kf04k1rs08= github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= @@ -601,6 +636,7 @@ github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/ github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.7/go.mod h1:n+brtR0CgQNWTVd5ZUFpTBC8YFBDLK/h/bpaJ8/DtOE= +github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8= github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU= github.com/google/go-containerregistry v0.21.5 h1:KTJG9Pn/jC0VdZR6ctV3/jcN+q6/Iqlx0sTVz3ywZlM= @@ -673,6 +709,7 @@ github.com/grpc-ecosystem/grpc-gateway v1.16.0 h1:gmcG1KaJ57LophUzW0Hy8NmPhnMZb4 github.com/grpc-ecosystem/grpc-gateway v1.16.0/go.mod h1:BDjrQk3hbvj6Nolgz8mAMFbcEtjT1g+wF4CSlocrBnw= github.com/grpc-ecosystem/grpc-gateway/v2 v2.26.3 h1:5ZPtiqj0JL5oKWmcsq4VMaAW5ukBEgSGXEN89zeH1Jo= github.com/grpc-ecosystem/grpc-gateway/v2 v2.26.3/go.mod h1:ndYquD05frm2vACXE1nsccT4oJzjhw2arTS2cpUD1PI= +github.com/grpc-ecosystem/grpc-gateway/v2 v2.28.0 h1:HWRh5R2+9EifMyIHV7ZV+MIZqgz+PMpZ14Jynv3O2Zs= github.com/h2non/filetype v1.1.3 h1:FKkx9QbD7HR/zjK1Ia5XiBsq9zdLi5Kf3zGyFTAFkGg= github.com/h2non/filetype v1.1.3/go.mod h1:319b3zT68BvV+WRj7cwy856M2ehB3HqNOt6sy1HndBY= github.com/hashicorp/aws-sdk-go-base/v2 v2.0.0-beta.72 h1:vTCWu1wbdYo7PEZFem/rlr01+Un+wwVmI7wiegFdRLk= @@ -946,6 +983,8 @@ github.com/pelletier/go-toml v1.9.5 h1:4yBQzkHv+7BHq2PQUZF3Mx0IYxG7LsP222s7Agd3v github.com/pelletier/go-toml v1.9.5/go.mod h1:u1nR/EPcESfeI/szUZKdtJ0xRNbUoANCkoOuaOx1Y+c= github.com/pelletier/go-toml/v2 v2.2.4 h1:mye9XuhQ6gvn5h28+VilKrrPoQVanw5PMw/TB0t5Ec4= github.com/pelletier/go-toml/v2 v2.2.4/go.mod h1:2gIqNv+qfxSVS7cM2xJQKtLSTLUE9V8t9Stt+h56mCY= +github.com/pelletier/go-toml/v2 v2.3.1 h1:MYEvvGnQjeNkRF1qUuGolNtNExTDwct51yp7olPtrEc= +github.com/pelletier/go-toml/v2 v2.3.1/go.mod h1:2gIqNv+qfxSVS7cM2xJQKtLSTLUE9V8t9Stt+h56mCY= github.com/peterbourgon/diskv v2.0.1+incompatible h1:UBdAOUP5p4RWqPBg048CAvpKN+vxiaj6gdUUzhl4XmI= github.com/peterbourgon/diskv v2.0.1+incompatible/go.mod h1:uqqh8zWWbv1HBMNONnaR/tNboyR3/BZd58JJSHlUSCU= github.com/phayes/freeport v0.0.0-20220201140144-74d24b5ae9f5 h1:Ii+DKncOVM8Cu1Hc+ETb5K+23HdAMvESYE3ZJ5b5cMI= @@ -987,11 +1026,13 @@ github.com/prometheus/common v0.4.1/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y8 github.com/prometheus/common v0.9.1/go.mod h1:yhUN8i9wzaXS3w1O07YhxHEBxD+W35wd8bs7vj7HSQ4= github.com/prometheus/common v0.66.1 h1:h5E0h5/Y8niHc5DlaLlWLArTQI7tMrsfQjHV+d9ZoGs= github.com/prometheus/common v0.66.1/go.mod h1:gcaUsgf3KfRSwHY4dIMXLPV0K/Wg1oZ8+SbZk/HH/dA= +github.com/prometheus/common v0.67.5 h1:pIgK94WWlQt1WLwAC5j2ynLaBRDiinoAb86HZHTUGI4= github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA= github.com/prometheus/procfs v0.0.8/go.mod h1:7Qr8sr6344vo1JqZ6HhLceV9o3AJ1Ff+GxbHq6oeK9A= github.com/prometheus/procfs v0.16.1 h1:hZ15bTNuirocR6u0JZ6BAHHmwS1p8B4P6MRqxtzMyRg= github.com/prometheus/procfs v0.16.1/go.mod h1:teAbpZRB1iIAJYREa1LsoWUXykVXA1KlTmWl8x/U+Is= +github.com/prometheus/procfs v0.19.2 h1:zUMhqEW66Ex7OXIiDkll3tl9a1ZdilUOd/F6ZXw4Vws= github.com/redis/go-redis/extra/rediscmd/v9 v9.0.5 h1:EaDatTxkdHG+U3Bk4EUr+DZ7fOGwTfezUiUJMaIcaho= github.com/redis/go-redis/extra/rediscmd/v9 v9.0.5/go.mod h1:fyalQWdtzDBECAQFBJuQe5bzQ02jGd5Qcbgb97Flm7U= github.com/redis/go-redis/extra/redisotel/v9 v9.0.5 h1:EfpWLLCyXw8PSM2/XNJLjI3Pb27yVE+gIAfeqp8LUCc= @@ -1190,8 +1231,12 @@ go.opentelemetry.io/contrib/exporters/autoexport v0.57.0 h1:jmTVJ86dP60C01K3slFQ go.opentelemetry.io/contrib/exporters/autoexport v0.57.0/go.mod h1:EJBheUMttD/lABFyLXhce47Wr6DPWYReCzaZiXadH7g= go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.63.0 h1:YH4g8lQroajqUwWbq/tr2QX1JFmEXaDLgG+ew9bLMWo= go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.63.0/go.mod h1:fvPi2qXDqFs8M4B4fmJhE92TyQs9Ydjlg3RvfUp+NbQ= +go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.68.0 h1:0Qx7VGBacMm9ZENQ7TnNObTYI4ShC+lHI16seduaxZo= +go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.68.0/go.mod h1:Sje3i3MjSPKTSPvVWCaL8ugBzJwik3u4smCjUeuupqg= go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.61.0 h1:F7Jx+6hwnZ41NSFTO5q4LYDtJRXBf2PD0rNBkeB/lus= go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.61.0/go.mod h1:UHB22Z8QsdRDrnAtX4PntOl36ajSxcdUMt1sF7Y6E7Q= +go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.68.0 h1:CqXxU8VOmDefoh0+ztfGaymYbhdB/tT3zs79QaZTNGY= +go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.68.0/go.mod h1:BuhAPThV8PBHBvg8ZzZ/Ok3idOdhWIodywz2xEcRbJo= go.opentelemetry.io/otel v1.43.0 h1:mYIM03dnh5zfN7HautFE4ieIig9amkNANT+xcVxAj9I= go.opentelemetry.io/otel v1.43.0/go.mod h1:JuG+u74mvjvcm8vj8pI5XiHy1zDeoCS2LB1spIq7Ay0= go.opentelemetry.io/otel/exporters/otlp/otlplog/otlploggrpc v0.8.0 h1:WzNab7hOOLzdDF/EoWCt4glhrbMPVMOO5JYTmpz36Ls= @@ -1204,10 +1249,13 @@ go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetrichttp v1.32.0 h1:t/Q go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetrichttp v1.32.0/go.mod h1:Rl61tySSdcOJWoEgYZVtmnKdA0GeKrSqkHC1t+91CH8= go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.35.0 h1:1fTNlAIJZGWLP5FVu0fikVry1IsiUnXjf7QFvoNN3Xw= go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.35.0/go.mod h1:zjPK58DtkqQFn+YUMbx0M2XV3QgKU0gS9LeGohREyK4= +go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.43.0 h1:88Y4s2C8oTui1LGM6bTWkw0ICGcOLCAI5l6zsD1j20k= go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.35.0 h1:m639+BofXTvcY1q8CGs4ItwQarYtJPOWmVobfM1HpVI= go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.35.0/go.mod h1:LjReUci/F4BUyv+y4dwnq3h/26iNOeC3wAIqgvTIZVo= +go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.43.0 h1:RAE+JPfvEmvy+0LzyUA25/SGawPwIUbZ6u0Wug54sLc= go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.35.0 h1:xJ2qHD0C1BeYVTLLR9sX12+Qb95kfeD/byKj6Ky1pXg= go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.35.0/go.mod h1:u5BF1xyjstDowA1R5QAO9JHzqK+ublenEW/dyqTjBVk= +go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.43.0 h1:3iZJKlCZufyRzPzlQhUIWVmfltrXuGyfjREgGP3UUjc= go.opentelemetry.io/otel/exporters/prometheus v0.54.0 h1:rFwzp68QMgtzu9PgP3jm9XaMICI6TsofWWPcBDKwlsU= go.opentelemetry.io/otel/exporters/prometheus v0.54.0/go.mod h1:QyjcV9qDP6VeK5qPyKETvNjmaaEc7+gqjh4SS0ZYzDU= go.opentelemetry.io/otel/exporters/stdout/stdoutlog v0.8.0 h1:CHXNXwfKWfzS65yrlB2PVds1IBZcdsX8Vepy9of0iRU= @@ -1231,11 +1279,14 @@ go.opentelemetry.io/otel/trace v1.43.0/go.mod h1:/QJhyVBUUswCphDVxq+8mld+AvhXZLh go.opentelemetry.io/proto/otlp v0.7.0/go.mod h1:PqfVotwruBrMGOCsRd/89rSnXhoiJIqeYNgFYFoEGnI= go.opentelemetry.io/proto/otlp v1.7.1 h1:gTOMpGDb0WTBOP8JaO72iL3auEZhVmAQg4ipjOVAtj4= go.opentelemetry.io/proto/otlp v1.7.1/go.mod h1:b2rVh6rfI/s2pHWNlB7ILJcRALpcNDzKhACevjI+ZnE= +go.opentelemetry.io/proto/otlp v1.10.0 h1:IQRWgT5srOCYfiWnpqUYz9CVmbO8bFmKcwYxpuCSL2g= go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc= go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto= go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE= go.uber.org/mock v0.5.2 h1:LbtPTcP8A5k9WPXj54PPPbjcI4Y6lhyOZXn+VS7wNko= go.uber.org/mock v0.5.2/go.mod h1:wLlUxC2vVTPTaE3UD51E0BGOAElKrILxhVSDYQLld5o= +go.uber.org/mock v0.6.0 h1:hyF9dfmbgIX5EfOdasqLsWD6xqpNZlXblLB/Dbnwv3Y= +go.uber.org/mock v0.6.0/go.mod h1:KiVJ4BqZJaMj4svdfmHM0AUx4NJYO8ZNpPnZn1Z+BBU= go.uber.org/multierr v1.6.0/go.mod h1:cdWPpRnG4AhwMwsgIHip0KRBQjJy5kYEpYjJxpXp9iU= go.uber.org/zap v1.17.0/go.mod h1:MXVU+bhUf/A7Xi2HNOnopQOrmycQ5Ih87HtOu4q5SSo= go.yaml.in/yaml/v2 v2.4.3 h1:6gvOSjQoTB3vt1l+CU+tSyi/HOjfOjRLJ4YwYZGwRO0= @@ -1258,6 +1309,7 @@ golang.org/x/crypto v0.0.0-20210817164053-32db794688a5/go.mod h1:GvvjBRRGRdwPK5y golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/crypto v0.0.0-20220622213112-05595931fe9d/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= golang.org/x/crypto v0.6.0/go.mod h1:OFC/31mSvZgRz0V1QTNCzfAI1aIRzbiufJtkMIlEp58= +golang.org/x/crypto v0.19.0/go.mod h1:Iy9bg/ha4yyC70EfRS8jz+B6ybOBKMaSxLj6P6oBDfU= golang.org/x/crypto v0.50.0 h1:zO47/JPrL6vsNkINmLoo/PH1gcxpls50DNogFvB5ZGI= golang.org/x/crypto v0.50.0/go.mod h1:3muZ7vA7PBCE6xgPX7nkzzjiUq87kRItoJQM1Yo8S+Q= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= @@ -1272,6 +1324,8 @@ golang.org/x/exp v0.0.0-20200207192155-f17229e696bd/go.mod h1:J/WKrq2StrnmMY6+EH golang.org/x/exp v0.0.0-20200224162631-6cc2880d07d6/go.mod h1:3jZMyOhIsHpP37uCMkUooju7aAi5cS1Q23tOzKc+0MU= golang.org/x/exp v0.0.0-20251023183803-a4bb9ffd2546 h1:mgKeJMpvi0yx/sU5GsxQ7p6s2wtOnGAHZWCHUM4KGzY= golang.org/x/exp v0.0.0-20251023183803-a4bb9ffd2546/go.mod h1:j/pmGrbnkbPtQfxEe5D0VQhZC6qKbfKifgD0oM7sR70= +golang.org/x/exp v0.0.0-20260410095643-746e56fc9e2f h1:W3F4c+6OLc6H2lb//N1q4WpJkhzJCK5J6kUi1NTVXfM= +golang.org/x/exp v0.0.0-20260410095643-746e56fc9e2f/go.mod h1:J1xhfL/vlindoeF/aINzNzt2Bket5bjo9sdOYzOsU80= golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js= golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= @@ -1299,6 +1353,7 @@ golang.org/x/mod v0.4.1/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.5.0/go.mod h1:5OXOZSfqPIIbmVBIIKWRFfZjPR0E5r58TLhUjH0a2Ro= golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= +golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= golang.org/x/mod v0.35.0 h1:Ww1D637e6Pg+Zb2KrWfHQUnH2dQRLBQyAtpr/haaJeM= golang.org/x/mod v0.35.0/go.mod h1:+GwiRhIInF8wPm+4AoT6L0FA1QWAad3OMdTRx4tFYlU= golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= @@ -1346,6 +1401,7 @@ golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qx golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= golang.org/x/net v0.7.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= +golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg= golang.org/x/net v0.53.0 h1:d+qAbo5L0orcWAr0a9JweQpjXF19LMXJE8Ey7hwOdUA= golang.org/x/net v0.53.0/go.mod h1:JvMuJH7rrdiCfbeHoo3fCQU24Lf5JJwT9W3sJFulfgs= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= @@ -1379,6 +1435,7 @@ golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJ golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.20.0 h1:e0PTpb7pjO8GAtTs2dQ6jYa5BWYlMuX047Dco/pItO4= golang.org/x/sync v0.20.0/go.mod h1:9xrNwdLfx4jkKbNva9FpL6vEN7evnE43NNNJQ2LF3+0= golang.org/x/sys v0.0.0-20180823144017-11551d06cbcc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= @@ -1456,12 +1513,16 @@ golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.17.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/sys v0.43.0 h1:Rlag2XtaFTxp19wS8MXlJwTvoh8ArU6ezoyFsMyCTNI= golang.org/x/sys v0.43.0/go.mod h1:4GL1E5IUh+htKOUEOaiffhrAeqysfVGipDYzABqnCmw= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k= +golang.org/x/term v0.8.0/go.mod h1:xPskH00ivmX89bAKVGSKKtLOWNx2+17Eiy94tnKShWo= +golang.org/x/term v0.17.0/go.mod h1:lLRBjIVuehSbZlaOtGMbcMncT+aqLLLmKrsjNrUguwk= golang.org/x/term v0.42.0 h1:UiKe+zDFmJobeJ5ggPwOshJIVt6/Ft0rcfrXZDLWAWY= golang.org/x/term v0.42.0/go.mod h1:Dq/D+snpsbazcBG5+F9Q1n2rXV8Ma+71xEjTRufARgY= golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= @@ -1474,6 +1535,8 @@ golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= +golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= +golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= golang.org/x/text v0.36.0 h1:JfKh3XmcRPqZPKevfXVpI1wXPTqbkE5f7JA92a55Yxg= golang.org/x/text v0.36.0/go.mod h1:NIdBknypM8iqVmPiuco0Dh6P5Jcdk8lJL0CUebqK164= golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= @@ -1536,6 +1599,7 @@ golang.org/x/tools v0.1.3/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= golang.org/x/tools v0.1.4/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= golang.org/x/tools v0.1.5/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= +golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU= golang.org/x/tools v0.44.0 h1:UP4ajHPIcuMjT1GqzDWRlalUEoY+uzoZKnhOjbIPD2c= golang.org/x/tools v0.44.0/go.mod h1:KA0AfVErSdxRZIsOVipbv3rQhVXTnlU6UhKxHd1seDI= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= @@ -1546,6 +1610,8 @@ golang.org/x/xerrors v0.0.0-20240903120638-7835f813f4da h1:noIWHXmPHxILtqtCOPIhS golang.org/x/xerrors v0.0.0-20240903120638-7835f813f4da/go.mod h1:NDW/Ps6MPRej6fsCIbMTohpP40sJ/P/vI1MoTEGwX90= gonum.org/v1/gonum v0.16.0 h1:5+ul4Swaf3ESvrOnidPp4GZbzf0mxVQpDCYUQE7OJfk= gonum.org/v1/gonum v0.16.0/go.mod h1:fef3am4MQ93R2HHpKnLk4/Tbh/s0+wqD5nfa6Pnwy4E= +gonum.org/v1/gonum v0.17.0 h1:VbpOemQlsSMrYmn7T2OUvQ4dqxQXU+ouZFQsZOx50z4= +gonum.org/v1/gonum v0.17.0/go.mod h1:El3tOrEuMpv2UdMrbNlKEh9vd86bmQ6vqIcDwxEOc1E= google.golang.org/api v0.4.0/go.mod h1:8k5glujaEP+g9n7WNsDg8QP6cUVNI86fCNMcbazEtwE= google.golang.org/api v0.7.0/go.mod h1:WtwebWUNSVBH/HAw79HIFXZNqEvBhG+Ra+ax0hx3E3M= google.golang.org/api v0.8.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg= @@ -1654,8 +1720,12 @@ google.golang.org/genproto v0.0.0-20260128011058-8636f8732409 h1:VQZ/yAbAtjkHgH8 google.golang.org/genproto v0.0.0-20260128011058-8636f8732409/go.mod h1:rxKD3IEILWEu3P44seeNOAwZN4SaoKaQ/2eTg4mM6EM= google.golang.org/genproto/googleapis/api v0.0.0-20260203192932-546029d2fa20 h1:7ei4lp52gK1uSejlA8AZl5AJjeLUOHBQscRQZUgAcu0= google.golang.org/genproto/googleapis/api v0.0.0-20260203192932-546029d2fa20/go.mod h1:ZdbssH/1SOVnjnDlXzxDHK2MCidiqXtbYccJNzNYPEE= +google.golang.org/genproto/googleapis/api v0.0.0-20260401024825-9d38bb4040a9 h1:VPWxll4HlMw1Vs/qXtN7BvhZqsS9cdAittCNvVENElA= +google.golang.org/genproto/googleapis/api v0.0.0-20260401024825-9d38bb4040a9/go.mod h1:7QBABkRtR8z+TEnmXTqIqwJLlzrZKVfAUm7tY3yGv0M= google.golang.org/genproto/googleapis/rpc v0.0.0-20260226221140-a57be14db171 h1:ggcbiqK8WWh6l1dnltU4BgWGIGo+EVYxCaAPih/zQXQ= google.golang.org/genproto/googleapis/rpc v0.0.0-20260226221140-a57be14db171/go.mod h1:4Hqkh8ycfw05ld/3BWL7rJOSfebL2Q+DVDeRgYgxUU8= +google.golang.org/genproto/googleapis/rpc v0.0.0-20260406210006-6f92a3bedf2d h1:wT2n40TBqFY6wiwazVK9/iTWbsQrgk5ZfCSVFLO9LQA= +google.golang.org/genproto/googleapis/rpc v0.0.0-20260406210006-6f92a3bedf2d/go.mod h1:4Hqkh8ycfw05ld/3BWL7rJOSfebL2Q+DVDeRgYgxUU8= google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38= google.golang.org/grpc v1.21.1/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM= @@ -1685,6 +1755,8 @@ google.golang.org/grpc v1.40.1/go.mod h1:ogyxbiOoUXAkP+4+xa6PZSE9DZgIHtSpzjDTB9K google.golang.org/grpc v1.42.0/go.mod h1:k+4IHHFw41K8+bbowsex27ge2rCb65oeWqe4jJ590SU= google.golang.org/grpc v1.79.3 h1:sybAEdRIEtvcD68Gx7dmnwjZKlyfuc61Dyo9pGXXkKE= google.golang.org/grpc v1.79.3/go.mod h1:KmT0Kjez+0dde/v2j9vzwoAScgEPx/Bw1CYChhHLrHQ= +google.golang.org/grpc v1.80.0 h1:Xr6m2WmWZLETvUNvIUmeD5OAagMw3FiKmMlTdViWsHM= +google.golang.org/grpc v1.80.0/go.mod h1:ho/dLnxwi3EDJA4Zghp7k2Ec1+c2jqup0bFkw07bwF4= google.golang.org/grpc/cmd/protoc-gen-go-grpc v1.1.0/go.mod h1:6Kw0yEErY5E/yWrBtf03jp27GLLJujG4z/JK95pnjjw= google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= @@ -1701,6 +1773,8 @@ google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQ google.golang.org/protobuf v1.27.1/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= google.golang.org/protobuf v1.36.11 h1:fV6ZwhNocDyBLK0dj+fg8ektcVegBBuEolpbTQyBNVE= google.golang.org/protobuf v1.36.11/go.mod h1:HTf+CrKn2C3g5S8VImy6tdcUvCska2kB7j23XfzDpco= +google.golang.org/protobuf v1.36.12-0.20260120151049-f2248ac996af h1:+5/Sw3GsDNlEmu7TfklWKPdQ0Ykja5VEmq2i817+jbI= +google.golang.org/protobuf v1.36.12-0.20260120151049-f2248ac996af/go.mod h1:HTf+CrKn2C3g5S8VImy6tdcUvCska2kB7j23XfzDpco= gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= @@ -1742,26 +1816,40 @@ honnef.co/go/tools v0.0.1-2020.1.3/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9 honnef.co/go/tools v0.0.1-2020.1.4/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= k8s.io/api v0.35.1 h1:0PO/1FhlK/EQNVK5+txc4FuhQibV25VLSdLMmGpDE/Q= k8s.io/api v0.35.1/go.mod h1:28uR9xlXWml9eT0uaGo6y71xK86JBELShLy4wR1XtxM= +k8s.io/api v0.36.0 h1:SgqDhZzHdOtMk40xVSvCXkP9ME0H05hPM3p9AB1kL80= +k8s.io/api v0.36.0/go.mod h1:m1LVrGPNYax5NBHdO+QuAedXyuzTt4RryI/qnmNvs34= k8s.io/apiextensions-apiserver v0.35.1 h1:p5vvALkknlOcAqARwjS20kJffgzHqwyQRM8vHLwgU7w= k8s.io/apiextensions-apiserver v0.35.1/go.mod h1:2CN4fe1GZ3HMe4wBr25qXyJnJyZaquy4nNlNmb3R7AQ= k8s.io/apimachinery v0.35.1 h1:yxO6gV555P1YV0SANtnTjXYfiivaTPvCTKX6w6qdDsU= k8s.io/apimachinery v0.35.1/go.mod h1:jQCgFZFR1F4Ik7hvr2g84RTJSZegBc8yHgFWKn//hns= +k8s.io/apimachinery v0.36.0 h1:jZyPzhd5Z+3h9vJLt0z9XdzW9VzNzWAUw+P1xZ9PXtQ= +k8s.io/apimachinery v0.36.0/go.mod h1:FklypaRJt6n5wUIwWXIP6GJlIpUizTgfo1T/As+Tyxc= k8s.io/apiserver v0.35.1 h1:potxdhhTL4i6AYAa2QCwtlhtB1eCdWQFvJV6fXgJzxs= k8s.io/apiserver v0.35.1/go.mod h1:BiL6Dd3A2I/0lBnteXfWmCFobHM39vt5+hJQd7Lbpi4= k8s.io/cli-runtime v0.35.1 h1:uKcXFe8J7AMAM4Gm2JDK4mp198dBEq2nyeYtO+JfGJE= k8s.io/cli-runtime v0.35.1/go.mod h1:55/hiXIq1C8qIJ3WBrWxEwDLdHQYhBNRdZOz9f7yvTw= k8s.io/client-go v0.35.1 h1:+eSfZHwuo/I19PaSxqumjqZ9l5XiTEKbIaJ+j1wLcLM= k8s.io/client-go v0.35.1/go.mod h1:1p1KxDt3a0ruRfc/pG4qT/3oHmUj1AhSHEcxNSGg+OA= +k8s.io/client-go v0.36.0 h1:pOYi7C4RHChYjMiHpZSpSbIM6ZxVbRXBy7CuiIwqA3c= +k8s.io/client-go v0.36.0/go.mod h1:ZKKcpwF0aLYfkHFCjillCKaTK/yBkEDHTDXCFY6AS9Y= k8s.io/component-base v0.35.1 h1:XgvpRf4srp037QWfGBLFsYMUQJkE5yMa94UsJU7pmcE= k8s.io/component-base v0.35.1/go.mod h1:HI/6jXlwkiOL5zL9bqA3en1Ygv60F03oEpnuU1G56Bs= +k8s.io/component-base v0.36.0 h1:hFjEktssxiJhrK1zfybkH4kJOi8iZuF+mIDCqS5+jRo= +k8s.io/component-base v0.36.0/go.mod h1:JZvIfcNHk+uck+8LhJzhSBtydWXaZNQwX2OdL+Mnwsk= k8s.io/klog/v2 v2.130.1 h1:n9Xl7H1Xvksem4KFG4PYbdQCQxqc/tTUyrgXaOhHSzk= k8s.io/klog/v2 v2.130.1/go.mod h1:3Jpz1GvMt720eyJH1ckRHK1EDfpxISzJ7I9OYgaDtPE= +k8s.io/klog/v2 v2.140.0 h1:Tf+J3AH7xnUzZyVVXhTgGhEKnFqye14aadWv7bzXdzc= +k8s.io/klog/v2 v2.140.0/go.mod h1:o+/RWfJ6PwpnFn7OyAG3QnO47BFsymfEfrz6XyYSSp0= k8s.io/kube-openapi v0.0.0-20250910181357-589584f1c912 h1:Y3gxNAuB0OBLImH611+UDZcmKS3g6CthxToOb37KgwE= k8s.io/kube-openapi v0.0.0-20250910181357-589584f1c912/go.mod h1:kdmbQkyfwUagLfXIad1y2TdrjPFWp2Q89B3qkRwf/pQ= +k8s.io/kube-openapi v0.0.0-20260319004828-5883c5ee87b9 h1:Sztf7ESG9tAXRW/ACJZjrj5jhdOUqS2KFRQT+CTvu78= +k8s.io/kube-openapi v0.0.0-20260319004828-5883c5ee87b9/go.mod h1:uGBT7iTA6c6MvqUvSXIaYZo9ukscABYi2btjhvgKGZ0= k8s.io/kubectl v0.35.1 h1:zP3Er8C5i1dcAFUMh9Eva0kVvZHptXIn/+8NtRWMxwg= k8s.io/kubectl v0.35.1/go.mod h1:cQ2uAPs5IO/kx8R5s5J3Ihv3VCYwrx0obCXum0CvnXo= k8s.io/utils v0.0.0-20251002143259-bc988d571ff4 h1:SjGebBtkBqHFOli+05xYbK8YF1Dzkbzn+gDM4X9T4Ck= k8s.io/utils v0.0.0-20251002143259-bc988d571ff4/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0= +k8s.io/utils v0.0.0-20260319190234-28399d86e0b5 h1:kBawHLSnx/mYHmRnNUf9d4CpjREbeZuxoSGOX/J+aYM= +k8s.io/utils v0.0.0-20260319190234-28399d86e0b5/go.mod h1:xDxuJ0whA3d0I4mf/C4ppKHxXynQ+fxnkmQH0vTHnuk= modernc.org/cc/v4 v4.27.1 h1:9W30zRlYrefrDV2JE2O8VDtJ1yPGownxciz5rrbQZis= modernc.org/cc/v4 v4.27.1/go.mod h1:uVtb5OGqUKpoLWhqwNQo/8LwvoiEBLvZXIQ/SmO6mL0= modernc.org/ccgo/v4 v4.32.0 h1:hjG66bI/kqIPX1b2yT6fr/jt+QedtP2fqojG2VrFuVw= @@ -1807,5 +1895,7 @@ sigs.k8s.io/randfill v1.0.0 h1:JfjMILfT8A6RbawdsK2JXGBR5AQVfd+9TbzrlneTyrU= sigs.k8s.io/randfill v1.0.0/go.mod h1:XeLlZ/jmk4i1HRopwe7/aU3H5n1zNUcX6TM94b3QxOY= sigs.k8s.io/structured-merge-diff/v6 v6.3.0 h1:jTijUJbW353oVOd9oTlifJqOGEkUw2jB/fXCbTiQEco= sigs.k8s.io/structured-merge-diff/v6 v6.3.0/go.mod h1:M3W8sfWvn2HhQDIbGWj3S099YozAsymCo/wrT5ohRUE= +sigs.k8s.io/structured-merge-diff/v6 v6.3.2 h1:kwVWMx5yS1CrnFWA/2QHyRVJ8jM6dBA80uLmm0wJkk8= +sigs.k8s.io/structured-merge-diff/v6 v6.3.2/go.mod h1:M3W8sfWvn2HhQDIbGWj3S099YozAsymCo/wrT5ohRUE= sigs.k8s.io/yaml v1.6.0 h1:G8fkbMSAFqgEFgh4b1wmtzDnioxFCUgTZhlbj5P9QYs= sigs.k8s.io/yaml v1.6.0/go.mod h1:796bPqUfzR/0jLAl6XjHl3Ck7MiyVv8dbTdyT3/pMf4= From 65f4dd01c75b780dbe43f76652761185d854b1a2 Mon Sep 17 00:00:00 2001 From: atishj99 <141334503+cx-atish-jadhav@users.noreply.github.com> Date: Wed, 27 May 2026 12:41:37 +0530 Subject: [PATCH 04/27] Fix additional SCA vulnerabilities: containerd, golang.org/x/image, and opencontainers/runc - Upgrade github.com/containerd/containerd v1.7.30 to v1.7.32 (CVE-2026-46680) - Upgrade golang.org/x/image v0.25.0 to v0.36.1-0.20260211191414-e3d762b1d37e (CVE-2026-33813) - Upgrade github.com/opencontainers/runc v1.3.3 to v1.3.4 (CVE-2025-52881) - Upgrade github.com/cilium/ebpf v0.16.0 to v0.17.3 (transitive dependency) Co-Authored-By: Claude Haiku 4.5 --- go.mod | 20 +++++++++++++++++++- go.sum | 41 +++++++++++++++++++++++++++++++++++++++++ 2 files changed, 60 insertions(+), 1 deletion(-) diff --git a/go.mod b/go.mod index 2ac014f7f..afc5207b2 100644 --- a/go.mod +++ b/go.mod @@ -46,6 +46,8 @@ require ( cloud.google.com/go/monitoring v1.24.3 // indirect cloud.google.com/go/storage v1.61.3 // indirect cyphar.com/go-pathrs v0.2.1 // indirect + github.com/AdaLogics/go-fuzz-headers v0.0.0-20240806141605-e8a1dd7889d6 // indirect + github.com/AdamKorcz/go-118-fuzz-build v0.0.0-20240914100643-eb91380d8434 // indirect github.com/GoogleCloudPlatform/opentelemetry-operations-go/detectors/gcp v1.31.0 // indirect github.com/GoogleCloudPlatform/opentelemetry-operations-go/exporter/metric v0.55.0 // indirect github.com/GoogleCloudPlatform/opentelemetry-operations-go/internal/resourcemapping v0.55.0 // indirect @@ -79,18 +81,25 @@ require ( github.com/bodgit/sevenzip v1.6.1 // indirect github.com/bodgit/windows v1.0.1 // indirect github.com/cespare/xxhash/v2 v2.3.0 // indirect + github.com/checkpoint-restore/go-criu/v6 v6.3.0 // indirect + github.com/cilium/ebpf v0.17.3 // indirect github.com/clipperhouse/displaywidth v0.10.0 // indirect github.com/clipperhouse/uax29/v2 v2.6.0 // indirect github.com/cncf/xds/go v0.0.0-20251210132809-ee656c7534f5 // indirect + github.com/containerd/console v1.0.5 // indirect github.com/containerd/containerd/v2 v2.3.1 // indirect github.com/containerd/plugin v1.1.0 // indirect + github.com/coreos/go-systemd/v22 v22.7.0 // indirect + github.com/cpuguy83/go-md2man/v2 v2.0.7 // indirect github.com/diskfs/go-diskfs v1.7.0 // indirect github.com/distribution/distribution/v3 v3.0.1-0.20260120145532-40594bd98e6d // indirect + github.com/docker/go-events v0.0.0-20250114142523-c867878c5e32 // indirect github.com/envoyproxy/go-control-plane/envoy v1.36.0 // indirect github.com/envoyproxy/protoc-gen-validate v1.3.0 // indirect github.com/go-jose/go-jose/v3 v3.0.5 // indirect github.com/go-jose/go-jose/v4 v4.1.4 // indirect github.com/goccy/go-yaml v1.19.2 // indirect + github.com/godbus/dbus/v5 v5.1.0 // indirect github.com/gohugoio/hashstructure v0.6.0 // indirect github.com/google/s2a-go v0.1.9 // indirect github.com/googleapis/enterprise-certificate-proxy v0.3.14 // indirect @@ -107,21 +116,30 @@ require ( github.com/minio/minlz v1.0.1 // indirect github.com/moby/moby/api v1.54.1 // indirect github.com/moby/moby/client v0.4.0 // indirect + github.com/moby/sys/capability v0.4.0 // indirect + github.com/mrunalp/fileutils v0.5.1 // indirect github.com/nix-community/go-nix v0.0.0-20250101154619-4bdde671e0a1 // indirect github.com/nwaples/rardecode/v2 v2.2.0 // indirect github.com/olekukonko/cat v0.0.0-20250911104152-50322a0618f6 // indirect github.com/olekukonko/errors v1.2.0 // indirect github.com/olekukonko/ll v0.1.6 // indirect + github.com/opencontainers/cgroups v0.0.4 // indirect + github.com/opencontainers/runc v1.3.4 // indirect github.com/pkg/xattr v0.4.9 // indirect github.com/planetscale/vtprotobuf v0.6.1-0.20240319094008-0393e58bdf10 // indirect + github.com/seccomp/libseccomp-golang v0.10.0 // indirect github.com/smallnest/ringbuffer v0.0.0-20241116012123-461381446e3d // indirect github.com/sorairolake/lzip-go v0.3.8 // indirect github.com/spiffe/go-spiffe/v2 v2.6.0 // indirect + github.com/urfave/cli v1.22.16 // indirect + github.com/vishvananda/netlink v1.3.1 // indirect + github.com/vishvananda/netns v0.0.5 // indirect go.opentelemetry.io/contrib/detectors/gcp v1.39.0 // indirect go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.68.0 // indirect go.opentelemetry.io/otel/sdk v1.43.0 // indirect go.opentelemetry.io/otel/sdk/metric v1.43.0 // indirect go4.org v0.0.0-20230225012048-214862532bf5 // indirect + golang.org/x/image v0.36.1-0.20260211191414-e3d762b1d37e // indirect gonum.org/v1/gonum v0.17.0 // indirect google.golang.org/api v0.271.0 // indirect google.golang.org/genproto/googleapis/api v0.0.0-20260401024825-9d38bb4040a9 // indirect @@ -177,7 +195,7 @@ require ( github.com/charmbracelet/x/term v0.2.2 // indirect github.com/cloudflare/circl v1.6.3 // indirect github.com/containerd/cgroups/v3 v3.1.3 // indirect - github.com/containerd/containerd v1.7.30 // indirect + github.com/containerd/containerd v1.7.32 // indirect github.com/containerd/containerd/api v1.11.1 // indirect github.com/containerd/continuity v0.5.0 // indirect github.com/containerd/errdefs v1.0.0 // indirect diff --git a/go.sum b/go.sum index d46acad4d..a63a6355c 100644 --- a/go.sum +++ b/go.sum @@ -76,12 +76,15 @@ filippo.io/edwards25519 v1.1.0 h1:FNf4tywRC1HmFuKW5xopWpigGjJKiJSV0Cqo0cJWDaA= filippo.io/edwards25519 v1.1.0/go.mod h1:BxyFTGdWcka3PhytdK4V28tE5sGfRvvvRV7EaN4VDT4= github.com/AdaLogics/go-fuzz-headers v0.0.0-20240806141605-e8a1dd7889d6 h1:He8afgbRMd7mFxO99hRNu+6tazq8nFF9lIwo9JFroBk= github.com/AdaLogics/go-fuzz-headers v0.0.0-20240806141605-e8a1dd7889d6/go.mod h1:8o94RPi1/7XTJvwPpRSzSUedZrtlirdB3r9Z20bi2f8= +github.com/AdamKorcz/go-118-fuzz-build v0.0.0-20240914100643-eb91380d8434 h1:t9mXVk8SurivauUmW28nWggC/aOm5NBZ+U2ddBfbyP8= +github.com/AdamKorcz/go-118-fuzz-build v0.0.0-20240914100643-eb91380d8434/go.mod h1:n+tj8pffsLO7fLdcrnbfl444A2OwGv8a6ISsac75Wow= github.com/Azure/go-ansiterm v0.0.0-20250102033503-faa5f7b0171c h1:udKWzYgxTojEKWjV8V+WSxDXJ4NFATAsZjh8iIbsQIg= github.com/Azure/go-ansiterm v0.0.0-20250102033503-faa5f7b0171c/go.mod h1:xomTg63KZ2rFqZQzSB4Vz2SUXa1BpHTVz9L5PTmPC4E= github.com/BobuSumisu/aho-corasick v1.0.3 h1:uuf+JHwU9CHP2Vx+wAy6jcksJThhJS9ehR8a+4nPE9g= github.com/BobuSumisu/aho-corasick v1.0.3/go.mod h1:hm4jLcvZKI2vRF2WDU1N4p/jpWtpOzp3nLmi9AzX/XE= github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= github.com/BurntSushi/toml v0.4.1/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbicEuybxQ= +github.com/BurntSushi/toml v1.4.0/go.mod h1:ukJfTF/6rtPPRCnwkur4qwRxa8vTRFBF0uk2lLoLwho= github.com/BurntSushi/toml v1.6.0 h1:dRaEfpa2VI55EwlIW72hMRHdWouJeRF7TPYhI+AUQjk= github.com/BurntSushi/toml v1.6.0/go.mod h1:ukJfTF/6rtPPRCnwkur4qwRxa8vTRFBF0uk2lLoLwho= github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo= @@ -307,6 +310,8 @@ github.com/charmbracelet/x/term v0.2.2 h1:xVRT/S2ZcKdhhOuSP4t5cLi5o+JxklsoEObBSg github.com/charmbracelet/x/term v0.2.2/go.mod h1:kF8CY5RddLWrsgVwpw4kAa6TESp6EB5y3uxGLeCqzAI= github.com/checkmarx/2ms/v3 v3.21.0 h1:EcabeDypNMsSidISQbziZ062HjMZQ+Hm/uOJ5AOxK8o= github.com/checkmarx/2ms/v3 v3.21.0/go.mod h1:e8f4F94MZ+iCetR/G3aw7nXdPe6TgPI92Zzk/NG1l0o= +github.com/checkpoint-restore/go-criu/v6 v6.3.0 h1:mIdrSO2cPNWQY1truPg6uHLXyKHk3Z5Odx4wjKOASzA= +github.com/checkpoint-restore/go-criu/v6 v6.3.0/go.mod h1:rrRTN/uSwY2X+BPRl/gkulo9gsKOSAeVp9/K2tv7xZI= github.com/chromedp/cdproto v0.0.0-20230802225258-3cf4e6d46a89/go.mod h1:GKljq0VrfU4D5yc+2qA6OVr8pmO/MBbPEWqWQ/oqGEs= github.com/chromedp/chromedp v0.9.2/go.mod h1:LkSXJKONWTCHAfQasKFUZI+mxqS4tZqhmtGzzhLsnLs= github.com/chromedp/sysutil v1.0.0/go.mod h1:kgWmDdq8fTzXYcKIBqIYvRRTnYb9aNS9moAV0xufSww= @@ -316,6 +321,8 @@ github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5P github.com/chzyer/readline v1.5.1/go.mod h1:Eh+b79XXUwfKfcPLepksvw2tcLE/Ct21YObkaSkeBlk= github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU= github.com/chzyer/test v1.0.0/go.mod h1:2JlltgoNkt4TW/z9V/IzDdFaMTM2JPIi26O1pF38GC8= +github.com/cilium/ebpf v0.17.3 h1:FnP4r16PWYSE4ux6zN+//jMcW4nMVRvuTLVTvCjyyjg= +github.com/cilium/ebpf v0.17.3/go.mod h1:G5EDHij8yiLzaqn0WjyfJHvRa+3aDlReIaLVRMvOyJk= github.com/circonus-labs/circonus-gometrics v2.3.1+incompatible/go.mod h1:nmEj6Dob7S7YxXgwXpfOuvO54S+tGdZdw9fuRZt25Ag= github.com/circonus-labs/circonusllhist v0.1.3/go.mod h1:kMXHVDlOchFAehlya5ePtbp5jckzBHf4XRpQvBOLI+I= github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= @@ -341,6 +348,8 @@ github.com/containerd/cgroups/v3 v3.1.2 h1:OSosXMtkhI6Qove637tg1XgK4q+DhR0mX8Wi8 github.com/containerd/cgroups/v3 v3.1.2/go.mod h1:PKZ2AcWmSBsY/tJUVhtS/rluX0b1uq1GmPO1ElCmbOw= github.com/containerd/cgroups/v3 v3.1.3 h1:eUNflyMddm18+yrDmZPn3jI7C5hJ9ahABE5q6dyLYXQ= github.com/containerd/cgroups/v3 v3.1.3/go.mod h1:PKZ2AcWmSBsY/tJUVhtS/rluX0b1uq1GmPO1ElCmbOw= +github.com/containerd/console v1.0.5 h1:R0ymNeydRqH2DmakFNdmjR2k0t7UPuiOV/N/27/qqsc= +github.com/containerd/console v1.0.5/go.mod h1:YynlIjWYF8myEu6sdkwKIvGQq+cOckRm6So2avqoYAk= github.com/containerd/containerd v1.7.32 h1:S54xuVcPxeLaYgaRABtpJ2VyVUVsy0IGf7qHBs+sbY8= github.com/containerd/containerd v1.7.32/go.mod h1:jdwD6s/BhV4XVJGrvtziNPVA+83n66TwptVaPKprq4E= github.com/containerd/containerd/api v1.10.0 h1:5n0oHYVBwN4VhoX9fFykCV9dF1/BvAXeg2F8W6UYq1o= @@ -387,8 +396,13 @@ github.com/coreos/go-systemd/v22 v22.5.0/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSV github.com/coreos/go-systemd/v22 v22.6.0 h1:aGVa/v8B7hpb0TKl0MWoAavPDmHvobFe5R5zn0bCJWo= github.com/coreos/go-systemd/v22 v22.6.0/go.mod h1:iG+pp635Fo7ZmV/j14KUcmEyWF+0X7Lua8rrTWzYgWU= github.com/coreos/go-systemd/v22 v22.7.0 h1:LAEzFkke61DFROc7zNLX/WA2i5J8gYqe0rSj9KI28KA= +github.com/coreos/go-systemd/v22 v22.7.0/go.mod h1:xNUYtjHu2EDXbsxz1i41wouACIwT7Ybq9o0BQhMwD0w= github.com/cpuguy83/go-md2man/v2 v2.0.1/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= +github.com/cpuguy83/go-md2man/v2 v2.0.2/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= +github.com/cpuguy83/go-md2man/v2 v2.0.5/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= github.com/cpuguy83/go-md2man/v2 v2.0.6/go.mod h1:oOW0eioCTA6cOiMLiUPZOpcVxMig6NIQQ7OS05n1F4g= +github.com/cpuguy83/go-md2man/v2 v2.0.7 h1:zbFlGlXEAKlwXpmvle3d8Oe3YnkKIK4xSRTd3sHPnBo= +github.com/cpuguy83/go-md2man/v2 v2.0.7/go.mod h1:oOW0eioCTA6cOiMLiUPZOpcVxMig6NIQQ7OS05n1F4g= github.com/creack/pty v1.1.24 h1:bJrF4RRfyJnbTJqzRLHzcGaZK1NeM5kTC9jGgovnR1s= github.com/creack/pty v1.1.24/go.mod h1:08sCNb52WyoAwi2QDyzUCTgcvVFhUzewun7wtTfvcwE= github.com/cyphar/filepath-securejoin v0.6.1 h1:5CeZ1jPXEiYt3+Z6zqprSAgSWiggmpVyciv8syjIpVE= @@ -570,6 +584,8 @@ github.com/gobwas/ws v1.2.1/go.mod h1:hRKAFb8wOxFROYNsT1bqfWnhX+b5MFeJM9r2ZSwg/K github.com/goccy/go-yaml v1.19.2 h1:PmFC1S6h8ljIz6gMRBopkjP1TVT7xuwrButHID66PoM= github.com/goccy/go-yaml v1.19.2/go.mod h1:XBurs7gK8ATbW4ZPGKgcbrY1Br56PdM69F7LkFRi1kA= github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= +github.com/godbus/dbus/v5 v5.1.0 h1:4KLkAxT3aOY8Li4FRJe/KvhoNFFxo0m6fNuFUO8QJUk= +github.com/godbus/dbus/v5 v5.1.0/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= github.com/gofrs/flock v0.13.0 h1:95JolYOvGMqeH31+FC7D2+uULf6mG61mEZ/A8dRYMzw= github.com/gofrs/flock v0.13.0/go.mod h1:jxeyy9R1auM5S6JYDBhDt+E2TCo7DkratH4Pgi8P+Z0= github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= @@ -912,6 +928,8 @@ github.com/moby/moby/api v1.54.1 h1:TqVzuJkOLsgLDDwNLmYqACUuTehOHRGKiPhvH8V3Nn4= github.com/moby/moby/api v1.54.1/go.mod h1:+RQ6wluLwtYaTd1WnPLykIDPekkuyD/ROWQClE83pzs= github.com/moby/moby/client v0.4.0 h1:S+2XegzHQrrvTCvF6s5HFzcrywWQmuVnhOXe2kiWjIw= github.com/moby/moby/client v0.4.0/go.mod h1:QWPbvWchQbxBNdaLSpoKpCdf5E+WxFAgNHogCWDoa7g= +github.com/moby/sys/capability v0.4.0 h1:4D4mI6KlNtWMCM1Z/K0i7RV1FkX+DBDHKVJpCndZoHk= +github.com/moby/sys/capability v0.4.0/go.mod h1:4g9IK291rVkms3LKCDOoYlnV8xKwoDTpIrNEE35Wq0I= github.com/moby/sys/mountinfo v0.7.2 h1:1shs6aH5s4o5H2zQLn796ADW1wMrIwHsyJ2v9KouLrg= github.com/moby/sys/mountinfo v0.7.2/go.mod h1:1YOa8w8Ih7uW0wALDUgT1dTTSBrZ+HiBLGws92L2RU4= github.com/moby/sys/sequential v0.6.0 h1:qrx7XFUd/5DxtqcoH1h438hF5TmOvzC/lspjy7zgvCU= @@ -934,6 +952,8 @@ github.com/modern-go/reflect2 v1.0.3-0.20250322232337-35a7c28c31ee h1:W5t00kpgFd github.com/modern-go/reflect2 v1.0.3-0.20250322232337-35a7c28c31ee/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk= github.com/monochromegane/go-gitignore v0.0.0-20200626010858-205db1a8cc00 h1:n6/2gBQ3RWajuToeY6ZtZTIKv2v7ThUy5KKusIT0yc0= github.com/monochromegane/go-gitignore v0.0.0-20200626010858-205db1a8cc00/go.mod h1:Pm3mSP3c5uWn86xMLZ5Sa7JB9GsEZySvHYXCTK4E9q4= +github.com/mrunalp/fileutils v0.5.1 h1:F+S7ZlNKnrwHfSwdlgNSkKo67ReVf8o9fel6C3dkm/Q= +github.com/mrunalp/fileutils v0.5.1/go.mod h1:M1WthSahJixYnrXQl/DFQuteStB1weuxD2QJNHXfbSQ= github.com/mssola/user_agent v0.6.0 h1:uwPR4rtWlCHRFyyP9u2KOV0u8iQXmS7Z7feTrstQwk4= github.com/mssola/user_agent v0.6.0/go.mod h1:TTPno8LPY3wAIEKRpAtkdMT0f8SE24pLRGPahjCH4uw= github.com/muesli/ansi v0.0.0-20230316100256-276c6243b2f6 h1:ZK8zHtRHOkbHy6Mmr5D264iyp3TiX5OmNcI5cIARiQI= @@ -965,10 +985,14 @@ github.com/onsi/ginkgo/v2 v2.27.2 h1:LzwLj0b89qtIy6SSASkzlNvX6WktqurSHwkk2ipF/Ns github.com/onsi/ginkgo/v2 v2.27.2/go.mod h1:ArE1D/XhNXBXCBkKOLkbsb2c81dQHCRcF5zwn/ykDRo= github.com/onsi/gomega v1.38.2 h1:eZCjf2xjZAqe+LeWvKb5weQ+NcPwX84kqJ0cZNxok2A= github.com/onsi/gomega v1.38.2/go.mod h1:W2MJcYxRGV63b418Ai34Ud0hEdTVXq9NW9+Sx6uXf3k= +github.com/opencontainers/cgroups v0.0.4 h1:XVj8P/IHVms/j+7eh8ggdkTLAxjz84ZzuFyGoE28DR4= +github.com/opencontainers/cgroups v0.0.4/go.mod h1:s8lktyhlGUqM7OSRL5P7eAW6Wb+kWPNvt4qvVfzA5vs= github.com/opencontainers/go-digest v1.0.0 h1:apOUWs51W5PlhuyGyz9FCeeBIOUDA/6nW8Oi/yOhh5U= github.com/opencontainers/go-digest v1.0.0/go.mod h1:0JzlMkj0TRzQZfJkVvzbP0HBR3IKzErnv2BNG4W4MAM= github.com/opencontainers/image-spec v1.1.1 h1:y0fUlFfIZhPF1W537XOLg0/fcx6zcHCJwooC2xJA040= github.com/opencontainers/image-spec v1.1.1/go.mod h1:qpqAh3Dmcf36wStyyWU+kCeDgrGnAve2nCC8+7h8Q0M= +github.com/opencontainers/runc v1.3.4 h1:+lwmPUTzbgv0JFqu8zBU2WtHYbm+JPPS9hxB/PvWd30= +github.com/opencontainers/runc v1.3.4/go.mod h1:o1wyv76EDlTkcf0KTFgN8bMWLPvgF/HfX709lDv+rr4= github.com/opencontainers/runtime-spec v1.3.0 h1:YZupQUdctfhpZy3TM39nN9Ika5CBWT5diQ8ibYCRkxg= github.com/opencontainers/runtime-spec v1.3.0/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0= github.com/opencontainers/selinux v1.13.0 h1:Zza88GWezyT7RLql12URvoxsbLfjFx988+LGaWfbL84= @@ -1076,6 +1100,8 @@ github.com/scylladb/go-set v1.0.3-0.20200225121959-cc7b2070d91e/go.mod h1:DkpGd7 github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529/go.mod h1:DxrIzT+xaE7yg65j358z/aeFdxmN0P9QXhEzd20vsDc= github.com/sebdah/goldie/v2 v2.8.0 h1:dZb9wR8q5++oplmEiJT+U/5KyotVD+HNGCAc5gNr8rc= github.com/sebdah/goldie/v2 v2.8.0/go.mod h1:oZ9fp0+se1eapSRjfYbsV/0Hqhbuu3bJVvKI/NNtssI= +github.com/seccomp/libseccomp-golang v0.10.0 h1:aA4bp+/Zzi0BnWZ2F1wgNBs5gTpm+na2rWM6M9YjLpY= +github.com/seccomp/libseccomp-golang v0.10.0/go.mod h1:JA8cRccbGaA1s33RQf7Y1+q9gHmZX1yB/z9WDN1C6fg= github.com/sergi/go-diff v1.1.0/go.mod h1:STckp+ISIX8hZLjrqAeVduY0gWCT9IjLuqbuNXdaHfM= github.com/sergi/go-diff v1.2.0/go.mod h1:STckp+ISIX8hZLjrqAeVduY0gWCT9IjLuqbuNXdaHfM= github.com/sergi/go-diff v1.4.0 h1:n/SP9D5ad1fORl+llWyN+D6qoUETXNZARKjyY2/KVCw= @@ -1112,6 +1138,7 @@ github.com/spf13/cast v1.4.1/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkU github.com/spf13/cast v1.10.0 h1:h2x0u2shc1QuLHfxi+cTJvs30+ZAHOGRic8uyGTDWxY= github.com/spf13/cast v1.10.0/go.mod h1:jNfB8QC9IA6ZuY2ZjDp0KtFO2LZZlg4S/7bzP6qqeHo= github.com/spf13/cobra v1.3.0/go.mod h1:BrRVncBjOJa/eUcVVm9CE+oC6as8k+VYr4NY7WCi9V4= +github.com/spf13/cobra v1.5.0/go.mod h1:dWXEIy2H428czQCjInthrTRUg7yKbok+2Qi/yBIJoUM= github.com/spf13/cobra v1.10.2 h1:DMTTonx5m65Ic0GOoRY2c16WCbHxOOw6xxezuLaBpcU= github.com/spf13/cobra v1.10.2/go.mod h1:7C1pvHqHw5A4vrJfjNwvOdzYu0Gml16OCs2GRiTUUS4= github.com/spf13/jwalterweatherman v1.1.0/go.mod h1:aNWZUN0dPAAO/Ljvb5BEdw96iTZ0EXowPYD95IqWIGo= @@ -1139,6 +1166,8 @@ github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/ github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= +github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= +github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= github.com/stretchr/testify v1.11.1 h1:7s2iGBzp5EwR7/aIZr8ao5+dra3wiQyKjjFuvgVKu7U= github.com/stretchr/testify v1.11.1/go.mod h1:wZwfW3scLgRK+23gO65QZefKpKQRnfz6sD981Nm4B6U= github.com/subosito/gotenv v1.2.0/go.mod h1:N0PQaV/YGNqwC0u51sEeR/aUtSLEXKX9iv69rRypqCw= @@ -1166,12 +1195,18 @@ github.com/tv42/httpunix v0.0.0-20150427012821-b75d8614f926/go.mod h1:9ESjWnEqri github.com/ulikunitz/xz v0.5.8/go.mod h1:nbz6k7qbPmH4IRqmfOplQw/tblSgqTqBwxkY0oWt/14= github.com/ulikunitz/xz v0.5.15 h1:9DNdB5s+SgV3bQ2ApL10xRc35ck0DuIX/isZvIk+ubY= github.com/ulikunitz/xz v0.5.15/go.mod h1:nbz6k7qbPmH4IRqmfOplQw/tblSgqTqBwxkY0oWt/14= +github.com/urfave/cli v1.22.16 h1:MH0k6uJxdwdeWQTwhSO42Pwr4YLrNLwBtg1MRgTqPdQ= +github.com/urfave/cli v1.22.16/go.mod h1:EeJR6BKodywf4zciqrdw6hpCPk68JO9z5LazXZMn5Po= github.com/vbatts/go-mtree v0.7.0 h1:ytmOc3MTRidZiBi9VBCyZ2BHe4fZS47L5v7BVXDWW4E= github.com/vbatts/go-mtree v0.7.0/go.mod h1:EjdpFC+LZy1TXbRGNa1MKKgjQ+7ew3foMFJK8o4/TdY= github.com/vbatts/tar-split v0.12.2 h1:w/Y6tjxpeiFMR47yzZPlPj/FcPLpXbTUi/9H7d3CPa4= github.com/vbatts/tar-split v0.12.2/go.mod h1:eF6B6i6ftWQcDqEn3/iGFRFRo8cBIMSJVOpnNdfTMFA= github.com/vifraa/gopom v1.0.0 h1:L9XlKbyvid8PAIK8nr0lihMApJQg/12OBvMA28BcWh0= github.com/vifraa/gopom v1.0.0/go.mod h1:oPa1dcrGrtlO37WPDBm5SqHAT+wTgF8An1Q71Z6Vv4o= +github.com/vishvananda/netlink v1.3.1 h1:3AEMt62VKqz90r0tmNhog0r/PpWKmrEShJU0wJW6bV0= +github.com/vishvananda/netlink v1.3.1/go.mod h1:ARtKouGSTGchR8aMwmkzC0qiNPrrWO5JS/XMVl45+b4= +github.com/vishvananda/netns v0.0.5 h1:DfiHV+j8bA32MFM7bfEunvT8IAqQ/NzSJHtcmW5zdEY= +github.com/vishvananda/netns v0.0.5/go.mod h1:SpkAiCQRtJ6TvvxPnOSyH3BMl6unz3xZlaprSwhNNJM= github.com/wagoodman/go-partybus v0.0.0-20230516145632-8ccac152c651 h1:jIVmlAFIqV3d+DOxazTR9v+zgj8+VYuQBzPgBZvWBHA= github.com/wagoodman/go-partybus v0.0.0-20230516145632-8ccac152c651/go.mod h1:b26F2tHLqaoRQf8DywqzVaV1MQ9yvjb0OMcNl7Nxu20= github.com/wagoodman/go-progress v0.0.0-20260303201901-10176f79b2c0 h1:EHsPe0Q0ANoLOZff1dBLAyeWLTA4sbPTpGI+2zb0FnM= @@ -1328,6 +1363,8 @@ golang.org/x/exp v0.0.0-20260410095643-746e56fc9e2f h1:W3F4c+6OLc6H2lb//N1q4WpJk golang.org/x/exp v0.0.0-20260410095643-746e56fc9e2f/go.mod h1:J1xhfL/vlindoeF/aINzNzt2Bket5bjo9sdOYzOsU80= golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js= golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= +golang.org/x/image v0.36.1-0.20260211191414-e3d762b1d37e h1:gkwT7ZpRdJBB47MJ0h7xeUSHKkd8f3RcM47FgUIRgd4= +golang.org/x/image v0.36.1-0.20260211191414-e3d762b1d37e/go.mod h1:ZK2ak7W75f61R/Pwr7T25elpTMmDbUsuiOt4FcDsNI0= golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU= golang.org/x/lint v0.0.0-20190301231843-5614ed5bae6f/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= @@ -1511,9 +1548,12 @@ golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.2.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.10.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.17.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/sys v0.43.0 h1:Rlag2XtaFTxp19wS8MXlJwTvoh8ArU6ezoyFsMyCTNI= @@ -1771,6 +1811,7 @@ google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlba google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= google.golang.org/protobuf v1.27.1/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= +google.golang.org/protobuf v1.28.1/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= google.golang.org/protobuf v1.36.11 h1:fV6ZwhNocDyBLK0dj+fg8ektcVegBBuEolpbTQyBNVE= google.golang.org/protobuf v1.36.11/go.mod h1:HTf+CrKn2C3g5S8VImy6tdcUvCska2kB7j23XfzDpco= google.golang.org/protobuf v1.36.12-0.20260120151049-f2248ac996af h1:+5/Sw3GsDNlEmu7TfklWKPdQ0Ykja5VEmq2i817+jbI= From e4e3aadc4d16e366f175921f29703d80aae0663c Mon Sep 17 00:00:00 2001 From: atishj99 <141334503+cx-atish-jadhav@users.noreply.github.com> Date: Wed, 27 May 2026 16:54:08 +0530 Subject: [PATCH 05/27] Fix k8s.io/kubectl version mismatch after SCA dependency upgrades Upgrade k8s.io/kubectl from v0.35.1 to v0.36.0 to resolve missing package k8s.io/api/scheduling/v1alpha1 caused by k8s.io/api being upgraded to v0.36.0 during SCA vulnerability remediation. Co-Authored-By: Claude Haiku 4.5 --- go.mod | 10 +++++----- go.sum | 12 ++++++++++++ 2 files changed, 17 insertions(+), 5 deletions(-) diff --git a/go.mod b/go.mod index afc5207b2..8cd6ba556 100644 --- a/go.mod +++ b/go.mod @@ -252,7 +252,7 @@ require ( github.com/google/go-cmp v0.7.0 // indirect github.com/google/go-containerregistry v0.21.5 // indirect github.com/google/licensecheck v0.3.1 // indirect - github.com/google/pprof v0.0.0-20250820193118-f64d9cf942d6 // indirect + github.com/google/pprof v0.0.0-20260115054156-294ebfa9ad83 // indirect github.com/gorilla/websocket v1.5.4-0.20250319132907-e064f32e3674 // indirect github.com/gosuri/uitable v0.0.4 // indirect github.com/gregjones/httpcache v0.0.0-20190611155906-901d90724c79 // indirect @@ -392,12 +392,12 @@ require ( k8s.io/apiextensions-apiserver v0.35.1 // indirect k8s.io/apimachinery v0.36.0 // indirect k8s.io/apiserver v0.35.1 // indirect - k8s.io/cli-runtime v0.35.1 // indirect + k8s.io/cli-runtime v0.36.0 // indirect k8s.io/client-go v0.36.0 // indirect k8s.io/component-base v0.36.0 // indirect k8s.io/klog/v2 v2.140.0 // indirect k8s.io/kube-openapi v0.0.0-20260319004828-5883c5ee87b9 // indirect - k8s.io/kubectl v0.35.1 // indirect + k8s.io/kubectl v0.36.0 // indirect k8s.io/utils v0.0.0-20260319190234-28399d86e0b5 // indirect modernc.org/libc v1.70.0 // indirect modernc.org/mathutil v1.7.1 // indirect @@ -405,8 +405,8 @@ require ( modernc.org/sqlite v1.46.2 // indirect oras.land/oras-go/v2 v2.6.0 // indirect sigs.k8s.io/json v0.0.0-20250730193827-2d320260d730 // indirect - sigs.k8s.io/kustomize/api v0.20.1 // indirect - sigs.k8s.io/kustomize/kyaml v0.20.1 // indirect + sigs.k8s.io/kustomize/api v0.21.1 // indirect + sigs.k8s.io/kustomize/kyaml v0.21.1 // indirect sigs.k8s.io/randfill v1.0.0 // indirect sigs.k8s.io/yaml v1.6.0 // indirect ) diff --git a/go.sum b/go.sum index a63a6355c..5db673f17 100644 --- a/go.sum +++ b/go.sum @@ -685,6 +685,8 @@ github.com/google/pprof v0.0.0-20211214055906-6f57359322fd/go.mod h1:KgnwoLYCZ8I github.com/google/pprof v0.0.0-20240227163752-401108e1b7e7/go.mod h1:czg5+yv1E0ZGTi6S6vVK1mke0fV+FaUhNGcd6VRS9Ik= github.com/google/pprof v0.0.0-20250820193118-f64d9cf942d6 h1:EEHtgt9IwisQ2AZ4pIsMjahcegHh6rmhqxzIRQIyepY= github.com/google/pprof v0.0.0-20250820193118-f64d9cf942d6/go.mod h1:I6V7YzU0XDpsHqbsyrghnFZLO1gwK6NPTNvmetQIk9U= +github.com/google/pprof v0.0.0-20260115054156-294ebfa9ad83 h1:z2ogiKUYzX5Is6zr/vP9vJGqPwcdqsWjOt+V8J7+bTc= +github.com/google/pprof v0.0.0-20260115054156-294ebfa9ad83/go.mod h1:MxpfABSjhmINe3F1It9d+8exIHFvUqtLIRCdOGNXqiI= github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= github.com/google/s2a-go v0.1.9 h1:LGD7gtMgezd8a/Xak7mEWL0PjoTQFvpRudN895yqKW0= github.com/google/s2a-go v0.1.9/go.mod h1:YA0Ei2ZQL3acow2O62kdp9UlnvMmU7kA6Eutn0dXayM= @@ -983,8 +985,10 @@ github.com/olekukonko/tablewriter v1.1.4 h1:ORUMI3dXbMnRlRggJX3+q7OzQFDdvgbN9nVW github.com/olekukonko/tablewriter v1.1.4/go.mod h1:+kedxuyTtgoZLwif3P1Em4hARJs+mVnzKxmsCL/C5RY= github.com/onsi/ginkgo/v2 v2.27.2 h1:LzwLj0b89qtIy6SSASkzlNvX6WktqurSHwkk2ipF/Ns= github.com/onsi/ginkgo/v2 v2.27.2/go.mod h1:ArE1D/XhNXBXCBkKOLkbsb2c81dQHCRcF5zwn/ykDRo= +github.com/onsi/ginkgo/v2 v2.28.1 h1:S4hj+HbZp40fNKuLUQOYLDgZLwNUVn19N3Atb98NCyI= github.com/onsi/gomega v1.38.2 h1:eZCjf2xjZAqe+LeWvKb5weQ+NcPwX84kqJ0cZNxok2A= github.com/onsi/gomega v1.38.2/go.mod h1:W2MJcYxRGV63b418Ai34Ud0hEdTVXq9NW9+Sx6uXf3k= +github.com/onsi/gomega v1.39.1 h1:1IJLAad4zjPn2PsnhH70V4DKRFlrCzGBNrNaru+Vf28= github.com/opencontainers/cgroups v0.0.4 h1:XVj8P/IHVms/j+7eh8ggdkTLAxjz84ZzuFyGoE28DR4= github.com/opencontainers/cgroups v0.0.4/go.mod h1:s8lktyhlGUqM7OSRL5P7eAW6Wb+kWPNvt4qvVfzA5vs= github.com/opencontainers/go-digest v1.0.0 h1:apOUWs51W5PlhuyGyz9FCeeBIOUDA/6nW8Oi/yOhh5U= @@ -1869,6 +1873,8 @@ k8s.io/apiserver v0.35.1 h1:potxdhhTL4i6AYAa2QCwtlhtB1eCdWQFvJV6fXgJzxs= k8s.io/apiserver v0.35.1/go.mod h1:BiL6Dd3A2I/0lBnteXfWmCFobHM39vt5+hJQd7Lbpi4= k8s.io/cli-runtime v0.35.1 h1:uKcXFe8J7AMAM4Gm2JDK4mp198dBEq2nyeYtO+JfGJE= k8s.io/cli-runtime v0.35.1/go.mod h1:55/hiXIq1C8qIJ3WBrWxEwDLdHQYhBNRdZOz9f7yvTw= +k8s.io/cli-runtime v0.36.0 h1:HNxciQpQMMOKS0/GiUXcKDyA6J2FDILJj9NmP2BZrTg= +k8s.io/cli-runtime v0.36.0/go.mod h1:KObkknK9Ro5LYX+1RdiKc7C8CvGg4aX+V/Zv+E8WPHA= k8s.io/client-go v0.35.1 h1:+eSfZHwuo/I19PaSxqumjqZ9l5XiTEKbIaJ+j1wLcLM= k8s.io/client-go v0.35.1/go.mod h1:1p1KxDt3a0ruRfc/pG4qT/3oHmUj1AhSHEcxNSGg+OA= k8s.io/client-go v0.36.0 h1:pOYi7C4RHChYjMiHpZSpSbIM6ZxVbRXBy7CuiIwqA3c= @@ -1887,6 +1893,8 @@ k8s.io/kube-openapi v0.0.0-20260319004828-5883c5ee87b9 h1:Sztf7ESG9tAXRW/ACJZjrj k8s.io/kube-openapi v0.0.0-20260319004828-5883c5ee87b9/go.mod h1:uGBT7iTA6c6MvqUvSXIaYZo9ukscABYi2btjhvgKGZ0= k8s.io/kubectl v0.35.1 h1:zP3Er8C5i1dcAFUMh9Eva0kVvZHptXIn/+8NtRWMxwg= k8s.io/kubectl v0.35.1/go.mod h1:cQ2uAPs5IO/kx8R5s5J3Ihv3VCYwrx0obCXum0CvnXo= +k8s.io/kubectl v0.36.0 h1:hEGr8NvIm2Wjqs2Xy48Uzmvo6lpHdGKlLyMvau2gTms= +k8s.io/kubectl v0.36.0/go.mod h1:iDe8aV5BEi45W8k+5n71I2pJ/nwE0PHDu+/2cejzYoo= k8s.io/utils v0.0.0-20251002143259-bc988d571ff4 h1:SjGebBtkBqHFOli+05xYbK8YF1Dzkbzn+gDM4X9T4Ck= k8s.io/utils v0.0.0-20251002143259-bc988d571ff4/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0= k8s.io/utils v0.0.0-20260319190234-28399d86e0b5 h1:kBawHLSnx/mYHmRnNUf9d4CpjREbeZuxoSGOX/J+aYM= @@ -1930,8 +1938,12 @@ sigs.k8s.io/json v0.0.0-20250730193827-2d320260d730 h1:IpInykpT6ceI+QxKBbEflcR5E sigs.k8s.io/json v0.0.0-20250730193827-2d320260d730/go.mod h1:mdzfpAEoE6DHQEN0uh9ZbOCuHbLK5wOm7dK4ctXE9Tg= sigs.k8s.io/kustomize/api v0.20.1 h1:iWP1Ydh3/lmldBnH/S5RXgT98vWYMaTUL1ADcr+Sv7I= sigs.k8s.io/kustomize/api v0.20.1/go.mod h1:t6hUFxO+Ph0VxIk1sKp1WS0dOjbPCtLJ4p8aADLwqjM= +sigs.k8s.io/kustomize/api v0.21.1 h1:lzqbzvz2CSvsjIUZUBNFKtIMsEw7hVLJp0JeSIVmuJs= +sigs.k8s.io/kustomize/api v0.21.1/go.mod h1:f3wkKByTrgpgltLgySCntrYoq5d3q7aaxveSagwTlwI= sigs.k8s.io/kustomize/kyaml v0.20.1 h1:PCMnA2mrVbRP3NIB6v9kYCAc38uvFLVs8j/CD567A78= sigs.k8s.io/kustomize/kyaml v0.20.1/go.mod h1:0EmkQHRUsJxY8Ug9Niig1pUMSCGHxQ5RklbpV/Ri6po= +sigs.k8s.io/kustomize/kyaml v0.21.1 h1:IVlbmhC076nf6foyL6Taw4BkrLuEsXUXNpsE+ScX7fI= +sigs.k8s.io/kustomize/kyaml v0.21.1/go.mod h1:hmxADesM3yUN2vbA5z1/YTBnzLJ1dajdqpQonwBL1FQ= sigs.k8s.io/randfill v1.0.0 h1:JfjMILfT8A6RbawdsK2JXGBR5AQVfd+9TbzrlneTyrU= sigs.k8s.io/randfill v1.0.0/go.mod h1:XeLlZ/jmk4i1HRopwe7/aU3H5n1zNUcX6TM94b3QxOY= sigs.k8s.io/structured-merge-diff/v6 v6.3.0 h1:jTijUJbW353oVOd9oTlifJqOGEkUw2jB/fXCbTiQEco= From 8249fe4b022ba24bab4f04ca3f793c7c04366b1a Mon Sep 17 00:00:00 2001 From: atishj99 <141334503+cx-atish-jadhav@users.noreply.github.com> Date: Thu, 28 May 2026 12:28:32 +0530 Subject: [PATCH 06/27] create CLAUDE.md file for ast-cli repo --- CLAUDE.md | 500 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 500 insertions(+) create mode 100644 CLAUDE.md diff --git a/CLAUDE.md b/CLAUDE.md new file mode 100644 index 000000000..54116995e --- /dev/null +++ b/CLAUDE.md @@ -0,0 +1,500 @@ +# CLAUDE.md + +This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository. + +## Project Overview + +Checkmarx One CLI (`cx`) — a standalone command-line interface for the Checkmarx One application security platform. It orchestrates SAST, SCA, KICS (IaC), API Security, Container Security, Software Supply Chain Security, and DAST scans, manages projects/applications, retrieves results in multiple formats (JSON, SARIF, PDF, SBOM), and decorates pull requests across GitHub, GitLab, Azure DevOps, and Bitbucket. Licensed under Apache 2.0. + +**The CLI is the backbone for all Checkmarx One plugins.** All plugins (IDE extensions, CI/CD integrations) wrap this CLI to initiate scans rather than calling APIs directly. This means changes here propagate to the entire plugin ecosystem — minimizing per-plugin updates but requiring careful backward compatibility. + +### Key Capabilities + +- **Project management:** Create, delete, list, show projects; manage tags +- **Scanning:** SAST, SCA, IaC Security, Container Security, API Security, Supply Chain Security +- **Results:** Retrieve, filter, export in JSON/SARIF/PDF/SBOM; CodeBashing training links; engine-specific exit codes +- **Utilities:** Shell auto-completion (bash/zsh/fish/PowerShell), environment variable display, contributor counting across SCMs (90-day window), PR decoration, SCA remediation (npm) +- **Integration:** CI/CD pipelines (Jenkins, Azure DevOps, GitHub Actions), IDEs, ServiceNow, Jira, Slack, Teams + + +### Plugin Ecosystem Context + +The CLI sits at the center of the Checkmarx One plugin architecture. Downstream consumers that wrap this CLI: +- **Language wrappers:** ast-cli-java-wrapper, ast-cli-javascript-wrapper +- **IDE plugins:** VS Code, JetBrains (IntelliJ), Eclipse, Visual Studio extensions +- **CI/CD plugins:** Jenkins, Azure DevOps, TeamCity, GitHub Action, Maven plugin + +All plugins invoke the `cx` binary rather than calling Checkmarx APIs directly. This centralizes API interaction logic but means CLI flag changes, exit code changes, or output format changes can break downstream consumers. + +### Layered Design: Commands → Services → Wrappers → HTTP Client + +1. **`cmd/main.go`** — Entry point. Instantiates all 30+ wrapper implementations via viper config keys and injects them into `commands.NewAstCLI()`. +2. **`internal/commands/`** — Cobra command definitions. Each command constructor accepts wrapper interfaces as parameters (e.g., `NewScanCommand(...wrappers...)`). Commands are registered in `root.go` via `rootCmd.AddCommand(...)`. +3. **`internal/services/`** — Business logic layer for multi-step operations (e.g., export, application management). +4. **`internal/wrappers/`** — HTTP abstractions for Checkmarx One APIs. Each service follows a triple-file pattern: + - Interface definition (e.g., `scans.go`) + - HTTP implementation (e.g., `scans-http.go`) + - Mock implementation in `mock/` subdirectory (e.g., `mock/scans-mock.go`) +5. **`internal/wrappers/client.go`** — Central HTTP client with OAuth2 auth, token caching, retry with exponential backoff, proxy support (Basic/NTLM/Kerberos/SSPI), TLS config, and request/response logging. +6. **`internal/wrappers/grpcs/`** — gRPC client for the ASCA (Abstract Syntax Code Analysis) engine running on localhost. + +### Adding a New API Integration + +- Define the wrapper interface in `internal/wrappers/` +- Create HTTP implementation in a `-http.go` file +- Create mock in `internal/wrappers/mock/` +- Add the wrapper parameter to `NewAstCLI()` in `internal/commands/root.go` and instantiate it in `cmd/main.go` +- Command constructors follow the pattern: `func NewXyzCommand(wrapper wrappers.XyzWrapper, ...) *cobra.Command` + +## Common User Flow + +1. **Configure:** `cx configure --apikey ` or set `CX_CLIENT_ID` + `CX_CLIENT_SECRET` env vars +2. **Create project:** `cx project create --name "MyProject"` +3. **Initiate scan:** `cx scan create --project-name "MyProject" --branch "main" --file-source "path/to/code" --scan-types "sast,sca,iac-security"` +4. **Retrieve results:** `cx results show --scan-id "" --report-format "json"` (supports json, sarif, pdf, sbom) +5. **Integrate findings:** PR decoration, IDE feedback, CI/CD pipeline exit codes + +Scans can target local directories (`--file-source`), Git repos (`--repo-url`), or container images (`--container-images`). Multiple engines can run simultaneously via `--scan-types`. + +## Repository Structure + +``` +cmd/ Entry point (main.go) — wrapper instantiation & DI +internal/ + commands/ Cobra command definitions (~20 top-level commands) + asca/ AI-powered code analysis subcommand + dast/ DAST environment management + util/ Shared utilities, printer, user count + .scripts/ CI test runner scripts (up.sh, integration_up.sh) + services/ Business logic (projects, applications, groups, export) + wrappers/ HTTP API abstractions (30+ wrapper interfaces) + mock/ Mock implementations for unit testing + grpcs/ gRPC clients (ASCA engine) + configuration/ Config file loading (~/.checkmarx/checkmarxcli.yaml) + bitbucketserver/ Bitbucket Server-specific wrapper + params/ CLI flags, env vars, viper keys, bindings + flags.go Flag name constants + envs.go Environment variable names (CX_* prefix) + keys.go Viper configuration keys + binds.go Flag-to-env-var bindings + constants/ + errors/ Domain-specific error constants + exit-codes/ Engine-specific exit codes for CI/CD + logger/ Logging with sensitive data sanitization +test/ + integration/ Integration tests (//go:build integration) + cleandata/ Post-test cleanup utilities +``` + +## Technology Stack + +- **Language:** Go 1.25.8 +- **CLI Framework:** Cobra v1.10.1 + Viper v1.20.1 +- **gRPC:** google.golang.org/grpc v1.79.3 + protobuf v1.36.10 +- **Auth:** golang-jwt/jwt/v5 v5.2.2, gokrb5/v8 (Kerberos), alexbrainman/sspi (Windows NTLM) +- **Container Analysis:** containers-resolver, containers-images-extractor, anchore/syft (SBOM) +- **Testing:** stretchr/testify v1.11.1, gotest.tools +- **Linting:** golangci-lint v2 with 20 enabled linters +- **Release:** GoReleaser, Cosign (image signing), gon (macOS notarization) +- **No database** — the CLI is stateless; all persistence is server-side + + +### Build + +```bash +# Build (runs fmt → vet → build) +make build + +# Individual steps +go fmt ./... +go vet ./... +go build -o bin/cx.exe ./cmd # Windows +go build -o bin/cx ./cmd # Linux/macOS + +# Initial CLI configuration +cx configure # Interactive prompt for base-uri, tenant, credentials +``` + +**Config file location:** `~/.checkmarx/checkmarxcli.yaml` (override with `--config-file-path` or `CX_CONFIG_FILE_PATH`). Uses file locking (`gofrs/flock`) for thread-safe writes. + +### Running Tests + +```bash +# Run all unit tests (excludes mock, wrappers, bitbucketserver, logger packages) +# Add -v for verbose output +go test $(go list ./... | grep -v "mock" | grep -v "wrappers" | grep -v "bitbucketserver" | grep -v "logger") -timeout 25m + +# Run tests for a specific package +go test ./internal/commands/ -v +go test ./internal/services/ -v + +# Run a specific test by name +go test ./internal/commands/ -run TestAuthValidate -v + +# Run tests matching a pattern +go test ./internal/commands/ -run TestScan -v # Runs all tests starting with "TestScan" + +# Run integration tests (requires env vars — see "Integration Test Configuration" below) +go test -tags integration -v -timeout 210m github.com/checkmarx/ast-cli/test/integration + +# Run a specific integration test +go test -tags integration -run TestScanCreate -v -timeout 210m github.com/checkmarx/ast-cli/test/integration +``` + +### Coverage + +```bash +# Generate coverage report (console summary) +go test $(go list ./... | grep -v "mock" | grep -v "wrappers" | grep -v "bitbucketserver" | grep -v "logger") -timeout 25m -coverprofile cover.out +go tool cover -func cover.out # Show per-function coverage +go tool cover -func cover.out | grep total # Show total coverage percentage + +# Generate detailed HTML coverage report +go tool cover -html=cover.out -o coverage.html + +# View coverage in browser +go tool cover -html=cover.out # Opens browser automatically + +# Integration test coverage (specific packages only) +go test -tags integration -v -timeout 210m \ + -coverpkg github.com/checkmarx/ast-cli/internal/commands,github.com/checkmarx/ast-cli/internal/services,github.com/checkmarx/ast-cli/internal/wrappers \ + -coverprofile cover-integration.out \ + github.com/checkmarx/ast-cli/test/integration +``` + +### Linting & Static Analysis + +```bash +# Run full linter suite (20 linters, see .golangci.yml) +golangci-lint run -c .golangci.yml +# or +make lint + +# Run Go vet only +go vet ./... + +# Run vulnerability scanner +govulncheck ./... +``` + +### Pre-Commit Checklist + +Always run before committing: + +```bash +go mod tidy +go vet ./... +go test -v $(go list ./... | grep -v "mock" | grep -v "wrappers" | grep -v "bitbucketserver" | grep -v "logger") -timeout 25m +golangci-lint run -c .golangci.yml +``` + +### Integration Test Configuration + +Integration tests require these environment variables (set via `.env` file or IDE run configuration): + +| Variable | Purpose | +|---|---| +| `CX_BASE_URI` | Checkmarx One API base URL | +| `CX_BASE_AUTH_URI` | Keycloak authentication URL | +| `CX_CLIENT_ID` | OAuth2 client ID | +| `CX_CLIENT_SECRET` | OAuth2 client secret | +| `CX_APIKEY` | API key (for API key auth tests) | +| `CX_TENANT` | Tenant name | +| `CX_AST_USERNAME` | Username (for basic auth tests) | +| `CX_AST_PASSWORD` | Password (for basic auth tests) | +| `CX_SCAN_SSH_KEY` | SSH key (for SSH scan tests) | +| `PERSONAL_ACCESS_TOKEN` | GitHub/GitLab token (for SCM tests) | +| `PR_GITHUB_TOKEN`, `PR_GITLAB_TOKEN`, `AZURE_TOKEN` | PR decoration tests | +| `PROXY_HOST`, `PROXY_PORT`, `PROXY_USERNAME`, `PROXY_PASSWORD` | Proxy tests | + +No `.env.example` file exists — refer to `.github/workflows/ci-tests.yml` (lines 55-93) for the full list of required secrets. + +## Coding Standards + +- **Flag naming:** kebab-case (e.g., `--scan-id`, `--client-secret`) +- **Environment variables:** `CX_` prefix in SCREAMING_SNAKE_CASE (e.g., `CX_BASE_URI`, `CX_CLIENT_ID`) +- **Max function length:** 200 lines / 100 statements (`funlen`) +- **Max cyclomatic complexity:** 15 (`gocyclo`) +- **Max line length:** 185 characters (`lll` — configured in `.golangci.yml` settings but not in the enabled linters list; not actively enforced) +- **Magic numbers:** Flagged by `mnd` linter (except in test files) +- **Duplicate code threshold:** 500 tokens (`dupl`) +- **Import restrictions:** `depguard` limits imports to stdlib + explicitly whitelisted packages in `.golangci.yml` +- **Formatters:** `gofmt` and `goimports` enforced + +## Project Rules + +- All wrapper dependencies must be injected through constructor parameters — never instantiate wrappers inside commands directly +- Every new wrapper needs all three files: interface, HTTP implementation, and mock +- When adding a wrapper, update both `NewAstCLI()` signature in `internal/commands/root.go` AND instantiation in `cmd/main.go` +- Viper config precedence (highest to lowest): CLI flags (`BindPFlag` in `root.go`) > env vars (`BindEnv` in `binds.go`) > config file > defaults +- Build with `CGO_ENABLED=0` for static linking (no C dependencies) +- Exit codes are engine-specific (SAST=2, SCA=3, KICS=4, API Security=5, multiple=1) — do not change these as CI/CD pipelines and downstream plugins depend on them +- The `depguard` linter will reject any import not on the allowlist — add new external packages to `.golangci.yml` before using them +- **Do not break CLI flag names, output formats, or exit codes without coordinating with the plugin ecosystem** — Java wrapper, JavaScript wrapper, and all IDE/CI plugins parse CLI output and depend on stable interfaces +- Dependabot PRs are auto-merged after CI passes — do not add manual approval gates to dependency update workflows + +## Testing Strategy + +### Coverage Thresholds + +- **Unit tests:** **77.7%** minimum (CI-enforced) +- **Integration tests:** **75%** minimum (CI-enforced) +- **CI pipeline order:** Unit tests → Integration tests → Lint (`golangci-lint`) → Vulnerability scan (`govulncheck`) → Docker image scan (Trivy) + +### Test File Creation Rules + +- Test files **must** end with `_test.go` and live in the same package as the code being tested +- **Unit tests in `internal/commands/`** must include `//go:build !integration` as the first line — this prevents them from running during integration test builds. Tests in other packages (`services/`, `wrappers/`) do not need this tag. +- **Integration tests must include** `//go:build integration` as the first line and live in `test/integration/` +- Each integration test file corresponds to a specific wrapper/service (e.g., `scan_test.go` for scanning) +- Test data files go in `test/integration/data/` (contains Dockerfiles, source files, ZIP archives, sample results) + +### Unit Test Patterns + +Unit tests use mock wrappers from `internal/wrappers/mock/`. The key setup function is `createASTTestCommand()` in `internal/commands/root_test.go`, which instantiates all mock wrappers and returns a fully-wired Cobra command: + +```go +//go:build !integration + +func TestMyFeature(t *testing.T) { + err := executeTestCommand(createASTTestCommand(), "scan", "create", "--project-name", "test") + assert.NilError(t, err) +} +``` + +**Helper functions** (defined in `internal/commands/root_test.go`): +- `createASTTestCommand()` — creates a CLI command with all mock wrappers injected +- `executeTestCommand(cmd, args...)` — executes command, resets viper after +- `execCmdNilAssertion(t, args...)` — execute and assert no error +- `execCmdNotNilAssertion(t, args...)` — execute and assert error returned +- `executeRedirectedTestCommand(args...)` — capture stdout to buffer + +**Assertion libraries:** `gotest.tools/assert` (primary: `assert.NilError()`, `assert.Assert()`, `assert.ErrorContains()`) and `stretchr/testify/assert` + +Both packages have a `TestMain(m *testing.M)` function for setup/teardown in `internal/commands/root_test.go` and `test/integration/root_test.go`. + +### Integration Test Patterns + +Integration tests use real HTTP wrappers (not mocks) and hit the **Checkmarx One integration environment configured via `CX_BASE_URI`**. The key setup function is `createASTIntegrationTestCommand(t)` in `test/integration/util_command.go`: + +```go +//go:build integration + +func TestScanCreate(t *testing.T) { + cmd := createASTIntegrationTestCommand(t) + err := execute(cmd, "scan", "create", "--project-name", projectName, "-b", "main", "-s", ".") + assert.NilError(t, err) +} +``` + +**Helper functions** (defined in `test/integration/util_command.go`): +- `createASTIntegrationTestCommand(t)` — creates CLI command with real HTTP wrappers +- `executeWithTimeout(cmd, timeout, args...)` — execute with context deadline and automatic retry/proxy flags +- `flag(f)` — adds `--` prefix to flag name + +**Test utilities** (defined in `test/integration/util.go`): +- `getProjectNameForTest()` / `GenerateRandomProjectNameForScan()` — unique project names +- `WriteProjectNameToFile(name)` — persist names for cleanup +- `formatTags(tags)` / `formatGroups(groups)` — format test data + +**Flaky test handling:** Integration test CI script (`internal/commands/.scripts/integration_up.sh`) includes automatic retry logic for flaky tests and uses `gocovmerge` to merge coverage profiles from retried runs. + + +## External Integrations + +| Integration | Protocol | Purpose | +|---|---|---| +| Checkmarx One API | REST/HTTPS | Scans, results, projects, applications, groups, policies, feature flags | +| ASCA Engine | gRPC (localhost) | AI-powered real-time code analysis | +| GitHub API | REST v3 | PR decoration, org/repo/commit fetching | +| GitLab API | REST v4 | PR decoration, project/commit fetching | +| Azure DevOps API | REST v5.0 | PR decoration, repo/project fetching | +| Bitbucket Cloud | REST | PR decoration, workspace/repo fetching | +| Bitbucket Server | REST v1.0 | PR decoration, project/repo fetching | +| SCA Realtime | HTTPS (`api-sca.checkmarx.net`) | Public endpoint for package vulnerability checks | +| Checkmarx Gen-AI | REST | AI chat for remediation guidance | +| Keycloak | OAuth2/OIDC | Token-based authentication | + +## Deployment + +- **Platforms:** Linux (amd64, arm, arm64), Windows (amd64), macOS (universal binary) +- **Formats:** tar.gz (Linux), ZIP (Windows), DMG (macOS), Docker image, Homebrew tap +- **Docker image:** Based on `checkmarx/bash:5.3` (Alpine), runs as `nonroot` user, SHA256-pinned base +- **Docker registries:** `checkmarx/ast-cli` and `cxsdlc/ast-cli` on Docker Hub +- **Signing:** Windows via AWS CloudHSM + osslsigncode, macOS via Apple Developer ID + gon notarization, Docker via Cosign +- **Release tool:** GoReleaser (`.goreleaser.yml` for production, `.goreleaser-dev.yml` for pre-releases) +- **Artifacts stored in:** GitHub Releases + AWS S3 (`CxOne/CLI/{tag}` and `CxOne/CLI/latest`) +- **Release workflow:** `.github/workflows/release.yml` — triggered via `workflow_dispatch` (manual) or `workflow_call` (from upstream). Runs on macOS 15 Intel. + +### Release Process + +1. Build binaries for all platforms (CGO_ENABLED=0, static linking) +2. Sign Windows binary (remote HSM signing), notarize macOS binary (gon) +3. Build and push Docker images (production only) +4. Sign Docker images with Cosign and verify signatures (production only) +5. Publish to GitHub Releases, S3, and Homebrew tap +6. **Notify** Microsoft Teams and JIRA with release info (production only) +7. **Dispatch auto-release** to downstream plugin repositories to update their CLI version + +### CI/CD Workflows (`.github/workflows/`) + +| Workflow | Purpose | +|---|---| +| `ci-tests.yml` | Unit tests, integration tests, lint, govulncheck, Trivy | +| `release.yml` | Full build, sign, publish, notify pipeline | +| `issue_automation.yml` | Auto-label and assign issues | +| `pr-add-reviewers.yml` | Auto-assign reviewers to PRs | +| `pr-label.yml` | Auto-label PRs | +| `pr-linter.yml` | Enforce PR guidelines | +| `checkmarx-one-scan.yml` | Security scan on PRs | +| `trivy-cache.yml` | Keep Trivy vulnerability definitions current | +| `ai-code-review.yml` | AI-powered code review on PRs | +| `dependabot-auto-merge.yml` | Auto-merge Dependabot PRs after CI passes | +| `nightly-parallel.yml` | Nightly parallel test runs | + +### JIRA Integration + +- JIRA tasks are automatically tagged with the release version upon deployment +- JIRA ticket numbers in PR titles (e.g., `AST-3432`) enable automation — see Contributing section for PR requirements + +## Performance Considerations + +- **HTTP timeout:** Default 5 seconds (configurable via `--timeout` / `CX_TIMEOUT`) +- **Connection pooling:** Persistent `KeepAlive` at 30 seconds via `http.Transport` +- **Token caching:** In-memory JWT cache with 10-second grace period before expiry; protected by `sync.Mutex` +- **Retry with exponential backoff:** Default 3 retries, 20s base delay. IAM retries: 4 attempts, 500ms base. Polling delay: 60s. +- **Rate limiting:** SCM-specific rate limit handling (GitHub, GitLab, Bitbucket, Azure) with 60s default wait and up to 3 retries +- **HTTP body logging cap:** Request/response bodies >1MB are not logged to prevent memory issues +- **Static binary:** `CGO_ENABLED=0` with `-s -w` flags strips symbols for smaller binaries + +## API / Endpoints / Interfaces + +All API paths are configured via environment variables with `CX_` prefix. Key endpoints: + +| Category | Env Var | Description | +|---|---|---| +| Core | `CX_BASE_URI` | Main Checkmarx One API URL | +| Auth | `CX_BASE_AUTH_URI` | Keycloak token endpoint | +| Scans | `CX_SCANS_PATH` | Scan CRUD operations | +| Results | `CX_RESULTS_PATH` | Scan result retrieval | +| Projects | `CX_PROJECTS_PATH` | Project management | +| Uploads | `CX_UPLOADS_PATH` | File upload (supports multipart via pre-signed URLs) | +| Feature Flags | `CX_FEATURE_FLAGS_PATH` | Feature gating per tenant | +| Export | `CX_EXPORT_PATH` | Bulk export operations | +| Reports | `CX_RESULTS_PDF_REPORT_PATH`, `CX_RESULTS_JSON_REPORT_PATH` | PDF/JSON report generation | + +Full list of env vars in `internal/params/envs.go`. Viper bindings in `internal/params/binds.go`. + +## Security & Access + +- **Authentication methods:** OAuth2 client credentials (`CX_CLIENT_ID` + `CX_CLIENT_SECRET`) or API key (`CX_APIKEY` — a JWT refresh token) +- **Token endpoint:** `{base_auth_uri}/auth/realms/{tenant}/protocol/openid-connect/token` +- **Token refresh:** Automatic on 401 responses; cached in-memory with mutex protection +- **TLS:** `--insecure` flag disables certificate verification (for testing only) +- **Sensitive data sanitization:** Logger automatically replaces values of `CX_APIKEY`, `CX_CLIENT_ID`, `CX_CLIENT_SECRET`, `--username`, `--password`, `ast-token`, `--ssh-key`, `CX_HTTP_PROXY`, `--token`, and `SCS_REPO_TOKEN` with `***` in all output +- **Config obfuscation:** Interactive `cx configure` shows only last 4 characters of sensitive values + +## Proxy Configuration + +The CLI supports four methods to configure proxy settings (in order of typical usage): + +### 1. Standard Environment Variables + +```bash +export HTTP_PROXY=http://username:password@proxy.example.com:8080 +export HTTPS_PROXY=http://username:password@proxy.example.com:8080 +export NO_PROXY=localhost,127.0.0.1,*.example.com +``` + +### 2. CX-Specific Environment Variables + +| Variable | Purpose | +|---|---| +| `CX_HTTP_PROXY` | Proxy server URL (overrides `HTTP_PROXY`) | +| `CX_PROXY_AUTH_TYPE` | Authentication type: `basic`, `ntlm`, `kerberos`, or `kerberos-native` | +| `CX_PROXY_NTLM_DOMAIN` | Windows domain for NTLM auth | +| `CX_PROXY_KERBEROS_SPN` | Kerberos SPN (e.g., `HTTP/proxy.example.com`) — required for Kerberos | +| `CX_PROXY_KERBEROS_KRB5_CONF` | Path to krb5.conf (default: `/etc/krb5.conf` or `C:\Windows\krb5.ini`) | +| `CX_PROXY_KERBEROS_CCACHE` | Path to Kerberos credential cache (optional) | +| `CX_IGNORE_PROXY` | Bypass proxy for current command | + +### 3. CLI Global Flags + +```bash +cx scan create --project-name "MyProject" \ + --proxy http://username:password@proxy.example.com:8080 \ + --proxy-auth-type ntlm \ + --proxy-ntlm-domain CORP +``` + +Flags: `--proxy`, `--proxy-auth-type` (basic/ntlm/kerberos/kerberos-native), `--proxy-ntlm-domain`, `--proxy-kerberos-spn`, `--ignore-proxy` + +Proxy URL format: `http://:` or `http://:@:` (must include `http://` prefix). + +### 4. CLI Config File + +Settings in `~/.checkmarx/checkmarxcli.yaml`: + +```yaml +cx_http_proxy: http://proxy.example.com:8080 +cx_proxy_auth_type: ntlm +cx_proxy_ntlm_domain: dm.cx +``` + +## Logging + +- **Debug mode:** `--debug` flag enables verbose output to stdout +- **File logging:** `--log-file ` writes to `/ast-cli.log` (file only) +- **File + console:** `--log-file-console ` writes to both file and stdout +- **HTTP tracing (debug mode):** Connection timing, DNS lookups, TLS handshake, full request/response dumps (sanitized, capped at 1MB, binary data excluded) +- **All log output** passes through `sanitizeLogs()` which replaces credential values with `***` + +## Debugging Steps + +### Runtime Debugging + +1. **Enable debug output:** Add `--debug` to any command (e.g., `cx scan create --debug ...`) +2. **Check auth:** `cx auth validate --debug` — shows token fetch, credential type, tenant resolution +3. **Inspect HTTP traffic:** Debug mode logs full request/response including headers, status codes, and timing +4. **Proxy issues:** Debug mode logs proxy type detection ("Creating HTTP Client with Proxy", "Using NTLM Proxy", "Using Kerberos Proxy") +5. **Token problems:** Look for "Fetching API access token", "Using cached API access token", "API access token not found in cache" in debug output +6. **Log to file for analysis:** `cx --log-file-console /tmp/logs` then inspect `/tmp/logs/ast-cli.log` +7. **Exit codes:** Non-zero exit identifies the failing engine (2=SAST, 3=SCA, 4=KICS, 5=API Security, 1=multiple) +8. **Config verification:** `cx utils env` shows current environment variable values +9. **Version check:** `cx version` to verify installed version and identify version-related issues +10. **Help:** `cx help` or `cx --help` for usage and available flags + +### Source Code Debugging + +1. Set environment variables via `.env` file or IDE run configuration (`CX_BASE_URI`, `CX_CLIENT_ID`, `CX_CLIENT_SECRET`, etc.) +2. Set the CLI command as program arguments in your IDE (e.g., `scan create --project-name "Test" -b main -s `) +3. Use **Delve** debugger to set breakpoints and step through code +4. Alternatively, add `fmt.Println` statements for quick variable inspection +5. Build and test: `go build -o bin/cx ./cmd` (Mac/Linux) or `go build -o bin/cx.exe ./cmd` (Windows) + +### Debugging Integration Tests + +1. Open `test/integration/` and select the test file for the functionality being debugged +2. Configure environment variables in your IDE run configuration +3. **Important:** Comment out `appendProxyArgs` call in `executeWithTimeout` function in `test/integration/util_command.go` before running locally — this avoids proxy-related failures in local debugging +4. Set breakpoints and run/debug the test; adjust test arguments to simulate scenarios +5. **Do NOT commit the `appendProxyArgs` change** — it is for local debugging only + +## Contributing + +- Branch naming: `feature/-name` or `hotfix/-name` +- PRs require associated issue marked "accepted" +- All changes need unit or integration tests meeting coverage thresholds +- Post-release, a dispatch triggers downstream plugin repositories to update their CLI version + +### PR Requirements — Team Members + +- Must have a valid JIRA ID in the PR title (e.g., `AST-3432`) — enables JIRA automation and traceability +- CI workflow must pass: **unit-tests**, **integration-tests**, **lint**, **cx-scan** +- Review by at least one team member +- Use the PR template (`.github/PULL_REQUEST_TEMPLATE.md`) — includes sections for changes, related issues, testing, and checklist + +### PR Requirements — Dependabot + +- CI workflow must pass: **unit-tests**, **integration-tests**, **lint**, **cx-scan** +- Auto-merged after CI passes (no manual review required) From ccb12ae25fa2beaa07ada6dc150de926720b7d8e Mon Sep 17 00:00:00 2001 From: atishj99 <141334503+cx-atish-jadhav@users.noreply.github.com> Date: Thu, 28 May 2026 14:33:57 +0530 Subject: [PATCH 07/27] Updated filters.go --- internal/params/filters.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/internal/params/filters.go b/internal/params/filters.go index fae79903f..7312918bc 100644 --- a/internal/params/filters.go +++ b/internal/params/filters.go @@ -182,7 +182,7 @@ var BaseIncludeFilters = []string{ "*.tex", "*.toml", "*.tsql", - "*.txt", + "CMakeLists*.txt", "*.vue", "*.xsaccess", "*.xsapp", From b6c006bedb72bb8d8a2f57e2eb9cbd74d565de36 Mon Sep 17 00:00:00 2001 From: atishj99 <141334503+cx-atish-jadhav@users.noreply.github.com> Date: Thu, 28 May 2026 16:02:30 +0530 Subject: [PATCH 08/27] fix failing unit test case --- internal/commands/result.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/internal/commands/result.go b/internal/commands/result.go index 34320193c..22803b39e 100644 --- a/internal/commands/result.go +++ b/internal/commands/result.go @@ -2912,7 +2912,7 @@ func parseURI(summaryBaseURI string) (hostName string) { } func printWarningIfIgnorePolicyOmiited() { - fmt.Printf("\n Warning: The --ignore-policy flag was not implemented because you don’t have the required permission.\n Only users with 'override-policy-management' permission can use this flag. \n\n") + fmt.Printf("\n Warning: The --ignore-policy flag was not implemented because you don't have the required permission.\n Only users with 'override-policy-management' permission can use this flag. \n\n") } func getFilterResultsForAPISecScanner(risksOverviewWrapper wrappers.RisksOverviewWrapper, scanID string, resultsParams map[string]string) (aPISecSeveritySummary *wrappers.APISecFilteredResult, err error) { From 2d38f62fdb92eb4ed103374643d4eadbd69bb2fd Mon Sep 17 00:00:00 2001 From: atishj99 <141334503+cx-atish-jadhav@users.noreply.github.com> Date: Thu, 28 May 2026 19:41:17 +0530 Subject: [PATCH 09/27] trivy and integration check fixes --- Dockerfile | 2 +- go.mod | 17 +- go.sum | 33 +++ internal/commands/result.go | 299 ++++++++++++--------- internal/params/filters.go | 12 +- internal/services/applications_test.go | 5 - internal/wrappers/mock/application-mock.go | 12 +- internal/wrappers/results-sarif.go | 3 + test/integration/data/config.yaml | 1 - 9 files changed, 232 insertions(+), 152 deletions(-) diff --git a/Dockerfile b/Dockerfile index f30a838bf..cca0b0fdd 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,4 +1,4 @@ -FROM checkmarx/bash:5.3-r12-0e56cb6e000601@sha256:0e56cb6e000601d35ed11ddcc973ca268c431a176be53cdc31bc85f3208dc44a +FROM checkmarx/bash:5.3-r12-f48dd8a45af577@sha256:f48dd8a45af5771e98cb5d56d204ada0e0dc045093ca3272b4c3dbe3f85e6e4f USER nonroot COPY cx /app/bin/cx diff --git a/go.mod b/go.mod index 8cd6ba556..1e3576d3f 100644 --- a/go.mod +++ b/go.mod @@ -14,7 +14,7 @@ require ( github.com/bouk/monkey v1.0.0 github.com/checkmarx/2ms/v3 v3.21.0 github.com/gofrs/flock v0.13.0 - github.com/golang-jwt/jwt/v5 v5.2.2 + github.com/golang-jwt/jwt/v5 v5.3.0 github.com/gomarkdown/markdown v0.0.0-20260417124207-7d523f7318df github.com/google/uuid v1.6.0 github.com/gookit/color v1.6.0 @@ -92,8 +92,8 @@ require ( github.com/coreos/go-systemd/v22 v22.7.0 // indirect github.com/cpuguy83/go-md2man/v2 v2.0.7 // indirect github.com/diskfs/go-diskfs v1.7.0 // indirect - github.com/distribution/distribution/v3 v3.0.1-0.20260120145532-40594bd98e6d // indirect - github.com/docker/go-events v0.0.0-20250114142523-c867878c5e32 // indirect + github.com/distribution/distribution/v3 v3.1.1 // indirect + github.com/docker/go-events v0.0.0-20250808211157-605354379745 // indirect github.com/envoyproxy/go-control-plane/envoy v1.36.0 // indirect github.com/envoyproxy/protoc-gen-validate v1.3.0 // indirect github.com/go-jose/go-jose/v3 v3.0.5 // indirect @@ -111,6 +111,7 @@ require ( github.com/hashicorp/go-version v1.8.0 // indirect github.com/hashicorp/golang-lru/v2 v2.0.7 // indirect github.com/henvic/httpretty v0.1.4 // indirect + github.com/klauspost/cpuid/v2 v2.3.0 // indirect github.com/mholt/archives v0.1.5 // indirect github.com/mikelolasagasti/xz v1.0.1 // indirect github.com/minio/minlz v1.0.1 // indirect @@ -139,7 +140,7 @@ require ( go.opentelemetry.io/otel/sdk v1.43.0 // indirect go.opentelemetry.io/otel/sdk/metric v1.43.0 // indirect go4.org v0.0.0-20230225012048-214862532bf5 // indirect - golang.org/x/image v0.36.1-0.20260211191414-e3d762b1d37e // indirect + golang.org/x/image v0.38.0 // indirect gonum.org/v1/gonum v0.17.0 // indirect google.golang.org/api v0.271.0 // indirect google.golang.org/genproto/googleapis/api v0.0.0-20260401024825-9d38bb4040a9 // indirect @@ -233,8 +234,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.8.1-0.20260506061021-07f2a0bf50e4 // indirect - github.com/go-git/go-git/v5 v5.18.1-0.20260420130857-e5bbc088b774 // indirect + github.com/go-git/go-billy/v5 v5.9.0 // indirect + github.com/go-git/go-git/v5 v5.19.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 @@ -317,7 +318,7 @@ require ( github.com/pelletier/go-toml/v2 v2.3.1 // indirect github.com/peterbourgon/diskv v2.0.1+incompatible // indirect github.com/pierrec/lz4/v4 v4.1.22 // indirect - github.com/pjbgf/sha1cd v0.3.2 // indirect + github.com/pjbgf/sha1cd v0.6.0 // indirect github.com/pkg/profile v1.7.0 // indirect github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec // indirect @@ -336,7 +337,7 @@ require ( github.com/shopspring/decimal v1.4.0 // indirect github.com/sirupsen/logrus v1.9.4 // indirect github.com/skeema/knownhosts v1.3.1 // indirect - github.com/slack-go/slack v0.12.2 // indirect + github.com/slack-go/slack v0.23.1 // indirect github.com/sourcegraph/conc v0.3.1-0.20240121214520-5f936abd7ae8 // indirect github.com/spdx/gordf v0.0.0-20250128162952-000978ccd6fb // indirect github.com/spdx/tools-golang v0.5.7 // indirect diff --git a/go.sum b/go.sum index 5db673f17..65c70b7f2 100644 --- a/go.sum +++ b/go.sum @@ -281,6 +281,7 @@ github.com/bradleyjkemp/cupaloy/v2 v2.8.0 h1:any4BmKE+jGIaMpnU8YgH/I2LPiLBufr6oM github.com/bradleyjkemp/cupaloy/v2 v2.8.0/go.mod h1:bm7JXdkRd4BHJk9HpwqAI8BoAY1lps46Enkdqw6aRX0= github.com/bshuster-repo/logrus-logstash-hook v1.0.0 h1:e+C0SB5R1pu//O4MQ3f9cFuPGoOVeF2fE4Og9otCc70= github.com/bshuster-repo/logrus-logstash-hook v1.0.0/go.mod h1:zsTqEiSzDgAa/8GZR7E1qaXrhYNDKBYy5/dWPTIflbk= +github.com/bshuster-repo/logrus-logstash-hook v1.1.0 h1:o2FzZifLg+z/DN1OFmzTWzZZx/roaqt8IPZCIVco8r4= github.com/bwmarrin/discordgo v0.27.1 h1:ib9AIc/dom1E/fSIulrBwnez0CToJE113ZGt4HoliGY= github.com/bwmarrin/discordgo v0.27.1/go.mod h1:NJZpH+1AfhIcyQsPeuBKsUtYrRnjkyu0kIVMCHkZtRY= github.com/cenkalti/backoff/v4 v4.3.0 h1:MyRJ/UdXutAwSAT+s3wNd7MfTIcy71VQueUuFK343L8= @@ -422,6 +423,8 @@ github.com/distribution/distribution/v3 v3.0.1-0.20250403190400-dbca4995c83c h1: github.com/distribution/distribution/v3 v3.0.1-0.20250403190400-dbca4995c83c/go.mod h1:tRNuFoZsUdyRVegq8xGNeds4KLjwLCRin/tTo6i1DhU= github.com/distribution/distribution/v3 v3.0.1-0.20260120145532-40594bd98e6d h1:c2HDaWKU1MalLXwrAek+Yks7n80p/salSR5u6alHPBo= github.com/distribution/distribution/v3 v3.0.1-0.20260120145532-40594bd98e6d/go.mod h1:WiiB9B3TqqAPe7hPjI1P9OMtEW7Ub/HHGndi11SqeDA= +github.com/distribution/distribution/v3 v3.1.1 h1:KUbk7C8CfaLXy8kbf/hGq9cad/wCoLB6dbWH6DMbmX0= +github.com/distribution/distribution/v3 v3.1.1/go.mod h1:d7lXwZpph0bVcOj4Aqn0nMrWHIwRQGdiV5TLeI+/w6Y= github.com/distribution/reference v0.6.0 h1:0IXCQ5g4/QMHHkarYzh5l+u8T3t73zM5QvfrDyIgxBk= github.com/distribution/reference v0.6.0/go.mod h1:BbU0aIcezP1/5jX/8MP0YiH4SdvB5Y4f/wlDRiLyi3E= github.com/djherbis/times v1.6.0 h1:w2ctJ92J8fBvWPxugmXIv7Nz7Q3iDMKNx9v5ocVH20c= @@ -438,6 +441,8 @@ github.com/docker/go-connections v0.6.0 h1:LlMG9azAe1TqfR7sO+NJttz1gy6KO7VJBh+pM github.com/docker/go-connections v0.6.0/go.mod h1:AahvXYshr6JgfUJGdDCs2b5EZG/vmaMAntpSFH5BFKE= github.com/docker/go-events v0.0.0-20250114142523-c867878c5e32 h1:EHZfspsnLAz8Hzccd67D5abwLiqoqym2jz/jOS39mCk= github.com/docker/go-events v0.0.0-20250114142523-c867878c5e32/go.mod h1:Uw6UezgYA44ePAFQYUehOuCzmy5zmg/+nl2ZfMWGkpA= +github.com/docker/go-events v0.0.0-20250808211157-605354379745 h1:yOn6Ze6IbYI/KAw2lw/83ELYvZh6hvsygTVkD0dzMC4= +github.com/docker/go-events v0.0.0-20250808211157-605354379745/go.mod h1:Uw6UezgYA44ePAFQYUehOuCzmy5zmg/+nl2ZfMWGkpA= github.com/docker/go-metrics v0.0.1 h1:AgB/0SvBxihN0X8OR4SjsblXkbMvalQ8cjmtKQ2rQV8= github.com/docker/go-metrics v0.0.1/go.mod h1:cG1hvH2utMXtqgqqYE9plW6lDxS3/5ayHzueweSI3Vw= github.com/docker/go-units v0.5.0 h1:69rxXcBk27SvSaaxTtLh/8llcHD8vYHT7WSdRZ/jvr4= @@ -531,12 +536,16 @@ github.com/go-git/go-billy/v5 v5.8.0 h1:I8hjc3LbBlXTtVuFNJuwYuMiHvQJDq1AT6u4DwDz github.com/go-git/go-billy/v5 v5.8.0/go.mod h1:RpvI/rw4Vr5QA+Z60c6d6LXH0rYJo0uD5SqfmrrheCY= github.com/go-git/go-billy/v5 v5.8.1-0.20260506061021-07f2a0bf50e4 h1:XK6pelr1UQyrCSXsrqrJxr0jkrHXg7QCzfPH3UQMYp8= github.com/go-git/go-billy/v5 v5.8.1-0.20260506061021-07f2a0bf50e4/go.mod h1:jCnQMLj9eUgGU7+ludSTYoZL/GGmii14RxKFj7ROgHw= +github.com/go-git/go-billy/v5 v5.9.0 h1:jItGXszUDRtR/AlferWPTMN4j38BQ88XnXKbilmmBPA= +github.com/go-git/go-billy/v5 v5.9.0/go.mod h1:jCnQMLj9eUgGU7+ludSTYoZL/GGmii14RxKFj7ROgHw= 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.18.0 h1:O831KI+0PR51hM2kep6T8k+w0/LIAD490gvqMCvL5hM= github.com/go-git/go-git/v5 v5.18.0/go.mod h1:pW/VmeqkanRFqR6AljLcs7EA7FbZaN5MQqO7oZADXpo= github.com/go-git/go-git/v5 v5.18.1-0.20260420130857-e5bbc088b774 h1:FED4o0JOD1z8x/dMcmM6IKkqoIz22xz7sWE81FEdXNQ= github.com/go-git/go-git/v5 v5.18.1-0.20260420130857-e5bbc088b774/go.mod h1:pW/VmeqkanRFqR6AljLcs7EA7FbZaN5MQqO7oZADXpo= +github.com/go-git/go-git/v5 v5.19.1 h1:nX27AnaU43/K5bKktKwgBmR9lawoYVe1Ckg0rgzzN00= +github.com/go-git/go-git/v5 v5.19.1/go.mod h1:Pb1v0c7/g8aGQJwx9Us09W85yGoyvSwuhEGMH7zjDKQ= 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= @@ -595,6 +604,8 @@ github.com/gohugoio/hashstructure v0.6.0 h1:7wMB/2CfXoThFYhdWRGv3u3rUM761Cq29CxU github.com/gohugoio/hashstructure v0.6.0/go.mod h1:lapVLk9XidheHG1IQ4ZSbyYrXcaILU1ZEP/+vno5rBQ= github.com/golang-jwt/jwt/v5 v5.2.2 h1:Rl4B7itRWVtYIHFrSNd7vhTiz9UpLdi6gZhZ3wEeDy8= github.com/golang-jwt/jwt/v5 v5.2.2/go.mod h1:pqrtFR0X4osieyHYxtmOUWsAWrfe1Q5UVIyoH402zdk= +github.com/golang-jwt/jwt/v5 v5.3.0 h1:pv4AsKCKKZuqlgs5sUmn4x8UlGa0kEVt/puTpKx9vvo= +github.com/golang-jwt/jwt/v5 v5.3.0/go.mod h1:fxCRLWMO43lRc8nhHWY6LGqRcf+1gQWArsqaEUEa5bE= github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/groupcache v0.0.0-20191227052852-215e87163ea7/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= @@ -834,7 +845,10 @@ github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+o github.com/klauspost/compress v1.4.1/go.mod h1:RyIbtBH6LamlWaDj8nUwkbUhJ87Yi3uG0guNDohfE1A= github.com/klauspost/compress v1.18.5 h1:/h1gH5Ce+VWNLSWqPzOVn6XBO+vJbCNGvjoaGBFW2IE= github.com/klauspost/compress v1.18.5/go.mod h1:cwPg85FWrGar70rWktvGQj8/hthj3wpl0PGDogxkrSQ= +github.com/klauspost/cpuid v1.2.0 h1:NMpwD2G9JSFOE1/TJjGSo5zG7Yb2bTe7eq1jH+irmeE= github.com/klauspost/cpuid v1.2.0/go.mod h1:Pj4uuM528wm8OyEC2QMXAi2YiTZ96dNQPGgoMS4s3ek= +github.com/klauspost/cpuid/v2 v2.3.0 h1:S4CRMLnYUhGeDFDqkGriYKdfoFlDnMtqTiI/sFzhA9Y= +github.com/klauspost/cpuid/v2 v2.3.0/go.mod h1:hqwkgyIinND0mEev00jJYCxPNVRVXFQeu1XKlok6oO0= github.com/klauspost/pgzip v1.2.6 h1:8RXeL5crjEUFnR2/Sn6GJNWtSQ3Dk8pq4CL3jvdDyjU= github.com/klauspost/pgzip v1.2.6/go.mod h1:Ch1tH69qFZu15pkjo5kYi6mth2Zzwzt50oCQKQE9RUs= github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= @@ -1021,6 +1035,8 @@ github.com/pierrec/lz4/v4 v4.1.22 h1:cKFw6uJDK+/gfw5BcDL0JL5aBsAFdsIT18eRtLj7VIU github.com/pierrec/lz4/v4 v4.1.22/go.mod h1:gZWDp/Ze/IJXGXf23ltt2EXimqmTUXEy0GFuRQyBid4= github.com/pjbgf/sha1cd v0.3.2 h1:a9wb0bp1oC2TGwStyn0Umc/IGKQnEgF0vVaZ8QF8eo4= github.com/pjbgf/sha1cd v0.3.2/go.mod h1:zQWigSxVmsHEZow5qaLtPYxpcKMMQpa09ixqBxuCS6A= +github.com/pjbgf/sha1cd v0.6.0 h1:3WJ8Wz8gvDz29quX1OcEmkAlUg9diU4GxJHqs0/XiwU= +github.com/pjbgf/sha1cd v0.6.0/go.mod h1:lhpGlyHLpQZoxMv8HcgXvZEhcGs0PG/vsZnEJ7H0iCM= github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= @@ -1061,6 +1077,7 @@ github.com/prometheus/procfs v0.0.8/go.mod h1:7Qr8sr6344vo1JqZ6HhLceV9o3AJ1Ff+Gx github.com/prometheus/procfs v0.16.1 h1:hZ15bTNuirocR6u0JZ6BAHHmwS1p8B4P6MRqxtzMyRg= github.com/prometheus/procfs v0.16.1/go.mod h1:teAbpZRB1iIAJYREa1LsoWUXykVXA1KlTmWl8x/U+Is= github.com/prometheus/procfs v0.19.2 h1:zUMhqEW66Ex7OXIiDkll3tl9a1ZdilUOd/F6ZXw4Vws= +github.com/prometheus/procfs v0.20.1 h1:XwbrGOIplXW/AU3YhIhLODXMJYyC1isLFfYCsTEycfc= github.com/redis/go-redis/extra/rediscmd/v9 v9.0.5 h1:EaDatTxkdHG+U3Bk4EUr+DZ7fOGwTfezUiUJMaIcaho= github.com/redis/go-redis/extra/rediscmd/v9 v9.0.5/go.mod h1:fyalQWdtzDBECAQFBJuQe5bzQ02jGd5Qcbgb97Flm7U= github.com/redis/go-redis/extra/redisotel/v9 v9.0.5 h1:EfpWLLCyXw8PSM2/XNJLjI3Pb27yVE+gIAfeqp8LUCc= @@ -1123,6 +1140,8 @@ github.com/skeema/knownhosts v1.3.1 h1:X2osQ+RAjK76shCbvhHHHVl3ZlgDm8apHEHFqRjnB github.com/skeema/knownhosts v1.3.1/go.mod h1:r7KTdC8l4uxWRyK2TpQZ/1o5HaSzh06ePQNxPwTcfiY= github.com/slack-go/slack v0.12.2 h1:x3OppyMyGIbbiyFhsBmpf9pwkUzMhthJMRNmNlA4LaQ= github.com/slack-go/slack v0.12.2/go.mod h1:hlGi5oXA+Gt+yWTPP0plCdRKmjsDxecdHxYQdlMQKOw= +github.com/slack-go/slack v0.23.1 h1:ZS5B96wxxYQRwvJ3/vJFtqtUZi3tXhsZCyT44Nv7M80= +github.com/slack-go/slack v0.23.1/go.mod h1:H0yR/YBuRJ39RkE+JpV/d/oEsbanzTRowR82bCN0cEs= github.com/smallnest/ringbuffer v0.0.0-20241116012123-461381446e3d h1:3VwvTjiRPA7cqtgOWddEL+JrcijMlXUmj99c/6YyZoY= github.com/smallnest/ringbuffer v0.0.0-20241116012123-461381446e3d/go.mod h1:tAG61zBM1DYRaGIPloumExGvScf08oHuo0kFoOqdbT0= github.com/sorairolake/lzip-go v0.3.8 h1:j5Q2313INdTA80ureWYRhX+1K78mUXfMoPZCw/ivWik= @@ -1264,10 +1283,12 @@ go.opentelemetry.io/auto/sdk v1.2.1 h1:jXsnJ4Lmnqd11kwkBV2LgLoFMZKizbCi5fNZ/ipaZ go.opentelemetry.io/auto/sdk v1.2.1/go.mod h1:KRTj+aOaElaLi+wW1kO/DZRXwkF4C5xPbEe3ZiIhN7Y= go.opentelemetry.io/contrib/bridges/prometheus v0.57.0 h1:UW0+QyeyBVhn+COBec3nGhfnFe5lwB0ic1JBVjzhk0w= go.opentelemetry.io/contrib/bridges/prometheus v0.57.0/go.mod h1:ppciCHRLsyCio54qbzQv0E4Jyth/fLWDTJYfvWpcSVk= +go.opentelemetry.io/contrib/bridges/prometheus v0.67.0 h1:dkBzNEAIKADEaFnuESzcXvpd09vxvDZsOjx11gjUqLk= go.opentelemetry.io/contrib/detectors/gcp v1.39.0 h1:kWRNZMsfBHZ+uHjiH4y7Etn2FK26LAGkNFw7RHv1DhE= go.opentelemetry.io/contrib/detectors/gcp v1.39.0/go.mod h1:t/OGqzHBa5v6RHZwrDBJ2OirWc+4q/w2fTbLZwAKjTk= go.opentelemetry.io/contrib/exporters/autoexport v0.57.0 h1:jmTVJ86dP60C01K3slFQa2NQ/Aoi7zA+wy7vMOKD9H4= go.opentelemetry.io/contrib/exporters/autoexport v0.57.0/go.mod h1:EJBheUMttD/lABFyLXhce47Wr6DPWYReCzaZiXadH7g= +go.opentelemetry.io/contrib/exporters/autoexport v0.67.0 h1:4fnRcNpc6YFtG3zsFw9achKn3XgmxPxuMuqIL5rE8e8= go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.63.0 h1:YH4g8lQroajqUwWbq/tr2QX1JFmEXaDLgG+ew9bLMWo= go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.63.0/go.mod h1:fvPi2qXDqFs8M4B4fmJhE92TyQs9Ydjlg3RvfUp+NbQ= go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.68.0 h1:0Qx7VGBacMm9ZENQ7TnNObTYI4ShC+lHI16seduaxZo= @@ -1280,12 +1301,16 @@ go.opentelemetry.io/otel v1.43.0 h1:mYIM03dnh5zfN7HautFE4ieIig9amkNANT+xcVxAj9I= go.opentelemetry.io/otel v1.43.0/go.mod h1:JuG+u74mvjvcm8vj8pI5XiHy1zDeoCS2LB1spIq7Ay0= go.opentelemetry.io/otel/exporters/otlp/otlplog/otlploggrpc v0.8.0 h1:WzNab7hOOLzdDF/EoWCt4glhrbMPVMOO5JYTmpz36Ls= go.opentelemetry.io/otel/exporters/otlp/otlplog/otlploggrpc v0.8.0/go.mod h1:hKvJwTzJdp90Vh7p6q/9PAOd55dI6WA6sWj62a/JvSs= +go.opentelemetry.io/otel/exporters/otlp/otlplog/otlploggrpc v0.18.0 h1:deI9UQMoGFgrg5iLPgzueqFPHevDl+28YKfSpPTI6rY= go.opentelemetry.io/otel/exporters/otlp/otlplog/otlploghttp v0.8.0 h1:S+LdBGiQXtJdowoJoQPEtI52syEP/JYBUpjO49EQhV8= go.opentelemetry.io/otel/exporters/otlp/otlplog/otlploghttp v0.8.0/go.mod h1:5KXybFvPGds3QinJWQT7pmXf+TN5YIa7CNYObWRkj50= +go.opentelemetry.io/otel/exporters/otlp/otlplog/otlploghttp v0.19.0 h1:HIBTQ3VO5aupLKjC90JgMqpezVXwFuq6Ryjn0/izoag= go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc v1.32.0 h1:j7ZSD+5yn+lo3sGV69nW04rRR0jhYnBwjuX3r0HvnK0= go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc v1.32.0/go.mod h1:WXbYJTUaZXAbYd8lbgGuvih0yuCfOFC5RJoYnoLcGz8= +go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc v1.42.0 h1:MdKucPl/HbzckWWEisiNqMPhRrAOQX8r4jTuGr636gk= go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetrichttp v1.32.0 h1:t/Qur3vKSkUCcDVaSumWF2PKHt85pc7fRvFuoVT8qFU= go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetrichttp v1.32.0/go.mod h1:Rl61tySSdcOJWoEgYZVtmnKdA0GeKrSqkHC1t+91CH8= +go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetrichttp v1.43.0 h1:w1K+pCJoPpQifuVpsKamUdn9U0zM3xUziVOqsGksUrY= go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.35.0 h1:1fTNlAIJZGWLP5FVu0fikVry1IsiUnXjf7QFvoNN3Xw= go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.35.0/go.mod h1:zjPK58DtkqQFn+YUMbx0M2XV3QgKU0gS9LeGohREyK4= go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.43.0 h1:88Y4s2C8oTui1LGM6bTWkw0ICGcOLCAI5l6zsD1j20k= @@ -1297,20 +1322,26 @@ go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.35.0/go.mod h go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.43.0 h1:3iZJKlCZufyRzPzlQhUIWVmfltrXuGyfjREgGP3UUjc= go.opentelemetry.io/otel/exporters/prometheus v0.54.0 h1:rFwzp68QMgtzu9PgP3jm9XaMICI6TsofWWPcBDKwlsU= go.opentelemetry.io/otel/exporters/prometheus v0.54.0/go.mod h1:QyjcV9qDP6VeK5qPyKETvNjmaaEc7+gqjh4SS0ZYzDU= +go.opentelemetry.io/otel/exporters/prometheus v0.64.0 h1:g0LRDXMX/G1SEZtK8zl8Chm4K6GBwRkjPKE36LxiTYs= go.opentelemetry.io/otel/exporters/stdout/stdoutlog v0.8.0 h1:CHXNXwfKWfzS65yrlB2PVds1IBZcdsX8Vepy9of0iRU= go.opentelemetry.io/otel/exporters/stdout/stdoutlog v0.8.0/go.mod h1:zKU4zUgKiaRxrdovSS2amdM5gOc59slmo/zJwGX+YBg= +go.opentelemetry.io/otel/exporters/stdout/stdoutlog v0.18.0 h1:KJVjPD3rcPb98rIs3HznyJlrfx9ge5oJvxxlGR+P/7s= go.opentelemetry.io/otel/exporters/stdout/stdoutmetric v1.40.0 h1:ZrPRak/kS4xI3AVXy8F7pipuDXmDsrO8Lg+yQjBLjw0= go.opentelemetry.io/otel/exporters/stdout/stdoutmetric v1.40.0/go.mod h1:3y6kQCWztq6hyW8Z9YxQDDm0Je9AJoFar2G0yDcmhRk= +go.opentelemetry.io/otel/exporters/stdout/stdoutmetric v1.42.0 h1:lSZHgNHfbmQTPfuTmWVkEu8J8qXaQwuV30pjCcAUvP8= go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.32.0 h1:cC2yDI3IQd0Udsux7Qmq8ToKAx1XCilTQECZ0KDZyTw= go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.32.0/go.mod h1:2PD5Ex6z8CFzDbTdOlwyNIUywRr1DN0ospafJM1wJ+s= +go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.42.0 h1:s/1iRkCKDfhlh1JF26knRneorus8aOwVIDhvYx9WoDw= go.opentelemetry.io/otel/log v0.8.0 h1:egZ8vV5atrUWUbnSsHn6vB8R21G2wrKqNiDt3iWertk= go.opentelemetry.io/otel/log v0.8.0/go.mod h1:M9qvDdUTRCopJcGRKg57+JSQ9LgLBrwwfC32epk5NX8= +go.opentelemetry.io/otel/log v0.19.0 h1:KUZs/GOsw79TBBMfDWsXS+KZ4g2Ckzksd1ymzsIEbo4= go.opentelemetry.io/otel/metric v1.43.0 h1:d7638QeInOnuwOONPp4JAOGfbCEpYb+K6DVWvdxGzgM= go.opentelemetry.io/otel/metric v1.43.0/go.mod h1:RDnPtIxvqlgO8GRW18W6Z/4P462ldprJtfxHxyKd2PY= go.opentelemetry.io/otel/sdk v1.43.0 h1:pi5mE86i5rTeLXqoF/hhiBtUNcrAGHLKQdhg4h4V9Dg= go.opentelemetry.io/otel/sdk v1.43.0/go.mod h1:P+IkVU3iWukmiit/Yf9AWvpyRDlUeBaRg6Y+C58QHzg= go.opentelemetry.io/otel/sdk/log v0.8.0 h1:zg7GUYXqxk1jnGF/dTdLPrK06xJdrXgqgFLnI4Crxvs= go.opentelemetry.io/otel/sdk/log v0.8.0/go.mod h1:50iXr0UVwQrYS45KbruFrEt4LvAdCaWWgIrsN3ZQggo= +go.opentelemetry.io/otel/sdk/log v0.19.0 h1:scYVLqT22D2gqXItnWiocLUKGH9yvkkeql5dBDiXyko= go.opentelemetry.io/otel/sdk/metric v1.43.0 h1:S88dyqXjJkuBNLeMcVPRFXpRw2fuwdvfCGLEo89fDkw= go.opentelemetry.io/otel/sdk/metric v1.43.0/go.mod h1:C/RJtwSEJ5hzTiUz5pXF1kILHStzb9zFlIEe85bhj6A= go.opentelemetry.io/otel/trace v1.43.0 h1:BkNrHpup+4k4w+ZZ86CZoHHEkohws8AY+WTX09nk+3A= @@ -1369,6 +1400,8 @@ golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMx golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= golang.org/x/image v0.36.1-0.20260211191414-e3d762b1d37e h1:gkwT7ZpRdJBB47MJ0h7xeUSHKkd8f3RcM47FgUIRgd4= golang.org/x/image v0.36.1-0.20260211191414-e3d762b1d37e/go.mod h1:ZK2ak7W75f61R/Pwr7T25elpTMmDbUsuiOt4FcDsNI0= +golang.org/x/image v0.38.0 h1:5l+q+Y9JDC7mBOMjo4/aPhMDcxEptsX+Tt3GgRQRPuE= +golang.org/x/image v0.38.0/go.mod h1:/3f6vaXC+6CEanU4KJxbcUZyEePbyKbaLoDOe4ehFYY= golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU= golang.org/x/lint v0.0.0-20190301231843-5614ed5bae6f/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= diff --git a/internal/commands/result.go b/internal/commands/result.go index 22803b39e..1c6a78f50 100644 --- a/internal/commands/result.go +++ b/internal/commands/result.go @@ -33,36 +33,37 @@ import ( ) const ( - failedCreatingSummary = "Failed creating summary" - failedGettingScan = "Failed getting scan" - failedListingResults = "Failed listing results" - failedListingCodeBashing = "Failed codebashing link" - mediumLabel = "medium" - criticalLabel = "critical" - highLabel = "high" - lowLabel = "low" - infoLabel = "info" - sonarTypeLabel = "_sonar" - glSastTypeLabel = ".gl-sast-report" - glScaTypeLabel = ".gl-sca-report" - directoryPermission = 0700 - infoSonar = "INFO" - lowSonar = "LOW" - mediumSonar = "MEDIUM" - highSonar = "HIGH" - criticalSonar = "BLOCKER" - infoLowSarif = "note" - mediumSarif = "warning" - highSarif = "error" - vulnerabilitySonar = "SECURITY" - cleanCodeAttribute = "FORMATTED" - infoCx = "INFO" - lowCx = "LOW" - mediumCx = "MEDIUM" - highCx = "HIGH" - criticalCx = "CRITICAL" - tableResultsFormat = " | %-10s %6v %5d %6d %5d %4d %-9s |\n" - stringTableResultsFormat = " | %-10s %5s %6s %6s %5s %4s %5s |\n" + failedCreatingSummary = "Failed creating summary" + failedGettingScan = "Failed getting scan" + failedListingResults = "Failed listing results" + failedListingCodeBashing = "Failed codebashing link" + mediumLabel = "medium" + criticalLabel = "critical" + highLabel = "high" + lowLabel = "low" + infoLabel = "info" + sonarTypeLabel = "_sonar" + glSastTypeLabel = ".gl-sast-report" + glScaTypeLabel = ".gl-sca-report" + directoryPermission = 0700 + infoSonar = "INFO" + lowSonar = "LOW" + mediumSonar = "MEDIUM" + highSonar = "HIGH" + criticalSonar = "BLOCKER" + infoLowSarif = "note" + mediumSarif = "warning" + highSarif = "error" + vulnerabilitySonar = "SECURITY" + cleanCodeAttribute = "FORMATTED" + infoCx = "INFO" + lowCx = "LOW" + mediumCx = "MEDIUM" + highCx = "HIGH" + criticalCx = "CRITICAL" + tableResultsFormat = " | %-10s %6v %5d %6d %5d %4d %-9s |\n" + stringTableResultsFormat = " | %-10s %5s %6s %6s %5s %4s %5s |\n" + // TableTitleFormat is the printf format string for the scan results summary table title row. TableTitleFormat = " | %-11s %4s %4s %6s %4s %4s %6s |\n" twoNewLines = "\n\n" tableLine = " --------------------------------------------------------------------- " @@ -109,11 +110,28 @@ const ( redundantLabel = "redundant" delayValueForReport = 10 fixLinkPrefix = "https://devhub.checkmarx.com/cve-details/" - ScaDevAndTestExclusionParam = "DEV_AND_TEST" - ScaExcludeResultTypesParam = "exclude-result-types" - noFileForScorecardResultString = "Issue Found in your GitHub repository" - CliType = "cli" - artifactLocationURIString = "This alert has no associated file" + // ScaDevAndTestExclusionParam is the SCA exclude-result-types value used to filter out dev and test dependencies. + ScaDevAndTestExclusionParam = "DEV_AND_TEST" + // ScaExcludeResultTypesParam is the SCA query parameter name used to exclude specific result types. + ScaExcludeResultTypesParam = "exclude-result-types" + noFileForScorecardResultString = "Issue Found in your GitHub repository" + // CliType identifies the report type used when generating reports through the CLI. + CliType = "cli" + artifactLocationURIString = "This alert has no associated file" + commandDocAnnotation = "command:doc" + showSubCommand = "show" + sectionScanSummary = "ScanSummary" + sectionExecutiveSummary = "ExecutiveSummary" + sectionScanResults = "ScanResults" + scaEngineLabel = "SCA" + sastEngineLabel = "SAST" + kicsEngineLabel = "KICS" + notAvailableValue = "NA" + originCode = "code" + originDocumentation = "documentation" + statusCompleted = "Completed" + statusPartial = "Partial" + statusFailed = "Failed" ) var ( @@ -176,6 +194,7 @@ var ( } ) +// NewResultsCommand returns the `results` Cobra command tree with all subcommands attached. func NewResultsCommand( resultsWrapper wrappers.ResultsWrapper, scanWrapper wrappers.ScansWrapper, @@ -195,7 +214,7 @@ func NewResultsCommand( Use: "results", Short: "Retrieve results", Annotations: map[string]string{ - "command:doc": heredoc.Doc( + commandDocAnnotation: heredoc.Doc( ` https://checkmarx.com/resource/documents/en/34965-68640-results.html `, @@ -268,7 +287,7 @@ func resultShowSubCommand( jwtWrapper wrappers.JWTWrapper, ) *cobra.Command { resultShowCmd := &cobra.Command{ - Use: "show", + Use: showSubCommand, Short: "Show results of a scan", Long: "The show command enables the ability to show results about a requested scan in Checkmarx One", Example: heredoc.Doc( @@ -396,6 +415,7 @@ func getRiskManagementResults(riskManagement wrappers.RiskManagementWrapper, pro return ASPMResult, nil } +// GetScannerResults returns per-scanner status entries for the given scan, optionally filtered by scan types. func GetScannerResults(scanWrapper wrappers.ScansWrapper, scanID, scanTypesFlagValue string) ([]ScannerResponse, error) { scanResponseModel, errorModel, err := scanWrapper.GetByID(scanID) if err != nil { @@ -609,27 +629,7 @@ func convertScanToResultsSummary(scanInfo *wrappers.ScanResponseModel, resultsWr enginesStatusCode[commonParams.ScsType] = 0 if len(scanInfo.StatusDetails) > 0 { - for _, statusDetailItem := range scanInfo.StatusDetails { - if statusDetailItem.Status == wrappers.ScanFailed || statusDetailItem.Status == wrappers.ScanCanceled { - if statusDetailItem.Name == commonParams.SastType { - sastIssues = notAvailableNumber - } else if statusDetailItem.Name == commonParams.ScaType { - scaIssues = notAvailableNumber - } else if statusDetailItem.Name == commonParams.KicsType { - kicsIssues = notAvailableNumber - } else if statusDetailItem.Name == commonParams.ScsType { - *scsIssues = notAvailableNumber - } else if statusDetailItem.Name == commonParams.ContainersType && wrappers.IsContainersEnabled { - *containersIssues = notAvailableNumber - } - } - switch statusDetailItem.Status { - case wrappers.ScanFailed: - handleScanStatus(statusDetailItem, enginesStatusCode, scanFailedNumber) - case wrappers.ScanCanceled: - handleScanStatus(statusDetailItem, enginesStatusCode, scanCanceledNumber) - } - } + applyScanStatusDetails(scanInfo.StatusDetails, &sastIssues, &scaIssues, &kicsIssues, scsIssues, containersIssues, enginesStatusCode) } summary := &wrappers.ResultSummary{ ScanID: scanInfo.ID, @@ -680,6 +680,42 @@ func convertScanToResultsSummary(scanInfo *wrappers.ScanResponseModel, resultsWr return summary, nil } +func applyScanStatusDetails( + statusDetails []wrappers.StatusInfo, + sastIssues, scaIssues, kicsIssues *int, + scsIssues, containersIssues *int, + enginesStatusCode map[string]int, +) { + for _, statusDetailItem := range statusDetails { + if statusDetailItem.Status == wrappers.ScanFailed || statusDetailItem.Status == wrappers.ScanCanceled { + markEngineNotAvailable(statusDetailItem.Name, sastIssues, scaIssues, kicsIssues, scsIssues, containersIssues) + } + switch statusDetailItem.Status { + case wrappers.ScanFailed: + handleScanStatus(statusDetailItem, enginesStatusCode, scanFailedNumber) + case wrappers.ScanCanceled: + handleScanStatus(statusDetailItem, enginesStatusCode, scanCanceledNumber) + } + } +} + +func markEngineNotAvailable(name string, sastIssues, scaIssues, kicsIssues, scsIssues, containersIssues *int) { + switch name { + case commonParams.SastType: + *sastIssues = notAvailableNumber + case commonParams.ScaType: + *scaIssues = notAvailableNumber + case commonParams.KicsType: + *kicsIssues = notAvailableNumber + case commonParams.ScsType: + *scsIssues = notAvailableNumber + case commonParams.ContainersType: + if wrappers.IsContainersEnabled { + *containersIssues = notAvailableNumber + } + } +} + func handleScanStatus(statusDetailItem wrappers.StatusInfo, targetTypes map[string]int, statusCode int) { if _, ok := targetTypes[statusDetailItem.Name]; ok { targetTypes[statusDetailItem.Name] = statusCode @@ -853,7 +889,7 @@ func writeMarkdownSummary(targetFile string, data *wrappers.ResultSummary) error if err != nil { return err } - defer file.Close() + defer func() { _ = file.Close() }() err = tmpl.Execute(file, &data) if err != nil { @@ -863,7 +899,7 @@ func writeMarkdownSummary(targetFile string, data *wrappers.ResultSummary) error } // nolint: whitespace -func writeConsoleSummary(summary *wrappers.ResultSummary, featureFlagsWrapper wrappers.FeatureFlagsWrapper, ignorePolicyFlagOmit bool) error { +func writeConsoleSummary(summary *wrappers.ResultSummary, ignorePolicyFlagOmit bool) error { if !isScanPending(summary.Status) { fmt.Printf(" Scan Summary: \n") fmt.Printf(" Created At: %s\n", summary.CreatedAt) @@ -885,7 +921,7 @@ func writeConsoleSummary(summary *wrappers.ResultSummary, featureFlagsWrapper wr } if summary.HasSCS() { - printSCSSummary(summary.SCSOverview.MicroEngineOverviews, featureFlagsWrapper) + printSCSSummary(summary.SCSOverview.MicroEngineOverviews) } fmt.Printf(" Checkmarx One - Scan Summary & Details: %s\n", summary.BaseURI) @@ -951,17 +987,17 @@ func printTableRow(title string, counts *wrappers.EngineResultSummary, statusNum } } -func printSCSSummary(microEngineOverviews []*wrappers.MicroEngineOverview, featureFlagsWrapper wrappers.FeatureFlagsWrapper) { +func printSCSSummary(microEngineOverviews []*wrappers.MicroEngineOverview) { fmt.Printf(" Supply Chain Security Results\n") fmt.Printf(" -------------------------------------------------------------------------- \n") fmt.Println(" | Critical High Medium Low Info Status |") for _, microEngineOverview := range microEngineOverviews { - printSCSTableRow(microEngineOverview, featureFlagsWrapper) + printSCSTableRow(microEngineOverview) } fmt.Printf(" -------------------------------------------------------------------------- \n\n") } -func printSCSTableRow(microEngineOverview *wrappers.MicroEngineOverview, featureFlagsWrapper wrappers.FeatureFlagsWrapper) { +func printSCSTableRow(microEngineOverview *wrappers.MicroEngineOverview) { formatString := " | %-20s %4v %4v %6v %4v %4v %-9s |\n" notAvailableFormatString := " | %-20s %4v %4s %6s %4s %4s %5s |\n" @@ -1104,14 +1140,14 @@ func runGetCodeBashingCommand( codeBashingWrapper wrappers.CodeBashingWrapper, ) func(cmd *cobra.Command, args []string) error { return func(cmd *cobra.Command, args []string) error { - language, _ := cmd.Flags().GetString(commonParams.LanguageFlag) + lang, _ := cmd.Flags().GetString(commonParams.LanguageFlag) cwe, _ := cmd.Flags().GetString(commonParams.CweIDFlag) vulType, _ := cmd.Flags().GetString(commonParams.VulnerabilityTypeFlag) params, err := codeBashingWrapper.BuildCodeBashingParams( []wrappers.CodeBashingParamsCollection{ { CweID: "CWE-" + cwe, - Language: language, + Language: lang, CxQueryName: strings.ReplaceAll(vulType, " ", "_"), }, }, @@ -1179,6 +1215,7 @@ func filterScsResultsByAgent(results *wrappers.ScanResultsCollection, agent stri return results } +// CreateScanReport produces the requested report formats for a scan and writes them to the target path. func CreateScanReport( resultsWrapper wrappers.ResultsWrapper, risksOverviewWrapper wrappers.RisksOverviewWrapper, @@ -1377,63 +1414,75 @@ func getScanOverviewForSCSScanner( } func isScanPending(scanStatus string) bool { - return !(strings.EqualFold(scanStatus, "Completed") || strings.EqualFold( - scanStatus, - "Partial", - ) || strings.EqualFold(scanStatus, "Failed")) + return !strings.EqualFold(scanStatus, statusCompleted) && + !strings.EqualFold(scanStatus, statusPartial) && + !strings.EqualFold(scanStatus, statusFailed) } -func isValidScanStatus(status, format string) bool { - if isScanPending(status) { - log.Printf("Result format file %s not create because scan status is %s", format, status) - return false - } - return true -} - -func createReport(format, - formatPdfToEmail, - formatPdfOptions, - formatSbomOptions, - targetFile, - targetPath string, +func createRawReport( + format, targetFile, targetPath string, results *wrappers.ScanResultsCollection, summary *wrappers.ResultSummary, - exportWrapper wrappers.ExportWrapper, - resultsPdfReportsWrapper wrappers.ResultsPdfWrapper, resultsJSONReportsWrapper wrappers.ResultsJSONWrapper, featureFlagsWrapper wrappers.FeatureFlagsWrapper, - ignorePolicyFlagOmit bool) error { +) (handled bool, err error) { if printer.IsFormat(format, printer.FormatIndentedJSON) { - return nil + return true, nil } if printer.IsFormat(format, printer.FormatSarif) && isValidScanStatus(summary.Status, printer.FormatSarif) { sarifRpt := createTargetName(targetFile, targetPath, printer.FormatSarif) - return exportSarifResults(sarifRpt, results) + return true, exportSarifResults(sarifRpt, results) } if printer.IsFormat(format, printer.FormatSonar) && isValidScanStatus(summary.Status, printer.FormatSonar) { sonarRpt := createTargetName(fmt.Sprintf("%s%s", targetFile, sonarTypeLabel), targetPath, printer.FormatJSON) - return exportSonarResults(sonarRpt, results) + return true, exportSonarResults(sonarRpt, results) } if printer.IsFormat(format, printer.FormatJSON) && isValidScanStatus(summary.Status, printer.FormatJSON) { jsonRpt := createTargetName(targetFile, targetPath, printer.FormatJSON) - return exportJSONResults(jsonRpt, results) + return true, exportJSONResults(jsonRpt, results) } if printer.IsFormat(format, printer.FormatJSONv2) && isValidScanStatus(summary.Status, printer.FormatJSONv2) { summaryRpt := createTargetName(targetFile, targetPath, printer.FormatJSON) - return exportJSONReportResults(resultsJSONReportsWrapper, summary, summaryRpt, featureFlagsWrapper) + return true, exportJSONReportResults(resultsJSONReportsWrapper, summary, summaryRpt, featureFlagsWrapper) } if printer.IsFormat(format, printer.FormatGLSast) { jsonRpt := createTargetName(fmt.Sprintf("%s%s", targetFile, glSastTypeLabel), targetPath, printer.FormatJSON) - return exportGlSastResults(jsonRpt, results, summary) + return true, exportGlSastResults(jsonRpt, results, summary) } if printer.IsFormat(format, printer.FormatGLSca) { jsonRpt := createTargetName(fmt.Sprintf("%s%s", targetFile, glScaTypeLabel), targetPath, printer.FormatJSON) - return exportGlScaResults(jsonRpt, results, summary) + return true, exportGlScaResults(jsonRpt, results, summary) + } + return false, nil +} + +func isValidScanStatus(status, format string) bool { + if isScanPending(status) { + log.Printf("Result format file %s not create because scan status is %s", format, status) + return false + } + return true +} + +func createReport(format, + formatPdfToEmail, + formatPdfOptions, + formatSbomOptions, + targetFile, + targetPath string, + results *wrappers.ScanResultsCollection, + summary *wrappers.ResultSummary, + exportWrapper wrappers.ExportWrapper, + resultsPdfReportsWrapper wrappers.ResultsPdfWrapper, + resultsJSONReportsWrapper wrappers.ResultsJSONWrapper, + featureFlagsWrapper wrappers.FeatureFlagsWrapper, + ignorePolicyFlagOmit bool) error { + if handled, err := createRawReport(format, targetFile, targetPath, results, summary, resultsJSONReportsWrapper, featureFlagsWrapper); handled { + return err } if printer.IsFormat(format, printer.FormatSummaryConsole) { - return writeConsoleSummary(summary, featureFlagsWrapper, ignorePolicyFlagOmit) + return writeConsoleSummary(summary, ignorePolicyFlagOmit) } if printer.IsFormat(format, printer.FormatSummary) { summaryRpt := createTargetName(targetFile, targetPath, printer.FormatHTML) @@ -1491,6 +1540,7 @@ func createDirectory(targetPath string) error { return nil } +// ReadResults fetches all scan results for the given scan and enriches them with SCA and SCS data as applicable. func ReadResults( resultsWrapper wrappers.ResultsWrapper, exportWrapper wrappers.ExportWrapper, @@ -1663,7 +1713,7 @@ func exportGlSastResults(targetFile string, results *wrappers.ScanResultsCollect if err != nil { return errors.Wrapf(err, "%s: failed to create target file ", failedListingResults) } - defer f.Close() + defer func() { _ = f.Close() }() _, _ = fmt.Fprintln(f, string(resultsJSON)) return nil } @@ -1688,8 +1738,8 @@ func exportGlScaResults(targetFile string, results *wrappers.ScanResultsCollecti if err != nil { return errors.Wrapf(err, "%s: failed to create target file ", failedListingResults) } + defer func() { _ = f.Close() }() _, _ = fmt.Fprintln(f, string(resultsJSON)) - defer f.Close() return nil } @@ -1845,16 +1895,16 @@ func exportJSONReportResults(jsonWrapper wrappers.ResultsJSONWrapper, summary *w func parseJSONOptions(enabledEngines []string, reportName string) (jsonOptionsSections, jsonOptionsEngines []string) { jsonOptionsSections = []string{ - "ScanSummary", - "ExecutiveSummary", - "ScanResults", + sectionScanSummary, + sectionExecutiveSummary, + sectionScanResults, } var jsonOptionsEnginesMap = map[string]string{ - commonParams.ScaType: "SCA", - commonParams.SastType: "SAST", - commonParams.KicsType: "KICS", - commonParams.IacType: "KICS", + commonParams.ScaType: scaEngineLabel, + commonParams.SastType: sastEngineLabel, + commonParams.KicsType: kicsEngineLabel, + commonParams.IacType: kicsEngineLabel, commonParams.ContainersType: "Containers", commonParams.ScsType: "Microengines", } @@ -1909,7 +1959,7 @@ func exportPdfResults(pdfWrapper wrappers.ResultsPdfWrapper, summary *wrappers.R // will generate pdf report and send it to the email list // instead of saving it to the file system - if len(formatPdfToEmail) > 0 { + if formatPdfToEmail != "" { emailList, validateErr := validateEmails(formatPdfToEmail) if validateErr != nil { return validateErr @@ -1958,16 +2008,16 @@ func exportPdfResults(pdfWrapper wrappers.ResultsPdfWrapper, summary *wrappers.R func parsePDFOptions(pdfOptions string, enabledEngines []string, reportName string) (pdfOptionsSections, pdfOptionsEngines []string, err error) { var pdfOptionsSectionsMap = map[string]string{ - "scansummary": "ScanSummary", - "executivesummary": "ExecutiveSummary", - "scanresults": "ScanResults", + "scansummary": sectionScanSummary, + "executivesummary": sectionExecutiveSummary, + "scanresults": sectionScanResults, } var pdfOptionsEnginesMap = map[string]string{ - commonParams.ScaType: "SCA", - commonParams.SastType: "SAST", - commonParams.KicsType: "KICS", - commonParams.IacType: "KICS", + commonParams.ScaType: scaEngineLabel, + commonParams.SastType: sastEngineLabel, + commonParams.KicsType: kicsEngineLabel, + commonParams.IacType: kicsEngineLabel, } pdfOptions = strings.ToLower(strings.ReplaceAll(pdfOptions, " ", "")) @@ -2000,9 +2050,9 @@ func translateReportSectionsForImproved(sections []string) []string { var resultSections = make([]string, 0) var pdfOptionsSectionsImprovedTranslation = map[string][]string{ - "ScanSummary": {"scan-information"}, - "ExecutiveSummary": {"results-overview"}, - "ScanResults": {"scan-results", "categories", "resolved-results", "vulnerability-details"}, + sectionScanSummary: {"scan-information"}, + sectionExecutiveSummary: {"results-overview"}, + sectionScanResults: {"scan-results", "categories", "resolved-results", "vulnerability-details"}, } for _, section := range sections { @@ -2087,7 +2137,7 @@ func parseGlSastVulnerability(result *wrappers.ScanResult, glSast *wrappers.GlSa Type: "source", Items: []wrappers.Item{ { - Signatures: []wrappers.Signature{{Algorithm: result.Type + "-Algorithm ", Value: "NA"}}, + Signatures: []wrappers.Signature{{Algorithm: result.Type + "-Algorithm ", Value: notAvailableValue}}, File: fileName, EndLine: endLine, StartLine: startLine, @@ -2166,7 +2216,7 @@ func collectScaFileLocations(result *wrappers.ScanResult) []wrappers.ScaDependen func collectScaPackageItemsDep(result *wrappers.ScanResult) []wrappers.ItemDep { allScaPackageItemDep := []wrappers.ItemDep{} allScaPackageItemDep = append(allScaPackageItemDep, wrappers.ItemDep{ - Signature: []wrappers.SignatureDep{{Algorithm: "SCA-Algorithm ", Value: "NA"}}, + Signature: []wrappers.SignatureDep{{Algorithm: "SCA-Algorithm ", Value: notAvailableValue}}, File: result.VulnerabilityDetails.CveName, EndLine: 0, StartLine: 0, @@ -2743,9 +2793,9 @@ func buildAuxiliaryScaMaps(resultsModel *wrappers.ScanResultsCollection, scaPack // Create map to be used to populate locations for each package path for _, result := range resultsModel.Results { if result.Type == commonParams.ScaType { - for _, packages := range *scaPackageModel { - currentPackage := packages - locationsByID[packages.ID] = currentPackage.Locations + for i := range *scaPackageModel { + pkg := &(*scaPackageModel)[i] + locationsByID[pkg.ID] = pkg.Locations } for _, types := range *scaTypeModel { identifier := fmt.Sprintf("%s:%s", types.ID, types.PackageID) @@ -2893,6 +2943,7 @@ func trimOsSeparatorFromFileName(result *wrappers.ScanResult) { } } +// ScannerResponse is the per-scanner status info returned by the results exit-code subcommand. type ScannerResponse struct { ScanID string `json:"ScanID,omitempty"` Name string `json:"Name,omitempty"` @@ -2943,11 +2994,11 @@ func getFilterResultsForAPISecScanner(risksOverviewWrapper wrappers.RisksOvervie totalRecords++ } var riskDistribution []wrappers.RiskDistributionEntry - if originCount["code"] > 0 { - riskDistribution = append(riskDistribution, wrappers.RiskDistributionEntry{Origin: "code", Total: originCount["code"]}) + if originCount[originCode] > 0 { + riskDistribution = append(riskDistribution, wrappers.RiskDistributionEntry{Origin: originCode, Total: originCount[originCode]}) } - if originCount["documentation"] > 0 { - riskDistribution = append(riskDistribution, wrappers.RiskDistributionEntry{Origin: "documentation", Total: originCount["documentation"]}) + if originCount[originDocumentation] > 0 { + riskDistribution = append(riskDistribution, wrappers.RiskDistributionEntry{Origin: originDocumentation, Total: originCount[originDocumentation]}) } return &wrappers.APISecFilteredResult{ SeverityCount: severityCount, diff --git a/internal/params/filters.go b/internal/params/filters.go index 7312918bc..56db130a8 100644 --- a/internal/params/filters.go +++ b/internal/params/filters.go @@ -123,9 +123,7 @@ var BaseIncludeFilters = []string{ "yarn.lock", "pyproject.toml", "poetry.lock", - "requirements.txt", - "requirement.txt", - "requirement*.txt", + "*requirement*.txt", "composer.lock", "*Dockerfile*", "*dock*", @@ -152,12 +150,10 @@ var BaseIncludeFilters = []string{ "*.vm", "*.ac", "*.am", - "*.app", "*.asax", "*.cmake", "*.dspf", "*.env", - "*.evt", "*.ftl", "*.gsp", "*.gtl", @@ -165,8 +161,6 @@ var BaseIncludeFilters = []string{ "*.ini", "*.jade", "*.jsf", - "*.latex", - "*.lock", "*.master", "*.mf", "*.mustache", @@ -179,17 +173,15 @@ var BaseIncludeFilters = []string{ "*.rpg38", "*.sqlrpg", "*.sqlrpgle", - "*.tex", "*.toml", "*.tsql", - "CMakeLists*.txt", + "*CMakeLists*.txt", "*.vue", "*.xsaccess", "*.xsapp", "*.pug", "*.lua", "*.ec", - "*.csv", "*.apxc", } diff --git a/internal/services/applications_test.go b/internal/services/applications_test.go index 0af427a97..c1be66a70 100644 --- a/internal/services/applications_test.go +++ b/internal/services/applications_test.go @@ -11,11 +11,6 @@ import ( "gotest.tools/assert" ) -const ( - mockApplicationName = "MOCK" - testProjectName = "test-project" -) - func Test_createApplicationIds(t *testing.T) { type args struct { applicationID []string diff --git a/internal/wrappers/mock/application-mock.go b/internal/wrappers/mock/application-mock.go index 8a0271492..8d1546455 100644 --- a/internal/wrappers/mock/application-mock.go +++ b/internal/wrappers/mock/application-mock.go @@ -9,7 +9,13 @@ import ( "github.com/pkg/errors" ) -const code = 355 +const ( + code = 355 + idNewProjectNameStr = "ID-new-project-name" + projectID1Str = "ProjectID1" + projectID2Str = "ProjectID2" + testProjectStr = "test_project" +) type ApplicationsMockWrapper struct{} @@ -31,14 +37,14 @@ func (a ApplicationsMockWrapper) Get(params map[string]string) (*wrappers.Applic Name: "MOCK", Description: "This is a mock application", Criticality: 2, - ProjectIds: []string{"ProjectID1", "ProjectID2", "test_project", "ID-new-project-name"}, + ProjectIds: []string{projectID1Str, projectID2Str, testProjectStr, idNewProjectNameStr}, CreatedAt: time.Now(), } if params["name"] == ExistingApplication { mockApplication.Name = ExistingApplication mockApplication.ID = "ID-newProject" // For ExistingApplication, include "ID-newProject" for polling tests - mockApplication.ProjectIds = []string{"ProjectID1", "ProjectID2", "test_project", "ID-new-project-name", "ID-newProject"} + mockApplication.ProjectIds = []string{projectID1Str, projectID2Str, testProjectStr, idNewProjectNameStr, "ID-newProject"} return &wrappers.ApplicationsResponseModel{ TotalCount: 1, Applications: []wrappers.Application{mockApplication}, diff --git a/internal/wrappers/results-sarif.go b/internal/wrappers/results-sarif.go index e73786532..60c6ec63a 100644 --- a/internal/wrappers/results-sarif.go +++ b/internal/wrappers/results-sarif.go @@ -63,14 +63,17 @@ type SarifScanResult struct { Properties *SarifResultProperties `json:"properties,omitempty"` } +// SarifCodeFlow represents a SARIF codeFlows entry. type SarifCodeFlow struct { ThreadFlows []SarifThreadFlow `json:"threadFlows"` } +// SarifThreadFlow represents a SARIF threadFlow entry. type SarifThreadFlow struct { Locations []SarifThreadFlowLocation `json:"locations"` } +// SarifThreadFlowLocation represents a single location within a SARIF threadFlow. type SarifThreadFlowLocation struct { Location SarifLocation `json:"location"` } diff --git a/test/integration/data/config.yaml b/test/integration/data/config.yaml index 6d6b4c836..b01de3ac2 100644 --- a/test/integration/data/config.yaml +++ b/test/integration/data/config.yaml @@ -18,7 +18,6 @@ cx_byor_path: api/byor cx_client_id: example_client_id cx_client_secret: example_client_secret cx_codebashing_path: api/codebashing/lessons -cx_config_file_path: data/config.yaml cx_create_oath2_client_path: auth/realms/organization/pip/clients cx_custom_states_path: api/custom-states cx_descriptions_path: api/queries/descriptions From 47eee8707859de31b3c5aabe71f0524bebda92ce Mon Sep 17 00:00:00 2001 From: atishj99 <141334503+cx-atish-jadhav@users.noreply.github.com> Date: Thu, 28 May 2026 20:48:05 +0530 Subject: [PATCH 10/27] CVE-2026-33813: fixing cxone scan vulnerability --- go.mod | 24 +- go.sum | 234 +- internal/commands/result.go | 6020 +++++++++++++++--------------- internal/commands/result_test.go | 6 +- 4 files changed, 3044 insertions(+), 3240 deletions(-) diff --git a/go.mod b/go.mod index 1e3576d3f..593b653b0 100644 --- a/go.mod +++ b/go.mod @@ -45,9 +45,6 @@ require ( cloud.google.com/go/iam v1.5.3 // indirect cloud.google.com/go/monitoring v1.24.3 // indirect cloud.google.com/go/storage v1.61.3 // indirect - cyphar.com/go-pathrs v0.2.1 // indirect - github.com/AdaLogics/go-fuzz-headers v0.0.0-20240806141605-e8a1dd7889d6 // indirect - github.com/AdamKorcz/go-118-fuzz-build v0.0.0-20240914100643-eb91380d8434 // indirect github.com/GoogleCloudPlatform/opentelemetry-operations-go/detectors/gcp v1.31.0 // indirect github.com/GoogleCloudPlatform/opentelemetry-operations-go/exporter/metric v0.55.0 // indirect github.com/GoogleCloudPlatform/opentelemetry-operations-go/internal/resourcemapping v0.55.0 // indirect @@ -81,25 +78,17 @@ require ( github.com/bodgit/sevenzip v1.6.1 // indirect github.com/bodgit/windows v1.0.1 // indirect github.com/cespare/xxhash/v2 v2.3.0 // indirect - github.com/checkpoint-restore/go-criu/v6 v6.3.0 // indirect - github.com/cilium/ebpf v0.17.3 // indirect github.com/clipperhouse/displaywidth v0.10.0 // indirect github.com/clipperhouse/uax29/v2 v2.6.0 // indirect github.com/cncf/xds/go v0.0.0-20251210132809-ee656c7534f5 // indirect - github.com/containerd/console v1.0.5 // indirect github.com/containerd/containerd/v2 v2.3.1 // indirect github.com/containerd/plugin v1.1.0 // indirect - github.com/coreos/go-systemd/v22 v22.7.0 // indirect - github.com/cpuguy83/go-md2man/v2 v2.0.7 // indirect github.com/diskfs/go-diskfs v1.7.0 // indirect github.com/distribution/distribution/v3 v3.1.1 // indirect - github.com/docker/go-events v0.0.0-20250808211157-605354379745 // indirect github.com/envoyproxy/go-control-plane/envoy v1.36.0 // indirect github.com/envoyproxy/protoc-gen-validate v1.3.0 // indirect - github.com/go-jose/go-jose/v3 v3.0.5 // indirect github.com/go-jose/go-jose/v4 v4.1.4 // indirect github.com/goccy/go-yaml v1.19.2 // indirect - github.com/godbus/dbus/v5 v5.1.0 // indirect github.com/gohugoio/hashstructure v0.6.0 // indirect github.com/google/s2a-go v0.1.9 // indirect github.com/googleapis/enterprise-certificate-proxy v0.3.14 // indirect @@ -117,30 +106,23 @@ require ( github.com/minio/minlz v1.0.1 // indirect github.com/moby/moby/api v1.54.1 // indirect github.com/moby/moby/client v0.4.0 // indirect - github.com/moby/sys/capability v0.4.0 // indirect - github.com/mrunalp/fileutils v0.5.1 // indirect github.com/nix-community/go-nix v0.0.0-20250101154619-4bdde671e0a1 // indirect github.com/nwaples/rardecode/v2 v2.2.0 // indirect github.com/olekukonko/cat v0.0.0-20250911104152-50322a0618f6 // indirect github.com/olekukonko/errors v1.2.0 // indirect github.com/olekukonko/ll v0.1.6 // indirect - github.com/opencontainers/cgroups v0.0.4 // indirect - github.com/opencontainers/runc v1.3.4 // indirect github.com/pkg/xattr v0.4.9 // indirect github.com/planetscale/vtprotobuf v0.6.1-0.20240319094008-0393e58bdf10 // indirect - github.com/seccomp/libseccomp-golang v0.10.0 // indirect + github.com/prometheus/procfs v0.20.1 // indirect github.com/smallnest/ringbuffer v0.0.0-20241116012123-461381446e3d // indirect github.com/sorairolake/lzip-go v0.3.8 // indirect github.com/spiffe/go-spiffe/v2 v2.6.0 // indirect - github.com/urfave/cli v1.22.16 // indirect - github.com/vishvananda/netlink v1.3.1 // indirect - github.com/vishvananda/netns v0.0.5 // indirect go.opentelemetry.io/contrib/detectors/gcp v1.39.0 // indirect go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.68.0 // indirect + go.opentelemetry.io/otel/exporters/stdout/stdoutmetric v1.42.0 // indirect go.opentelemetry.io/otel/sdk v1.43.0 // indirect go.opentelemetry.io/otel/sdk/metric v1.43.0 // indirect go4.org v0.0.0-20230225012048-214862532bf5 // indirect - golang.org/x/image v0.38.0 // indirect gonum.org/v1/gonum v0.17.0 // indirect google.golang.org/api v0.271.0 // indirect google.golang.org/genproto/googleapis/api v0.0.0-20260401024825-9d38bb4040a9 // indirect @@ -256,7 +238,6 @@ require ( github.com/google/pprof v0.0.0-20260115054156-294ebfa9ad83 // indirect github.com/gorilla/websocket v1.5.4-0.20250319132907-e064f32e3674 // indirect github.com/gosuri/uitable v0.0.4 // indirect - github.com/gregjones/httpcache v0.0.0-20190611155906-901d90724c79 // indirect github.com/h2non/filetype v1.1.3 // indirect github.com/hashicorp/errwrap v1.1.0 // indirect github.com/hashicorp/go-multierror v1.1.1 // indirect @@ -312,7 +293,6 @@ require ( github.com/opencontainers/go-digest v1.0.0 // indirect github.com/opencontainers/image-spec v1.1.1 // indirect github.com/opencontainers/runtime-spec v1.3.0 // indirect - github.com/opencontainers/selinux v1.13.1 // indirect github.com/pborman/indent v1.2.1 // indirect github.com/pelletier/go-toml v1.9.5 // indirect github.com/pelletier/go-toml/v2 v2.3.1 // indirect diff --git a/go.sum b/go.sum index 65c70b7f2..0a4e739f9 100644 --- a/go.sum +++ b/go.sum @@ -67,8 +67,6 @@ cloud.google.com/go/storage v1.61.3 h1:VS//ZfBuPGDvakfD9xyPW1RGF1Vy3BWUoVZXgW1KM cloud.google.com/go/storage v1.61.3/go.mod h1:JtqK8BBB7TWv0HVGHubtUdzYYrakOQIsMLffZ2Z/HWk= cloud.google.com/go/trace v1.11.7 h1:kDNDX8JkaAG3R2nq1lIdkb7FCSi1rCmsEtKVsty7p+U= cloud.google.com/go/trace v1.11.7/go.mod h1:TNn9d5V3fQVf6s4SCveVMIBS2LJUqo73GACmq/Tky0s= -cyphar.com/go-pathrs v0.2.1 h1:9nx1vOgwVvX1mNBWDu93+vaceedpbsDqo+XuBGL40b8= -cyphar.com/go-pathrs v0.2.1/go.mod h1:y8f1EMG7r+hCuFf/rXsKqMJrJAUoADZGNh5/vZPKcGc= dario.cat/mergo v1.0.2 h1:85+piFYR1tMbRrLcDwR18y4UKJ3aH1Tbzi24VRW1TK8= dario.cat/mergo v1.0.2/go.mod h1:E/hbnu0NxMFBjpMIE34DRGLWqDy0g5FuKDhCb31ngxA= dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU= @@ -76,15 +74,12 @@ filippo.io/edwards25519 v1.1.0 h1:FNf4tywRC1HmFuKW5xopWpigGjJKiJSV0Cqo0cJWDaA= filippo.io/edwards25519 v1.1.0/go.mod h1:BxyFTGdWcka3PhytdK4V28tE5sGfRvvvRV7EaN4VDT4= github.com/AdaLogics/go-fuzz-headers v0.0.0-20240806141605-e8a1dd7889d6 h1:He8afgbRMd7mFxO99hRNu+6tazq8nFF9lIwo9JFroBk= github.com/AdaLogics/go-fuzz-headers v0.0.0-20240806141605-e8a1dd7889d6/go.mod h1:8o94RPi1/7XTJvwPpRSzSUedZrtlirdB3r9Z20bi2f8= -github.com/AdamKorcz/go-118-fuzz-build v0.0.0-20240914100643-eb91380d8434 h1:t9mXVk8SurivauUmW28nWggC/aOm5NBZ+U2ddBfbyP8= -github.com/AdamKorcz/go-118-fuzz-build v0.0.0-20240914100643-eb91380d8434/go.mod h1:n+tj8pffsLO7fLdcrnbfl444A2OwGv8a6ISsac75Wow= github.com/Azure/go-ansiterm v0.0.0-20250102033503-faa5f7b0171c h1:udKWzYgxTojEKWjV8V+WSxDXJ4NFATAsZjh8iIbsQIg= github.com/Azure/go-ansiterm v0.0.0-20250102033503-faa5f7b0171c/go.mod h1:xomTg63KZ2rFqZQzSB4Vz2SUXa1BpHTVz9L5PTmPC4E= github.com/BobuSumisu/aho-corasick v1.0.3 h1:uuf+JHwU9CHP2Vx+wAy6jcksJThhJS9ehR8a+4nPE9g= github.com/BobuSumisu/aho-corasick v1.0.3/go.mod h1:hm4jLcvZKI2vRF2WDU1N4p/jpWtpOzp3nLmi9AzX/XE= github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= github.com/BurntSushi/toml v0.4.1/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbicEuybxQ= -github.com/BurntSushi/toml v1.4.0/go.mod h1:ukJfTF/6rtPPRCnwkur4qwRxa8vTRFBF0uk2lLoLwho= github.com/BurntSushi/toml v1.6.0 h1:dRaEfpa2VI55EwlIW72hMRHdWouJeRF7TPYhI+AUQjk= github.com/BurntSushi/toml v1.6.0/go.mod h1:ukJfTF/6rtPPRCnwkur4qwRxa8vTRFBF0uk2lLoLwho= github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo= @@ -111,8 +106,6 @@ github.com/DATA-DOG/go-sqlmock v1.5.2/go.mod h1:88MAG/4G7SMwSE3CeA0ZKzrT5CiOU3OJ github.com/DataDog/datadog-go v3.2.0+incompatible/go.mod h1:LButxg5PwREeZtORoXG3tL4fMGNddJ+vMq1mwgfaqoQ= github.com/DataDog/zstd v1.5.6 h1:LbEglqepa/ipmmQJUDnSsfvA8e8IStVcGaFWDuxvGOY= github.com/DataDog/zstd v1.5.6/go.mod h1:g4AWEaM3yOg3HYfnJ3YIawPnVdXJh9QME85blwSAmyw= -github.com/GoogleCloudPlatform/opentelemetry-operations-go/detectors/gcp v1.30.0 h1:sBEjpZlNHzK1voKq9695PJSX2o5NEXl7/OL3coiIY0c= -github.com/GoogleCloudPlatform/opentelemetry-operations-go/detectors/gcp v1.30.0/go.mod h1:P4WPRUkOhJC13W//jWpyfJNDAIpvRbAUIYLX/4jtlE0= github.com/GoogleCloudPlatform/opentelemetry-operations-go/detectors/gcp v1.31.0 h1:DHa2U07rk8syqvCge0QIGMCE1WxGj9njT44GH7zNJLQ= github.com/GoogleCloudPlatform/opentelemetry-operations-go/detectors/gcp v1.31.0/go.mod h1:P4WPRUkOhJC13W//jWpyfJNDAIpvRbAUIYLX/4jtlE0= github.com/GoogleCloudPlatform/opentelemetry-operations-go/exporter/metric v0.55.0 h1:UnDZ/zFfG1JhH/DqxIZYU/1CUAlTUScoXD/LcM2Ykk8= @@ -132,12 +125,8 @@ github.com/Masterminds/sprig/v3 v3.3.0/go.mod h1:Zy1iXRYNqNLUolqCpL4uhk6SHUMAOSC github.com/Masterminds/squirrel v1.5.4 h1:uUcX/aBc8O7Fg9kaISIUsHXdKuqehiXAMQTYX8afzqM= github.com/Masterminds/squirrel v1.5.4/go.mod h1:NNaOrjSoIDfDA40n7sr2tPNZRfjzjA400rg+riTZj10= github.com/Microsoft/go-winio v0.5.2/go.mod h1:WpS1mjBmmwHBEWmogvA2mj8546UReBk4v8QkMxJ6pZY= -github.com/Microsoft/go-winio v0.6.2 h1:F2VQgta7ecxGYO8k3ZZz3RS8fVIXVxONVUPlNERoyfY= -github.com/Microsoft/go-winio v0.6.2/go.mod h1:yd8OoFMLzJbo9gZq8j5qaps8bJ9aShtEA8Ipt1oGCvU= github.com/Microsoft/go-winio v0.6.3-0.20251027160822-ad3df93bed29 h1:0kQAzHq8vLs7Pptv+7TxjdETLf/nIqJpIB4oC6Ba4vY= github.com/Microsoft/go-winio v0.6.3-0.20251027160822-ad3df93bed29/go.mod h1:ZWa7ssZJT30CCDGJ7fk/2SBTq9BIQrrVjrcss0UW2s0= -github.com/Microsoft/hcsshim v0.14.1 h1:CMuB3fqQVfPdhyXhUqYdUmPUIOhJkmghCx3dJet8Cqs= -github.com/Microsoft/hcsshim v0.14.1/go.mod h1:VnzvPLyWUhxiPVsJ31P6XadxCcTogTguBFDy/1GR/OM= github.com/Microsoft/hcsshim v0.15.0-rc.1 h1:FbbwtQmiD+BVHynGkx5S65JkLyhkEiiTP8nrpmg2SZw= github.com/Microsoft/hcsshim v0.15.0-rc.1/go.mod h1:HWvvUPIy9HF6LotILj1G4VyS065rcLQ6tqj6tMUdOfI= github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU= @@ -183,8 +172,6 @@ github.com/anchore/go-version v1.2.2-0.20200701162849-18adb9c92b9b h1:e1bmaoJfZV github.com/anchore/go-version v1.2.2-0.20200701162849-18adb9c92b9b/go.mod h1:Bkc+JYWjMCF8OyZ340IMSIi2Ebf3uwByOk6ho4wne1E= github.com/anchore/packageurl-go v0.2.0 h1:CkrM4RMUwrEGAiE1OVlxaZNzWj0TuHRey7o4T/EAErk= github.com/anchore/packageurl-go v0.2.0/go.mod h1:2JCgOQMIsqZ7TmliXG4PnUthPJAKE3mWQbsW2XHjAOE= -github.com/anchore/stereoscope v0.1.23 h1:q9i3CtbicTuSlcCnA+5pfoT9WDCEoSqvXDfHMH1hyWo= -github.com/anchore/stereoscope v0.1.23/go.mod h1:JLnun49fkLkuv3ebU0ROvFl/0JiRmNmUtCzc6y4ollo= github.com/anchore/stereoscope v0.2.0 h1:8haOu2ugLymmxvyfrZR7OTBFiRFRBh5LlNUtRrSRoxI= github.com/anchore/stereoscope v0.2.0/go.mod h1:PYx3fD4lvBVsYoQ/fBdauhZ5hmkRrJgw1B73svKx7/U= github.com/anchore/syft v1.43.0 h1:m6BwN48vgD0j2U4uk/wwqkUCxVKp2On30ZnKWQGCjKI= @@ -279,13 +266,12 @@ github.com/bouk/monkey v1.0.0 h1:k6z8fLlPhETfn5l9rlWVE7Q6B23DoaqosTdArvNQRdc= github.com/bouk/monkey v1.0.0/go.mod h1:PG/63f4XEUlVyW1ttIeOJmJhhe1+t9EC/je3eTjvFhE= github.com/bradleyjkemp/cupaloy/v2 v2.8.0 h1:any4BmKE+jGIaMpnU8YgH/I2LPiLBufr6oMMlVBbn9M= github.com/bradleyjkemp/cupaloy/v2 v2.8.0/go.mod h1:bm7JXdkRd4BHJk9HpwqAI8BoAY1lps46Enkdqw6aRX0= -github.com/bshuster-repo/logrus-logstash-hook v1.0.0 h1:e+C0SB5R1pu//O4MQ3f9cFuPGoOVeF2fE4Og9otCc70= -github.com/bshuster-repo/logrus-logstash-hook v1.0.0/go.mod h1:zsTqEiSzDgAa/8GZR7E1qaXrhYNDKBYy5/dWPTIflbk= github.com/bshuster-repo/logrus-logstash-hook v1.1.0 h1:o2FzZifLg+z/DN1OFmzTWzZZx/roaqt8IPZCIVco8r4= +github.com/bshuster-repo/logrus-logstash-hook v1.1.0/go.mod h1:Q2aXOe7rNuPgbBtPCOzYyWDvKX7+FpxE5sRdvcPoui0= github.com/bwmarrin/discordgo v0.27.1 h1:ib9AIc/dom1E/fSIulrBwnez0CToJE113ZGt4HoliGY= github.com/bwmarrin/discordgo v0.27.1/go.mod h1:NJZpH+1AfhIcyQsPeuBKsUtYrRnjkyu0kIVMCHkZtRY= -github.com/cenkalti/backoff/v4 v4.3.0 h1:MyRJ/UdXutAwSAT+s3wNd7MfTIcy71VQueUuFK343L8= -github.com/cenkalti/backoff/v4 v4.3.0/go.mod h1:Y3VNntkOUPxTVeUxJ/G5vcM//AlwfmyYozVcomhLiZE= +github.com/cenkalti/backoff/v5 v5.0.3 h1:ZN+IMa753KfX5hd8vVaMixjnqRZ3y8CuJKRKj1xcsSM= +github.com/cenkalti/backoff/v5 v5.0.3/go.mod h1:rkhZdG3JZukswDf7f0cwqPNk4K0sa+F97BxZthm/crw= github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= github.com/census-instrumentation/opencensus-proto v0.3.0/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc= @@ -311,8 +297,6 @@ github.com/charmbracelet/x/term v0.2.2 h1:xVRT/S2ZcKdhhOuSP4t5cLi5o+JxklsoEObBSg github.com/charmbracelet/x/term v0.2.2/go.mod h1:kF8CY5RddLWrsgVwpw4kAa6TESp6EB5y3uxGLeCqzAI= github.com/checkmarx/2ms/v3 v3.21.0 h1:EcabeDypNMsSidISQbziZ062HjMZQ+Hm/uOJ5AOxK8o= github.com/checkmarx/2ms/v3 v3.21.0/go.mod h1:e8f4F94MZ+iCetR/G3aw7nXdPe6TgPI92Zzk/NG1l0o= -github.com/checkpoint-restore/go-criu/v6 v6.3.0 h1:mIdrSO2cPNWQY1truPg6uHLXyKHk3Z5Odx4wjKOASzA= -github.com/checkpoint-restore/go-criu/v6 v6.3.0/go.mod h1:rrRTN/uSwY2X+BPRl/gkulo9gsKOSAeVp9/K2tv7xZI= github.com/chromedp/cdproto v0.0.0-20230802225258-3cf4e6d46a89/go.mod h1:GKljq0VrfU4D5yc+2qA6OVr8pmO/MBbPEWqWQ/oqGEs= github.com/chromedp/chromedp v0.9.2/go.mod h1:LkSXJKONWTCHAfQasKFUZI+mxqS4tZqhmtGzzhLsnLs= github.com/chromedp/sysutil v1.0.0/go.mod h1:kgWmDdq8fTzXYcKIBqIYvRRTnYb9aNS9moAV0xufSww= @@ -322,8 +306,6 @@ github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5P github.com/chzyer/readline v1.5.1/go.mod h1:Eh+b79XXUwfKfcPLepksvw2tcLE/Ct21YObkaSkeBlk= github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU= github.com/chzyer/test v1.0.0/go.mod h1:2JlltgoNkt4TW/z9V/IzDdFaMTM2JPIi26O1pF38GC8= -github.com/cilium/ebpf v0.17.3 h1:FnP4r16PWYSE4ux6zN+//jMcW4nMVRvuTLVTvCjyyjg= -github.com/cilium/ebpf v0.17.3/go.mod h1:G5EDHij8yiLzaqn0WjyfJHvRa+3aDlReIaLVRMvOyJk= github.com/circonus-labs/circonus-gometrics v2.3.1+incompatible/go.mod h1:nmEj6Dob7S7YxXgwXpfOuvO54S+tGdZdw9fuRZt25Ag= github.com/circonus-labs/circonusllhist v0.1.3/go.mod h1:kMXHVDlOchFAehlya5ePtbp5jckzBHf4XRpQvBOLI+I= github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= @@ -345,28 +327,14 @@ github.com/cncf/xds/go v0.0.0-20211011173535-cb28da3451f1/go.mod h1:eXthEFrGJvWH github.com/cncf/xds/go v0.0.0-20211130200136-a8f946100490/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= github.com/cncf/xds/go v0.0.0-20251210132809-ee656c7534f5 h1:6xNmx7iTtyBRev0+D/Tv1FZd4SCg8axKApyNyRsAt/w= github.com/cncf/xds/go v0.0.0-20251210132809-ee656c7534f5/go.mod h1:KdCmV+x/BuvyMxRnYBlmVaq4OLiKW6iRQfvC62cvdkI= -github.com/containerd/cgroups/v3 v3.1.2 h1:OSosXMtkhI6Qove637tg1XgK4q+DhR0mX8Wi8EhrHa4= -github.com/containerd/cgroups/v3 v3.1.2/go.mod h1:PKZ2AcWmSBsY/tJUVhtS/rluX0b1uq1GmPO1ElCmbOw= github.com/containerd/cgroups/v3 v3.1.3 h1:eUNflyMddm18+yrDmZPn3jI7C5hJ9ahABE5q6dyLYXQ= github.com/containerd/cgroups/v3 v3.1.3/go.mod h1:PKZ2AcWmSBsY/tJUVhtS/rluX0b1uq1GmPO1ElCmbOw= -github.com/containerd/console v1.0.5 h1:R0ymNeydRqH2DmakFNdmjR2k0t7UPuiOV/N/27/qqsc= -github.com/containerd/console v1.0.5/go.mod h1:YynlIjWYF8myEu6sdkwKIvGQq+cOckRm6So2avqoYAk= github.com/containerd/containerd v1.7.32 h1:S54xuVcPxeLaYgaRABtpJ2VyVUVsy0IGf7qHBs+sbY8= github.com/containerd/containerd v1.7.32/go.mod h1:jdwD6s/BhV4XVJGrvtziNPVA+83n66TwptVaPKprq4E= -github.com/containerd/containerd/api v1.10.0 h1:5n0oHYVBwN4VhoX9fFykCV9dF1/BvAXeg2F8W6UYq1o= -github.com/containerd/containerd/api v1.10.0/go.mod h1:NBm1OAk8ZL+LG8R0ceObGxT5hbUYj7CzTmR3xh0DlMM= -github.com/containerd/containerd/api v1.11.0 h1:smv4e74S/wwIx0Sj7lhwO1t3M/oi+mSzk2VXqHq8aO0= -github.com/containerd/containerd/api v1.11.0/go.mod h1:CaQFRu+N1MtbgL6JDOJLUB1hCKESU1lD6MuTJhgtdlw= github.com/containerd/containerd/api v1.11.1 h1:h8nfoDW9+fNsC/9TwiAHj8B1GzXKtR4eFtkhi/X5RLU= github.com/containerd/containerd/api v1.11.1/go.mod h1:CaQFRu+N1MtbgL6JDOJLUB1hCKESU1lD6MuTJhgtdlw= -github.com/containerd/containerd/v2 v2.2.3 h1:mOBRLaHGvmgy0bRo1Sg6OD8ugMKZIvCoWWMeMMygliA= -github.com/containerd/containerd/v2 v2.2.3/go.mod h1:ns24cwt+p36mRnuKE3hLRxVBpuSP+a/Y25AMki1t/RY= -github.com/containerd/containerd/v2 v2.3.0 h1:qpB5dyToxPqea1OdedyAiAnnor5wxTM+Py9nWt5CnWY= -github.com/containerd/containerd/v2 v2.3.0/go.mod h1:+chyhxLNeqUVOcTJGgaSu/IbDGX6p3+d8AJjAaerAS8= github.com/containerd/containerd/v2 v2.3.1 h1:4dVXBdlvotRBlaP2TmNbY/EGc06KJrMDDUqQdxX/HOk= github.com/containerd/containerd/v2 v2.3.1/go.mod h1:xVoxGPWZBwwph8DF2IbDhriLKdHfjdpO0b3wFP9wQ1I= -github.com/containerd/continuity v0.4.5 h1:ZRoN1sXq9u7V6QoHMcVWGhOwDFqZ4B9i5H6un1Wh0x4= -github.com/containerd/continuity v0.4.5/go.mod h1:/lNJvtJKUQStBzpVQ1+rasXO1LAWtUQssk28EZvJ3nE= github.com/containerd/continuity v0.5.0 h1:7a85HZpCSs+1Zps0Ee3DPSuAWY+0SJM1JNM51nlEVDg= github.com/containerd/continuity v0.5.0/go.mod h1:/lNJvtJKUQStBzpVQ1+rasXO1LAWtUQssk28EZvJ3nE= github.com/containerd/errdefs v1.0.0 h1:tg5yIfIlQIrxYtu9ajqY42W3lpS19XqdxRQeEwYG8PI= @@ -379,14 +347,10 @@ github.com/containerd/log v0.1.0 h1:TCJt7ioM2cr/tfR8GPbGf9/VRAX8D2B4PjzCpfX540I= github.com/containerd/log v0.1.0/go.mod h1:VRRf09a7mHDIRezVKTRCrOq78v577GXq3bSa3EhrzVo= github.com/containerd/platforms v1.0.0-rc.4 h1:M42JrUT4zfZTqtkUwkr0GzmUWbfyO5VO0Q5b3op97T4= github.com/containerd/platforms v1.0.0-rc.4/go.mod h1:lKlMXyLybmBedS/JJm11uDofzI8L2v0J2ZbYvNsbq1A= -github.com/containerd/plugin v1.0.0 h1:c8Kf1TNl6+e2TtMHZt+39yAPDbouRH9WAToRjex483Y= -github.com/containerd/plugin v1.0.0/go.mod h1:hQfJe5nmWfImiqT1q8Si3jLv3ynMUIBB47bQ+KexvO8= github.com/containerd/plugin v1.1.0 h1:O+7lczNJVMy8rz0YNx3xGB8tTf5qY4i5abF041Ew19U= github.com/containerd/plugin v1.1.0/go.mod h1:qBTum+A8lJ6lO44A19Eo7y1OlcLj4OWFH1DA/vnHmcc= github.com/containerd/stargz-snapshotter/estargz v0.18.2 h1:yXkZFYIzz3eoLwlTUZKz2iQ4MrckBxJjkmD16ynUTrw= github.com/containerd/stargz-snapshotter/estargz v0.18.2/go.mod h1:XyVU5tcJ3PRpkA9XS2T5us6Eg35yM0214Y+wvrZTBrY= -github.com/containerd/ttrpc v1.2.7 h1:qIrroQvuOL9HQ1X6KHe2ohc7p+HP/0VE6XPU7elJRqQ= -github.com/containerd/ttrpc v1.2.7/go.mod h1:YCXHsb32f+Sq5/72xHubdiJRQY9inL4a4ZQrAbN1q9o= github.com/containerd/ttrpc v1.2.8 h1:xbVu6D4qF2jihdh9rDVOKqUMiFBQk6YctTdo1zk087Y= github.com/containerd/ttrpc v1.2.8/go.mod h1:wyZW2K79t4Hfcxl+GUvkZqRBzJlqFFvgEeeWXa42tyE= github.com/containerd/typeurl/v2 v2.2.3 h1:yNA/94zxWdvYACdYO8zofhrTVuQY73fFU1y++dYSw40= @@ -394,16 +358,10 @@ github.com/containerd/typeurl/v2 v2.2.3/go.mod h1:95ljDnPfD3bAbDJRugOiShd/DlAAsx github.com/coreos/go-semver v0.3.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk= github.com/coreos/go-systemd/v22 v22.3.2/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc= github.com/coreos/go-systemd/v22 v22.5.0/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc= -github.com/coreos/go-systemd/v22 v22.6.0 h1:aGVa/v8B7hpb0TKl0MWoAavPDmHvobFe5R5zn0bCJWo= -github.com/coreos/go-systemd/v22 v22.6.0/go.mod h1:iG+pp635Fo7ZmV/j14KUcmEyWF+0X7Lua8rrTWzYgWU= github.com/coreos/go-systemd/v22 v22.7.0 h1:LAEzFkke61DFROc7zNLX/WA2i5J8gYqe0rSj9KI28KA= github.com/coreos/go-systemd/v22 v22.7.0/go.mod h1:xNUYtjHu2EDXbsxz1i41wouACIwT7Ybq9o0BQhMwD0w= github.com/cpuguy83/go-md2man/v2 v2.0.1/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= -github.com/cpuguy83/go-md2man/v2 v2.0.2/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= -github.com/cpuguy83/go-md2man/v2 v2.0.5/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= github.com/cpuguy83/go-md2man/v2 v2.0.6/go.mod h1:oOW0eioCTA6cOiMLiUPZOpcVxMig6NIQQ7OS05n1F4g= -github.com/cpuguy83/go-md2man/v2 v2.0.7 h1:zbFlGlXEAKlwXpmvle3d8Oe3YnkKIK4xSRTd3sHPnBo= -github.com/cpuguy83/go-md2man/v2 v2.0.7/go.mod h1:oOW0eioCTA6cOiMLiUPZOpcVxMig6NIQQ7OS05n1F4g= github.com/creack/pty v1.1.24 h1:bJrF4RRfyJnbTJqzRLHzcGaZK1NeM5kTC9jGgovnR1s= github.com/creack/pty v1.1.24/go.mod h1:08sCNb52WyoAwi2QDyzUCTgcvVFhUzewun7wtTfvcwE= github.com/cyphar/filepath-securejoin v0.6.1 h1:5CeZ1jPXEiYt3+Z6zqprSAgSWiggmpVyciv8syjIpVE= @@ -419,10 +377,6 @@ github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f h1:lO4WD4F/r github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f/go.mod h1:cuUVRXasLTGF7a8hSLbxyZXjz+1KgoB3wDUb6vlszIc= github.com/diskfs/go-diskfs v1.7.0 h1:vonWmt5CMowXwUc79jWyGrf2DIMeoOjkLlMnQYGVOs8= github.com/diskfs/go-diskfs v1.7.0/go.mod h1:LhQyXqOugWFRahYUSw47NyZJPezFzB9UELwhpszLP/k= -github.com/distribution/distribution/v3 v3.0.1-0.20250403190400-dbca4995c83c h1:tFjIrcN2x16eg3aob8g8LPNJClLxtQbu1wqeUMydXRc= -github.com/distribution/distribution/v3 v3.0.1-0.20250403190400-dbca4995c83c/go.mod h1:tRNuFoZsUdyRVegq8xGNeds4KLjwLCRin/tTo6i1DhU= -github.com/distribution/distribution/v3 v3.0.1-0.20260120145532-40594bd98e6d h1:c2HDaWKU1MalLXwrAek+Yks7n80p/salSR5u6alHPBo= -github.com/distribution/distribution/v3 v3.0.1-0.20260120145532-40594bd98e6d/go.mod h1:WiiB9B3TqqAPe7hPjI1P9OMtEW7Ub/HHGndi11SqeDA= github.com/distribution/distribution/v3 v3.1.1 h1:KUbk7C8CfaLXy8kbf/hGq9cad/wCoLB6dbWH6DMbmX0= github.com/distribution/distribution/v3 v3.1.1/go.mod h1:d7lXwZpph0bVcOj4Aqn0nMrWHIwRQGdiV5TLeI+/w6Y= github.com/distribution/reference v0.6.0 h1:0IXCQ5g4/QMHHkarYzh5l+u8T3t73zM5QvfrDyIgxBk= @@ -431,16 +385,12 @@ github.com/djherbis/times v1.6.0 h1:w2ctJ92J8fBvWPxugmXIv7Nz7Q3iDMKNx9v5ocVH20c= github.com/djherbis/times v1.6.0/go.mod h1:gOHeRAz2h+VJNZ5Gmc/o7iD9k4wW7NMVqieYCY99oc0= github.com/dlclark/regexp2 v1.11.0 h1:G/nrcoOa7ZXlpoa/91N3X7mM3r8eIlMBBJZvsz/mxKI= github.com/dlclark/regexp2 v1.11.0/go.mod h1:DHkYz0B9wPfa6wondMfaivmHpzrQ3v9q8cnmRbL6yW8= -github.com/docker/cli v29.4.0+incompatible h1:+IjXULMetlvWJiuSI0Nbor36lcJ5BTcVpUmB21KBoVM= -github.com/docker/cli v29.4.0+incompatible/go.mod h1:JLrzqnKDaYBop7H2jaqPtU4hHvMKP+vjCwu2uszcLI8= github.com/docker/cli v29.4.3+incompatible h1:u+UliYm2J/rYrIh2FqHQg32neRG8GjbvNuwQRTzGspU= github.com/docker/cli v29.4.3+incompatible/go.mod h1:JLrzqnKDaYBop7H2jaqPtU4hHvMKP+vjCwu2uszcLI8= github.com/docker/docker-credential-helpers v0.9.5 h1:EFNN8DHvaiK8zVqFA2DT6BjXE0GzfLOZ38ggPTKePkY= github.com/docker/docker-credential-helpers v0.9.5/go.mod h1:v1S+hepowrQXITkEfw6o4+BMbGot02wiKpzWhGUZK6c= github.com/docker/go-connections v0.6.0 h1:LlMG9azAe1TqfR7sO+NJttz1gy6KO7VJBh+pMmjSD94= github.com/docker/go-connections v0.6.0/go.mod h1:AahvXYshr6JgfUJGdDCs2b5EZG/vmaMAntpSFH5BFKE= -github.com/docker/go-events v0.0.0-20250114142523-c867878c5e32 h1:EHZfspsnLAz8Hzccd67D5abwLiqoqym2jz/jOS39mCk= -github.com/docker/go-events v0.0.0-20250114142523-c867878c5e32/go.mod h1:Uw6UezgYA44ePAFQYUehOuCzmy5zmg/+nl2ZfMWGkpA= github.com/docker/go-events v0.0.0-20250808211157-605354379745 h1:yOn6Ze6IbYI/KAw2lw/83ELYvZh6hvsygTVkD0dzMC4= github.com/docker/go-events v0.0.0-20250808211157-605354379745/go.mod h1:Uw6UezgYA44ePAFQYUehOuCzmy5zmg/+nl2ZfMWGkpA= github.com/docker/go-metrics v0.0.1 h1:AgB/0SvBxihN0X8OR4SjsblXkbMvalQ8cjmtKQ2rQV8= @@ -483,6 +433,8 @@ github.com/envoyproxy/protoc-gen-validate v1.3.0 h1:TvGH1wof4H33rezVKWSpqKz5NXWg github.com/envoyproxy/protoc-gen-validate v1.3.0/go.mod h1:HvYl7zwPa5mffgyeTUHA9zHIH36nmrm7oCbo4YKoSWA= github.com/erikgeiser/coninput v0.0.0-20211004153227-1c3628e74d0f h1:Y/CXytFA4m6baUTXGLOoWe4PQhGxaX0KpnayAqC48p4= github.com/erikgeiser/coninput v0.0.0-20211004153227-1c3628e74d0f/go.mod h1:vw97MGsxSvLiUE2X8qFplwetxpGLQrlU1Q9AUEIzCaM= +github.com/erofs/go-erofs v0.3.0 h1:o/W5ABAA3sHYl97WL93dacKEfeDpJhdFf3c2snAti7I= +github.com/erofs/go-erofs v0.3.0/go.mod h1:XkSeN9MHszGd4+3gcEjadJLYHCQpWzJ7/8yznzMuzJs= github.com/evanphx/json-patch v5.9.11+incompatible h1:ixHHqfcGvxhWkniF1tWxBHA0yb4Z+d1UQi45df52xW8= github.com/evanphx/json-patch v5.9.11+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk= github.com/exponent-io/jsonpath v0.0.0-20210407135951-1de76d718b3f h1:Wl78ApPPB2Wvf/TIe2xdyJxTlb6obmF18d8QdkxNDu4= @@ -532,18 +484,10 @@ 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.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-billy/v5 v5.8.1-0.20260506061021-07f2a0bf50e4 h1:XK6pelr1UQyrCSXsrqrJxr0jkrHXg7QCzfPH3UQMYp8= -github.com/go-git/go-billy/v5 v5.8.1-0.20260506061021-07f2a0bf50e4/go.mod h1:jCnQMLj9eUgGU7+ludSTYoZL/GGmii14RxKFj7ROgHw= github.com/go-git/go-billy/v5 v5.9.0 h1:jItGXszUDRtR/AlferWPTMN4j38BQ88XnXKbilmmBPA= github.com/go-git/go-billy/v5 v5.9.0/go.mod h1:jCnQMLj9eUgGU7+ludSTYoZL/GGmii14RxKFj7ROgHw= 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.18.0 h1:O831KI+0PR51hM2kep6T8k+w0/LIAD490gvqMCvL5hM= -github.com/go-git/go-git/v5 v5.18.0/go.mod h1:pW/VmeqkanRFqR6AljLcs7EA7FbZaN5MQqO7oZADXpo= -github.com/go-git/go-git/v5 v5.18.1-0.20260420130857-e5bbc088b774 h1:FED4o0JOD1z8x/dMcmM6IKkqoIz22xz7sWE81FEdXNQ= -github.com/go-git/go-git/v5 v5.18.1-0.20260420130857-e5bbc088b774/go.mod h1:pW/VmeqkanRFqR6AljLcs7EA7FbZaN5MQqO7oZADXpo= github.com/go-git/go-git/v5 v5.19.1 h1:nX27AnaU43/K5bKktKwgBmR9lawoYVe1Ckg0rgzzN00= github.com/go-git/go-git/v5 v5.19.1/go.mod h1:Pb1v0c7/g8aGQJwx9Us09W85yGoyvSwuhEGMH7zjDKQ= github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU= @@ -551,8 +495,6 @@ github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2 github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= github.com/go-gorp/gorp/v3 v3.1.0 h1:ItKF/Vbuj31dmV4jxA1qblpSwkl9g1typ24xoe70IGs= github.com/go-gorp/gorp/v3 v3.1.0/go.mod h1:dLEjIyyRNiXvNZ8PSmzpt1GsWAUK8kjVhEpjH8TixEw= -github.com/go-jose/go-jose/v3 v3.0.5 h1:BLLJWbC4nMZOfuPVxoZIxeYsn6Nl2r1fITaJ78UQlVQ= -github.com/go-jose/go-jose/v3 v3.0.5/go.mod h1:5b+7YgP7ZICgJDBdfjZaIt+H/9L9T/YQrVfLAMboGkQ= github.com/go-jose/go-jose/v4 v4.1.4 h1:moDMcTHmvE6Groj34emNPLs/qtYXRVcd6S7NHbHz3kA= github.com/go-jose/go-jose/v4 v4.1.4/go.mod h1:x4oUasVrzR7071A4TnHLGSPpNOm2a21K9Kf04k1rs08= github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= @@ -580,7 +522,6 @@ github.com/go-sql-driver/mysql v1.8.1/go.mod h1:wEBSXgmK//2ZFJyE+qWnIsVGmvmEKlqw github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= github.com/go-task/slim-sprig/v3 v3.0.0 h1:sUs3vkvUymDpBKi3qH1YSqBQk9+9D/8M2mN1vB6EwHI= github.com/go-task/slim-sprig/v3 v3.0.0/go.mod h1:W848ghGpv3Qj3dhTPRyJypKRiqCdHZiAzKg9hl15HA8= -github.com/go-test/deep v1.0.4/go.mod h1:wGDj63lr65AM2AQyKZd/NYHGb0R+1RLqB8NKt3aSFNA= github.com/go-test/deep v1.1.1 h1:0r/53hagsehfO4bzD2Pgr/+RgHqhmf+k1Bpse2cTu1U= github.com/go-test/deep v1.1.1/go.mod h1:5C2ZWiW0ErCdrYzpqxLbTX7MG14M9iiw8DgHncVwcsE= github.com/go-viper/mapstructure/v2 v2.5.0 h1:vM5IJoUAy3d7zRSVtIwQgBj7BiWtMPfmPEgAXnvj1Ro= @@ -593,8 +534,6 @@ github.com/gobwas/ws v1.2.1/go.mod h1:hRKAFb8wOxFROYNsT1bqfWnhX+b5MFeJM9r2ZSwg/K github.com/goccy/go-yaml v1.19.2 h1:PmFC1S6h8ljIz6gMRBopkjP1TVT7xuwrButHID66PoM= github.com/goccy/go-yaml v1.19.2/go.mod h1:XBurs7gK8ATbW4ZPGKgcbrY1Br56PdM69F7LkFRi1kA= github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= -github.com/godbus/dbus/v5 v5.1.0 h1:4KLkAxT3aOY8Li4FRJe/KvhoNFFxo0m6fNuFUO8QJUk= -github.com/godbus/dbus/v5 v5.1.0/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= github.com/gofrs/flock v0.13.0 h1:95JolYOvGMqeH31+FC7D2+uULf6mG61mEZ/A8dRYMzw= github.com/gofrs/flock v0.13.0/go.mod h1:jxeyy9R1auM5S6JYDBhDt+E2TCo7DkratH4Pgi8P+Z0= github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= @@ -602,8 +541,6 @@ github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q= github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q= github.com/gohugoio/hashstructure v0.6.0 h1:7wMB/2CfXoThFYhdWRGv3u3rUM761Cq29CxUW+NltUg= github.com/gohugoio/hashstructure v0.6.0/go.mod h1:lapVLk9XidheHG1IQ4ZSbyYrXcaILU1ZEP/+vno5rBQ= -github.com/golang-jwt/jwt/v5 v5.2.2 h1:Rl4B7itRWVtYIHFrSNd7vhTiz9UpLdi6gZhZ3wEeDy8= -github.com/golang-jwt/jwt/v5 v5.2.2/go.mod h1:pqrtFR0X4osieyHYxtmOUWsAWrfe1Q5UVIyoH402zdk= github.com/golang-jwt/jwt/v5 v5.3.0 h1:pv4AsKCKKZuqlgs5sUmn4x8UlGa0kEVt/puTpKx9vvo= github.com/golang-jwt/jwt/v5 v5.3.0/go.mod h1:fxCRLWMO43lRc8nhHWY6LGqRcf+1gQWArsqaEUEa5bE= github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= @@ -662,8 +599,6 @@ github.com/google/go-cmp v0.5.3/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/ github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.7/go.mod h1:n+brtR0CgQNWTVd5ZUFpTBC8YFBDLK/h/bpaJ8/DtOE= -github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8= github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU= github.com/google/go-containerregistry v0.21.5 h1:KTJG9Pn/jC0VdZR6ctV3/jcN+q6/Iqlx0sTVz3ywZlM= @@ -694,8 +629,6 @@ github.com/google/pprof v0.0.0-20210609004039-a478d1d731e9/go.mod h1:kpwsk12EmLe github.com/google/pprof v0.0.0-20210720184732-4bb14d4b1be1/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= github.com/google/pprof v0.0.0-20211214055906-6f57359322fd/go.mod h1:KgnwoLYCZ8IQu3XUZ8Nc/bM9CCZFOyjUNOSygVozoDg= github.com/google/pprof v0.0.0-20240227163752-401108e1b7e7/go.mod h1:czg5+yv1E0ZGTi6S6vVK1mke0fV+FaUhNGcd6VRS9Ik= -github.com/google/pprof v0.0.0-20250820193118-f64d9cf942d6 h1:EEHtgt9IwisQ2AZ4pIsMjahcegHh6rmhqxzIRQIyepY= -github.com/google/pprof v0.0.0-20250820193118-f64d9cf942d6/go.mod h1:I6V7YzU0XDpsHqbsyrghnFZLO1gwK6NPTNvmetQIk9U= github.com/google/pprof v0.0.0-20260115054156-294ebfa9ad83 h1:z2ogiKUYzX5Is6zr/vP9vJGqPwcdqsWjOt+V8J7+bTc= github.com/google/pprof v0.0.0-20260115054156-294ebfa9ad83/go.mod h1:MxpfABSjhmINe3F1It9d+8exIHFvUqtLIRCdOGNXqiI= github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= @@ -732,13 +665,10 @@ github.com/gosuri/uitable v0.0.4 h1:IG2xLKRvErL3uhY6e1BylFzG+aJiwQviDDTfOKeKTpY= github.com/gosuri/uitable v0.0.4/go.mod h1:tKR86bXuXPZazfOTG1FIzvjIdXzd0mo4Vtn16vt0PJo= github.com/gpustack/gguf-parser-go v0.24.0 h1:tdJceXYp9e5RhE9RwVYIuUpir72Jz2D68NEtDXkKCKc= github.com/gpustack/gguf-parser-go v0.24.0/go.mod h1:y4TwTtDqFWTK+xvprOjRUh+dowgU2TKCX37vRKvGiZ0= -github.com/gregjones/httpcache v0.0.0-20190611155906-901d90724c79 h1:+ngKgrYPPJrOjhax5N+uePQ0Fh1Z7PheYoUI/0nzkPA= -github.com/gregjones/httpcache v0.0.0-20190611155906-901d90724c79/go.mod h1:FecbI9+v66THATjSRHfNgh1IVFe/9kFxbXtjV0ctIMA= github.com/grpc-ecosystem/grpc-gateway v1.16.0 h1:gmcG1KaJ57LophUzW0Hy8NmPhnMZb4M0+kPpLofRdBo= github.com/grpc-ecosystem/grpc-gateway v1.16.0/go.mod h1:BDjrQk3hbvj6Nolgz8mAMFbcEtjT1g+wF4CSlocrBnw= -github.com/grpc-ecosystem/grpc-gateway/v2 v2.26.3 h1:5ZPtiqj0JL5oKWmcsq4VMaAW5ukBEgSGXEN89zeH1Jo= -github.com/grpc-ecosystem/grpc-gateway/v2 v2.26.3/go.mod h1:ndYquD05frm2vACXE1nsccT4oJzjhw2arTS2cpUD1PI= github.com/grpc-ecosystem/grpc-gateway/v2 v2.28.0 h1:HWRh5R2+9EifMyIHV7ZV+MIZqgz+PMpZ14Jynv3O2Zs= +github.com/grpc-ecosystem/grpc-gateway/v2 v2.28.0/go.mod h1:JfhWUomR1baixubs02l85lZYYOm7LV6om4ceouMv45c= github.com/h2non/filetype v1.1.3 h1:FKkx9QbD7HR/zjK1Ia5XiBsq9zdLi5Kf3zGyFTAFkGg= github.com/h2non/filetype v1.1.3/go.mod h1:319b3zT68BvV+WRj7cwy856M2ehB3HqNOt6sy1HndBY= github.com/hashicorp/aws-sdk-go-base/v2 v2.0.0-beta.72 h1:vTCWu1wbdYo7PEZFem/rlr01+Un+wwVmI7wiegFdRLk= @@ -845,7 +775,6 @@ github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+o github.com/klauspost/compress v1.4.1/go.mod h1:RyIbtBH6LamlWaDj8nUwkbUhJ87Yi3uG0guNDohfE1A= github.com/klauspost/compress v1.18.5 h1:/h1gH5Ce+VWNLSWqPzOVn6XBO+vJbCNGvjoaGBFW2IE= github.com/klauspost/compress v1.18.5/go.mod h1:cwPg85FWrGar70rWktvGQj8/hthj3wpl0PGDogxkrSQ= -github.com/klauspost/cpuid v1.2.0 h1:NMpwD2G9JSFOE1/TJjGSo5zG7Yb2bTe7eq1jH+irmeE= github.com/klauspost/cpuid v1.2.0/go.mod h1:Pj4uuM528wm8OyEC2QMXAi2YiTZ96dNQPGgoMS4s3ek= github.com/klauspost/cpuid/v2 v2.3.0 h1:S4CRMLnYUhGeDFDqkGriYKdfoFlDnMtqTiI/sFzhA9Y= github.com/klauspost/cpuid/v2 v2.3.0/go.mod h1:hqwkgyIinND0mEev00jJYCxPNVRVXFQeu1XKlok6oO0= @@ -944,8 +873,6 @@ github.com/moby/moby/api v1.54.1 h1:TqVzuJkOLsgLDDwNLmYqACUuTehOHRGKiPhvH8V3Nn4= github.com/moby/moby/api v1.54.1/go.mod h1:+RQ6wluLwtYaTd1WnPLykIDPekkuyD/ROWQClE83pzs= github.com/moby/moby/client v0.4.0 h1:S+2XegzHQrrvTCvF6s5HFzcrywWQmuVnhOXe2kiWjIw= github.com/moby/moby/client v0.4.0/go.mod h1:QWPbvWchQbxBNdaLSpoKpCdf5E+WxFAgNHogCWDoa7g= -github.com/moby/sys/capability v0.4.0 h1:4D4mI6KlNtWMCM1Z/K0i7RV1FkX+DBDHKVJpCndZoHk= -github.com/moby/sys/capability v0.4.0/go.mod h1:4g9IK291rVkms3LKCDOoYlnV8xKwoDTpIrNEE35Wq0I= github.com/moby/sys/mountinfo v0.7.2 h1:1shs6aH5s4o5H2zQLn796ADW1wMrIwHsyJ2v9KouLrg= github.com/moby/sys/mountinfo v0.7.2/go.mod h1:1YOa8w8Ih7uW0wALDUgT1dTTSBrZ+HiBLGws92L2RU4= github.com/moby/sys/sequential v0.6.0 h1:qrx7XFUd/5DxtqcoH1h438hF5TmOvzC/lspjy7zgvCU= @@ -968,8 +895,6 @@ github.com/modern-go/reflect2 v1.0.3-0.20250322232337-35a7c28c31ee h1:W5t00kpgFd github.com/modern-go/reflect2 v1.0.3-0.20250322232337-35a7c28c31ee/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk= github.com/monochromegane/go-gitignore v0.0.0-20200626010858-205db1a8cc00 h1:n6/2gBQ3RWajuToeY6ZtZTIKv2v7ThUy5KKusIT0yc0= github.com/monochromegane/go-gitignore v0.0.0-20200626010858-205db1a8cc00/go.mod h1:Pm3mSP3c5uWn86xMLZ5Sa7JB9GsEZySvHYXCTK4E9q4= -github.com/mrunalp/fileutils v0.5.1 h1:F+S7ZlNKnrwHfSwdlgNSkKo67ReVf8o9fel6C3dkm/Q= -github.com/mrunalp/fileutils v0.5.1/go.mod h1:M1WthSahJixYnrXQl/DFQuteStB1weuxD2QJNHXfbSQ= github.com/mssola/user_agent v0.6.0 h1:uwPR4rtWlCHRFyyP9u2KOV0u8iQXmS7Z7feTrstQwk4= github.com/mssola/user_agent v0.6.0/go.mod h1:TTPno8LPY3wAIEKRpAtkdMT0f8SE24pLRGPahjCH4uw= github.com/muesli/ansi v0.0.0-20230316100256-276c6243b2f6 h1:ZK8zHtRHOkbHy6Mmr5D264iyp3TiX5OmNcI5cIARiQI= @@ -997,24 +922,16 @@ github.com/olekukonko/ll v0.1.6 h1:lGVTHO+Qc4Qm+fce/2h2m5y9LvqaW+DCN7xW9hsU3uA= github.com/olekukonko/ll v0.1.6/go.mod h1:NVUmjBb/aCtUpjKk75BhWrOlARz3dqsM+OtszpY4o88= github.com/olekukonko/tablewriter v1.1.4 h1:ORUMI3dXbMnRlRggJX3+q7OzQFDdvgbN9nVWj1drm6I= github.com/olekukonko/tablewriter v1.1.4/go.mod h1:+kedxuyTtgoZLwif3P1Em4hARJs+mVnzKxmsCL/C5RY= -github.com/onsi/ginkgo/v2 v2.27.2 h1:LzwLj0b89qtIy6SSASkzlNvX6WktqurSHwkk2ipF/Ns= -github.com/onsi/ginkgo/v2 v2.27.2/go.mod h1:ArE1D/XhNXBXCBkKOLkbsb2c81dQHCRcF5zwn/ykDRo= github.com/onsi/ginkgo/v2 v2.28.1 h1:S4hj+HbZp40fNKuLUQOYLDgZLwNUVn19N3Atb98NCyI= -github.com/onsi/gomega v1.38.2 h1:eZCjf2xjZAqe+LeWvKb5weQ+NcPwX84kqJ0cZNxok2A= -github.com/onsi/gomega v1.38.2/go.mod h1:W2MJcYxRGV63b418Ai34Ud0hEdTVXq9NW9+Sx6uXf3k= +github.com/onsi/ginkgo/v2 v2.28.1/go.mod h1:CLtbVInNckU3/+gC8LzkGUb9oF+e8W8TdUsxPwvdOgE= github.com/onsi/gomega v1.39.1 h1:1IJLAad4zjPn2PsnhH70V4DKRFlrCzGBNrNaru+Vf28= -github.com/opencontainers/cgroups v0.0.4 h1:XVj8P/IHVms/j+7eh8ggdkTLAxjz84ZzuFyGoE28DR4= -github.com/opencontainers/cgroups v0.0.4/go.mod h1:s8lktyhlGUqM7OSRL5P7eAW6Wb+kWPNvt4qvVfzA5vs= +github.com/onsi/gomega v1.39.1/go.mod h1:hL6yVALoTOxeWudERyfppUcZXjMwIMLnuSfruD2lcfg= github.com/opencontainers/go-digest v1.0.0 h1:apOUWs51W5PlhuyGyz9FCeeBIOUDA/6nW8Oi/yOhh5U= github.com/opencontainers/go-digest v1.0.0/go.mod h1:0JzlMkj0TRzQZfJkVvzbP0HBR3IKzErnv2BNG4W4MAM= github.com/opencontainers/image-spec v1.1.1 h1:y0fUlFfIZhPF1W537XOLg0/fcx6zcHCJwooC2xJA040= github.com/opencontainers/image-spec v1.1.1/go.mod h1:qpqAh3Dmcf36wStyyWU+kCeDgrGnAve2nCC8+7h8Q0M= -github.com/opencontainers/runc v1.3.4 h1:+lwmPUTzbgv0JFqu8zBU2WtHYbm+JPPS9hxB/PvWd30= -github.com/opencontainers/runc v1.3.4/go.mod h1:o1wyv76EDlTkcf0KTFgN8bMWLPvgF/HfX709lDv+rr4= github.com/opencontainers/runtime-spec v1.3.0 h1:YZupQUdctfhpZy3TM39nN9Ika5CBWT5diQ8ibYCRkxg= github.com/opencontainers/runtime-spec v1.3.0/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0= -github.com/opencontainers/selinux v1.13.0 h1:Zza88GWezyT7RLql12URvoxsbLfjFx988+LGaWfbL84= -github.com/opencontainers/selinux v1.13.0/go.mod h1:XxWTed+A/s5NNq4GmYScVy+9jzXhGBVEOAyucdRUY8s= github.com/orisano/pixelmatch v0.0.0-20220722002657-fb0b55479cde/go.mod h1:nZgzbfBr3hhjoZnS66nKrHmduYNpc34ny7RK4z5/HM0= github.com/pascaldekloe/goe v0.0.0-20180627143212-57f6aae5913c/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc= github.com/pascaldekloe/goe v0.1.0/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc= @@ -1023,8 +940,6 @@ github.com/pborman/indent v1.2.1/go.mod h1:FitS+t35kIYtB5xWTZAPhnmrxcciEEOdbyrrp github.com/pelletier/go-toml v1.9.4/go.mod h1:u1nR/EPcESfeI/szUZKdtJ0xRNbUoANCkoOuaOx1Y+c= github.com/pelletier/go-toml v1.9.5 h1:4yBQzkHv+7BHq2PQUZF3Mx0IYxG7LsP222s7Agd3ve8= github.com/pelletier/go-toml v1.9.5/go.mod h1:u1nR/EPcESfeI/szUZKdtJ0xRNbUoANCkoOuaOx1Y+c= -github.com/pelletier/go-toml/v2 v2.2.4 h1:mye9XuhQ6gvn5h28+VilKrrPoQVanw5PMw/TB0t5Ec4= -github.com/pelletier/go-toml/v2 v2.2.4/go.mod h1:2gIqNv+qfxSVS7cM2xJQKtLSTLUE9V8t9Stt+h56mCY= github.com/pelletier/go-toml/v2 v2.3.1 h1:MYEvvGnQjeNkRF1qUuGolNtNExTDwct51yp7olPtrEc= github.com/pelletier/go-toml/v2 v2.3.1/go.mod h1:2gIqNv+qfxSVS7cM2xJQKtLSTLUE9V8t9Stt+h56mCY= github.com/peterbourgon/diskv v2.0.1+incompatible h1:UBdAOUP5p4RWqPBg048CAvpKN+vxiaj6gdUUzhl4XmI= @@ -1033,8 +948,6 @@ github.com/phayes/freeport v0.0.0-20220201140144-74d24b5ae9f5 h1:Ii+DKncOVM8Cu1H github.com/phayes/freeport v0.0.0-20220201140144-74d24b5ae9f5/go.mod h1:iIss55rKnNBTvrwdmkUpLnDpZoAHvWaiq5+iMmen4AE= github.com/pierrec/lz4/v4 v4.1.22 h1:cKFw6uJDK+/gfw5BcDL0JL5aBsAFdsIT18eRtLj7VIU= github.com/pierrec/lz4/v4 v4.1.22/go.mod h1:gZWDp/Ze/IJXGXf23ltt2EXimqmTUXEy0GFuRQyBid4= -github.com/pjbgf/sha1cd v0.3.2 h1:a9wb0bp1oC2TGwStyn0Umc/IGKQnEgF0vVaZ8QF8eo4= -github.com/pjbgf/sha1cd v0.3.2/go.mod h1:zQWigSxVmsHEZow5qaLtPYxpcKMMQpa09ixqBxuCS6A= github.com/pjbgf/sha1cd v0.6.0 h1:3WJ8Wz8gvDz29quX1OcEmkAlUg9diU4GxJHqs0/XiwU= github.com/pjbgf/sha1cd v0.6.0/go.mod h1:lhpGlyHLpQZoxMv8HcgXvZEhcGs0PG/vsZnEJ7H0iCM= github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= @@ -1068,16 +981,15 @@ github.com/prometheus/client_model v0.6.2 h1:oBsgwpGs7iVziMvrGhE53c/GrLUsZdHnqNw github.com/prometheus/client_model v0.6.2/go.mod h1:y3m2F6Gdpfy6Ut/GBsUqTWZqCUvMVzSfMLjcu6wAwpE= github.com/prometheus/common v0.4.1/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= github.com/prometheus/common v0.9.1/go.mod h1:yhUN8i9wzaXS3w1O07YhxHEBxD+W35wd8bs7vj7HSQ4= -github.com/prometheus/common v0.66.1 h1:h5E0h5/Y8niHc5DlaLlWLArTQI7tMrsfQjHV+d9ZoGs= -github.com/prometheus/common v0.66.1/go.mod h1:gcaUsgf3KfRSwHY4dIMXLPV0K/Wg1oZ8+SbZk/HH/dA= github.com/prometheus/common v0.67.5 h1:pIgK94WWlQt1WLwAC5j2ynLaBRDiinoAb86HZHTUGI4= +github.com/prometheus/common v0.67.5/go.mod h1:SjE/0MzDEEAyrdr5Gqc6G+sXI67maCxzaT3A2+HqjUw= +github.com/prometheus/otlptranslator v1.0.0 h1:s0LJW/iN9dkIH+EnhiD3BlkkP5QVIUVEoIwkU+A6qos= +github.com/prometheus/otlptranslator v1.0.0/go.mod h1:vRYWnXvI6aWGpsdY/mOT/cbeVRBlPWtBNDb7kGR3uKM= github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA= github.com/prometheus/procfs v0.0.8/go.mod h1:7Qr8sr6344vo1JqZ6HhLceV9o3AJ1Ff+GxbHq6oeK9A= -github.com/prometheus/procfs v0.16.1 h1:hZ15bTNuirocR6u0JZ6BAHHmwS1p8B4P6MRqxtzMyRg= -github.com/prometheus/procfs v0.16.1/go.mod h1:teAbpZRB1iIAJYREa1LsoWUXykVXA1KlTmWl8x/U+Is= -github.com/prometheus/procfs v0.19.2 h1:zUMhqEW66Ex7OXIiDkll3tl9a1ZdilUOd/F6ZXw4Vws= github.com/prometheus/procfs v0.20.1 h1:XwbrGOIplXW/AU3YhIhLODXMJYyC1isLFfYCsTEycfc= +github.com/prometheus/procfs v0.20.1/go.mod h1:o9EMBZGRyvDrSPH1RqdxhojkuXstoe4UlK79eF5TGGo= github.com/redis/go-redis/extra/rediscmd/v9 v9.0.5 h1:EaDatTxkdHG+U3Bk4EUr+DZ7fOGwTfezUiUJMaIcaho= github.com/redis/go-redis/extra/rediscmd/v9 v9.0.5/go.mod h1:fyalQWdtzDBECAQFBJuQe5bzQ02jGd5Qcbgb97Flm7U= github.com/redis/go-redis/extra/redisotel/v9 v9.0.5 h1:EfpWLLCyXw8PSM2/XNJLjI3Pb27yVE+gIAfeqp8LUCc= @@ -1121,8 +1033,6 @@ github.com/scylladb/go-set v1.0.3-0.20200225121959-cc7b2070d91e/go.mod h1:DkpGd7 github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529/go.mod h1:DxrIzT+xaE7yg65j358z/aeFdxmN0P9QXhEzd20vsDc= github.com/sebdah/goldie/v2 v2.8.0 h1:dZb9wR8q5++oplmEiJT+U/5KyotVD+HNGCAc5gNr8rc= github.com/sebdah/goldie/v2 v2.8.0/go.mod h1:oZ9fp0+se1eapSRjfYbsV/0Hqhbuu3bJVvKI/NNtssI= -github.com/seccomp/libseccomp-golang v0.10.0 h1:aA4bp+/Zzi0BnWZ2F1wgNBs5gTpm+na2rWM6M9YjLpY= -github.com/seccomp/libseccomp-golang v0.10.0/go.mod h1:JA8cRccbGaA1s33RQf7Y1+q9gHmZX1yB/z9WDN1C6fg= github.com/sergi/go-diff v1.1.0/go.mod h1:STckp+ISIX8hZLjrqAeVduY0gWCT9IjLuqbuNXdaHfM= github.com/sergi/go-diff v1.2.0/go.mod h1:STckp+ISIX8hZLjrqAeVduY0gWCT9IjLuqbuNXdaHfM= github.com/sergi/go-diff v1.4.0 h1:n/SP9D5ad1fORl+llWyN+D6qoUETXNZARKjyY2/KVCw= @@ -1138,8 +1048,6 @@ github.com/sirupsen/logrus v1.9.4 h1:TsZE7l11zFCLZnZ+teH4Umoq5BhEIfIzfRDZ1Uzql2w github.com/sirupsen/logrus v1.9.4/go.mod h1:ftWc9WdOfJ0a92nsE2jF5u5ZwH8Bv2zdeOC42RjbV2g= github.com/skeema/knownhosts v1.3.1 h1:X2osQ+RAjK76shCbvhHHHVl3ZlgDm8apHEHFqRjnBY8= github.com/skeema/knownhosts v1.3.1/go.mod h1:r7KTdC8l4uxWRyK2TpQZ/1o5HaSzh06ePQNxPwTcfiY= -github.com/slack-go/slack v0.12.2 h1:x3OppyMyGIbbiyFhsBmpf9pwkUzMhthJMRNmNlA4LaQ= -github.com/slack-go/slack v0.12.2/go.mod h1:hlGi5oXA+Gt+yWTPP0plCdRKmjsDxecdHxYQdlMQKOw= github.com/slack-go/slack v0.23.1 h1:ZS5B96wxxYQRwvJ3/vJFtqtUZi3tXhsZCyT44Nv7M80= github.com/slack-go/slack v0.23.1/go.mod h1:H0yR/YBuRJ39RkE+JpV/d/oEsbanzTRowR82bCN0cEs= github.com/smallnest/ringbuffer v0.0.0-20241116012123-461381446e3d h1:3VwvTjiRPA7cqtgOWddEL+JrcijMlXUmj99c/6YyZoY= @@ -1161,7 +1069,6 @@ github.com/spf13/cast v1.4.1/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkU github.com/spf13/cast v1.10.0 h1:h2x0u2shc1QuLHfxi+cTJvs30+ZAHOGRic8uyGTDWxY= github.com/spf13/cast v1.10.0/go.mod h1:jNfB8QC9IA6ZuY2ZjDp0KtFO2LZZlg4S/7bzP6qqeHo= github.com/spf13/cobra v1.3.0/go.mod h1:BrRVncBjOJa/eUcVVm9CE+oC6as8k+VYr4NY7WCi9V4= -github.com/spf13/cobra v1.5.0/go.mod h1:dWXEIy2H428czQCjInthrTRUg7yKbok+2Qi/yBIJoUM= github.com/spf13/cobra v1.10.2 h1:DMTTonx5m65Ic0GOoRY2c16WCbHxOOw6xxezuLaBpcU= github.com/spf13/cobra v1.10.2/go.mod h1:7C1pvHqHw5A4vrJfjNwvOdzYu0Gml16OCs2GRiTUUS4= github.com/spf13/jwalterweatherman v1.1.0/go.mod h1:aNWZUN0dPAAO/Ljvb5BEdw96iTZ0EXowPYD95IqWIGo= @@ -1189,8 +1096,6 @@ github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/ github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= -github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= -github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= github.com/stretchr/testify v1.11.1 h1:7s2iGBzp5EwR7/aIZr8ao5+dra3wiQyKjjFuvgVKu7U= github.com/stretchr/testify v1.11.1/go.mod h1:wZwfW3scLgRK+23gO65QZefKpKQRnfz6sD981Nm4B6U= github.com/subosito/gotenv v1.2.0/go.mod h1:N0PQaV/YGNqwC0u51sEeR/aUtSLEXKX9iv69rRypqCw= @@ -1218,18 +1123,12 @@ github.com/tv42/httpunix v0.0.0-20150427012821-b75d8614f926/go.mod h1:9ESjWnEqri github.com/ulikunitz/xz v0.5.8/go.mod h1:nbz6k7qbPmH4IRqmfOplQw/tblSgqTqBwxkY0oWt/14= github.com/ulikunitz/xz v0.5.15 h1:9DNdB5s+SgV3bQ2ApL10xRc35ck0DuIX/isZvIk+ubY= github.com/ulikunitz/xz v0.5.15/go.mod h1:nbz6k7qbPmH4IRqmfOplQw/tblSgqTqBwxkY0oWt/14= -github.com/urfave/cli v1.22.16 h1:MH0k6uJxdwdeWQTwhSO42Pwr4YLrNLwBtg1MRgTqPdQ= -github.com/urfave/cli v1.22.16/go.mod h1:EeJR6BKodywf4zciqrdw6hpCPk68JO9z5LazXZMn5Po= github.com/vbatts/go-mtree v0.7.0 h1:ytmOc3MTRidZiBi9VBCyZ2BHe4fZS47L5v7BVXDWW4E= github.com/vbatts/go-mtree v0.7.0/go.mod h1:EjdpFC+LZy1TXbRGNa1MKKgjQ+7ew3foMFJK8o4/TdY= github.com/vbatts/tar-split v0.12.2 h1:w/Y6tjxpeiFMR47yzZPlPj/FcPLpXbTUi/9H7d3CPa4= github.com/vbatts/tar-split v0.12.2/go.mod h1:eF6B6i6ftWQcDqEn3/iGFRFRo8cBIMSJVOpnNdfTMFA= github.com/vifraa/gopom v1.0.0 h1:L9XlKbyvid8PAIK8nr0lihMApJQg/12OBvMA28BcWh0= github.com/vifraa/gopom v1.0.0/go.mod h1:oPa1dcrGrtlO37WPDBm5SqHAT+wTgF8An1Q71Z6Vv4o= -github.com/vishvananda/netlink v1.3.1 h1:3AEMt62VKqz90r0tmNhog0r/PpWKmrEShJU0wJW6bV0= -github.com/vishvananda/netlink v1.3.1/go.mod h1:ARtKouGSTGchR8aMwmkzC0qiNPrrWO5JS/XMVl45+b4= -github.com/vishvananda/netns v0.0.5 h1:DfiHV+j8bA32MFM7bfEunvT8IAqQ/NzSJHtcmW5zdEY= -github.com/vishvananda/netns v0.0.5/go.mod h1:SpkAiCQRtJ6TvvxPnOSyH3BMl6unz3xZlaprSwhNNJM= github.com/wagoodman/go-partybus v0.0.0-20230516145632-8ccac152c651 h1:jIVmlAFIqV3d+DOxazTR9v+zgj8+VYuQBzPgBZvWBHA= github.com/wagoodman/go-partybus v0.0.0-20230516145632-8ccac152c651/go.mod h1:b26F2tHLqaoRQf8DywqzVaV1MQ9yvjb0OMcNl7Nxu20= github.com/wagoodman/go-progress v0.0.0-20260303201901-10176f79b2c0 h1:EHsPe0Q0ANoLOZff1dBLAyeWLTA4sbPTpGI+2zb0FnM= @@ -1281,80 +1180,58 @@ go.opencensus.io v0.24.0 h1:y73uSU6J157QMP2kn2r30vwW1A2W2WFwSCGnAVxeaD0= go.opencensus.io v0.24.0/go.mod h1:vNK8G9p7aAivkbmorf4v+7Hgx+Zs0yY+0fOtgBfjQKo= go.opentelemetry.io/auto/sdk v1.2.1 h1:jXsnJ4Lmnqd11kwkBV2LgLoFMZKizbCi5fNZ/ipaZ64= go.opentelemetry.io/auto/sdk v1.2.1/go.mod h1:KRTj+aOaElaLi+wW1kO/DZRXwkF4C5xPbEe3ZiIhN7Y= -go.opentelemetry.io/contrib/bridges/prometheus v0.57.0 h1:UW0+QyeyBVhn+COBec3nGhfnFe5lwB0ic1JBVjzhk0w= -go.opentelemetry.io/contrib/bridges/prometheus v0.57.0/go.mod h1:ppciCHRLsyCio54qbzQv0E4Jyth/fLWDTJYfvWpcSVk= go.opentelemetry.io/contrib/bridges/prometheus v0.67.0 h1:dkBzNEAIKADEaFnuESzcXvpd09vxvDZsOjx11gjUqLk= +go.opentelemetry.io/contrib/bridges/prometheus v0.67.0/go.mod h1:Z5RIwRkZgauOIfnG5IpidvLpERjhTninpP1dTG2jTl4= go.opentelemetry.io/contrib/detectors/gcp v1.39.0 h1:kWRNZMsfBHZ+uHjiH4y7Etn2FK26LAGkNFw7RHv1DhE= go.opentelemetry.io/contrib/detectors/gcp v1.39.0/go.mod h1:t/OGqzHBa5v6RHZwrDBJ2OirWc+4q/w2fTbLZwAKjTk= -go.opentelemetry.io/contrib/exporters/autoexport v0.57.0 h1:jmTVJ86dP60C01K3slFQa2NQ/Aoi7zA+wy7vMOKD9H4= -go.opentelemetry.io/contrib/exporters/autoexport v0.57.0/go.mod h1:EJBheUMttD/lABFyLXhce47Wr6DPWYReCzaZiXadH7g= go.opentelemetry.io/contrib/exporters/autoexport v0.67.0 h1:4fnRcNpc6YFtG3zsFw9achKn3XgmxPxuMuqIL5rE8e8= -go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.63.0 h1:YH4g8lQroajqUwWbq/tr2QX1JFmEXaDLgG+ew9bLMWo= -go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.63.0/go.mod h1:fvPi2qXDqFs8M4B4fmJhE92TyQs9Ydjlg3RvfUp+NbQ= +go.opentelemetry.io/contrib/exporters/autoexport v0.67.0/go.mod h1:qTvIHMFKoxW7HXg02gm6/Wofhq5p3Ib/A/NNt1EoBSQ= go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.68.0 h1:0Qx7VGBacMm9ZENQ7TnNObTYI4ShC+lHI16seduaxZo= go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.68.0/go.mod h1:Sje3i3MjSPKTSPvVWCaL8ugBzJwik3u4smCjUeuupqg= -go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.61.0 h1:F7Jx+6hwnZ41NSFTO5q4LYDtJRXBf2PD0rNBkeB/lus= -go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.61.0/go.mod h1:UHB22Z8QsdRDrnAtX4PntOl36ajSxcdUMt1sF7Y6E7Q= go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.68.0 h1:CqXxU8VOmDefoh0+ztfGaymYbhdB/tT3zs79QaZTNGY= go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.68.0/go.mod h1:BuhAPThV8PBHBvg8ZzZ/Ok3idOdhWIodywz2xEcRbJo= go.opentelemetry.io/otel v1.43.0 h1:mYIM03dnh5zfN7HautFE4ieIig9amkNANT+xcVxAj9I= go.opentelemetry.io/otel v1.43.0/go.mod h1:JuG+u74mvjvcm8vj8pI5XiHy1zDeoCS2LB1spIq7Ay0= -go.opentelemetry.io/otel/exporters/otlp/otlplog/otlploggrpc v0.8.0 h1:WzNab7hOOLzdDF/EoWCt4glhrbMPVMOO5JYTmpz36Ls= -go.opentelemetry.io/otel/exporters/otlp/otlplog/otlploggrpc v0.8.0/go.mod h1:hKvJwTzJdp90Vh7p6q/9PAOd55dI6WA6sWj62a/JvSs= go.opentelemetry.io/otel/exporters/otlp/otlplog/otlploggrpc v0.18.0 h1:deI9UQMoGFgrg5iLPgzueqFPHevDl+28YKfSpPTI6rY= -go.opentelemetry.io/otel/exporters/otlp/otlplog/otlploghttp v0.8.0 h1:S+LdBGiQXtJdowoJoQPEtI52syEP/JYBUpjO49EQhV8= -go.opentelemetry.io/otel/exporters/otlp/otlplog/otlploghttp v0.8.0/go.mod h1:5KXybFvPGds3QinJWQT7pmXf+TN5YIa7CNYObWRkj50= +go.opentelemetry.io/otel/exporters/otlp/otlplog/otlploggrpc v0.18.0/go.mod h1:PFx9NgpNUKXdf7J4Q3agRxMs3Y07QhTCVipKmLsMKnU= go.opentelemetry.io/otel/exporters/otlp/otlplog/otlploghttp v0.19.0 h1:HIBTQ3VO5aupLKjC90JgMqpezVXwFuq6Ryjn0/izoag= -go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc v1.32.0 h1:j7ZSD+5yn+lo3sGV69nW04rRR0jhYnBwjuX3r0HvnK0= -go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc v1.32.0/go.mod h1:WXbYJTUaZXAbYd8lbgGuvih0yuCfOFC5RJoYnoLcGz8= +go.opentelemetry.io/otel/exporters/otlp/otlplog/otlploghttp v0.19.0/go.mod h1:ji9vId85hMxqfvICA0Jt8JqEdrXaAkcpkI9HPXya0ro= go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc v1.42.0 h1:MdKucPl/HbzckWWEisiNqMPhRrAOQX8r4jTuGr636gk= -go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetrichttp v1.32.0 h1:t/Qur3vKSkUCcDVaSumWF2PKHt85pc7fRvFuoVT8qFU= -go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetrichttp v1.32.0/go.mod h1:Rl61tySSdcOJWoEgYZVtmnKdA0GeKrSqkHC1t+91CH8= +go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc v1.42.0/go.mod h1:RolT8tWtfHcjajEH5wFIZ4Dgh5jpPdFXYV9pTAk/qjc= go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetrichttp v1.43.0 h1:w1K+pCJoPpQifuVpsKamUdn9U0zM3xUziVOqsGksUrY= -go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.35.0 h1:1fTNlAIJZGWLP5FVu0fikVry1IsiUnXjf7QFvoNN3Xw= -go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.35.0/go.mod h1:zjPK58DtkqQFn+YUMbx0M2XV3QgKU0gS9LeGohREyK4= +go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetrichttp v1.43.0/go.mod h1:HBy4BjzgVE8139ieRI75oXm3EcDN+6GhD88JT1Kjvxg= go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.43.0 h1:88Y4s2C8oTui1LGM6bTWkw0ICGcOLCAI5l6zsD1j20k= -go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.35.0 h1:m639+BofXTvcY1q8CGs4ItwQarYtJPOWmVobfM1HpVI= -go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.35.0/go.mod h1:LjReUci/F4BUyv+y4dwnq3h/26iNOeC3wAIqgvTIZVo= +go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.43.0/go.mod h1:Vl1/iaggsuRlrHf/hfPJPvVag77kKyvrLeD10kpMl+A= go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.43.0 h1:RAE+JPfvEmvy+0LzyUA25/SGawPwIUbZ6u0Wug54sLc= -go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.35.0 h1:xJ2qHD0C1BeYVTLLR9sX12+Qb95kfeD/byKj6Ky1pXg= -go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.35.0/go.mod h1:u5BF1xyjstDowA1R5QAO9JHzqK+ublenEW/dyqTjBVk= +go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.43.0/go.mod h1:AGmbycVGEsRx9mXMZ75CsOyhSP6MFIcj/6dnG+vhVjk= go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.43.0 h1:3iZJKlCZufyRzPzlQhUIWVmfltrXuGyfjREgGP3UUjc= -go.opentelemetry.io/otel/exporters/prometheus v0.54.0 h1:rFwzp68QMgtzu9PgP3jm9XaMICI6TsofWWPcBDKwlsU= -go.opentelemetry.io/otel/exporters/prometheus v0.54.0/go.mod h1:QyjcV9qDP6VeK5qPyKETvNjmaaEc7+gqjh4SS0ZYzDU= +go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.43.0/go.mod h1:/G+nUPfhq2e+qiXMGxMwumDrP5jtzU+mWN7/sjT2rak= go.opentelemetry.io/otel/exporters/prometheus v0.64.0 h1:g0LRDXMX/G1SEZtK8zl8Chm4K6GBwRkjPKE36LxiTYs= -go.opentelemetry.io/otel/exporters/stdout/stdoutlog v0.8.0 h1:CHXNXwfKWfzS65yrlB2PVds1IBZcdsX8Vepy9of0iRU= -go.opentelemetry.io/otel/exporters/stdout/stdoutlog v0.8.0/go.mod h1:zKU4zUgKiaRxrdovSS2amdM5gOc59slmo/zJwGX+YBg= +go.opentelemetry.io/otel/exporters/prometheus v0.64.0/go.mod h1:UrgcjnarfdlBDP3GjDIJWe6HTprwSazNjwsI+Ru6hro= go.opentelemetry.io/otel/exporters/stdout/stdoutlog v0.18.0 h1:KJVjPD3rcPb98rIs3HznyJlrfx9ge5oJvxxlGR+P/7s= -go.opentelemetry.io/otel/exporters/stdout/stdoutmetric v1.40.0 h1:ZrPRak/kS4xI3AVXy8F7pipuDXmDsrO8Lg+yQjBLjw0= -go.opentelemetry.io/otel/exporters/stdout/stdoutmetric v1.40.0/go.mod h1:3y6kQCWztq6hyW8Z9YxQDDm0Je9AJoFar2G0yDcmhRk= +go.opentelemetry.io/otel/exporters/stdout/stdoutlog v0.18.0/go.mod h1:K3kRa2ckmHWQaTWQdPRHc7qGXASuVuoEQXzrvlA98Ws= go.opentelemetry.io/otel/exporters/stdout/stdoutmetric v1.42.0 h1:lSZHgNHfbmQTPfuTmWVkEu8J8qXaQwuV30pjCcAUvP8= -go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.32.0 h1:cC2yDI3IQd0Udsux7Qmq8ToKAx1XCilTQECZ0KDZyTw= -go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.32.0/go.mod h1:2PD5Ex6z8CFzDbTdOlwyNIUywRr1DN0ospafJM1wJ+s= +go.opentelemetry.io/otel/exporters/stdout/stdoutmetric v1.42.0/go.mod h1:so9ounLcuoRDu033MW/E0AD4hhUjVqswrMF5FoZlBcw= go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.42.0 h1:s/1iRkCKDfhlh1JF26knRneorus8aOwVIDhvYx9WoDw= -go.opentelemetry.io/otel/log v0.8.0 h1:egZ8vV5atrUWUbnSsHn6vB8R21G2wrKqNiDt3iWertk= -go.opentelemetry.io/otel/log v0.8.0/go.mod h1:M9qvDdUTRCopJcGRKg57+JSQ9LgLBrwwfC32epk5NX8= +go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.42.0/go.mod h1:UI3wi0FXg1Pofb8ZBiBLhtMzgoTm1TYkMvn71fAqDzs= go.opentelemetry.io/otel/log v0.19.0 h1:KUZs/GOsw79TBBMfDWsXS+KZ4g2Ckzksd1ymzsIEbo4= +go.opentelemetry.io/otel/log v0.19.0/go.mod h1:5DQYeGmxVIr4n0/BcJvF4upsraHjg6vudJJpnkL6Ipk= go.opentelemetry.io/otel/metric v1.43.0 h1:d7638QeInOnuwOONPp4JAOGfbCEpYb+K6DVWvdxGzgM= go.opentelemetry.io/otel/metric v1.43.0/go.mod h1:RDnPtIxvqlgO8GRW18W6Z/4P462ldprJtfxHxyKd2PY= go.opentelemetry.io/otel/sdk v1.43.0 h1:pi5mE86i5rTeLXqoF/hhiBtUNcrAGHLKQdhg4h4V9Dg= go.opentelemetry.io/otel/sdk v1.43.0/go.mod h1:P+IkVU3iWukmiit/Yf9AWvpyRDlUeBaRg6Y+C58QHzg= -go.opentelemetry.io/otel/sdk/log v0.8.0 h1:zg7GUYXqxk1jnGF/dTdLPrK06xJdrXgqgFLnI4Crxvs= -go.opentelemetry.io/otel/sdk/log v0.8.0/go.mod h1:50iXr0UVwQrYS45KbruFrEt4LvAdCaWWgIrsN3ZQggo= go.opentelemetry.io/otel/sdk/log v0.19.0 h1:scYVLqT22D2gqXItnWiocLUKGH9yvkkeql5dBDiXyko= +go.opentelemetry.io/otel/sdk/log v0.19.0/go.mod h1:vFBowwXGLlW9AvpuF7bMgnNI95LiW10szrOdvzBHlAg= go.opentelemetry.io/otel/sdk/metric v1.43.0 h1:S88dyqXjJkuBNLeMcVPRFXpRw2fuwdvfCGLEo89fDkw= go.opentelemetry.io/otel/sdk/metric v1.43.0/go.mod h1:C/RJtwSEJ5hzTiUz5pXF1kILHStzb9zFlIEe85bhj6A= go.opentelemetry.io/otel/trace v1.43.0 h1:BkNrHpup+4k4w+ZZ86CZoHHEkohws8AY+WTX09nk+3A= go.opentelemetry.io/otel/trace v1.43.0/go.mod h1:/QJhyVBUUswCphDVxq+8mld+AvhXZLhe+8WVFxiFff0= go.opentelemetry.io/proto/otlp v0.7.0/go.mod h1:PqfVotwruBrMGOCsRd/89rSnXhoiJIqeYNgFYFoEGnI= -go.opentelemetry.io/proto/otlp v1.7.1 h1:gTOMpGDb0WTBOP8JaO72iL3auEZhVmAQg4ipjOVAtj4= -go.opentelemetry.io/proto/otlp v1.7.1/go.mod h1:b2rVh6rfI/s2pHWNlB7ILJcRALpcNDzKhACevjI+ZnE= go.opentelemetry.io/proto/otlp v1.10.0 h1:IQRWgT5srOCYfiWnpqUYz9CVmbO8bFmKcwYxpuCSL2g= +go.opentelemetry.io/proto/otlp v1.10.0/go.mod h1:/CV4QoCR/S9yaPj8utp3lvQPoqMtxXdzn7ozvvozVqk= go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc= go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto= go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE= -go.uber.org/mock v0.5.2 h1:LbtPTcP8A5k9WPXj54PPPbjcI4Y6lhyOZXn+VS7wNko= -go.uber.org/mock v0.5.2/go.mod h1:wLlUxC2vVTPTaE3UD51E0BGOAElKrILxhVSDYQLld5o= go.uber.org/mock v0.6.0 h1:hyF9dfmbgIX5EfOdasqLsWD6xqpNZlXblLB/Dbnwv3Y= go.uber.org/mock v0.6.0/go.mod h1:KiVJ4BqZJaMj4svdfmHM0AUx4NJYO8ZNpPnZn1Z+BBU= go.uber.org/multierr v1.6.0/go.mod h1:cdWPpRnG4AhwMwsgIHip0KRBQjJy5kYEpYjJxpXp9iU= @@ -1379,7 +1256,6 @@ golang.org/x/crypto v0.0.0-20210817164053-32db794688a5/go.mod h1:GvvjBRRGRdwPK5y golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/crypto v0.0.0-20220622213112-05595931fe9d/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= golang.org/x/crypto v0.6.0/go.mod h1:OFC/31mSvZgRz0V1QTNCzfAI1aIRzbiufJtkMIlEp58= -golang.org/x/crypto v0.19.0/go.mod h1:Iy9bg/ha4yyC70EfRS8jz+B6ybOBKMaSxLj6P6oBDfU= golang.org/x/crypto v0.50.0 h1:zO47/JPrL6vsNkINmLoo/PH1gcxpls50DNogFvB5ZGI= golang.org/x/crypto v0.50.0/go.mod h1:3muZ7vA7PBCE6xgPX7nkzzjiUq87kRItoJQM1Yo8S+Q= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= @@ -1392,16 +1268,10 @@ golang.org/x/exp v0.0.0-20191227195350-da58074b4299/go.mod h1:2RIsYlXP63K8oxa1u0 golang.org/x/exp v0.0.0-20200119233911-0405dc783f0a/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= golang.org/x/exp v0.0.0-20200207192155-f17229e696bd/go.mod h1:J/WKrq2StrnmMY6+EHIKF9dgMWnmCNThgcyBT1FY9mM= golang.org/x/exp v0.0.0-20200224162631-6cc2880d07d6/go.mod h1:3jZMyOhIsHpP37uCMkUooju7aAi5cS1Q23tOzKc+0MU= -golang.org/x/exp v0.0.0-20251023183803-a4bb9ffd2546 h1:mgKeJMpvi0yx/sU5GsxQ7p6s2wtOnGAHZWCHUM4KGzY= -golang.org/x/exp v0.0.0-20251023183803-a4bb9ffd2546/go.mod h1:j/pmGrbnkbPtQfxEe5D0VQhZC6qKbfKifgD0oM7sR70= golang.org/x/exp v0.0.0-20260410095643-746e56fc9e2f h1:W3F4c+6OLc6H2lb//N1q4WpJkhzJCK5J6kUi1NTVXfM= golang.org/x/exp v0.0.0-20260410095643-746e56fc9e2f/go.mod h1:J1xhfL/vlindoeF/aINzNzt2Bket5bjo9sdOYzOsU80= golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js= golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= -golang.org/x/image v0.36.1-0.20260211191414-e3d762b1d37e h1:gkwT7ZpRdJBB47MJ0h7xeUSHKkd8f3RcM47FgUIRgd4= -golang.org/x/image v0.36.1-0.20260211191414-e3d762b1d37e/go.mod h1:ZK2ak7W75f61R/Pwr7T25elpTMmDbUsuiOt4FcDsNI0= -golang.org/x/image v0.38.0 h1:5l+q+Y9JDC7mBOMjo4/aPhMDcxEptsX+Tt3GgRQRPuE= -golang.org/x/image v0.38.0/go.mod h1:/3f6vaXC+6CEanU4KJxbcUZyEePbyKbaLoDOe4ehFYY= golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU= golang.org/x/lint v0.0.0-20190301231843-5614ed5bae6f/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= @@ -1427,7 +1297,6 @@ golang.org/x/mod v0.4.1/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.5.0/go.mod h1:5OXOZSfqPIIbmVBIIKWRFfZjPR0E5r58TLhUjH0a2Ro= golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= -golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= golang.org/x/mod v0.35.0 h1:Ww1D637e6Pg+Zb2KrWfHQUnH2dQRLBQyAtpr/haaJeM= golang.org/x/mod v0.35.0/go.mod h1:+GwiRhIInF8wPm+4AoT6L0FA1QWAad3OMdTRx4tFYlU= golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= @@ -1475,7 +1344,6 @@ golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qx golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= golang.org/x/net v0.7.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= -golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg= golang.org/x/net v0.53.0 h1:d+qAbo5L0orcWAr0a9JweQpjXF19LMXJE8Ey7hwOdUA= golang.org/x/net v0.53.0/go.mod h1:JvMuJH7rrdiCfbeHoo3fCQU24Lf5JJwT9W3sJFulfgs= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= @@ -1509,7 +1377,6 @@ golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJ golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.20.0 h1:e0PTpb7pjO8GAtTs2dQ6jYa5BWYlMuX047Dco/pItO4= golang.org/x/sync v0.20.0/go.mod h1:9xrNwdLfx4jkKbNva9FpL6vEN7evnE43NNNJQ2LF3+0= golang.org/x/sys v0.0.0-20180823144017-11551d06cbcc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= @@ -1585,21 +1452,14 @@ golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.2.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.10.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.17.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/sys v0.43.0 h1:Rlag2XtaFTxp19wS8MXlJwTvoh8ArU6ezoyFsMyCTNI= golang.org/x/sys v0.43.0/go.mod h1:4GL1E5IUh+htKOUEOaiffhrAeqysfVGipDYzABqnCmw= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k= -golang.org/x/term v0.8.0/go.mod h1:xPskH00ivmX89bAKVGSKKtLOWNx2+17Eiy94tnKShWo= -golang.org/x/term v0.17.0/go.mod h1:lLRBjIVuehSbZlaOtGMbcMncT+aqLLLmKrsjNrUguwk= golang.org/x/term v0.42.0 h1:UiKe+zDFmJobeJ5ggPwOshJIVt6/Ft0rcfrXZDLWAWY= golang.org/x/term v0.42.0/go.mod h1:Dq/D+snpsbazcBG5+F9Q1n2rXV8Ma+71xEjTRufARgY= golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= @@ -1612,8 +1472,6 @@ golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= -golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= -golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= golang.org/x/text v0.36.0 h1:JfKh3XmcRPqZPKevfXVpI1wXPTqbkE5f7JA92a55Yxg= golang.org/x/text v0.36.0/go.mod h1:NIdBknypM8iqVmPiuco0Dh6P5Jcdk8lJL0CUebqK164= golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= @@ -1676,7 +1534,6 @@ golang.org/x/tools v0.1.3/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= golang.org/x/tools v0.1.4/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= golang.org/x/tools v0.1.5/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= -golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU= golang.org/x/tools v0.44.0 h1:UP4ajHPIcuMjT1GqzDWRlalUEoY+uzoZKnhOjbIPD2c= golang.org/x/tools v0.44.0/go.mod h1:KA0AfVErSdxRZIsOVipbv3rQhVXTnlU6UhKxHd1seDI= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= @@ -1685,8 +1542,6 @@ golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8T golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20240903120638-7835f813f4da h1:noIWHXmPHxILtqtCOPIhSt0ABwskkZKjD3bXGnZGpNY= golang.org/x/xerrors v0.0.0-20240903120638-7835f813f4da/go.mod h1:NDW/Ps6MPRej6fsCIbMTohpP40sJ/P/vI1MoTEGwX90= -gonum.org/v1/gonum v0.16.0 h1:5+ul4Swaf3ESvrOnidPp4GZbzf0mxVQpDCYUQE7OJfk= -gonum.org/v1/gonum v0.16.0/go.mod h1:fef3am4MQ93R2HHpKnLk4/Tbh/s0+wqD5nfa6Pnwy4E= gonum.org/v1/gonum v0.17.0 h1:VbpOemQlsSMrYmn7T2OUvQ4dqxQXU+ouZFQsZOx50z4= gonum.org/v1/gonum v0.17.0/go.mod h1:El3tOrEuMpv2UdMrbNlKEh9vd86bmQ6vqIcDwxEOc1E= google.golang.org/api v0.4.0/go.mod h1:8k5glujaEP+g9n7WNsDg8QP6cUVNI86fCNMcbazEtwE= @@ -1795,12 +1650,8 @@ google.golang.org/genproto v0.0.0-20211206160659-862468c7d6e0/go.mod h1:5CzLGKJ6 google.golang.org/genproto v0.0.0-20211208223120-3a66f561d7aa/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= google.golang.org/genproto v0.0.0-20260128011058-8636f8732409 h1:VQZ/yAbAtjkHgH80teYd2em3xtIkkHd7ZhqfH2N9CsM= google.golang.org/genproto v0.0.0-20260128011058-8636f8732409/go.mod h1:rxKD3IEILWEu3P44seeNOAwZN4SaoKaQ/2eTg4mM6EM= -google.golang.org/genproto/googleapis/api v0.0.0-20260203192932-546029d2fa20 h1:7ei4lp52gK1uSejlA8AZl5AJjeLUOHBQscRQZUgAcu0= -google.golang.org/genproto/googleapis/api v0.0.0-20260203192932-546029d2fa20/go.mod h1:ZdbssH/1SOVnjnDlXzxDHK2MCidiqXtbYccJNzNYPEE= google.golang.org/genproto/googleapis/api v0.0.0-20260401024825-9d38bb4040a9 h1:VPWxll4HlMw1Vs/qXtN7BvhZqsS9cdAittCNvVENElA= google.golang.org/genproto/googleapis/api v0.0.0-20260401024825-9d38bb4040a9/go.mod h1:7QBABkRtR8z+TEnmXTqIqwJLlzrZKVfAUm7tY3yGv0M= -google.golang.org/genproto/googleapis/rpc v0.0.0-20260226221140-a57be14db171 h1:ggcbiqK8WWh6l1dnltU4BgWGIGo+EVYxCaAPih/zQXQ= -google.golang.org/genproto/googleapis/rpc v0.0.0-20260226221140-a57be14db171/go.mod h1:4Hqkh8ycfw05ld/3BWL7rJOSfebL2Q+DVDeRgYgxUU8= google.golang.org/genproto/googleapis/rpc v0.0.0-20260406210006-6f92a3bedf2d h1:wT2n40TBqFY6wiwazVK9/iTWbsQrgk5ZfCSVFLO9LQA= google.golang.org/genproto/googleapis/rpc v0.0.0-20260406210006-6f92a3bedf2d/go.mod h1:4Hqkh8ycfw05ld/3BWL7rJOSfebL2Q+DVDeRgYgxUU8= google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= @@ -1830,8 +1681,6 @@ google.golang.org/grpc v1.39.1/go.mod h1:PImNr+rS9TWYb2O4/emRugxiyHZ5JyHW5F+RPnD google.golang.org/grpc v1.40.0/go.mod h1:ogyxbiOoUXAkP+4+xa6PZSE9DZgIHtSpzjDTB9KAK34= google.golang.org/grpc v1.40.1/go.mod h1:ogyxbiOoUXAkP+4+xa6PZSE9DZgIHtSpzjDTB9KAK34= google.golang.org/grpc v1.42.0/go.mod h1:k+4IHHFw41K8+bbowsex27ge2rCb65oeWqe4jJ590SU= -google.golang.org/grpc v1.79.3 h1:sybAEdRIEtvcD68Gx7dmnwjZKlyfuc61Dyo9pGXXkKE= -google.golang.org/grpc v1.79.3/go.mod h1:KmT0Kjez+0dde/v2j9vzwoAScgEPx/Bw1CYChhHLrHQ= google.golang.org/grpc v1.80.0 h1:Xr6m2WmWZLETvUNvIUmeD5OAagMw3FiKmMlTdViWsHM= google.golang.org/grpc v1.80.0/go.mod h1:ho/dLnxwi3EDJA4Zghp7k2Ec1+c2jqup0bFkw07bwF4= google.golang.org/grpc/cmd/protoc-gen-go-grpc v1.1.0/go.mod h1:6Kw0yEErY5E/yWrBtf03jp27GLLJujG4z/JK95pnjjw= @@ -1848,9 +1697,6 @@ google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlba google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= google.golang.org/protobuf v1.27.1/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= -google.golang.org/protobuf v1.28.1/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= -google.golang.org/protobuf v1.36.11 h1:fV6ZwhNocDyBLK0dj+fg8ektcVegBBuEolpbTQyBNVE= -google.golang.org/protobuf v1.36.11/go.mod h1:HTf+CrKn2C3g5S8VImy6tdcUvCska2kB7j23XfzDpco= google.golang.org/protobuf v1.36.12-0.20260120151049-f2248ac996af h1:+5/Sw3GsDNlEmu7TfklWKPdQ0Ykja5VEmq2i817+jbI= google.golang.org/protobuf v1.36.12-0.20260120151049-f2248ac996af/go.mod h1:HTf+CrKn2C3g5S8VImy6tdcUvCska2kB7j23XfzDpco= gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw= @@ -1892,44 +1738,26 @@ honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWh honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg= honnef.co/go/tools v0.0.1-2020.1.3/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= honnef.co/go/tools v0.0.1-2020.1.4/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= -k8s.io/api v0.35.1 h1:0PO/1FhlK/EQNVK5+txc4FuhQibV25VLSdLMmGpDE/Q= -k8s.io/api v0.35.1/go.mod h1:28uR9xlXWml9eT0uaGo6y71xK86JBELShLy4wR1XtxM= k8s.io/api v0.36.0 h1:SgqDhZzHdOtMk40xVSvCXkP9ME0H05hPM3p9AB1kL80= k8s.io/api v0.36.0/go.mod h1:m1LVrGPNYax5NBHdO+QuAedXyuzTt4RryI/qnmNvs34= k8s.io/apiextensions-apiserver v0.35.1 h1:p5vvALkknlOcAqARwjS20kJffgzHqwyQRM8vHLwgU7w= k8s.io/apiextensions-apiserver v0.35.1/go.mod h1:2CN4fe1GZ3HMe4wBr25qXyJnJyZaquy4nNlNmb3R7AQ= -k8s.io/apimachinery v0.35.1 h1:yxO6gV555P1YV0SANtnTjXYfiivaTPvCTKX6w6qdDsU= -k8s.io/apimachinery v0.35.1/go.mod h1:jQCgFZFR1F4Ik7hvr2g84RTJSZegBc8yHgFWKn//hns= k8s.io/apimachinery v0.36.0 h1:jZyPzhd5Z+3h9vJLt0z9XdzW9VzNzWAUw+P1xZ9PXtQ= k8s.io/apimachinery v0.36.0/go.mod h1:FklypaRJt6n5wUIwWXIP6GJlIpUizTgfo1T/As+Tyxc= k8s.io/apiserver v0.35.1 h1:potxdhhTL4i6AYAa2QCwtlhtB1eCdWQFvJV6fXgJzxs= k8s.io/apiserver v0.35.1/go.mod h1:BiL6Dd3A2I/0lBnteXfWmCFobHM39vt5+hJQd7Lbpi4= -k8s.io/cli-runtime v0.35.1 h1:uKcXFe8J7AMAM4Gm2JDK4mp198dBEq2nyeYtO+JfGJE= -k8s.io/cli-runtime v0.35.1/go.mod h1:55/hiXIq1C8qIJ3WBrWxEwDLdHQYhBNRdZOz9f7yvTw= k8s.io/cli-runtime v0.36.0 h1:HNxciQpQMMOKS0/GiUXcKDyA6J2FDILJj9NmP2BZrTg= k8s.io/cli-runtime v0.36.0/go.mod h1:KObkknK9Ro5LYX+1RdiKc7C8CvGg4aX+V/Zv+E8WPHA= -k8s.io/client-go v0.35.1 h1:+eSfZHwuo/I19PaSxqumjqZ9l5XiTEKbIaJ+j1wLcLM= -k8s.io/client-go v0.35.1/go.mod h1:1p1KxDt3a0ruRfc/pG4qT/3oHmUj1AhSHEcxNSGg+OA= k8s.io/client-go v0.36.0 h1:pOYi7C4RHChYjMiHpZSpSbIM6ZxVbRXBy7CuiIwqA3c= k8s.io/client-go v0.36.0/go.mod h1:ZKKcpwF0aLYfkHFCjillCKaTK/yBkEDHTDXCFY6AS9Y= -k8s.io/component-base v0.35.1 h1:XgvpRf4srp037QWfGBLFsYMUQJkE5yMa94UsJU7pmcE= -k8s.io/component-base v0.35.1/go.mod h1:HI/6jXlwkiOL5zL9bqA3en1Ygv60F03oEpnuU1G56Bs= k8s.io/component-base v0.36.0 h1:hFjEktssxiJhrK1zfybkH4kJOi8iZuF+mIDCqS5+jRo= k8s.io/component-base v0.36.0/go.mod h1:JZvIfcNHk+uck+8LhJzhSBtydWXaZNQwX2OdL+Mnwsk= -k8s.io/klog/v2 v2.130.1 h1:n9Xl7H1Xvksem4KFG4PYbdQCQxqc/tTUyrgXaOhHSzk= -k8s.io/klog/v2 v2.130.1/go.mod h1:3Jpz1GvMt720eyJH1ckRHK1EDfpxISzJ7I9OYgaDtPE= k8s.io/klog/v2 v2.140.0 h1:Tf+J3AH7xnUzZyVVXhTgGhEKnFqye14aadWv7bzXdzc= k8s.io/klog/v2 v2.140.0/go.mod h1:o+/RWfJ6PwpnFn7OyAG3QnO47BFsymfEfrz6XyYSSp0= -k8s.io/kube-openapi v0.0.0-20250910181357-589584f1c912 h1:Y3gxNAuB0OBLImH611+UDZcmKS3g6CthxToOb37KgwE= -k8s.io/kube-openapi v0.0.0-20250910181357-589584f1c912/go.mod h1:kdmbQkyfwUagLfXIad1y2TdrjPFWp2Q89B3qkRwf/pQ= k8s.io/kube-openapi v0.0.0-20260319004828-5883c5ee87b9 h1:Sztf7ESG9tAXRW/ACJZjrj5jhdOUqS2KFRQT+CTvu78= k8s.io/kube-openapi v0.0.0-20260319004828-5883c5ee87b9/go.mod h1:uGBT7iTA6c6MvqUvSXIaYZo9ukscABYi2btjhvgKGZ0= -k8s.io/kubectl v0.35.1 h1:zP3Er8C5i1dcAFUMh9Eva0kVvZHptXIn/+8NtRWMxwg= -k8s.io/kubectl v0.35.1/go.mod h1:cQ2uAPs5IO/kx8R5s5J3Ihv3VCYwrx0obCXum0CvnXo= k8s.io/kubectl v0.36.0 h1:hEGr8NvIm2Wjqs2Xy48Uzmvo6lpHdGKlLyMvau2gTms= k8s.io/kubectl v0.36.0/go.mod h1:iDe8aV5BEi45W8k+5n71I2pJ/nwE0PHDu+/2cejzYoo= -k8s.io/utils v0.0.0-20251002143259-bc988d571ff4 h1:SjGebBtkBqHFOli+05xYbK8YF1Dzkbzn+gDM4X9T4Ck= -k8s.io/utils v0.0.0-20251002143259-bc988d571ff4/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0= k8s.io/utils v0.0.0-20260319190234-28399d86e0b5 h1:kBawHLSnx/mYHmRnNUf9d4CpjREbeZuxoSGOX/J+aYM= k8s.io/utils v0.0.0-20260319190234-28399d86e0b5/go.mod h1:xDxuJ0whA3d0I4mf/C4ppKHxXynQ+fxnkmQH0vTHnuk= modernc.org/cc/v4 v4.27.1 h1:9W30zRlYrefrDV2JE2O8VDtJ1yPGownxciz5rrbQZis= @@ -1969,18 +1797,12 @@ rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0= rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA= sigs.k8s.io/json v0.0.0-20250730193827-2d320260d730 h1:IpInykpT6ceI+QxKBbEflcR5EXP7sU1kvOlxwZh5txg= sigs.k8s.io/json v0.0.0-20250730193827-2d320260d730/go.mod h1:mdzfpAEoE6DHQEN0uh9ZbOCuHbLK5wOm7dK4ctXE9Tg= -sigs.k8s.io/kustomize/api v0.20.1 h1:iWP1Ydh3/lmldBnH/S5RXgT98vWYMaTUL1ADcr+Sv7I= -sigs.k8s.io/kustomize/api v0.20.1/go.mod h1:t6hUFxO+Ph0VxIk1sKp1WS0dOjbPCtLJ4p8aADLwqjM= sigs.k8s.io/kustomize/api v0.21.1 h1:lzqbzvz2CSvsjIUZUBNFKtIMsEw7hVLJp0JeSIVmuJs= sigs.k8s.io/kustomize/api v0.21.1/go.mod h1:f3wkKByTrgpgltLgySCntrYoq5d3q7aaxveSagwTlwI= -sigs.k8s.io/kustomize/kyaml v0.20.1 h1:PCMnA2mrVbRP3NIB6v9kYCAc38uvFLVs8j/CD567A78= -sigs.k8s.io/kustomize/kyaml v0.20.1/go.mod h1:0EmkQHRUsJxY8Ug9Niig1pUMSCGHxQ5RklbpV/Ri6po= sigs.k8s.io/kustomize/kyaml v0.21.1 h1:IVlbmhC076nf6foyL6Taw4BkrLuEsXUXNpsE+ScX7fI= sigs.k8s.io/kustomize/kyaml v0.21.1/go.mod h1:hmxADesM3yUN2vbA5z1/YTBnzLJ1dajdqpQonwBL1FQ= sigs.k8s.io/randfill v1.0.0 h1:JfjMILfT8A6RbawdsK2JXGBR5AQVfd+9TbzrlneTyrU= sigs.k8s.io/randfill v1.0.0/go.mod h1:XeLlZ/jmk4i1HRopwe7/aU3H5n1zNUcX6TM94b3QxOY= -sigs.k8s.io/structured-merge-diff/v6 v6.3.0 h1:jTijUJbW353oVOd9oTlifJqOGEkUw2jB/fXCbTiQEco= -sigs.k8s.io/structured-merge-diff/v6 v6.3.0/go.mod h1:M3W8sfWvn2HhQDIbGWj3S099YozAsymCo/wrT5ohRUE= sigs.k8s.io/structured-merge-diff/v6 v6.3.2 h1:kwVWMx5yS1CrnFWA/2QHyRVJ8jM6dBA80uLmm0wJkk8= sigs.k8s.io/structured-merge-diff/v6 v6.3.2/go.mod h1:M3W8sfWvn2HhQDIbGWj3S099YozAsymCo/wrT5ohRUE= sigs.k8s.io/yaml v1.6.0 h1:G8fkbMSAFqgEFgh4b1wmtzDnioxFCUgTZhlbj5P9QYs= diff --git a/internal/commands/result.go b/internal/commands/result.go index 1c6a78f50..51a155a60 100644 --- a/internal/commands/result.go +++ b/internal/commands/result.go @@ -1,3010 +1,3010 @@ -package commands - -import ( - "encoding/json" - "fmt" - "html" - "log" - "net/url" - "os" - "path/filepath" - "regexp" - "slices" - "strconv" - "strings" - "text/template" - "time" - - "github.com/MakeNowJust/heredoc" - "github.com/checkmarx/ast-cli/internal/commands/util" - "github.com/checkmarx/ast-cli/internal/commands/util/printer" - errorConstants "github.com/checkmarx/ast-cli/internal/constants/errors" - "github.com/checkmarx/ast-cli/internal/logger" - "github.com/checkmarx/ast-cli/internal/services" - "github.com/checkmarx/ast-cli/internal/wrappers" - "github.com/checkmarx/ast-cli/internal/wrappers/utils" - "golang.org/x/text/cases" - "golang.org/x/text/language" - - commonParams "github.com/checkmarx/ast-cli/internal/params" - - "github.com/pkg/errors" - "github.com/spf13/cobra" -) - -const ( - failedCreatingSummary = "Failed creating summary" - failedGettingScan = "Failed getting scan" - failedListingResults = "Failed listing results" - failedListingCodeBashing = "Failed codebashing link" - mediumLabel = "medium" - criticalLabel = "critical" - highLabel = "high" - lowLabel = "low" - infoLabel = "info" - sonarTypeLabel = "_sonar" - glSastTypeLabel = ".gl-sast-report" - glScaTypeLabel = ".gl-sca-report" - directoryPermission = 0700 - infoSonar = "INFO" - lowSonar = "LOW" - mediumSonar = "MEDIUM" - highSonar = "HIGH" - criticalSonar = "BLOCKER" - infoLowSarif = "note" - mediumSarif = "warning" - highSarif = "error" - vulnerabilitySonar = "SECURITY" - cleanCodeAttribute = "FORMATTED" - infoCx = "INFO" - lowCx = "LOW" - mediumCx = "MEDIUM" - highCx = "HIGH" - criticalCx = "CRITICAL" - tableResultsFormat = " | %-10s %6v %5d %6d %5d %4d %-9s |\n" - stringTableResultsFormat = " | %-10s %5s %6s %6s %5s %4s %5s |\n" - // TableTitleFormat is the printf format string for the scan results summary table title row. - TableTitleFormat = " | %-11s %4s %4s %6s %4s %4s %6s |\n" - twoNewLines = "\n\n" - tableLine = " --------------------------------------------------------------------- " - codeBashingKey = "cb-url" - failedGettingBfl = "Failed getting BFL" - notAvailableString = "-" - disabledString = "N/A" - scanFailedString = "Failed " - scanCanceledString = "Canceled" - scanSuccessString = "Completed" - scanPartialString = "Partial" - scsScanUnavailableString = "" - notAvailableNumber = -1 - scanFailedNumber = -2 - scanCanceledNumber = -3 - scanPartialNumber = -4 - defaultPaddingSize = -13 - scanPendingMessage = "Scan triggered in asynchronous mode or still running. Click more details to get the full status." - directDependencyType = "Direct Dependency" - indirectDependencyType = "Transitive Dependency" - startedStatus = "started" - requestedStatus = "requested" - completedStatus = "completed" - pdfToEmailFlagDescription = "Send the PDF report to the specified email address." + - " Use \",\" as the delimiter for multiple emails" - pdfOptionsFlagDescription = "Sections to generate PDF report. Available options: Iac-Security,Sast,Sca," + - defaultPdfOptionsDataSections - sbomReportFlagDescription = "Sections to generate SBOM report. Available options: CycloneDxJson,CycloneDxXml,SpdxJson" - reportNameScanReport = "scan-report" - reportNameImprovedScanReport = "improved-scan-report" - reportTypeEmail = "email" - defaultPdfOptionsDataSections = "ScanSummary,ExecutiveSummary,ScanResults" - exploitablePathFlagDescription = "Enable or disable exploitable path in scan. Available options: true,false" - scaLastScanTimeFlagDescription = "SCA last scan time. Available options: integer above 1" - projectPrivatePackageFlagDescription = "Enable or disable project private package. Available options: true,false" - scaPrivatePackageVersionFlagDescription = "SCA project private package version. Example: 0.1.1" - scaHideDevAndTestDepFlagDescription = "Filter SCA results to exclude dev and test dependencies" - policeManagementNoneStatus = "none" - apiDocumentationFlagDescription = "Swagger folder/file filter for API-Security scan. Example: ./swagger.json" - summaryCreatedAtLayout = "2006-01-02, 15:04:05" - glTimeFormat = "2006-01-02T15:04:05" - sarifNodeFileLength = 2 - fixLabel = "fix" - redundantLabel = "redundant" - delayValueForReport = 10 - fixLinkPrefix = "https://devhub.checkmarx.com/cve-details/" - // ScaDevAndTestExclusionParam is the SCA exclude-result-types value used to filter out dev and test dependencies. - ScaDevAndTestExclusionParam = "DEV_AND_TEST" - // ScaExcludeResultTypesParam is the SCA query parameter name used to exclude specific result types. - ScaExcludeResultTypesParam = "exclude-result-types" - noFileForScorecardResultString = "Issue Found in your GitHub repository" - // CliType identifies the report type used when generating reports through the CLI. - CliType = "cli" - artifactLocationURIString = "This alert has no associated file" - commandDocAnnotation = "command:doc" - showSubCommand = "show" - sectionScanSummary = "ScanSummary" - sectionExecutiveSummary = "ExecutiveSummary" - sectionScanResults = "ScanResults" - scaEngineLabel = "SCA" - sastEngineLabel = "SAST" - kicsEngineLabel = "KICS" - notAvailableValue = "NA" - originCode = "code" - originDocumentation = "documentation" - statusCompleted = "Completed" - statusPartial = "Partial" - statusFailed = "Failed" -) - -var ( - summaryFormats = []string{ - printer.FormatSummaryConsole, - printer.FormatSummary, - printer.FormatSummaryJSON, - printer.FormatPDF, - printer.FormatSummaryMarkdown, - printer.FormatSbom, - printer.FormatGLSast, - printer.FormatGLSca, - printer.FormatSonar, - } - - filterResultsListFlagUsage = fmt.Sprintf( - "Filter the list of results. Use ';' as the delimiter for arrays. Available filters are: %s", - strings.Join( - []string{ - commonParams.ScanIDQueryParam, - commonParams.LimitQueryParam, - commonParams.OffsetQueryParam, - commonParams.SortQueryParam, - commonParams.IncludeNodesQueryParam, - commonParams.NodeIDsQueryParam, - commonParams.QueryQueryParam, - commonParams.GroupQueryParam, - commonParams.StatusQueryParam, - commonParams.SeverityQueryParam, - commonParams.StateQueryParam, - }, ",", - ), - ) - - // Follows: over 9.0 is critical, 7.0 to 8.9 is high, 4.0 to 6.9 is medium and 3.9 or less is low. - securities = map[string]string{ - infoCx: "1.0", - lowCx: "2.0", - mediumCx: "4.0", - highCx: "7.0", - criticalCx: "9.0", - } - - // Match cx severity with sonar severity - sonarSeverities = map[string]string{ - infoCx: infoSonar, - lowCx: lowSonar, - mediumCx: mediumSonar, - highCx: highSonar, - criticalCx: criticalSonar, - } - - containerEngineUnsupportedAgents = []string{ - commonParams.JetbrainsAgent, commonParams.VSCodeAgent, commonParams.VisualStudioAgent, commonParams.EclipseAgent, - } - - sscsEngineToOverviewEngineMap = map[string]string{ - commonParams.SCSScorecardType: commonParams.SCSScorecardOverviewType, - commonParams.SCSSecretDetectionType: commonParams.SCSSecretDetectionOverviewType, - } -) - -// NewResultsCommand returns the `results` Cobra command tree with all subcommands attached. -func NewResultsCommand( - resultsWrapper wrappers.ResultsWrapper, - scanWrapper wrappers.ScansWrapper, - exportWrapper wrappers.ExportWrapper, - resultsPdfReportsWrapper wrappers.ResultsPdfWrapper, - resultsJSONReportsWrapper wrappers.ResultsJSONWrapper, - codeBashingWrapper wrappers.CodeBashingWrapper, - bflWrapper wrappers.BflWrapper, - risksOverviewWrapper wrappers.RisksOverviewWrapper, - riskManagementWrapper wrappers.RiskManagementWrapper, - scsScanOverviewWrapper wrappers.ScanOverviewWrapper, - policyWrapper wrappers.PolicyWrapper, - featureFlagsWrapper wrappers.FeatureFlagsWrapper, - jwtWrapper wrappers.JWTWrapper, -) *cobra.Command { - resultCmd := &cobra.Command{ - Use: "results", - Short: "Retrieve results", - Annotations: map[string]string{ - commandDocAnnotation: heredoc.Doc( - ` - https://checkmarx.com/resource/documents/en/34965-68640-results.html - `, - ), - }, - } - showResultCmd := resultShowSubCommand(resultsWrapper, scanWrapper, exportWrapper, resultsPdfReportsWrapper, resultsJSONReportsWrapper, - risksOverviewWrapper, scsScanOverviewWrapper, policyWrapper, featureFlagsWrapper, jwtWrapper) - codeBashingCmd := resultCodeBashing(codeBashingWrapper) - bflResultCmd := resultBflSubCommand(bflWrapper) - exitCodeSubcommand := exitCodeSubCommand(scanWrapper) - riskManagementSubCommand := riskManagementSubCommand(riskManagementWrapper, featureFlagsWrapper) - resultCmd.AddCommand( - showResultCmd, bflResultCmd, codeBashingCmd, exitCodeSubcommand, riskManagementSubCommand, - ) - return resultCmd -} - -func exitCodeSubCommand(scanWrapper wrappers.ScansWrapper) *cobra.Command { - exitCodeCmd := &cobra.Command{ - Use: "exit-code", - Short: "Get exit code and details of a scan", - Long: "The exit-code command enables you to get the exit code and failure details of a requested scan in Checkmarx One", - Example: heredoc.Doc( - ` - $ cx results exit-code --scan-id --scan-types - `, - ), - RunE: runGetExitCodeCommand(scanWrapper), - } - - exitCodeCmd.PersistentFlags().String(commonParams.ScanIDFlag, "", "Scan ID") - exitCodeCmd.PersistentFlags().String(commonParams.ScanTypes, "", "Scan types") - - return exitCodeCmd -} -func riskManagementSubCommand(riskManagement wrappers.RiskManagementWrapper, featureFlagsWrapper wrappers.FeatureFlagsWrapper, -) *cobra.Command { - riskManagementCmd := &cobra.Command{ - Use: "risk-management", - Short: "Show risk-management results of a project", - Long: "The risk-management command displays risk management results for a specific project in Checkmarx One", - Example: heredoc.Doc( - ` - $ cx results risk-management --project-id --scan-id --limit (1-50, default: 50) - `, - ), - RunE: runRiskManagementCommand(riskManagement, featureFlagsWrapper), - } - - riskManagementCmd.PersistentFlags().String(commonParams.ProjectIDFlag, "", "Project ID") - riskManagementCmd.PersistentFlags().String(commonParams.ScanIDFlag, "", "Scan ID") - riskManagementCmd.PersistentFlags().Int(commonParams.LimitFlag, -1, "Limit") - - addFormatFlag(riskManagementCmd, printer.FormatJSON, printer.FormatTable, printer.FormatList) - - return riskManagementCmd -} - -func resultShowSubCommand( - resultsWrapper wrappers.ResultsWrapper, - scanWrapper wrappers.ScansWrapper, - exportWrapper wrappers.ExportWrapper, - resultsPdfReportsWrapper wrappers.ResultsPdfWrapper, - resultsJSONReportsWrapper wrappers.ResultsJSONWrapper, - risksOverviewWrapper wrappers.RisksOverviewWrapper, - scsScanOverviewWrapper wrappers.ScanOverviewWrapper, - policyWrapper wrappers.PolicyWrapper, - featureFlagsWrapper wrappers.FeatureFlagsWrapper, - jwtWrapper wrappers.JWTWrapper, -) *cobra.Command { - resultShowCmd := &cobra.Command{ - Use: showSubCommand, - Short: "Show results of a scan", - Long: "The show command enables the ability to show results about a requested scan in Checkmarx One", - Example: heredoc.Doc( - ` - $ cx results show --scan-id - `, - ), - RunE: runGetResultCommand(resultsWrapper, scanWrapper, exportWrapper, resultsPdfReportsWrapper, resultsJSONReportsWrapper, risksOverviewWrapper, scsScanOverviewWrapper, policyWrapper, featureFlagsWrapper, jwtWrapper), - } - addScanIDFlag(resultShowCmd, "ID to report on") - addResultFormatFlag( - resultShowCmd, - printer.FormatJSON, - printer.FormatJSONv2, - printer.FormatSummary, - printer.FormatSummaryConsole, - printer.FormatSarif, - printer.FormatSummaryJSON, - printer.FormatSbom, - printer.FormatPDF, - printer.FormatSummaryMarkdown, - printer.FormatGLSast, - printer.FormatGLSca, - printer.FormatSonar, - ) - resultShowCmd.PersistentFlags().String(commonParams.ReportFormatPdfToEmailFlag, "", pdfToEmailFlagDescription) - resultShowCmd.PersistentFlags().String(commonParams.ReportSbomFormatFlag, services.DefaultSbomOption, sbomReportFlagDescription) - resultShowCmd.PersistentFlags().String(commonParams.ReportFormatPdfOptionsFlag, defaultPdfOptionsDataSections, pdfOptionsFlagDescription) - resultShowCmd.PersistentFlags().String(commonParams.TargetFlag, "cx_result", "Output file") - resultShowCmd.PersistentFlags().String(commonParams.TargetPathFlag, ".", "Output Path") - resultShowCmd.PersistentFlags().StringSlice(commonParams.FilterFlag, []string{}, filterResultsListFlagUsage) - - resultShowCmd.PersistentFlags().IntP( - commonParams.WaitDelayFlag, - "", - commonParams.WaitDelayDefault, - "Polling wait time in seconds", - ) - resultShowCmd.PersistentFlags().Int( - commonParams.PolicyTimeoutFlag, - commonParams.ResultPolicyDefaultTimeout, - "Cancel the policy evaluation and fail after the timeout in minutes", - ) - resultShowCmd.PersistentFlags().Bool(commonParams.IgnorePolicyFlag, false, "Skip policy evaluation. Requires override-policy-management permission.") - resultShowCmd.PersistentFlags().Bool(commonParams.SastRedundancyFlag, false, - "Populate SAST results 'data.redundancy' with values '"+fixLabel+"' (to fix) or '"+redundantLabel+"' (no need to fix)") - resultShowCmd.PersistentFlags().Bool(commonParams.ScaHideDevAndTestDepFlag, false, scaHideDevAndTestDepFlagDescription) - - return resultShowCmd -} - -func resultBflSubCommand(bflWrapper wrappers.BflWrapper) *cobra.Command { - resultBflCmd := &cobra.Command{ - Use: "bfl", - Short: "Show best fix location for a query id within the scan result", - Long: "The bfl command enables the ability to show best fix location for a querid within the scan result", - Example: heredoc.Doc( - ` - $ cx results bfl --scan-id --query-id - `, - ), - RunE: runGetBestFixLocationCommand(bflWrapper), - } - addScanIDFlag(resultBflCmd, "ID to report on") - addQueryIDFlag(resultBflCmd, "Query Id from the result") - addFormatFlag(resultBflCmd, printer.FormatList, printer.FormatJSON) - - markFlagAsRequired(resultBflCmd, commonParams.ScanIDFlag) - markFlagAsRequired(resultBflCmd, commonParams.QueryIDFlag) - - return resultBflCmd -} - -func runGetExitCodeCommand(scanWrapper wrappers.ScansWrapper) func(cmd *cobra.Command, args []string) error { - return func(cmd *cobra.Command, args []string) error { - scanID, _ := cmd.Flags().GetString(commonParams.ScanIDFlag) - if scanID == "" { - return errors.New(errorConstants.ScanIDRequired) - } - scanTypesFlagValue, _ := cmd.Flags().GetString(commonParams.ScanTypes) - results, err := GetScannerResults(scanWrapper, scanID, scanTypesFlagValue) - if err != nil { - return err - } - - if len(results) == 0 { - return nil - } - - return printer.Print(cmd.OutOrStdout(), results, printer.FormatIndentedJSON) - } -} - -func runRiskManagementCommand(riskManagement wrappers.RiskManagementWrapper, featureFlagsWrapper wrappers.FeatureFlagsWrapper, -) func(cmd *cobra.Command, args []string) error { - return func(cmd *cobra.Command, args []string) error { - projectID, _ := cmd.Flags().GetString(commonParams.ProjectIDFlag) - scanID, _ := cmd.Flags().GetString(commonParams.ScanIDFlag) - - limit, _ := cmd.Flags().GetInt(commonParams.LimitFlag) - - flagResponse, _ := wrappers.GetSpecificFeatureFlag(featureFlagsWrapper, wrappers.RiskManagementEnabled) - ASPMEnabled := flagResponse.Status - if !ASPMEnabled { - return errors.Errorf("%s", "Risk management results are currently unavailable for your tenant.") - } - results, err := getRiskManagementResults(riskManagement, projectID, scanID) - if err != nil { - return err - } - results.Results = utils.LimitSlice(results.Results, limit) - err = printByFormat(cmd, results) - return err - } -} - -func getRiskManagementResults(riskManagement wrappers.RiskManagementWrapper, projectID, scanID string) (*wrappers.ASPMResult, error) { - ASPMResult, errorModel, err := riskManagement.GetTopVulnerabilitiesByProjectID(projectID, scanID) - if err != nil { - return nil, errors.Wrapf(err, "%s", failedListingResults) - } - if errorModel != nil { - return nil, errors.Errorf("%s: CODE: %d, %s", failedListingResults, errorModel.Code, errorModel.Message) - } - return ASPMResult, nil -} - -// GetScannerResults returns per-scanner status entries for the given scan, optionally filtered by scan types. -func GetScannerResults(scanWrapper wrappers.ScansWrapper, scanID, scanTypesFlagValue string) ([]ScannerResponse, error) { - scanResponseModel, errorModel, err := scanWrapper.GetByID(scanID) - if err != nil { - return nil, errors.Wrapf(err, "%s", failedGetting) - } - if errorModel != nil { - return nil, errors.Errorf("%s: CODE: %d, %s", failedGettingScan, errorModel.Code, errorModel.Message) - } - results := getScannerResponse(scanTypesFlagValue, scanResponseModel) - return results, nil -} - -func getScannerResponse(scanTypesFlagValue string, scanResponseModel *wrappers.ScanResponseModel) []ScannerResponse { - var results []ScannerResponse - - if scanResponseModel.Status == wrappers.ScanCanceled || - scanResponseModel.Status == wrappers.ScanRunning || - scanResponseModel.Status == wrappers.ScanQueued || - scanResponseModel.Status == wrappers.ScanPartial || - scanResponseModel.Status == wrappers.ScanCompleted { - result := ScannerResponse{ - ScanID: scanResponseModel.ID, - Status: string(scanResponseModel.Status), - } - results = append(results, result) - return results - } - - if scanTypesFlagValue == "" { - results = createAllFailedScannersResponse(scanResponseModel) - } else { - scanTypes := sanitizeScannerNames(scanTypesFlagValue) - results = createRequestedScannersResponse(scanTypes, scanResponseModel) - } - - return results -} - -func createRequestedScannersResponse(scanTypes map[string]string, scanResponseModel *wrappers.ScanResponseModel) []ScannerResponse { - var results []ScannerResponse - for i := range scanResponseModel.StatusDetails { - if _, ok := scanTypes[scanResponseModel.StatusDetails[i].Name]; ok { - results = append(results, createScannerResponse(&scanResponseModel.StatusDetails[i])) - } - } - return results -} - -func createAllFailedScannersResponse(scanResponseModel *wrappers.ScanResponseModel) []ScannerResponse { - var results []ScannerResponse - for i := range scanResponseModel.StatusDetails { - if scanResponseModel.StatusDetails[i].Status == wrappers.ScanFailed { - results = append(results, createScannerResponse(&scanResponseModel.StatusDetails[i])) - } - } - return results -} - -func sanitizeScannerNames(scanTypes string) map[string]string { - scanTypeSlice := strings.Split(scanTypes, ",") - scanTypeMap := make(map[string]string) - for i := range scanTypeSlice { - lowered := strings.ToLower(scanTypeSlice[i]) - scanTypeMap[lowered] = lowered - } - - return scanTypeMap -} - -func createScannerResponse(statusDetails *wrappers.StatusInfo) ScannerResponse { - return ScannerResponse{ - Name: statusDetails.Name, - Status: statusDetails.Status, - Details: statusDetails.Details, - ErrorCode: stringifyErrorCode(statusDetails.ErrorCode), - } -} - -func stringifyErrorCode(errorCode int) string { - if errorCode == 0 { - return "" - } - return strconv.Itoa(errorCode) -} - -func runGetBestFixLocationCommand(bflWrapper wrappers.BflWrapper) func(cmd *cobra.Command, args []string) error { - return func(cmd *cobra.Command, args []string) error { - var bflResponseModel *wrappers.BFLResponseModel - var errorModel *wrappers.WebError - var err error - - scanID, _ := cmd.Flags().GetString(commonParams.ScanIDFlag) - queryID, _ := cmd.Flags().GetString(commonParams.QueryIDFlag) - - scanIds := strings.Split(scanID, ",") - if len(scanIds) > 1 { - return errors.Errorf("%s", "Multiple scan-ids are not allowed.") - } - queryIds := strings.Split(queryID, ",") - if len(queryIds) > 1 { - return errors.Errorf("%s", "Multiple query-ids are not allowed.") - } - - params := make(map[string]string) - params[commonParams.ScanIDQueryParam] = scanID - params[commonParams.QueryIDQueryParam] = queryID - - bflResponseModel, errorModel, err = bflWrapper.GetBflByScanIDAndQueryID(params) - - if err != nil { - return errors.Wrapf(err, "%s", failedGettingBfl) - } - - // Checking the response - if errorModel != nil { - return errors.Errorf("%s: CODE: %d, %s", failedGettingBfl, errorModel.Code, errorModel.Message) - } else if bflResponseModel != nil { - err = printByFormat(cmd, toBflView(*bflResponseModel)) - if err != nil { - return err - } - } - - return nil - } -} - -func toBflView(bflResponseModel wrappers.BFLResponseModel) []wrappers.ScanResultNode { - if (bflResponseModel.TotalCount) > 0 { - views := make([]wrappers.ScanResultNode, bflResponseModel.TotalCount) - - for i := 0; i < bflResponseModel.TotalCount; i++ { - views[i] = wrappers.ScanResultNode{ - Name: bflResponseModel.Trees[i].BFL.Name, - FileName: bflResponseModel.Trees[i].BFL.FileName, - FullName: bflResponseModel.Trees[i].BFL.FullName, - Column: bflResponseModel.Trees[i].BFL.Column, - Length: bflResponseModel.Trees[i].BFL.Length, - Line: bflResponseModel.Trees[i].BFL.Line, - MethodLine: bflResponseModel.Trees[i].BFL.MethodLine, - Method: bflResponseModel.Trees[i].BFL.Method, - DomType: bflResponseModel.Trees[i].BFL.DomType, - } - } - return views - } - views := make([]wrappers.ScanResultNode, 0) - return views -} - -func resultCodeBashing(codeBashingWrapper wrappers.CodeBashingWrapper) *cobra.Command { - // Create a codeBashing wrapper - resultCmd := &cobra.Command{ - Use: "codebashing", - Short: "Get codebashing lesson link", - Long: "The codebashing command enables the ability to retrieve the link about a specific vulnerability", - Example: heredoc.Doc( - ` - $ cx results codebashing --language --vulnerability-type --cwe-id --format - `, - ), - RunE: runGetCodeBashingCommand(codeBashingWrapper), - } - resultCmd.PersistentFlags().String(commonParams.LanguageFlag, "", "Language of the vulnerability") - err := resultCmd.MarkPersistentFlagRequired(commonParams.LanguageFlag) - if err != nil { - log.Fatal(err) - } - resultCmd.PersistentFlags().String(commonParams.VulnerabilityTypeFlag, "", "Vulnerability type") - err = resultCmd.MarkPersistentFlagRequired(commonParams.VulnerabilityTypeFlag) - if err != nil { - log.Fatal(err) - } - resultCmd.PersistentFlags().String(commonParams.CweIDFlag, "", "CWE ID for the vulnerability") - err = resultCmd.MarkPersistentFlagRequired(commonParams.CweIDFlag) - if err != nil { - log.Fatal(err) - } - addFormatFlag(resultCmd, printer.FormatJSON, printer.FormatTable, printer.FormatList) - return resultCmd -} - -func convertScanToResultsSummary(scanInfo *wrappers.ScanResponseModel, resultsWrapper wrappers.ResultsWrapper) (*wrappers.ResultSummary, error) { - if scanInfo == nil { - return nil, errors.New(failedCreatingSummary) - } - - scanInfo.ReplaceMicroEnginesWithSCS() - - sastIssues := 0 - scaIssues := 0 - kicsIssues := 0 - var containersIssues *int - var scsIssues *int - enginesStatusCode := map[string]int{ - commonParams.SastType: 0, - commonParams.ScaType: 0, - commonParams.KicsType: 0, - commonParams.APISecType: 0, - commonParams.ScsType: 0, - commonParams.ContainersType: 0, - } - if wrappers.IsContainersEnabled { - containersIssues = new(int) - *containersIssues = 0 - enginesStatusCode[commonParams.ContainersType] = 0 - } - - scsIssues = new(int) - *scsIssues = 0 - enginesStatusCode[commonParams.ScsType] = 0 - - if len(scanInfo.StatusDetails) > 0 { - applyScanStatusDetails(scanInfo.StatusDetails, &sastIssues, &scaIssues, &kicsIssues, scsIssues, containersIssues, enginesStatusCode) - } - summary := &wrappers.ResultSummary{ - ScanID: scanInfo.ID, - Status: string(scanInfo.Status), - CreatedAt: scanInfo.CreatedAt.Format("2006-01-02, 15:04:05"), - ProjectID: scanInfo.ProjectID, - RiskStyle: "", - RiskMsg: "", - CriticalIssues: 0, - HighIssues: 0, - MediumIssues: 0, - LowIssues: 0, - InfoIssues: 0, - SastIssues: sastIssues, - KicsIssues: kicsIssues, - ScaIssues: scaIssues, - ScsIssues: scsIssues, - ContainersIssues: containersIssues, - Tags: scanInfo.Tags, - ProjectName: scanInfo.ProjectName, - BranchName: scanInfo.Branch, - EnginesEnabled: scanInfo.Engines, - EnginesResult: map[string]*wrappers.EngineResultSummary{ - commonParams.SastType: {StatusCode: enginesStatusCode[commonParams.SastType]}, - commonParams.ScaType: {StatusCode: enginesStatusCode[commonParams.ScaType]}, - commonParams.KicsType: {StatusCode: enginesStatusCode[commonParams.KicsType]}, - commonParams.APISecType: {StatusCode: enginesStatusCode[commonParams.APISecType]}, - commonParams.ContainersType: {StatusCode: enginesStatusCode[commonParams.ContainersType]}, - }, - } - if wrappers.IsContainersEnabled { - summary.EnginesResult[commonParams.ContainersType] = &wrappers.EngineResultSummary{StatusCode: enginesStatusCode[commonParams.ContainersType]} - } - - summary.EnginesResult[commonParams.ScsType] = &wrappers.EngineResultSummary{StatusCode: enginesStatusCode[commonParams.ScsType]} - - baseURI, err := resultsWrapper.GetResultsURL(summary.ProjectID) - if err != nil { - return nil, err - } - - summary.BaseURI = baseURI - summary.BaseURI = generateScanSummaryURL(summary) - if isScanPending(summary.Status) { - summary.ScanInfoMessage = scanPendingMessage - } - - return summary, nil -} - -func applyScanStatusDetails( - statusDetails []wrappers.StatusInfo, - sastIssues, scaIssues, kicsIssues *int, - scsIssues, containersIssues *int, - enginesStatusCode map[string]int, -) { - for _, statusDetailItem := range statusDetails { - if statusDetailItem.Status == wrappers.ScanFailed || statusDetailItem.Status == wrappers.ScanCanceled { - markEngineNotAvailable(statusDetailItem.Name, sastIssues, scaIssues, kicsIssues, scsIssues, containersIssues) - } - switch statusDetailItem.Status { - case wrappers.ScanFailed: - handleScanStatus(statusDetailItem, enginesStatusCode, scanFailedNumber) - case wrappers.ScanCanceled: - handleScanStatus(statusDetailItem, enginesStatusCode, scanCanceledNumber) - } - } -} - -func markEngineNotAvailable(name string, sastIssues, scaIssues, kicsIssues, scsIssues, containersIssues *int) { - switch name { - case commonParams.SastType: - *sastIssues = notAvailableNumber - case commonParams.ScaType: - *scaIssues = notAvailableNumber - case commonParams.KicsType: - *kicsIssues = notAvailableNumber - case commonParams.ScsType: - *scsIssues = notAvailableNumber - case commonParams.ContainersType: - if wrappers.IsContainersEnabled { - *containersIssues = notAvailableNumber - } - } -} - -func handleScanStatus(statusDetailItem wrappers.StatusInfo, targetTypes map[string]int, statusCode int) { - if _, ok := targetTypes[statusDetailItem.Name]; ok { - targetTypes[statusDetailItem.Name] = statusCode - } -} - -func summaryReport( - summary *wrappers.ResultSummary, - policies *wrappers.PolicyResponseModel, - risksOverviewWrapper wrappers.RisksOverviewWrapper, - scsScanOverviewWrapper wrappers.ScanOverviewWrapper, - featureFlagsWrapper wrappers.FeatureFlagsWrapper, - results *wrappers.ScanResultsCollection, - resultsParams map[string]string, -) (*wrappers.ResultSummary, error) { - if summary.HasAPISecurity() { - apiSecFilterRisks, err := getFilterResultsForAPISecScanner(risksOverviewWrapper, summary.ScanID, resultsParams) - if err != nil { - return nil, err - } - if apiSecFilterRisks != nil { - summary.APISecurity = *apiSecFilterRisks - } - apiSecRisks, err := getResultsForAPISecScanner(risksOverviewWrapper, summary.ScanID) - if err != nil { - return nil, err - } - if apiSecRisks != nil { - summary.APISecurity.APICount = apiSecRisks.APICount - } - } - if summary.HasSCS() { - // Getting the base SCS overview. Results counts are overwritten in enhanceWithScanSummary->countResult - SCSOverview, err := getScanOverviewForSCSScanner(scsScanOverviewWrapper, summary.ScanID) - if err != nil { - return nil, err - } - summary.SCSOverview = SCSOverview - } - - if policies != nil { - summary.Policies = filterViolatedRules(*policies) - } - - enhanceWithScanSummary(summary, results, featureFlagsWrapper) - - setNotAvailableNumberIfZero(summary, &summary.SastIssues, commonParams.SastType) - setNotAvailableNumberIfZero(summary, &summary.ScaIssues, commonParams.ScaType) - setNotAvailableNumberIfZero(summary, &summary.KicsIssues, commonParams.KicsType) - setNotAvailableNumberIfZero(summary, summary.ScsIssues, commonParams.ScsType) - - if wrappers.IsContainersEnabled { - setNotAvailableNumberIfZero(summary, summary.ContainersIssues, commonParams.ContainersType) - } - - setRiskMsgAndStyle(summary) - setNotAvailableEnginesStatusCode(summary) - - return summary, nil -} - -func setNotAvailableEnginesStatusCode(summary *wrappers.ResultSummary) { - for engineName, engineResult := range summary.EnginesResult { - setNotAvailableNumberIfZero(summary, &engineResult.StatusCode, engineName) - } -} - -func setRiskMsgAndStyle(summary *wrappers.ResultSummary) { - if summary.CriticalIssues > 0 { - summary.RiskStyle = criticalLabel - summary.RiskMsg = "Critical Risk" - } else if summary.HighIssues > 0 { - summary.RiskStyle = highLabel - summary.RiskMsg = "High Risk" - } else if summary.MediumIssues > 0 { - summary.RiskStyle = mediumLabel - summary.RiskMsg = "Medium Risk" - } else if summary.LowIssues > 0 { - summary.RiskStyle = lowLabel - summary.RiskMsg = "Low Risk" - } else if summary.TotalIssues == 0 { - summary.RiskMsg = "No Risk" - } -} - -func setNotAvailableNumberIfZero(summary *wrappers.ResultSummary, counter *int, engineType string) { - if *counter == 0 && !contains(summary.EnginesEnabled, engineType) { - *counter = notAvailableNumber - } -} - -func enhanceWithScanSummary(summary *wrappers.ResultSummary, results *wrappers.ScanResultsCollection, featureFlagsWrapper wrappers.FeatureFlagsWrapper) { - for _, result := range results.Results { - countResult(summary, result) - } - // Set critical count for a specific engine if critical is disabled - flagResponse, _ := wrappers.GetSpecificFeatureFlag(featureFlagsWrapper, wrappers.CVSSV3Enabled) - criticalEnabled := flagResponse.Status - if summary.HasAPISecurity() { - summary.EnginesResult[commonParams.APISecType].Low = summary.APISecurity.SeverityCount["low"] - summary.EnginesResult[commonParams.APISecType].Medium = summary.APISecurity.SeverityCount["medium"] - summary.EnginesResult[commonParams.APISecType].High = summary.APISecurity.SeverityCount["high"] - if !criticalEnabled { - summary.EnginesResult[commonParams.APISecType].Critical = notAvailableNumber - } else { - summary.EnginesResult[commonParams.APISecType].Critical = summary.APISecurity.SeverityCount["critical"] - } - } - - summary.TotalIssues = summary.SastIssues + summary.ScaIssues + summary.KicsIssues + summary.GetAPISecurityDocumentationTotal() - - if summary.HasSCS() { - // Special case for SCS where status is partial if any microengines failed - if summary.SCSOverview.Status == scanPartialString { - summary.EnginesResult[commonParams.ScsType].StatusCode = scanPartialNumber - } - if !criticalEnabled { - summary.EnginesResult[commonParams.ScsType].Critical = notAvailableNumber - removeCriticalFromSCSOverview(summary) - } - if *summary.ScsIssues >= 0 { - summary.TotalIssues += *summary.ScsIssues - } - } - if wrappers.IsContainersEnabled { - if *summary.ContainersIssues >= 0 { - summary.TotalIssues += *summary.ContainersIssues - } - } - if !criticalEnabled { - summary.EnginesResult[commonParams.SastType].Critical = notAvailableNumber - summary.EnginesResult[commonParams.KicsType].Critical = notAvailableNumber - summary.EnginesResult[commonParams.ScaType].Critical = notAvailableNumber - summary.EnginesResult[commonParams.ContainersType].Critical = notAvailableNumber - } -} - -func removeCriticalFromSCSOverview(summary *wrappers.ResultSummary) { - criticalCount := summary.SCSOverview.RiskSummary[criticalLabel] - summary.SCSOverview.TotalRisksCount -= criticalCount - summary.SCSOverview.RiskSummary[criticalLabel] = notAvailableNumber - for _, microEngineOverview := range summary.SCSOverview.MicroEngineOverviews { - if microEngineOverview.RiskSummary != nil && microEngineOverview.RiskSummary[criticalLabel] != nil { - engineCriticalCount := microEngineOverview.RiskSummary[criticalLabel] - microEngineOverview.TotalRisks -= engineCriticalCount.(int) - microEngineOverview.RiskSummary[criticalLabel] = disabledString - } - } -} - -func writeHTMLSummary(targetFile string, summary *wrappers.ResultSummary) error { - log.Println("Creating Summary Report: ", targetFile) - summaryTemp, err := template.New("summaryTemplate").Parse(wrappers.SummaryTemplate(isScanPending(summary.Status))) - if err == nil { - f, err := os.Create(targetFile) - if err == nil { - _ = summaryTemp.ExecuteTemplate(f, "SummaryTemplate", summary) - _ = f.Close() - } - return err - } - return nil -} -func writeMarkdownSummary(targetFile string, data *wrappers.ResultSummary) error { - log.Println("Creating Markdown Summary Report: ", targetFile) - tmpl, err := template.New(printer.FormatSummaryMarkdown).Parse(wrappers.SummaryMarkdownTemplate(isScanPending(data.Status))) - if err != nil { - return err - } - file, err := os.Create(targetFile) - if err != nil { - return err - } - defer func() { _ = file.Close() }() - - err = tmpl.Execute(file, &data) - if err != nil { - return err - } - return nil -} - -// nolint: whitespace -func writeConsoleSummary(summary *wrappers.ResultSummary, ignorePolicyFlagOmit bool) error { - if !isScanPending(summary.Status) { - fmt.Printf(" Scan Summary: \n") - fmt.Printf(" Created At: %s\n", summary.CreatedAt) - fmt.Printf(" Project Name: %s \n", summary.ProjectName) - fmt.Printf(" Scan ID: %s \n\n", summary.ScanID) - fmt.Printf(" Results Summary: \n") - fmt.Printf( - " Risk Level: %s \n", - summary.RiskMsg, - ) - if summary.Policies != nil && !strings.EqualFold(summary.Policies.Status, policeManagementNoneStatus) { - printPoliciesSummary(summary, ignorePolicyFlagOmit) - } - - printResultsSummaryTable(summary) - - if summary.HasAPISecurity() { - printAPIsSecuritySummary(summary) - } - - if summary.HasSCS() { - printSCSSummary(summary.SCSOverview.MicroEngineOverviews) - } - - 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") - fmt.Printf("For more information: %s\n", summary.BaseURI) - } - return nil -} - -func printPoliciesSummary(summary *wrappers.ResultSummary, ignorePolicyFlagOmit bool) { - hasViolations := false - for _, policy := range summary.Policies.Policies { - if len(policy.RulesViolated) > 0 { - hasViolations = true - break - } - } - if hasViolations { - fmt.Printf(tableLine + "\n") - if ignorePolicyFlagOmit { - printWarningIfIgnorePolicyOmiited() - } - if summary.Policies.BreakBuild { - fmt.Printf(" Policy Management Violation - Break Build Enabled: \n") - } else { - fmt.Printf(" Policy Management Violation: \n") - } - for _, police := range summary.Policies.Policies { - if len(police.RulesViolated) > 0 { - fmt.Printf(" Policy: %s | Break Build: %t | Violated Rules: ", police.Name, police.BreakBuild) - for _, violatedRule := range police.RulesViolated { - fmt.Printf("%s;", violatedRule) - } - } - fmt.Printf("\n") - } - fmt.Printf("\n") - } -} - -func printAPIsSecuritySummary(summary *wrappers.ResultSummary) { - fmt.Printf(" API Security - Total Detected APIs: %d \n", summary.APISecurity.APICount) - fmt.Printf(" APIS WITH RISK: %*d \n", defaultPaddingSize, summary.APISecurity.TotalRisksCount) - if summary.HasAPISecurityDocumentation() { - fmt.Printf(" APIS DOCUMENTATION: %*d \n", defaultPaddingSize, summary.GetAPISecurityDocumentationTotal()) - } - fmt.Printf(tableLine + twoNewLines) -} - -func printTableRow(title string, counts *wrappers.EngineResultSummary, statusNumber int) { - switch statusNumber { - case notAvailableNumber: - fmt.Printf(stringTableResultsFormat, title, notAvailableString, notAvailableString, notAvailableString, notAvailableString, notAvailableString, notAvailableString) - case scanFailedNumber: - fmt.Printf(tableResultsFormat, title, getCountValue(counts.Critical), counts.High, counts.Medium, counts.Low, counts.Info, scanFailedString) - case scanCanceledNumber: - fmt.Printf(tableResultsFormat, title, getCountValue(counts.Critical), counts.High, counts.Medium, counts.Low, counts.Info, scanCanceledString) - case scanPartialNumber: - fmt.Printf(tableResultsFormat, title, getCountValue(counts.Critical), counts.High, counts.Medium, counts.Low, counts.Info, scanPartialString) - default: - fmt.Printf(tableResultsFormat, title, getCountValue(counts.Critical), counts.High, counts.Medium, counts.Low, counts.Info, scanSuccessString) - } -} - -func printSCSSummary(microEngineOverviews []*wrappers.MicroEngineOverview) { - fmt.Printf(" Supply Chain Security Results\n") - fmt.Printf(" -------------------------------------------------------------------------- \n") - fmt.Println(" | Critical High Medium Low Info Status |") - for _, microEngineOverview := range microEngineOverviews { - printSCSTableRow(microEngineOverview) - } - fmt.Printf(" -------------------------------------------------------------------------- \n\n") -} - -func printSCSTableRow(microEngineOverview *wrappers.MicroEngineOverview) { - formatString := " | %-20s %4v %4v %6v %4v %4v %-9s |\n" - notAvailableFormatString := " | %-20s %4v %4s %6s %4s %4s %5s |\n" - - riskSummary := microEngineOverview.RiskSummary - microEngineName := microEngineOverview.FullName - - switch microEngineOverview.Status { - case scsScanUnavailableString: - fmt.Printf(notAvailableFormatString, microEngineName, notAvailableString, notAvailableString, notAvailableString, notAvailableString, notAvailableString, notAvailableString) - default: - fmt.Printf(formatString, microEngineName, riskSummary[criticalLabel], riskSummary[highLabel], riskSummary[mediumLabel], riskSummary[lowLabel], - riskSummary[infoLabel], microEngineOverview.Status) - } -} - -func getCountValue(count int) interface{} { - if count < 0 { - return disabledString - } - return count -} - -func printResultsSummaryTable(summary *wrappers.ResultSummary) { - totalCriticalIssues := summary.EnginesResult.GetCriticalIssues() - totalHighIssues := summary.EnginesResult.GetHighIssues() - totalMediumIssues := summary.EnginesResult.GetMediumIssues() - totalLowIssues := summary.EnginesResult.GetLowIssues() - totalInfoIssues := summary.EnginesResult.GetInfoIssues() - fmt.Printf(tableLine + twoNewLines) - fmt.Printf(" Total Results: %d (Total Results includes only API documentation vulnerabilities\n and does not include API code vulnerabilities.)\n", summary.TotalIssues) - fmt.Println(tableLine) - fmt.Printf(TableTitleFormat, " ", "Critical", "High", "Medium", "Low", "Info", "Status") - - printTableRow("APIs", summary.EnginesResult[commonParams.APISecType], summary.EnginesResult[commonParams.APISecType].StatusCode) - printTableRow("IAC", summary.EnginesResult[commonParams.KicsType], summary.EnginesResult[commonParams.KicsType].StatusCode) - printTableRow("SAST", summary.EnginesResult[commonParams.SastType], summary.EnginesResult[commonParams.SastType].StatusCode) - printTableRow("SCA", summary.EnginesResult[commonParams.ScaType], summary.EnginesResult[commonParams.ScaType].StatusCode) - printTableRow("SCS", summary.EnginesResult[commonParams.ScsType], summary.EnginesResult[commonParams.ScsType].StatusCode) - - if wrappers.IsContainersEnabled { - printTableRow("CONTAINERS", summary.EnginesResult[commonParams.ContainersType], summary.EnginesResult[commonParams.ContainersType].StatusCode) - } - - fmt.Println(tableLine) - fmt.Printf(tableResultsFormat, - "TOTAL", getCountValue(totalCriticalIssues), totalHighIssues, totalMediumIssues, totalLowIssues, totalInfoIssues, summary.Status) - fmt.Printf(tableLine + twoNewLines) -} - -func generateScanSummaryURL(summary *wrappers.ResultSummary) string { - summaryURL := fmt.Sprintf( - strings.Replace(summary.BaseURI, "overview", "scans?id=%s&branch=%s", 1), - summary.ScanID, url.QueryEscape(summary.BranchName), - ) - return summaryURL -} - -func runGetResultCommand( - resultsWrapper wrappers.ResultsWrapper, - scanWrapper wrappers.ScansWrapper, - exportWrapper wrappers.ExportWrapper, - resultsPdfReportsWrapper wrappers.ResultsPdfWrapper, - resultsJSONReportsWrapper wrappers.ResultsJSONWrapper, - risksOverviewWrapper wrappers.RisksOverviewWrapper, - scsScanOverviewWrapper wrappers.ScanOverviewWrapper, - policyWrapper wrappers.PolicyWrapper, - featureFlagsWrapper wrappers.FeatureFlagsWrapper, - jwtWrapper wrappers.JWTWrapper, -) func(cmd *cobra.Command, args []string) error { - return func(cmd *cobra.Command, args []string) error { - targetFile, _ := cmd.Flags().GetString(commonParams.TargetFlag) - targetPath, _ := cmd.Flags().GetString(commonParams.TargetPathFlag) - format, _ := cmd.Flags().GetString(commonParams.TargetFormatFlag) - formatPdfToEmail, _ := cmd.Flags().GetString(commonParams.ReportFormatPdfToEmailFlag) - formatPdfOptions, _ := cmd.Flags().GetString(commonParams.ReportFormatPdfOptionsFlag) - formatSbomOptions, _ := cmd.Flags().GetString(commonParams.ReportSbomFormatFlag) - sastRedundancy, _ := cmd.Flags().GetBool(commonParams.SastRedundancyFlag) - agent, _ := cmd.Flags().GetString(commonParams.AgentFlag) - scaHideDevAndTestDep, _ := cmd.Flags().GetBool(commonParams.ScaHideDevAndTestDepFlag) - ignorePolicy, _ := cmd.Flags().GetBool(commonParams.IgnorePolicyFlag) - // Check if the user has permission to override policy management if --ignore-policy is set - ignorePolicyFlagOmit := false - if ignorePolicy { - overridePolicyManagementPer, err := jwtWrapper.CheckPermissionByAccessToken(OverridePolicyManagement) - if err != nil { - return err - } - if !overridePolicyManagementPer { - ignorePolicyFlagOmit = true - ignorePolicy = false - } - } - waitDelay, _ := cmd.Flags().GetInt(commonParams.WaitDelayFlag) - policyTimeout, _ := cmd.Flags().GetInt(commonParams.PolicyTimeoutFlag) - - scanID, _ := cmd.Flags().GetString(commonParams.ScanIDFlag) - if scanID == "" { - return errors.Errorf("%s: Please provide a scan ID", failedListingResults) - } - - resultsParams, err := getFilters(cmd) - if err != nil { - return errors.Wrapf(err, "%s", failedListingResults) - } - - if scaHideDevAndTestDep { - resultsParams[ScaExcludeResultTypesParam] = ScaDevAndTestExclusionParam - } - - scan, errorModel, scanErr := scanWrapper.GetByID(scanID) - if scanErr != nil { - return errors.Wrapf(scanErr, "%s", failedGetting) - } - if errorModel != nil { - return errors.Errorf("%s: CODE: %d, %s", failedGettingScan, errorModel.Code, errorModel.Message) - } - - var policyResponseModel *wrappers.PolicyResponseModel - if !isScanPending(string(scan.Status)) { - policyResponseModel, err = services.HandlePolicyEvaluation(cmd, policyWrapper, scan, ignorePolicy, agent, waitDelay, policyTimeout) - if err != nil { - return err - } - } else { - logger.PrintIfVerbose("Policy violations aren't returned in the pipeline for scans run in async mode.") - } - - if sastRedundancy { - resultsParams[commonParams.SastRedundancyFlag] = "" - } - - _, err = CreateScanReport(resultsWrapper, risksOverviewWrapper, scsScanOverviewWrapper, exportWrapper, - policyResponseModel, resultsPdfReportsWrapper, resultsJSONReportsWrapper, scan, format, formatPdfToEmail, formatPdfOptions, - formatSbomOptions, targetFile, targetPath, agent, resultsParams, featureFlagsWrapper, ignorePolicyFlagOmit) - return err - } -} - -func runGetCodeBashingCommand( - codeBashingWrapper wrappers.CodeBashingWrapper, -) func(cmd *cobra.Command, args []string) error { - return func(cmd *cobra.Command, args []string) error { - lang, _ := cmd.Flags().GetString(commonParams.LanguageFlag) - cwe, _ := cmd.Flags().GetString(commonParams.CweIDFlag) - vulType, _ := cmd.Flags().GetString(commonParams.VulnerabilityTypeFlag) - params, err := codeBashingWrapper.BuildCodeBashingParams( - []wrappers.CodeBashingParamsCollection{ - { - CweID: "CWE-" + cwe, - Language: lang, - CxQueryName: strings.ReplaceAll(vulType, " ", "_"), - }, - }, - ) - if err != nil { - return err - } - // Fetch the cached token or a new one to obtain the codebashing URL incoded in the jwt token - codeBashingURL, err := codeBashingWrapper.GetCodeBashingURL(codeBashingKey) - if err != nil { - return err - } - // Make the request to the api to obtain the codebashing link and send the codebashing url to enrich the path - CodeBashingModel, webError, err := codeBashingWrapper.GetCodeBashingLinks(params, codeBashingURL) - if err != nil { - return err - } - if webError != nil { - return errors.New(webError.Message) - } - err = printByFormat(cmd, *CodeBashingModel) - if err != nil { - return errors.Wrapf(err, "%s", failedListingCodeBashing) - } - return nil - } -} - -func setIsContainersEnabled(agent string) { - wrappers.IsContainersEnabled = !containsIgnoreCase(containerEngineUnsupportedAgents, agent) -} - -func filterResultsByType(results *wrappers.ScanResultsCollection, excludedTypes map[string]struct{}) *wrappers.ScanResultsCollection { - var filteredResults []*wrappers.ScanResult - - for _, result := range results.Results { - if _, shouldExclude := excludedTypes[result.Type]; shouldExclude { - results.TotalCount-- - } else { - filteredResults = append(filteredResults, result) - } - } - results.Results = filteredResults - return results -} - -func filterScsResultsByAgent(results *wrappers.ScanResultsCollection, agent string) *wrappers.ScanResultsCollection { - unsupportedTypesByAgent := map[string][]string{ - commonParams.VSCodeAgent: {commonParams.SCSScorecardType}, - commonParams.JetbrainsAgent: {commonParams.SCSScorecardType}, - commonParams.EclipseAgent: {commonParams.SCSScorecardType, commonParams.SCSSecretDetectionType}, - commonParams.VisualStudioAgent: {commonParams.SCSScorecardType}, - } - - excludedTypes := make(map[string]struct{}) - - if typesToExclude, exists := unsupportedTypesByAgent[agent]; exists { - for _, excludeType := range typesToExclude { - excludedTypes[excludeType] = struct{}{} - } - } - - results = filterResultsByType(results, excludedTypes) - - return results -} - -// CreateScanReport produces the requested report formats for a scan and writes them to the target path. -func CreateScanReport( - resultsWrapper wrappers.ResultsWrapper, - risksOverviewWrapper wrappers.RisksOverviewWrapper, - scsScanOverviewWrapper wrappers.ScanOverviewWrapper, - exportWrapper wrappers.ExportWrapper, - policyResponseModel *wrappers.PolicyResponseModel, - resultsPdfReportsWrapper wrappers.ResultsPdfWrapper, - resultsJSONReportsWrapper wrappers.ResultsJSONWrapper, - scan *wrappers.ScanResponseModel, - reportTypes, - formatPdfToEmail, - formatPdfOptions, - formatSbomOptions, - targetFile, - targetPath string, - agent string, - resultsParams map[string]string, - featureFlagsWrapper wrappers.FeatureFlagsWrapper, - ignorePolicyFlagOmit bool, -) (*wrappers.ScanResultsCollection, error) { - reportList := strings.Split(reportTypes, ",") - results := &wrappers.ScanResultsCollection{} - setIsContainersEnabled(agent) - summary, err := convertScanToResultsSummary(scan, resultsWrapper) - if err != nil { - return nil, err - } - scanPending := isScanPending(summary.Status) - - err = createDirectory(targetPath) - if err != nil { - return nil, err - } - if !scanPending { - results, err = ReadResults(resultsWrapper, exportWrapper, scan, resultsParams, agent, featureFlagsWrapper) - if err != nil { - return nil, err - } - } - isSummaryNeeded := verifyFormatsByReportList(reportList, summaryFormats...) - if isSummaryNeeded && !scanPending { - summary, err = summaryReport(summary, policyResponseModel, risksOverviewWrapper, scsScanOverviewWrapper, featureFlagsWrapper, results, resultsParams) - if err != nil { - return nil, err - } - } - for _, reportType := range reportList { - err = createReport(reportType, formatPdfToEmail, formatPdfOptions, formatSbomOptions, targetFile, - targetPath, results, summary, exportWrapper, resultsPdfReportsWrapper, resultsJSONReportsWrapper, featureFlagsWrapper, ignorePolicyFlagOmit) - if err != nil { - return nil, err - } - } - return results, nil -} - -func countResult(summary *wrappers.ResultSummary, result *wrappers.ScanResult) { - engineType := strings.TrimSpace(result.Type) - severity := strings.ToLower(result.Severity) - if contains(summary.EnginesEnabled, engineType) && isExploitable(result.State) { - if engineType == commonParams.SastType { - summary.SastIssues++ - summary.TotalIssues++ - } else if engineType == commonParams.ScaType { - summary.ScaIssues++ - summary.TotalIssues++ - } else if engineType == commonParams.KicsType { - summary.KicsIssues++ - summary.TotalIssues++ - } else if engineType == commonParams.ContainersType { - if wrappers.IsContainersEnabled { - *summary.ContainersIssues++ - summary.TotalIssues++ - } else { - return - } - } else if strings.HasPrefix(engineType, commonParams.SscsType) { - addResultToSCSOverview(summary, result) - engineType = commonParams.ScsType - *summary.ScsIssues++ - summary.TotalIssues++ - } else { - return - } - - switch severity { - case criticalLabel: - summary.CriticalIssues++ - case highLabel: - summary.HighIssues++ - case mediumLabel: - summary.MediumIssues++ - case lowLabel: - summary.LowIssues++ - case infoLabel: - summary.InfoIssues++ - } - - summary.UpdateEngineResultSummary(engineType, severity) - } -} - -func addResultToSCSOverview(summary *wrappers.ResultSummary, result *wrappers.ScanResult) { - if engineOverviewName, engineExists := sscsEngineToOverviewEngineMap[result.Type]; engineExists { - for _, microEngineOverview := range summary.SCSOverview.MicroEngineOverviews { - if microEngineOverview.Name == engineOverviewName { - if microEngineOverview.RiskSummary != nil { - severity := strings.ToLower(result.Severity) - if severityCount, exists := microEngineOverview.RiskSummary[severity]; exists { - summary.SCSOverview.RiskSummary[severity]++ - microEngineOverview.TotalRisks++ - summary.SCSOverview.TotalRisksCount++ - microEngineOverview.RiskSummary[severity] = severityCount.(int) + 1 - } - } - } - } - } -} - -func verifyFormatsByReportList(reportFormats []string, formats ...string) bool { - for _, reportFormat := range reportFormats { - for _, format := range formats { - if printer.IsFormat(reportFormat, format) { - return true - } - } - } - return false -} - -func validateEmails(emailString string) ([]string, error) { - re := regexp.MustCompile(`^[a-zA-Z0-9_.+-]+@[a-zA-Z0-9-]+\.[a-zA-Z0-9-.]+$`) - emails := strings.Split(emailString, ",") - var validEmails []string - for _, emailStr := range emails { - email := strings.TrimSpace(emailStr) - if re.MatchString(email) { - validEmails = append(validEmails, email) - } else { - return nil, errors.Errorf("report not sent, invalid email address: %s", email) - } - } - return validEmails, nil -} - -func getResultsForAPISecScanner( - risksOverviewWrapper wrappers.RisksOverviewWrapper, - scanID string, -) (results *wrappers.APISecResult, err error) { - var apiSecResultsModel *wrappers.APISecResult - var errorModel *wrappers.WebError - - apiSecResultsModel, errorModel, err = risksOverviewWrapper.GetAllAPISecRisksByScanID(scanID) - if err != nil { - return nil, errors.Wrapf(err, "%s", failedListingResults) - } - if errorModel != nil { - return nil, errors.Errorf("%s: CODE: %d, %s", failedListingResults, errorModel.Code, errorModel.Message) - } else if apiSecResultsModel != nil { - return apiSecResultsModel, nil - } - return nil, nil -} - -func getScanOverviewForSCSScanner( - scsScanOverviewWrapper wrappers.ScanOverviewWrapper, - scanID string, -) (results *wrappers.SCSOverview, err error) { - var scsOverview *wrappers.SCSOverview - var errorModel *wrappers.WebError - - scsOverview, errorModel, err = scsScanOverviewWrapper.GetSCSOverviewByScanID(scanID) - if err != nil { - return nil, errors.Wrapf(err, "SCS: %s", failedListingResults) - } - if errorModel != nil { - return nil, errors.Errorf("SCS: %s: CODE: %d, %s", failedListingResults, errorModel.Code, errorModel.Message) - } else if scsOverview != nil { - // Setting all counts to 0. Results are recounted in enhanceWithScanSummary->countResult - scsOverview.TotalRisksCount = 0 - for key := range scsOverview.RiskSummary { - scsOverview.RiskSummary[key] = 0 - } - for _, microEngineOverview := range scsOverview.MicroEngineOverviews { - microEngineOverview.TotalRisks = 0 - if microEngineOverview.RiskSummary != nil { - for severity := range microEngineOverview.RiskSummary { - microEngineOverview.RiskSummary[severity] = 0 - } - } - } - return scsOverview, nil - } - return nil, nil -} - -func isScanPending(scanStatus string) bool { - return !strings.EqualFold(scanStatus, statusCompleted) && - !strings.EqualFold(scanStatus, statusPartial) && - !strings.EqualFold(scanStatus, statusFailed) -} - -func createRawReport( - format, targetFile, targetPath string, - results *wrappers.ScanResultsCollection, - summary *wrappers.ResultSummary, - resultsJSONReportsWrapper wrappers.ResultsJSONWrapper, - featureFlagsWrapper wrappers.FeatureFlagsWrapper, -) (handled bool, err error) { - if printer.IsFormat(format, printer.FormatIndentedJSON) { - return true, nil - } - if printer.IsFormat(format, printer.FormatSarif) && isValidScanStatus(summary.Status, printer.FormatSarif) { - sarifRpt := createTargetName(targetFile, targetPath, printer.FormatSarif) - return true, exportSarifResults(sarifRpt, results) - } - if printer.IsFormat(format, printer.FormatSonar) && isValidScanStatus(summary.Status, printer.FormatSonar) { - sonarRpt := createTargetName(fmt.Sprintf("%s%s", targetFile, sonarTypeLabel), targetPath, printer.FormatJSON) - return true, exportSonarResults(sonarRpt, results) - } - if printer.IsFormat(format, printer.FormatJSON) && isValidScanStatus(summary.Status, printer.FormatJSON) { - jsonRpt := createTargetName(targetFile, targetPath, printer.FormatJSON) - return true, exportJSONResults(jsonRpt, results) - } - if printer.IsFormat(format, printer.FormatJSONv2) && isValidScanStatus(summary.Status, printer.FormatJSONv2) { - summaryRpt := createTargetName(targetFile, targetPath, printer.FormatJSON) - return true, exportJSONReportResults(resultsJSONReportsWrapper, summary, summaryRpt, featureFlagsWrapper) - } - if printer.IsFormat(format, printer.FormatGLSast) { - jsonRpt := createTargetName(fmt.Sprintf("%s%s", targetFile, glSastTypeLabel), targetPath, printer.FormatJSON) - return true, exportGlSastResults(jsonRpt, results, summary) - } - if printer.IsFormat(format, printer.FormatGLSca) { - jsonRpt := createTargetName(fmt.Sprintf("%s%s", targetFile, glScaTypeLabel), targetPath, printer.FormatJSON) - return true, exportGlScaResults(jsonRpt, results, summary) - } - return false, nil -} - -func isValidScanStatus(status, format string) bool { - if isScanPending(status) { - log.Printf("Result format file %s not create because scan status is %s", format, status) - return false - } - return true -} - -func createReport(format, - formatPdfToEmail, - formatPdfOptions, - formatSbomOptions, - targetFile, - targetPath string, - results *wrappers.ScanResultsCollection, - summary *wrappers.ResultSummary, - exportWrapper wrappers.ExportWrapper, - resultsPdfReportsWrapper wrappers.ResultsPdfWrapper, - resultsJSONReportsWrapper wrappers.ResultsJSONWrapper, - featureFlagsWrapper wrappers.FeatureFlagsWrapper, - ignorePolicyFlagOmit bool) error { - if handled, err := createRawReport(format, targetFile, targetPath, results, summary, resultsJSONReportsWrapper, featureFlagsWrapper); handled { - return err - } - - if printer.IsFormat(format, printer.FormatSummaryConsole) { - return writeConsoleSummary(summary, ignorePolicyFlagOmit) - } - if printer.IsFormat(format, printer.FormatSummary) { - summaryRpt := createTargetName(targetFile, targetPath, printer.FormatHTML) - convertNotAvailableNumberToZero(summary) - return writeHTMLSummary(summaryRpt, summary) - } - if printer.IsFormat(format, printer.FormatSummaryJSON) { - summaryRpt := createTargetName(targetFile, targetPath, printer.FormatJSON) - convertNotAvailableNumberToZero(summary) - return exportJSONSummaryResults(summaryRpt, summary) - } - if printer.IsFormat(format, printer.FormatPDF) && isValidScanStatus(summary.Status, printer.FormatPDF) { - summaryRpt := createTargetName(targetFile, targetPath, printer.FormatPDF) - return exportPdfResults(resultsPdfReportsWrapper, summary, summaryRpt, formatPdfToEmail, formatPdfOptions, featureFlagsWrapper) - } - if printer.IsFormat(format, printer.FormatSummaryMarkdown) { - summaryRpt := createTargetName(targetFile, targetPath, "md") - convertNotAvailableNumberToZero(summary) - return writeMarkdownSummary(summaryRpt, summary) - } - if printer.IsFormat(format, printer.FormatSbom) && isValidScanStatus(summary.Status, printer.FormatSbom) { - targetType := printer.FormatJSON - if strings.Contains(strings.ToLower(formatSbomOptions), printer.FormatXML) { - targetType = printer.FormatXML - } - summaryRpt := createTargetName(fmt.Sprintf("%s_%s", targetFile, printer.FormatSbom), targetPath, targetType) - convertNotAvailableNumberToZero(summary) - - if !contains(summary.EnginesEnabled, commonParams.ScaType) { - return fmt.Errorf("unable to generate %s report - SCA engine must be enabled on scan summary", printer.FormatSbom) - } - - if summary.ScaIssues == notAvailableNumber { - return fmt.Errorf("unable to generate %s report - SCA engine did not complete successfully", printer.FormatSbom) - } - - return services.ExportSbomResults(exportWrapper, summaryRpt, summary, formatSbomOptions) - } - return fmt.Errorf("bad report format %s", format) -} - -func createTargetName(targetFile, targetPath, targetType string) string { - return filepath.Join(targetPath, targetFile+"."+targetType) -} - -func createDirectory(targetPath string) error { - if _, err := os.Stat(targetPath); os.IsNotExist(err) { - log.Printf("\nOutput path not found: %s\n", targetPath) - log.Printf("Creating directory: %s\n", targetPath) - err = os.Mkdir(targetPath, directoryPermission) - if err != nil { - return err - } - } - return nil -} - -// ReadResults fetches all scan results for the given scan and enriches them with SCA and SCS data as applicable. -func ReadResults( - resultsWrapper wrappers.ResultsWrapper, - exportWrapper wrappers.ExportWrapper, - scan *wrappers.ScanResponseModel, - resultsParams map[string]string, - agent string, featureflagsWrappers wrappers.FeatureFlagsWrapper) (results *wrappers.ScanResultsCollection, err error) { - var resultsModel *wrappers.ScanResultsCollection - var errorModel *wrappers.WebError - - resultsParams[commonParams.ScanIDQueryParam] = scan.ID - _, sastRedundancy := resultsParams[commonParams.SastRedundancyFlag] - - scaHideDevAndTestDep := resultsParams[ScaExcludeResultTypesParam] == ScaDevAndTestExclusionParam - - resultsModel, errorModel, err = resultsWrapper.GetAllResultsByScanID(resultsParams) - - if err != nil { - return nil, errors.Wrapf(err, "%s", failedListingResults) - } - if errorModel != nil { - return nil, errors.Errorf("%s: CODE: %d, %s", failedListingResults, errorModel.Code, errorModel.Message) - } - - if resultsModel != nil { - if slices.Contains(scan.Engines, commonParams.SastType) && sastRedundancy { - // Compute SAST results redundancy - resultsModel = ComputeRedundantSastResults(resultsModel) - } - resultsModel, err = enrichScaResults(exportWrapper, scan, resultsModel, scaHideDevAndTestDep, featureflagsWrappers) - if err != nil { - return nil, err - } - - if slices.Contains(scan.Engines, commonParams.ScsType) { - resultsModel = filterScsResultsByAgent(resultsModel, agent) - } - - resultsModel.ScanID = scan.ID - return resultsModel, nil - } - return nil, nil -} - -func enrichScaResults( - exportWrapper wrappers.ExportWrapper, - scan *wrappers.ScanResponseModel, - resultsModel *wrappers.ScanResultsCollection, - scaHideDevAndTestDep bool, featureflagWrapper wrappers.FeatureFlagsWrapper) (*wrappers.ScanResultsCollection, error) { - if slices.Contains(scan.Engines, commonParams.ScaType) { - scaExportDetails, err := services.GetExportPackage(exportWrapper, scan.ID, scaHideDevAndTestDep, featureflagWrapper) - if err != nil { - return nil, errors.Wrapf(err, "%s", failedListingResults) - } - scaPackageModel := parseScaExportPackage(scaExportDetails.Packages) - scaTypeModel := parseExportScaVulnerability(scaExportDetails.ScaTypes) - if scaPackageModel != nil { - resultsModel = addPackageInformation(resultsModel, scaPackageModel, scaTypeModel) - } - } - if slices.Contains(scan.Engines, commonParams.ContainersType) && !wrappers.IsContainersEnabled { - resultsModel = removeResultsByType(resultsModel, commonParams.ContainersType) - } - return resultsModel, nil -} - -func parseExportScaVulnerability(types []wrappers.ScaType) *[]wrappers.ScaTypeCollection { - var scaTypes []wrappers.ScaTypeCollection - for _, t := range types { - scaTypes = append(scaTypes, wrappers.ScaTypeCollection(t)) - } - return &scaTypes -} - -func parseScaExportPackage(packages []wrappers.ScaPackage) *[]wrappers.ScaPackageCollection { - var scaPackages []wrappers.ScaPackageCollection - for _, pkg := range packages { - pkg := pkg - scaPackages = append(scaPackages, wrappers.ScaPackageCollection{ - ID: pkg.ID, - Locations: pkg.Locations, - DependencyPathArray: parsePackagePathToDependencyPath(&pkg), - Outdated: pkg.Outdated, - IsDirectDependency: pkg.IsDirectDependency, - IsDevelopmentDependency: pkg.IsDevelopmentDependency, - IsTestDependency: pkg.IsTestDependency, - }) - } - return &scaPackages -} - -func parsePackagePathToDependencyPath(pkg *wrappers.ScaPackage) [][]wrappers.DependencyPath { - var dependencyPathArray [][]wrappers.DependencyPath - for _, path := range pkg.PackagePathArray { - var dependencyPath []wrappers.DependencyPath - for _, dep := range path { - dependencyPath = append(dependencyPath, wrappers.DependencyPath{ - ID: dep.ID, - Name: dep.Name, - Version: dep.Version, - }) - } - dependencyPathArray = append(dependencyPathArray, dependencyPath) - } - - // We are doing this to maintain the same structure that was in risk-management api response - // in risk-management, if the length of the dependency path array is 1, it will be the main package - // in export service, if there are no dependencies, the package path array will be empty - if len(dependencyPathArray) == 0 { - appendMainPackageToDependencyPath(&dependencyPathArray, pkg) - } - return dependencyPathArray -} - -func appendMainPackageToDependencyPath(dependencyPathArray *[][]wrappers.DependencyPath, pkg *wrappers.ScaPackage) { - *dependencyPathArray = append(*dependencyPathArray, []wrappers.DependencyPath{{ - ID: pkg.ID, - Locations: pkg.Locations, - Name: pkg.Name, - IsDevelopment: pkg.IsDevelopmentDependency, - }}) -} - -func removeResultsByType(model *wrappers.ScanResultsCollection, resultType string) *wrappers.ScanResultsCollection { - var newResults []*wrappers.ScanResult - for _, result := range model.Results { - isResultType := result.Type == resultType - if resultType == commonParams.SscsType { - isResultType = strings.HasPrefix(result.Type, resultType) - } - if !isResultType { - newResults = append(newResults, result) - } - } - model.Results = newResults - model.TotalCount = uint(len(newResults)) - return model -} - -func exportSarifResults(targetFile string, results *wrappers.ScanResultsCollection) error { - var err error - var resultsJSON []byte - log.Println("Creating SARIF Report: ", targetFile) - var sarifResults = convertCxResultsToSarif(results) - resultsJSON, err = json.Marshal(sarifResults) - if err != nil { - return errors.Wrapf(err, "%s: failed to serialize results response ", failedGettingAll) - } - f, err := os.Create(targetFile) - if err != nil { - return errors.Wrapf(err, "%s: failed to create target file ", failedGettingAll) - } - _, _ = fmt.Fprintln(f, string(resultsJSON)) - _ = f.Close() - return nil -} -func exportGlSastResults(targetFile string, results *wrappers.ScanResultsCollection, summary *wrappers.ResultSummary) error { - log.Println("Creating gl-sast Report: ", targetFile) - var glSast = new(wrappers.GlSastResultsCollection) - glSast.Vulnerabilities = []wrappers.GlVulnerabilities{} - err := addScanToGlSastReport(summary, glSast) - if err != nil { - return errors.Wrapf(err, "%s: failed to add scan to gl-sast report", failedListingResults) - } - convertCxResultToGlSastVulnerability(results, glSast, summary) - resultsJSON, err := json.Marshal(glSast) - if err != nil { - return errors.Wrapf(err, "%s: failed to serialize gl-sast report ", failedListingResults) - } - f, err := os.Create(targetFile) - if err != nil { - return errors.Wrapf(err, "%s: failed to create target file ", failedListingResults) - } - defer func() { _ = f.Close() }() - _, _ = fmt.Fprintln(f, string(resultsJSON)) - return nil -} - -func exportGlScaResults(targetFile string, results *wrappers.ScanResultsCollection, summary *wrappers.ResultSummary) error { - log.Println("Creating Gl-sca Report: ", targetFile) - glScaResult := &wrappers.GlScaResultsCollection{ - Vulnerabilities: []wrappers.GlScaDepVulnerabilities{}, // Initialize arrays to prevent GitLab schema validation errors. - ScaDependencyFiles: []wrappers.ScaDependencyFile{}, - } - err := addScanToGlScaReport(summary, glScaResult) - if err != nil { - return errors.Wrapf(err, "%s: failed to denerate GL-Sca report ", failedListingResults) - } - convertCxResultToGlScaVulnerability(results, glScaResult) - convertCxResultToGlScaFiles(results, glScaResult) - resultsJSON, err := json.Marshal(glScaResult) - if err != nil { - return errors.Wrapf(err, "%s: failed to serialize GL-Sca report ", failedListingResults) - } - f, err := os.Create(targetFile) - if err != nil { - return errors.Wrapf(err, "%s: failed to create target file ", failedListingResults) - } - defer func() { _ = f.Close() }() - _, _ = fmt.Fprintln(f, string(resultsJSON)) - - return nil -} - -func addScanToGlScaReport(summary *wrappers.ResultSummary, glScaResult *wrappers.GlScaResultsCollection) error { - createdAt, err := time.Parse(summaryCreatedAtLayout, summary.CreatedAt) - if err != nil { - return err - } - - glScaResult.Schema = wrappers.ScaSchema - glScaResult.Version = wrappers.SchemaVersion - glScaResult.Scan.Analyzer.VendorGlSCA.VendorGlname = wrappers.AnalyzerScaID - glScaResult.Scan.Analyzer.Name = wrappers.AnalyzerScaID - glScaResult.Scan.Analyzer.Name = wrappers.AnalyzerScaID - glScaResult.Scan.Analyzer.ID = wrappers.ScannerID - glScaResult.Scan.Scanner.ID = wrappers.ScannerID - glScaResult.Scan.Scanner.Name = wrappers.AnalyzerScaID - glScaResult.Scan.Scanner.VendorGlSCA.VendorGlname = wrappers.AnalyzerScaID - glScaResult.Scan.Status = commonParams.Success - glScaResult.Scan.Type = wrappers.ScannerType - glScaResult.Scan.StartTime = createdAt.Format(glTimeFormat) - glScaResult.Scan.EndTime = createdAt.Format(glTimeFormat) - glScaResult.Scan.Scanner.Name = wrappers.AnalyzerScaID - glScaResult.Scan.Scanner.VersionGlSca = commonParams.Version - glScaResult.Scan.Analyzer.VersionGlSca = commonParams.Version - - return nil -} - -func addScanToGlSastReport(summary *wrappers.ResultSummary, glSast *wrappers.GlSastResultsCollection) error { - createdAt, err := time.Parse(summaryCreatedAtLayout, summary.CreatedAt) - if err != nil { - return err - } - - glSast.Scan = wrappers.ScanGlReport{} - glSast.Schema = wrappers.SastSchema - glSast.Version = wrappers.SastSchemaVersion - glSast.Scan.Analyzer.URL = wrappers.AnalyzerURL - glSast.Scan.Analyzer.Name = wrappers.VendorName - glSast.Scan.Analyzer.Vendor.Name = wrappers.VendorName - glSast.Scan.Analyzer.ID = wrappers.AnalyzerID - glSast.Scan.Scanner.ID = wrappers.AnalyzerID - glSast.Scan.Scanner.Name = wrappers.VendorName - glSast.Scan.Status = commonParams.Success - glSast.Scan.Type = commonParams.SastType - glSast.Scan.StartTime = createdAt.Format(glTimeFormat) - glSast.Scan.EndTime = createdAt.Format(glTimeFormat) - glSast.Scan.Scanner.Vendor.Name = wrappers.VendorName - glSast.Scan.Scanner.Version = commonParams.Version - glSast.Scan.Analyzer.Version = commonParams.Version - - return nil -} -func exportSonarResults(targetFile string, results *wrappers.ScanResultsCollection) error { - var err error - var resultsJSON []byte - log.Println("Creating SONAR Report: ", targetFile) - var sonarResults = convertCxResultsToSonar(results) - resultsJSON, err = json.Marshal(sonarResults) - if err != nil { - return errors.Wrapf(err, "%s: failed to serialize results response ", failedGettingAll) - } - f, err := os.Create(targetFile) - if err != nil { - return errors.Wrapf(err, "%s: failed to create target file ", failedGettingAll) - } - _, _ = fmt.Fprintln(f, string(resultsJSON)) - _ = f.Close() - return nil -} - -// Function to decode HTML entities in the ScanResultsCollection -func decodeHTMLEntitiesInResults(results *wrappers.ScanResultsCollection) { - for _, result := range results.Results { - result.Description = html.UnescapeString(result.Description) - result.DescriptionHTML = html.UnescapeString(result.DescriptionHTML) - for _, node := range result.ScanResultData.Nodes { - node.FullName = html.UnescapeString(node.FullName) - node.Name = html.UnescapeString(node.Name) - } - } -} - -func exportJSONResults(targetFile string, results *wrappers.ScanResultsCollection) error { - decodeHTMLEntitiesInResults(results) - var err error - var resultsJSON []byte - log.Println("Creating JSON Report: ", targetFile) - resultsJSON, err = json.Marshal(results) - if err != nil { - return errors.Wrapf(err, "%s: failed to serialize results response ", failedGettingAll) - } - f, err := os.Create(targetFile) - if err != nil { - return errors.Wrapf(err, "%s: failed to create target file ", failedGettingAll) - } - _, _ = fmt.Fprintln(f, string(resultsJSON)) - _ = f.Close() - return nil -} - -func exportJSONReportResults(jsonWrapper wrappers.ResultsJSONWrapper, summary *wrappers.ResultSummary, summaryRpt string, featureFlagsWrapper wrappers.FeatureFlagsWrapper) error { - jsonReportsPayload := &wrappers.JSONReportsPayload{} - pollingResp := &wrappers.JSONPollingResponse{} - jsonReportsPayload.ReportName = reportNameImprovedScanReport - - jsonOptionsSections, jsonOptionsEngines := parseJSONOptions(summary.EnginesEnabled, jsonReportsPayload.ReportName) - - jsonReportsPayload.ReportType = CliType - jsonReportsPayload.FileFormat = printer.FormatJSON - jsonReportsPayload.Data.ScanID = summary.ScanID - jsonReportsPayload.Data.ProjectID = summary.ProjectID - jsonReportsPayload.Data.BranchName = summary.BranchName - jsonReportsPayload.Data.Scanners = jsonOptionsEngines - jsonReportsPayload.Data.Sections = jsonOptionsSections - - jsonReportID, webErr, err := jsonWrapper.GenerateJSONReport(jsonReportsPayload) - if webErr != nil { - return errors.Errorf("Error generating JSON report - %s", webErr.Message) - } - if err != nil { - return errors.Errorf("Error generating JSON report - %s", err.Error()) - } - log.Println("Generating JSON report") - pollingResp.Status = startedStatus - for pollingResp.Status == startedStatus || pollingResp.Status == requestedStatus { - pollingResp, webErr, err = jsonWrapper.CheckJSONReportStatus(jsonReportID.ReportID) - if err != nil || webErr != nil { - return errors.Wrapf(err, "%v", webErr) - } - logger.PrintfIfVerbose("JSON report status: %s", pollingResp.Status) - time.Sleep(delayValueForReport * time.Millisecond) - } - if pollingResp.Status != completedStatus { - return errors.Errorf("JSON generating failed - Current status: %s", pollingResp.Status) - } - - minioEnabled, _ := wrappers.GetSpecificFeatureFlag(featureFlagsWrapper, wrappers.MinioEnabled) - infoPathType := "" - if minioEnabled.Status { - infoPathType = jsonReportID.ReportID - } else { - infoPathType = pollingResp.URL - } - err = jsonWrapper.DownloadJSONReport(infoPathType, summaryRpt, minioEnabled.Status) - if err != nil { - return errors.Wrapf(err, "%s", "Failed downloading JSON report") - } - return nil -} - -func parseJSONOptions(enabledEngines []string, reportName string) (jsonOptionsSections, jsonOptionsEngines []string) { - jsonOptionsSections = []string{ - sectionScanSummary, - sectionExecutiveSummary, - sectionScanResults, - } - - var jsonOptionsEnginesMap = map[string]string{ - commonParams.ScaType: scaEngineLabel, - commonParams.SastType: sastEngineLabel, - commonParams.KicsType: kicsEngineLabel, - commonParams.IacType: kicsEngineLabel, - commonParams.ContainersType: "Containers", - commonParams.ScsType: "Microengines", - } - if jsonOptionsEngines == nil { - for _, engine := range enabledEngines { - if jsonOptionsEnginesMap[engine] != "" { - jsonOptionsEngines = append(jsonOptionsEngines, jsonOptionsEnginesMap[engine]) - } - } - } - - if reportName == reportNameImprovedScanReport { - jsonOptionsSections = translateReportSectionsForImproved(jsonOptionsSections) - } - - return jsonOptionsSections, jsonOptionsEngines -} - -func exportJSONSummaryResults(targetFile string, results *wrappers.ResultSummary) error { - var err error - var resultsJSON []byte - log.Println("Creating summary JSON Report: ", targetFile) - resultsJSON, err = json.Marshal(results) - if err != nil { - return errors.Wrapf(err, "%s: failed to serialize results response ", failedGettingAll) - } - f, err := os.Create(targetFile) - if err != nil { - return errors.Wrapf(err, "%s: failed to create target file ", failedGettingAll) - } - _, _ = fmt.Fprintln(f, string(resultsJSON)) - _ = f.Close() - return nil -} - -func exportPdfResults(pdfWrapper wrappers.ResultsPdfWrapper, summary *wrappers.ResultSummary, summaryRpt, formatPdfToEmail, - pdfOptions string, featureFlagsWrapper wrappers.FeatureFlagsWrapper) error { - pdfReportsPayload := &wrappers.PdfReportsPayload{} - pollingResp := &wrappers.PdfPollingResponse{} - pdfReportsPayload.ReportName = reportNameImprovedScanReport - pdfOptionsSections, pdfOptionsEngines, err := parsePDFOptions(pdfOptions, summary.EnginesEnabled, pdfReportsPayload.ReportName) - if err != nil { - return err - } - pdfReportsPayload.ReportType = CliType - pdfReportsPayload.FileFormat = printer.FormatPDF - pdfReportsPayload.Data.ScanID = summary.ScanID - pdfReportsPayload.Data.ProjectID = summary.ProjectID - pdfReportsPayload.Data.BranchName = summary.BranchName - pdfReportsPayload.Data.Scanners = pdfOptionsEngines - pdfReportsPayload.Data.Sections = pdfOptionsSections - - // will generate pdf report and send it to the email list - // instead of saving it to the file system - if formatPdfToEmail != "" { - emailList, validateErr := validateEmails(formatPdfToEmail) - if validateErr != nil { - return validateErr - } - pdfReportsPayload.ReportType = reportTypeEmail - pdfReportsPayload.Data.Email = emailList - } - pdfReportID, webErr, err := pdfWrapper.GeneratePdfReport(pdfReportsPayload) - if webErr != nil { - return errors.Errorf("Error generating PDF report - %s", webErr.Message) - } - if err != nil { - return errors.Errorf("Error generating PDF report - %s", err.Error()) - } - if pdfReportsPayload.ReportType == reportTypeEmail { - log.Println("Sending PDF report to: ", pdfReportsPayload.Data.Email) - return nil - } - log.Println("Generating PDF report") - pollingResp.Status = startedStatus - for pollingResp.Status == startedStatus || pollingResp.Status == requestedStatus { - pollingResp, webErr, err = pdfWrapper.CheckPdfReportStatus(pdfReportID.ReportID) - if err != nil || webErr != nil { - return errors.Wrapf(err, "%v", webErr) - } - logger.PrintfIfVerbose("PDF report status: %s", pollingResp.Status) - time.Sleep(delayValueForReport * time.Millisecond) - } - if pollingResp.Status != completedStatus { - return errors.Errorf("PDF generating failed - Current status: %s", pollingResp.Status) - } - - minioEnabled, _ := wrappers.GetSpecificFeatureFlag(featureFlagsWrapper, wrappers.MinioEnabled) - infoPathType := "" - if minioEnabled.Status { - infoPathType = pdfReportID.ReportID - } else { - infoPathType = pollingResp.URL - } - err = pdfWrapper.DownloadPdfReport(infoPathType, summaryRpt, minioEnabled.Status) - if err != nil { - return errors.Wrapf(err, "%s", "Failed downloading PDF report") - } - return nil -} - -func parsePDFOptions(pdfOptions string, enabledEngines []string, reportName string) (pdfOptionsSections, pdfOptionsEngines []string, err error) { - var pdfOptionsSectionsMap = map[string]string{ - "scansummary": sectionScanSummary, - "executivesummary": sectionExecutiveSummary, - "scanresults": sectionScanResults, - } - - var pdfOptionsEnginesMap = map[string]string{ - commonParams.ScaType: scaEngineLabel, - commonParams.SastType: sastEngineLabel, - commonParams.KicsType: kicsEngineLabel, - commonParams.IacType: kicsEngineLabel, - } - - pdfOptions = strings.ToLower(strings.ReplaceAll(pdfOptions, " ", "")) - options := strings.Split(strings.ReplaceAll(pdfOptions, "\n", ""), ",") - for _, s := range options { - if pdfOptionsEnginesMap[s] != "" { - pdfOptionsEngines = append(pdfOptionsEngines, pdfOptionsEnginesMap[s]) - } else if pdfOptionsSectionsMap[s] != "" { - pdfOptionsSections = append(pdfOptionsSections, pdfOptionsSectionsMap[s]) - } else { - return nil, nil, errors.Errorf("report option \"%s\" unavailable", s) - } - } - if pdfOptionsEngines == nil { - for _, engine := range enabledEngines { - if pdfOptionsEnginesMap[engine] != "" { - pdfOptionsEngines = append(pdfOptionsEngines, pdfOptionsEnginesMap[engine]) - } - } - } - - if reportName == reportNameImprovedScanReport { - pdfOptionsSections = translateReportSectionsForImproved(pdfOptionsSections) - } - - return pdfOptionsSections, pdfOptionsEngines, nil -} - -func translateReportSectionsForImproved(sections []string) []string { - var resultSections = make([]string, 0) - - var pdfOptionsSectionsImprovedTranslation = map[string][]string{ - sectionScanSummary: {"scan-information"}, - sectionExecutiveSummary: {"results-overview"}, - sectionScanResults: {"scan-results", "categories", "resolved-results", "vulnerability-details"}, - } - - for _, section := range sections { - if translatedSections := pdfOptionsSectionsImprovedTranslation[section]; translatedSections != nil { - resultSections = append(resultSections, translatedSections...) - } - } - - return resultSections -} - -func convertCxResultsToSarif(results *wrappers.ScanResultsCollection) *wrappers.SarifResultsCollection { - var sarif = new(wrappers.SarifResultsCollection) - sarif.Schema = "https://raw.githubusercontent.com/oasis-tcs/sarif-spec/master/Schemata/sarif-schema-2.1.0.json" - sarif.Version = "2.1.0" - sarif.Runs = []wrappers.SarifRun{} - sarif.Runs = append(sarif.Runs, createSarifRun(results)) - return sarif -} - -func convertCxResultToGlSastVulnerability(results *wrappers.ScanResultsCollection, glSast *wrappers.GlSastResultsCollection, summary *wrappers.ResultSummary) { - for _, result := range results.Results { - if strings.TrimSpace(result.Type) == commonParams.SastType { - glSast = parseGlSastVulnerability(result, glSast, summary) - } - } -} - -func convertCxResultToGlScaVulnerability(results *wrappers.ScanResultsCollection, glScaResult *wrappers.GlScaResultsCollection) { - for _, result := range results.Results { - if strings.TrimSpace(result.Type) == commonParams.ScaType { - glScaResult = parseGlscaVulnerability(result, glScaResult) - } - } -} - -func convertCxResultToGlScaFiles(results *wrappers.ScanResultsCollection, glScaResult *wrappers.GlScaResultsCollection) { - for _, result := range results.Results { - if strings.TrimSpace(result.Type) == commonParams.ScaType { - glScaResult = parseGlScaFiles(result, glScaResult) - } - } -} -func parseGlSastVulnerability(result *wrappers.ScanResult, glSast *wrappers.GlSastResultsCollection, summary *wrappers.ResultSummary) *wrappers.GlSastResultsCollection { - hostName := parseURI(summary.BaseURI) - - queryName := result.ScanResultData.QueryName - fileName := result.ScanResultData.Nodes[0].FileName - lineNumber := strconv.FormatUint(uint64(result.ScanResultData.Nodes[0].Line), 10) - startLine := result.ScanResultData.Nodes[0].Line - endLine := result.ScanResultData.Nodes[0].Line + result.ScanResultData.Nodes[0].Length - ID := fmt.Sprintf("%s:%s:%s", queryName, fileName, lineNumber) - category := fmt.Sprintf("%s-%s", wrappers.VendorName, result.Type) - message := fmt.Sprintf("%s@%s:%s", queryName, fileName, lineNumber) - QueryDescriptionLink := fmt.Sprintf("%s/results/%s/%s/sast/description/%s/%s", hostName, summary.ScanID, summary.ProjectID, result.VulnerabilityDetails.CweID, result.ScanResultData.QueryID) - - glSast.Vulnerabilities = append(glSast.Vulnerabilities, wrappers.GlVulnerabilities{ - ID: ID, - Category: category, - Name: queryName, - Message: message, - Description: result.Description + " \n" + QueryDescriptionLink, - CVE: ID, - Severity: cases.Title(language.English).String(result.Severity), - Confidence: cases.Title(language.English).String(result.Severity), - Solution: "", - - Scanner: wrappers.GlScanner{ - ID: category, - Name: category, - }, - Identifiers: []wrappers.Identifier{ - { - Type: "cxOneScan", - Name: "CxOne Scan", - URL: summary.BaseURI, - Value: result.ID, - }, - }, - Links: make([]string, 0), - Tracking: wrappers.Tracking{ - Type: "source", - Items: []wrappers.Item{ - { - Signatures: []wrappers.Signature{{Algorithm: result.Type + "-Algorithm ", Value: notAvailableValue}}, - File: fileName, - EndLine: endLine, - StartLine: startLine, - }, - }, - }, - Flags: make([]wrappers.Flag, 0), - Location: wrappers.Location{ - File: fileName, - StartLine: startLine, - EndLine: endLine, - }, - }) - return glSast -} -func parseGlscaVulnerability(result *wrappers.ScanResult, glDependencyResult *wrappers.GlScaResultsCollection) *wrappers.GlScaResultsCollection { - if result.ScanResultData.ScaPackageCollection != nil { - glDependencyResult.Vulnerabilities = append(glDependencyResult.Vulnerabilities, wrappers.GlScaDepVulnerabilities{ - ID: result.ID, - Name: result.VulnerabilityDetails.CveName, - Description: result.Description, - Severity: cases.Title(language.English).String(result.Severity), - Solution: result.ScanResultData.RecommendedVersion, - Identifiers: collectScaPackageData(result), - Links: collectScaPackageLinks(result), - TrackingDep: wrappers.TrackingDep{ - Items: collectScaPackageItemsDep(result), - }, - Flags: make([]string, 0), - LocationDep: wrappers.GlScaDepVulnerabilityLocation{ - File: parseGlDependencyLocation(result), - Dependency: wrappers.ScaDependencyLocation{ - Package: wrappers.PackageName{Name: result.ScanResultData.PackageIdentifier}, - ScaDependencyLocationVersion: "", - Direct: result.ScanResultData.ScaPackageCollection.IsDirectDependency, - ScaDependencyPath: result.ScanResultData.Line, - }, - }, - }) - } - return glDependencyResult -} -func parseGlDependencyLocation(result *wrappers.ScanResult) string { - var location string - if result != nil && result.ScanResultData.ScaPackageCollection != nil && result.ScanResultData.ScaPackageCollection.Locations != nil { - location = *result.ScanResultData.ScaPackageCollection.Locations[0] - } else { - location = "" - } - return location -} -func parseGlScaFiles(result *wrappers.ScanResult, glScaResult *wrappers.GlScaResultsCollection) *wrappers.GlScaResultsCollection { - if result.ScanResultData.ScaPackageCollection != nil && result.ScanResultData.ScaPackageCollection.Locations != nil { - glScaResult.ScaDependencyFiles = append(glScaResult.ScaDependencyFiles, wrappers.ScaDependencyFile{ - Path: *result.ScanResultData.ScaPackageCollection.Locations[0], - PackageManager: result.ScanResultData.ScaPackageCollection.ID, - Dependencies: collectScaFileLocations(result), - }) - } - return glScaResult -} -func collectScaFileLocations(result *wrappers.ScanResult) []wrappers.ScaDependencyLocation { - allScaIdentifierLocations := []wrappers.ScaDependencyLocation{} - for _, packageInfo := range result.ScanResultData.PackageData { - allScaIdentifierLocations = append(allScaIdentifierLocations, wrappers.ScaDependencyLocation{ - Package: wrappers.PackageName{ - Name: packageInfo.Type, - }, - ScaDependencyLocationVersion: packageInfo.URL, - Direct: true, - ScaDependencyPath: result.ScanResultData.Line, - }) - } - return allScaIdentifierLocations -} -func collectScaPackageItemsDep(result *wrappers.ScanResult) []wrappers.ItemDep { - allScaPackageItemDep := []wrappers.ItemDep{} - allScaPackageItemDep = append(allScaPackageItemDep, wrappers.ItemDep{ - Signature: []wrappers.SignatureDep{{Algorithm: "SCA-Algorithm ", Value: notAvailableValue}}, - File: result.VulnerabilityDetails.CveName, - EndLine: 0, - StartLine: 0, - }) - return allScaPackageItemDep -} -func collectScaPackageLinks(result *wrappers.ScanResult) []wrappers.LinkDep { - allScaPackageLinks := []wrappers.LinkDep{} - for _, packageInfo := range result.ScanResultData.PackageData { - allScaPackageLinks = append(allScaPackageLinks, wrappers.LinkDep{ - Name: packageInfo.Type, - URL: packageInfo.URL, - }) - } - return allScaPackageLinks -} -func collectScaPackageData(result *wrappers.ScanResult) []wrappers.IdentifierDep { - allIdentifierDep := []wrappers.IdentifierDep{} - for _, packageInfo := range result.ScanResultData.PackageData { - allIdentifierDep = append(allIdentifierDep, wrappers.IdentifierDep{ - Type: packageInfo.Type, - Value: packageInfo.URL, - Name: packageInfo.URL, - }) - } - return allIdentifierDep -} - -func convertCxResultsToSonar(results *wrappers.ScanResultsCollection) *wrappers.ScanResultsSonar { - var sonar = new(wrappers.ScanResultsSonar) - sonar.Issues, sonar.Rules = parseSonar(results) - return sonar -} - -func createSarifRun(results *wrappers.ScanResultsCollection) wrappers.SarifRun { - var sarifRun wrappers.SarifRun - sarifRun.Tool.Driver.Name = wrappers.SarifName - sarifRun.Tool.Driver.Version = wrappers.SarifVersion - sarifRun.Tool.Driver.InformationURI = wrappers.SarifInformationURI - sarifRun.Tool.Driver.Rules, sarifRun.Results = parseResults(results) - return sarifRun -} - -func parseResults(results *wrappers.ScanResultsCollection) ([]wrappers.SarifDriverRule, []wrappers.SarifScanResult) { - var sarifRules = make([]wrappers.SarifDriverRule, 0) - var sarifResults = make([]wrappers.SarifScanResult, 0) - if results != nil { - ruleIds := map[interface{}]bool{} - for _, result := range results.Results { - if rule := findRule(ruleIds, result); rule != nil { - sarifRules = append(sarifRules, *rule) - } - if sarifResult := findResult(result); sarifResult != nil { - sarifResults = append(sarifResults, sarifResult...) - } - } - } - return sarifRules, sarifResults -} - -func parseSonar(results *wrappers.ScanResultsCollection) ([]wrappers.SonarIssues, []wrappers.SonarRules) { - var sonarIssues []wrappers.SonarIssues - var sonarRules []wrappers.SonarRules - seenRuleIDs := make(map[string]bool) // Track already added rule IDs - - if results != nil { - for _, result := range results.Results { - var auxRules = initSonarRules(result) - var auxIssue = initSonarIssue(result) - - if !seenRuleIDs[auxRules.ID] { - sonarRules = append(sonarRules, auxRules) - seenRuleIDs[auxRules.ID] = true - } - - engineType := strings.TrimSpace(result.Type) - - if engineType == commonParams.SastType { - auxIssue.PrimaryLocation = parseSonarPrimaryLocation(result) - auxIssue.SecondaryLocations = parseSonarSecondaryLocations(result) - sonarIssues = append(sonarIssues, auxIssue) - } else if engineType == commonParams.KicsType { - auxIssue.PrimaryLocation = parseLocationKics(result) - sonarIssues = append(sonarIssues, auxIssue) - } else if engineType == commonParams.ScaType { - sonarIssuesByLocation := parseScaSonarLocations(result) - sonarIssues = append(sonarIssues, sonarIssuesByLocation...) - } else if wrappers.IsContainersEnabled && engineType == commonParams.ContainersType { - auxIssue.PrimaryLocation = parseContainersSonar(result) - sonarIssues = append(sonarIssues, auxIssue) - } else if strings.HasPrefix(engineType, commonParams.SscsType) { - sscsSonarIssue := parseSscsSonar(result, &auxIssue) - sonarIssues = append(sonarIssues, sscsSonarIssue) - } - } - } - return sonarIssues, sonarRules -} - -func parseContainersSonar(result *wrappers.ScanResult) wrappers.SonarLocation { - var auxLocation wrappers.SonarLocation - auxLocation.FilePath = result.ScanResultData.ImageFilePath - auxLocation.Message = html.UnescapeString(result.Description) - var textRange wrappers.SonarTextRange - textRange.StartColumn = 1 - textRange.EndColumn = 2 - textRange.StartLine = 1 - textRange.EndLine = 2 - auxLocation.TextRange = textRange - return auxLocation -} - -func parseSscsSonar(result *wrappers.ScanResult, sonarIssue *wrappers.SonarIssues) wrappers.SonarIssues { - sonarIssue.PrimaryLocation.FilePath = result.ScanResultData.Filename - - sonarIssue.PrimaryLocation.Message = html.UnescapeString(result.ScanResultData.Remediation) - var textRange wrappers.SonarTextRange - textRange.StartColumn = 1 - textRange.EndColumn = 2 - textRange.StartLine = result.ScanResultData.Line - sonarIssue.PrimaryLocation.TextRange = textRange - return *sonarIssue -} - -func initSonarIssue(result *wrappers.ScanResult) wrappers.SonarIssues { - var sonarIssue wrappers.SonarIssues - engineType := strings.TrimSpace(result.Type) - if engineType == commonParams.SastType { - sonarIssue.RuleID = result.ScanResultData.LanguageName + " - " + result.ScanResultData.QueryName - } else if engineType == commonParams.KicsType { - sonarIssue.RuleID = result.ScanResultData.QueryName - } else if engineType == commonParams.ScaType { - sonarIssue.RuleID = result.ID - } else if wrappers.IsContainersEnabled && engineType == commonParams.ContainersType { - sonarIssue.RuleID = result.ID - } else if strings.HasPrefix(engineType, commonParams.SscsType) { - sonarIssue.RuleID = result.ID - } - - sonarIssue.PrimaryLocation.Message = html.UnescapeString(result.Description) - sonarIssue.EffortMinutes = 0 - - return sonarIssue -} - -func initSonarRules(result *wrappers.ScanResult) wrappers.SonarRules { - var sonarRules wrappers.SonarRules - var sonarImpacts wrappers.SonarImpacts - - sonarImpacts.Severity = sonarSeverities[result.Severity] - sonarImpacts.SoftwareQuality = vulnerabilitySonar - - sonarRules.EngineID = result.Type - sonarRules.CleanCodeAttribute = cleanCodeAttribute - - engineType := strings.TrimSpace(result.Type) - if engineType == commonParams.SastType { - sonarRules.Name = result.ScanResultData.QueryName - sonarRules.Description = html.UnescapeString(result.Description) - sonarRules.ID = result.ScanResultData.LanguageName + " - " + result.ScanResultData.QueryName - } else if engineType == commonParams.KicsType { - sonarRules.Name = result.ScanResultData.QueryName - sonarRules.Description = html.UnescapeString(result.Description) - sonarRules.ID = result.ScanResultData.QueryName - } else if engineType == commonParams.ScaType { - sonarRules.Name = result.ScanResultData.PackageIdentifier - sonarRules.Description = html.UnescapeString(result.Description) - sonarRules.ID = result.ID - } else if wrappers.IsContainersEnabled && engineType == commonParams.ContainersType { - sonarRules.Name = result.ScanResultData.ImageTag - sonarRules.Description = html.UnescapeString(result.Description) - sonarRules.ID = result.ID - } else if strings.HasPrefix(engineType, commonParams.SscsType) { - sonarRules.Name = result.ScanResultData.RuleName - sonarRules.Description = html.UnescapeString(result.ScanResultData.RuleDescription) - sonarRules.ID = result.ID - } - - sonarRules.Impacts = []wrappers.SonarImpacts{sonarImpacts} - - return sonarRules -} - -func parseScaSonarLocations(result *wrappers.ScanResult) []wrappers.SonarIssues { - if result == nil || result.ScanResultData.ScaPackageCollection == nil || result.ScanResultData.ScaPackageCollection.Locations == nil { - return []wrappers.SonarIssues{} - } - - var issuesByLocation []wrappers.SonarIssues - - for _, location := range result.ScanResultData.ScaPackageCollection.Locations { - issueByLocation := initSonarIssue(result) - - var primaryLocation wrappers.SonarLocation - - primaryLocation.FilePath = *location - _, _, primaryLocation.Message = findRuleID(result) - - var textRange wrappers.SonarTextRange - textRange.StartColumn = 1 - textRange.EndColumn = 2 - textRange.StartLine = 1 - textRange.EndLine = 2 - - primaryLocation.TextRange = textRange - - issueByLocation.PrimaryLocation = primaryLocation - - issuesByLocation = append(issuesByLocation, issueByLocation) - } - - return issuesByLocation -} - -func parseLocationKics(results *wrappers.ScanResult) wrappers.SonarLocation { - var auxLocation wrappers.SonarLocation - auxLocation.FilePath = strings.TrimLeft(results.ScanResultData.Filename, "/") - auxLocation.Message = html.UnescapeString(results.ScanResultData.Value) - var auxTextRange wrappers.SonarTextRange - auxTextRange.StartLine = results.ScanResultData.Line - auxTextRange.StartColumn = 0 - auxTextRange.EndColumn = 1 - auxLocation.TextRange = auxTextRange - return auxLocation -} - -func parseSonarPrimaryLocation(results *wrappers.ScanResult) wrappers.SonarLocation { - var auxLocation wrappers.SonarLocation - // fill the details in the primary Location - if len(results.ScanResultData.Nodes) > 0 { - auxLocation.FilePath = strings.TrimLeft(results.ScanResultData.Nodes[0].FileName, "/") - auxLocation.Message = html.UnescapeString(strings.ReplaceAll(results.ScanResultData.QueryName, "_", " ")) - auxLocation.TextRange = parseSonarTextRange(results.ScanResultData.Nodes[0]) - } - return auxLocation -} - -func parseSonarSecondaryLocations(results *wrappers.ScanResult) []wrappers.SonarLocation { - var auxSecondaryLocations []wrappers.SonarLocation - // Traverse all the rest of the scan result nodes into secondary location of sonar - if len(results.ScanResultData.Nodes) >= 1 { - for _, node := range results.ScanResultData.Nodes[1:] { - var auxSecondaryLocation wrappers.SonarLocation - auxSecondaryLocation.FilePath = strings.TrimLeft(node.FileName, "/") - auxSecondaryLocation.Message = html.UnescapeString(strings.ReplaceAll(results.ScanResultData.QueryName, "_", " ")) - auxSecondaryLocation.TextRange = parseSonarTextRange(node) - auxSecondaryLocations = append(auxSecondaryLocations, auxSecondaryLocation) - } - } - return auxSecondaryLocations -} - -func parseSonarTextRange(results *wrappers.ScanResultNode) wrappers.SonarTextRange { - var auxTextRange wrappers.SonarTextRange - auxTextRange.StartLine = results.Line - startColumn := getSastStartColumn(results.Column) - - auxTextRange.StartColumn = startColumn - auxTextRange.EndColumn = startColumn + results.Length - - if auxTextRange.StartColumn == auxTextRange.EndColumn { - auxTextRange.EndColumn++ - } - - return auxTextRange -} - -func findRule(ruleIds map[interface{}]bool, result *wrappers.ScanResult) *wrappers.SarifDriverRule { - var sarifRule wrappers.SarifDriverRule - sarifRule.ID, sarifRule.Name, _ = findRuleID(result) - sarifRule.FullDescription = findFullDescription(result) - sarifRule.Help = findHelp(result) - sarifRule.HelpURI = findHelpURI(result) - sarifRule.Properties = findProperties(result) - - if !ruleIds[sarifRule.ID] { - ruleIds[sarifRule.ID] = true - return &sarifRule - } - - return nil -} - -func getSastStartColumn(column uint) uint { - if column == 0 { - return 0 - } - return column - 1 -} - -func findRuleID(result *wrappers.ScanResult) (ruleID, ruleName, shortMessage string) { - caser := cases.Title(language.English) - - if result.ScanResultData.QueryID == nil && result.ScanResultData.RuleID == nil { - return fmt.Sprintf("%s (%s)", result.ID, result.Type), - caser.String(strings.ToLower(strings.ReplaceAll(result.ID, "-", ""))), - html.UnescapeString(fmt.Sprintf("%s (%s)", result.ScanResultData.PackageIdentifier, result.ID)) - } - - if result.ScanResultData.RuleID != nil { - ruleName = strings.ReplaceAll(result.ScanResultData.RuleName, "_", " ") - return fmt.Sprintf("%s - %s (%s)", ruleName, *result.ScanResultData.RuleID, result.Type), - ruleName, - ruleName - } - - ruleName = strings.ReplaceAll(result.ScanResultData.QueryName, "_", " ") - return fmt.Sprintf("%v - %s (%s)", ruleName, result.ScanResultData.QueryID, result.Type), - ruleName, - ruleName -} - -func findFullDescription(result *wrappers.ScanResult) wrappers.SarifDescription { - var sarifDescription wrappers.SarifDescription - sarifDescription.Text = findDescriptionText(result) - return sarifDescription -} - -func findHelp(result *wrappers.ScanResult) wrappers.SarifHelp { - var sarifHelp wrappers.SarifHelp - sarifHelp.Text = findHelpText(result) - sarifHelp.Markdown = findHelpMarkdownText(result) - - return sarifHelp -} - -func findHelpURI(result *wrappers.ScanResult) string { - if strings.HasPrefix(result.Type, commonParams.SscsType) { - if result.ScanResultData.RemediationLink != "" { - return result.ScanResultData.RemediationLink - } - } - - return wrappers.SarifInformationURI -} - -func findDescriptionText(result *wrappers.ScanResult) string { - if result.Type == commonParams.KicsType { - return fmt.Sprintf( - "%s Value: %s Excepted value: %s", - result.Description, result.ScanResultData.Value, result.ScanResultData.ExpectedValue, - ) - } else if strings.HasPrefix(result.Type, commonParams.SscsType) { - return result.ScanResultData.RuleDescription - } - - return result.Description -} - -func findHelpText(result *wrappers.ScanResult) string { - if strings.HasPrefix(result.Type, commonParams.SscsType) { - return findHelpMarkdownText(result) - } - - return findDescriptionText(result) -} - -func findHelpMarkdownText(result *wrappers.ScanResult) string { - if result.Type == commonParams.KicsType { - return fmt.Sprintf( - "%s

Value: %s
Excepted value: %s", - result.Description, result.ScanResultData.Value, result.ScanResultData.ExpectedValue, - ) - } else if strings.HasPrefix(result.Type, commonParams.SscsType) { - return result.ScanResultData.Remediation - } - - return result.Description -} - -func findProperties(result *wrappers.ScanResult) wrappers.SarifProperties { - var sarifProperties wrappers.SarifProperties - sarifProperties.ID, sarifProperties.Name, _ = findRuleID(result) - sarifProperties.Description = findDescriptionText(result) - sarifProperties.SecuritySeverity = securities[result.Severity] - sarifProperties.Tags = []string{"security", "checkmarx", result.Type} - return sarifProperties -} - -func findSarifLevel(result *wrappers.ScanResult) string { - level := map[string]string{ - infoCx: infoLowSarif, - lowCx: infoLowSarif, - mediumCx: mediumSarif, - highCx: highSarif, - criticalCx: highSarif, - } - return level[result.Severity] -} - -func initSarifResult(result *wrappers.ScanResult) wrappers.SarifScanResult { - var scanResult wrappers.SarifScanResult - scanResult.RuleID, _, scanResult.Message.Text = findRuleID(result) - scanResult.Level = findSarifLevel(result) - scanResult.Locations = []wrappers.SarifLocation{} - - return scanResult -} - -func findResult(result *wrappers.ScanResult) []wrappers.SarifScanResult { - var scanResults []wrappers.SarifScanResult - - if len(result.ScanResultData.Nodes) > 0 { - scanResults = parseSarifResultSast(result, scanResults) - } else if result.Type == commonParams.KicsType { - scanResults = parseSarifResultKics(result, scanResults) - } else if result.Type == commonParams.ScaType { - scanResults = parseSarifResultsSca(result, scanResults) - } else if result.Type == commonParams.ContainersType && wrappers.IsContainersEnabled { - scanResults = parseSarifResultsContainers(result, scanResults) - } else if strings.HasPrefix(result.Type, commonParams.SscsType) { - scanResults = parseSarifResultsSscs(result, scanResults) - } - - if len(scanResults) > 0 { - return scanResults - } - return nil -} - -func parseSarifResultsContainers(result *wrappers.ScanResult, scanResults []wrappers.SarifScanResult) []wrappers.SarifScanResult { - var scanResult = initSarifResult(result) - var scanLocation wrappers.SarifLocation - - scanLocation.PhysicalLocation.ArtifactLocation.URI = result.ScanResultData.ImageFilePath - scanLocation.PhysicalLocation.Region = &wrappers.SarifRegion{} - scanLocation.PhysicalLocation.Region.StartLine = 1 - scanLocation.PhysicalLocation.Region.StartColumn = 1 - scanLocation.PhysicalLocation.Region.EndColumn = 2 - scanResult.Locations = append(scanResult.Locations, scanLocation) - - scanResults = append(scanResults, scanResult) - return scanResults -} - -func parseSarifResultsSca(result *wrappers.ScanResult, scanResults []wrappers.SarifScanResult) []wrappers.SarifScanResult { - if result == nil || result.ScanResultData.ScaPackageCollection == nil || result.ScanResultData.ScaPackageCollection.Locations == nil { - return scanResults - } - for _, location := range result.ScanResultData.ScaPackageCollection.Locations { - var scanResult = initSarifResult(result) - - var scanLocation wrappers.SarifLocation - scanLocation.PhysicalLocation.ArtifactLocation.URI = *location - scanLocation.PhysicalLocation.Region = &wrappers.SarifRegion{} - scanLocation.PhysicalLocation.Region.StartLine = 1 - scanLocation.PhysicalLocation.Region.StartColumn = 1 - scanLocation.PhysicalLocation.Region.EndColumn = 2 - scanResult.Locations = append(scanResult.Locations, scanLocation) - - scanResults = append(scanResults, scanResult) - } - return scanResults -} - -func parseSarifResultKics(result *wrappers.ScanResult, scanResults []wrappers.SarifScanResult) []wrappers.SarifScanResult { - var scanResult = initSarifResult(result) - var scanLocation wrappers.SarifLocation - - scanLocation.PhysicalLocation.ArtifactLocation.URI = strings.Replace( - result.ScanResultData.Filename, - "/", - "", - 1, - ) - scanLocation.PhysicalLocation.Region = &wrappers.SarifRegion{} - scanLocation.PhysicalLocation.Region.StartLine = result.ScanResultData.Line - scanLocation.PhysicalLocation.Region.StartColumn = 1 - scanLocation.PhysicalLocation.Region.EndColumn = 2 - scanResult.Locations = append(scanResult.Locations, scanLocation) - - scanResults = append(scanResults, scanResult) - return scanResults -} - -func parseSarifResultSast(result *wrappers.ScanResult, scanResults []wrappers.SarifScanResult) []wrappers.SarifScanResult { - if result == nil || result.ScanResultData.Nodes == nil { - return scanResults - } - var scanResult = initSarifResult(result) - - var allLocations []wrappers.SarifLocation - for _, node := range result.ScanResultData.Nodes { - var scanLocation wrappers.SarifLocation - if len(node.FileName) >= sarifNodeFileLength { - scanLocation.PhysicalLocation.ArtifactLocation.URI = node.FileName[1:] - if node.Line <= 0 { - continue - } - scanLocation.PhysicalLocation.Region = &wrappers.SarifRegion{} - scanLocation.PhysicalLocation.Region.StartLine = node.Line - column := node.Column - length := node.Length - scanLocation.PhysicalLocation.Region.StartColumn = column - scanLocation.PhysicalLocation.Region.EndColumn = column + length - - allLocations = append(allLocations, scanLocation) - } - } - - if len(allLocations) > 0 { - var threadFlowLocations []wrappers.SarifThreadFlowLocation - for _, loc := range allLocations { - threadFlowLocations = append(threadFlowLocations, wrappers.SarifThreadFlowLocation{Location: loc}) - } - scanResult.CodeFlows = []wrappers.SarifCodeFlow{ - { - ThreadFlows: []wrappers.SarifThreadFlow{ - { - Locations: threadFlowLocations, - }, - }, - }, - } - } - - scanResults = append(scanResults, scanResult) - return scanResults -} - -func parseSarifResultsSscs(result *wrappers.ScanResult, scanResults []wrappers.SarifScanResult) []wrappers.SarifScanResult { - var scanResult = initSarifResult(result) - scanResult.Message.Text = result.Description - - var scanLocation wrappers.SarifLocation - - trimOsSeparatorFromFileName(result) - if result.Type == commonParams.SCSScorecardType && result.ScanResultData.Filename == noFileForScorecardResultString { - scanLocation.PhysicalLocation.ArtifactLocation.URI = artifactLocationURIString - scanLocation.PhysicalLocation.ArtifactLocation.Description = &wrappers.SarifMessage{} - scanLocation.PhysicalLocation.ArtifactLocation.Description.Text = result.ScanResultData.Filename - } else { - scanLocation.PhysicalLocation.ArtifactLocation.URI = result.ScanResultData.Filename - } - - scanLocation.PhysicalLocation.Region = &wrappers.SarifRegion{} - scanLocation.PhysicalLocation.Region.StartLine = result.ScanResultData.Line - scanLocation.PhysicalLocation.Region.StartColumn = 1 - scanLocation.PhysicalLocation.Region.EndColumn = 2 - if result.ScanResultData.Snippet != "" { - scanLocation.PhysicalLocation.Region.Snippet = &wrappers.SarifSnippet{} - scanLocation.PhysicalLocation.Region.Snippet.Text = result.ScanResultData.Snippet - } - - scanResult.Locations = append(scanResult.Locations, scanLocation) - - var properties wrappers.SarifResultProperties - properties.Severity = result.Severity - properties.Validity = result.ScanResultData.Validity - properties.IsInSource = result.ScanResultData.IsInSource - properties.CommitURL = result.ScanResultData.CommitURL - scanResult.Properties = &properties - - scanResults = append(scanResults, scanResult) - return scanResults -} - -func convertNotAvailableNumberToZero(summary *wrappers.ResultSummary) { - if summary.KicsIssues == notAvailableNumber { - summary.KicsIssues = 0 - } else if summary.SastIssues == notAvailableNumber { - summary.SastIssues = 0 - } else if summary.ScaIssues == notAvailableNumber { - summary.ScaIssues = 0 - } else if wrappers.IsContainersEnabled && *summary.ContainersIssues == notAvailableNumber { - *summary.ContainersIssues = 0 - } -} - -func buildAuxiliaryScaMaps(resultsModel *wrappers.ScanResultsCollection, scaPackageModel *[]wrappers.ScaPackageCollection, - scaTypeModel *[]wrappers.ScaTypeCollection) (locationsByID map[string][]*string, typesByCVE map[string]wrappers.ScaTypeCollection) { - locationsByID = make(map[string][]*string) - typesByCVE = make(map[string]wrappers.ScaTypeCollection) - // Create map to be used to populate locations for each package path - for _, result := range resultsModel.Results { - if result.Type == commonParams.ScaType { - for i := range *scaPackageModel { - pkg := &(*scaPackageModel)[i] - locationsByID[pkg.ID] = pkg.Locations - } - for _, types := range *scaTypeModel { - identifier := fmt.Sprintf("%s:%s", types.ID, types.PackageID) - typesByCVE[identifier] = types - } - } - } - return locationsByID, typesByCVE -} - -func buildScaType(typesByCVE map[string]wrappers.ScaTypeCollection, result *wrappers.ScanResult) string { - identifier := buildVulnerabilityIdentifier(result) - types, ok := typesByCVE[identifier] - if ok && types.Type == "SupplyChain" { - return "Supply Chain" - } - return "Vulnerability" -} - -func buildScaState(typesByCVE map[string]wrappers.ScaTypeCollection, result *wrappers.ScanResult) string { - identifier := buildVulnerabilityIdentifier(result) - types, ok := typesByCVE[identifier] - if ok && types.IsIgnored { - return notExploitable - } - return result.State -} - -func buildVulnerabilityIdentifier(result *wrappers.ScanResult) string { - return fmt.Sprintf("%s:%s", result.ID, result.ScanResultData.PackageIdentifier) -} - -func addPackageInformation( - resultsModel *wrappers.ScanResultsCollection, - scaPackageModel *[]wrappers.ScaPackageCollection, - scaTypeModel *[]wrappers.ScaTypeCollection, -) *wrappers.ScanResultsCollection { - locationsByID, typesByCVE := buildAuxiliaryScaMaps(resultsModel, scaPackageModel, scaTypeModel) - scaPackageMap := buildScaPackageMap(*scaPackageModel) - - for _, result := range resultsModel.Results { - if result.Type == commonParams.ScaType { - processResult(result, locationsByID, typesByCVE, scaPackageMap) - } - } - - return resultsModel -} - -func processResult( - result *wrappers.ScanResult, - locationsByID map[string][]*string, - typesByCVE map[string]wrappers.ScaTypeCollection, - scaPackageMap map[string]wrappers.ScaPackageCollection, // Updated parameter -) { - const precision = 1 - - currentID := result.ScanResultData.PackageIdentifier - result.VulnerabilityDetails.CvssScore = util.RoundFloat(result.VulnerabilityDetails.CvssScore, precision) - result.ScaType = buildScaType(typesByCVE, result) - result.State = buildScaState(typesByCVE, result) - - updatePackages(result, scaPackageMap, locationsByID, currentID) -} - -func updatePackages( - result *wrappers.ScanResult, - scaPackageMap map[string]wrappers.ScaPackageCollection, - locationsByID map[string][]*string, - currentID string, -) { - packages, found := scaPackageMap[currentID] - if !found { - return - } - - updateDependencyPaths(packages.DependencyPathArray, locationsByID) - if !packages.SupportsQuickFix { - packages.SupportsQuickFix = hasQuickFix(packages.DependencyPathArray) - } - - if packages.IsDirectDependency { - packages.TypeOfDependency = directDependencyType - } else { - packages.TypeOfDependency = indirectDependencyType - } - - packages.FixLink = buildFixLink(result) - result.ScanResultData.ScaPackageCollection = &packages -} - -func hasQuickFix(dependencyPaths [][]wrappers.DependencyPath) bool { - for i := range dependencyPaths { - head := &dependencyPaths[i][0] - if head.SupportsQuickFix { - return true - } - } - return false -} - -func buildScaPackageMap(scaPackageModel []wrappers.ScaPackageCollection) map[string]wrappers.ScaPackageCollection { - scaPackageMap := make(map[string]wrappers.ScaPackageCollection) - for i := range scaPackageModel { - scaPackageMap[scaPackageModel[i].ID] = scaPackageModel[i] - } - return scaPackageMap -} - -func updateDependencyPaths(dependencyPaths [][]wrappers.DependencyPath, locationsByID map[string][]*string) { - for i := range dependencyPaths { - head := &dependencyPaths[i][0] - head.Locations = locationsByID[head.ID] - head.SupportsQuickFix = len(dependencyPaths[i]) == 1 - - for _, location := range locationsByID[head.ID] { - head.SupportsQuickFix = head.SupportsQuickFix && util.IsPackageFileSupported(*location) - } - } -} - -func buildFixLink(result *wrappers.ScanResult) string { - if result.ID != "" { - return fmt.Sprint(fixLinkPrefix, result.ID) - } - return "" -} - -func filterViolatedRules(policyModel wrappers.PolicyResponseModel) *wrappers.PolicyResponseModel { - i := 0 - for _, policy := range policyModel.Policies { - if len(policy.RulesViolated) > 0 { - policyModel.Policies[i] = policy - i++ - } - } - policyModel.Policies = policyModel.Policies[:i] - return &policyModel -} - -func trimOsSeparatorFromFileName(result *wrappers.ScanResult) { - if result.ScanResultData.Filename != "" { - result.ScanResultData.Filename = strings.TrimPrefix(result.ScanResultData.Filename, "/") - result.ScanResultData.Filename = strings.TrimPrefix(result.ScanResultData.Filename, "\\") - } -} - -// ScannerResponse is the per-scanner status info returned by the results exit-code subcommand. -type ScannerResponse struct { - ScanID string `json:"ScanID,omitempty"` - Name string `json:"Name,omitempty"` - Status string `json:"Status,omitempty"` - Details string `json:"Details,omitempty"` - ErrorCode string `json:"ErrorCode,omitempty"` -} - -func parseURI(summaryBaseURI string) (hostName string) { - parsedURL, err := url.Parse(summaryBaseURI) - if err != nil { - return "" - } - hostName = fmt.Sprintf("%s://%s", parsedURL.Scheme, parsedURL.Host) - - return hostName -} - -func printWarningIfIgnorePolicyOmiited() { - fmt.Printf("\n Warning: The --ignore-policy flag was not implemented because you don't have the required permission.\n Only users with 'override-policy-management' permission can use this flag. \n\n") -} - -func getFilterResultsForAPISecScanner(risksOverviewWrapper wrappers.RisksOverviewWrapper, scanID string, resultsParams map[string]string) (aPISecSeveritySummary *wrappers.APISecFilteredResult, err error) { - var apiSecRiskEntriesResult wrappers.APISecRiskEntriesResult - var errorModel *wrappers.WebError - - apiSecRiskEntriesResult, errorModel, err = risksOverviewWrapper.GetFilterResultForAPISecByScanID(scanID, resultsParams) - if err != nil { - return nil, errors.Wrapf(err, "%s", failedListingResults) - } - if errorModel != nil { - return nil, errors.Errorf("%s: CODE: %d, %s", failedListingResults, errorModel.Code, errorModel.Message) - } - if len(apiSecRiskEntriesResult.Entries) > 0 { - entries := apiSecRiskEntriesResult.Entries - severityCount := make(map[string]int) - originCount := make(map[string]int) - totalRecords := 0 - for i := range entries { - entry := &entries[i] - if !isExploitable(entry.State) { - continue - } - sev := strings.ToLower(entry.Severity) - severityCount[sev]++ - orig := strings.ToLower(entry.Origin) - originCount[orig]++ - totalRecords++ - } - var riskDistribution []wrappers.RiskDistributionEntry - if originCount[originCode] > 0 { - riskDistribution = append(riskDistribution, wrappers.RiskDistributionEntry{Origin: originCode, Total: originCount[originCode]}) - } - if originCount[originDocumentation] > 0 { - riskDistribution = append(riskDistribution, wrappers.RiskDistributionEntry{Origin: originDocumentation, Total: originCount[originDocumentation]}) - } - return &wrappers.APISecFilteredResult{ - SeverityCount: severityCount, - RiskDistribution: riskDistribution, - TotalRisksCount: totalRecords, - }, nil - } - return nil, nil -} +package commands + +import ( + "encoding/json" + "fmt" + "html" + "log" + "net/url" + "os" + "path/filepath" + "regexp" + "slices" + "strconv" + "strings" + "text/template" + "time" + + "github.com/MakeNowJust/heredoc" + "github.com/checkmarx/ast-cli/internal/commands/util" + "github.com/checkmarx/ast-cli/internal/commands/util/printer" + errorConstants "github.com/checkmarx/ast-cli/internal/constants/errors" + "github.com/checkmarx/ast-cli/internal/logger" + "github.com/checkmarx/ast-cli/internal/services" + "github.com/checkmarx/ast-cli/internal/wrappers" + "github.com/checkmarx/ast-cli/internal/wrappers/utils" + "golang.org/x/text/cases" + "golang.org/x/text/language" + + commonParams "github.com/checkmarx/ast-cli/internal/params" + + "github.com/pkg/errors" + "github.com/spf13/cobra" +) + +const ( + failedCreatingSummary = "Failed creating summary" + failedGettingScan = "Failed getting scan" + failedListingResults = "Failed listing results" + failedListingCodeBashing = "Failed codebashing link" + mediumLabel = "medium" + criticalLabel = "critical" + highLabel = "high" + lowLabel = "low" + infoLabel = "info" + sonarTypeLabel = "_sonar" + glSastTypeLabel = ".gl-sast-report" + glScaTypeLabel = ".gl-sca-report" + directoryPermission = 0700 + infoSonar = "INFO" + lowSonar = "LOW" + mediumSonar = "MEDIUM" + highSonar = "HIGH" + criticalSonar = "BLOCKER" + infoLowSarif = "note" + mediumSarif = "warning" + highSarif = "error" + vulnerabilitySonar = "SECURITY" + cleanCodeAttribute = "FORMATTED" + infoCx = "INFO" + lowCx = "LOW" + mediumCx = "MEDIUM" + highCx = "HIGH" + criticalCx = "CRITICAL" + tableResultsFormat = " | %-10s %6v %5d %6d %5d %4d %-9s |\n" + stringTableResultsFormat = " | %-10s %5s %6s %6s %5s %4s %5s |\n" + // TableTitleFormat is the printf format string for the scan results summary table title row. + TableTitleFormat = " | %-11s %4s %4s %6s %4s %4s %6s |\n" + twoNewLines = "\n\n" + tableLine = " --------------------------------------------------------------------- " + codeBashingKey = "cb-url" + failedGettingBfl = "Failed getting BFL" + notAvailableString = "-" + disabledString = "N/A" + scanFailedString = "Failed " + scanCanceledString = "Canceled" + scanSuccessString = "Completed" + scanPartialString = "Partial" + scsScanUnavailableString = "" + notAvailableNumber = -1 + scanFailedNumber = -2 + scanCanceledNumber = -3 + scanPartialNumber = -4 + defaultPaddingSize = -13 + scanPendingMessage = "Scan triggered in asynchronous mode or still running. Click more details to get the full status." + directDependencyType = "Direct Dependency" + indirectDependencyType = "Transitive Dependency" + startedStatus = "started" + requestedStatus = "requested" + completedStatus = "completed" + pdfToEmailFlagDescription = "Send the PDF report to the specified email address." + + " Use \",\" as the delimiter for multiple emails" + pdfOptionsFlagDescription = "Sections to generate PDF report. Available options: Iac-Security,Sast,Sca," + + defaultPdfOptionsDataSections + sbomReportFlagDescription = "Sections to generate SBOM report. Available options: CycloneDxJson,CycloneDxXml,SpdxJson" + reportNameScanReport = "scan-report" + reportNameImprovedScanReport = "improved-scan-report" + reportTypeEmail = "email" + defaultPdfOptionsDataSections = "ScanSummary,ExecutiveSummary,ScanResults" + exploitablePathFlagDescription = "Enable or disable exploitable path in scan. Available options: true,false" + scaLastScanTimeFlagDescription = "SCA last scan time. Available options: integer above 1" + projectPrivatePackageFlagDescription = "Enable or disable project private package. Available options: true,false" + scaPrivatePackageVersionFlagDescription = "SCA project private package version. Example: 0.1.1" + scaHideDevAndTestDepFlagDescription = "Filter SCA results to exclude dev and test dependencies" + policeManagementNoneStatus = "none" + apiDocumentationFlagDescription = "Swagger folder/file filter for API-Security scan. Example: ./swagger.json" + summaryCreatedAtLayout = "2006-01-02, 15:04:05" + glTimeFormat = "2006-01-02T15:04:05" + sarifNodeFileLength = 2 + fixLabel = "fix" + redundantLabel = "redundant" + delayValueForReport = 10 + fixLinkPrefix = "https://devhub.checkmarx.com/cve-details/" + // ScaDevAndTestExclusionParam is the SCA exclude-result-types value used to filter out dev and test dependencies. + ScaDevAndTestExclusionParam = "DEV_AND_TEST" + // ScaExcludeResultTypesParam is the SCA query parameter name used to exclude specific result types. + ScaExcludeResultTypesParam = "exclude-result-types" + noFileForScorecardResultString = "Issue Found in your GitHub repository" + // CliType identifies the report type used when generating reports through the CLI. + CliType = "cli" + artifactLocationURIString = "This alert has no associated file" + commandDocAnnotation = "command:doc" + showSubCommand = "show" + sectionScanSummary = "ScanSummary" + sectionExecutiveSummary = "ExecutiveSummary" + sectionScanResults = "ScanResults" + scaEngineLabel = "SCA" + sastEngineLabel = "SAST" + kicsEngineLabel = "KICS" + notAvailableValue = "NA" + originCode = "code" + originDocumentation = "documentation" + statusCompleted = "Completed" + statusPartial = "Partial" + statusFailed = "Failed" +) + +var ( + summaryFormats = []string{ + printer.FormatSummaryConsole, + printer.FormatSummary, + printer.FormatSummaryJSON, + printer.FormatPDF, + printer.FormatSummaryMarkdown, + printer.FormatSbom, + printer.FormatGLSast, + printer.FormatGLSca, + printer.FormatSonar, + } + + filterResultsListFlagUsage = fmt.Sprintf( + "Filter the list of results. Use ';' as the delimiter for arrays. Available filters are: %s", + strings.Join( + []string{ + commonParams.ScanIDQueryParam, + commonParams.LimitQueryParam, + commonParams.OffsetQueryParam, + commonParams.SortQueryParam, + commonParams.IncludeNodesQueryParam, + commonParams.NodeIDsQueryParam, + commonParams.QueryQueryParam, + commonParams.GroupQueryParam, + commonParams.StatusQueryParam, + commonParams.SeverityQueryParam, + commonParams.StateQueryParam, + }, ",", + ), + ) + + // Follows: over 9.0 is critical, 7.0 to 8.9 is high, 4.0 to 6.9 is medium and 3.9 or less is low. + securities = map[string]string{ + infoCx: "1.0", + lowCx: "2.0", + mediumCx: "4.0", + highCx: "7.0", + criticalCx: "9.0", + } + + // Match cx severity with sonar severity + sonarSeverities = map[string]string{ + infoCx: infoSonar, + lowCx: lowSonar, + mediumCx: mediumSonar, + highCx: highSonar, + criticalCx: criticalSonar, + } + + containerEngineUnsupportedAgents = []string{ + commonParams.JetbrainsAgent, commonParams.VSCodeAgent, commonParams.VisualStudioAgent, commonParams.EclipseAgent, + } + + sscsEngineToOverviewEngineMap = map[string]string{ + commonParams.SCSScorecardType: commonParams.SCSScorecardOverviewType, + commonParams.SCSSecretDetectionType: commonParams.SCSSecretDetectionOverviewType, + } +) + +// NewResultsCommand returns the `results` Cobra command tree with all subcommands attached. +func NewResultsCommand( + resultsWrapper wrappers.ResultsWrapper, + scanWrapper wrappers.ScansWrapper, + exportWrapper wrappers.ExportWrapper, + resultsPdfReportsWrapper wrappers.ResultsPdfWrapper, + resultsJSONReportsWrapper wrappers.ResultsJSONWrapper, + codeBashingWrapper wrappers.CodeBashingWrapper, + bflWrapper wrappers.BflWrapper, + risksOverviewWrapper wrappers.RisksOverviewWrapper, + riskManagementWrapper wrappers.RiskManagementWrapper, + scsScanOverviewWrapper wrappers.ScanOverviewWrapper, + policyWrapper wrappers.PolicyWrapper, + featureFlagsWrapper wrappers.FeatureFlagsWrapper, + jwtWrapper wrappers.JWTWrapper, +) *cobra.Command { + resultCmd := &cobra.Command{ + Use: "results", + Short: "Retrieve results", + Annotations: map[string]string{ + commandDocAnnotation: heredoc.Doc( + ` + https://checkmarx.com/resource/documents/en/34965-68640-results.html + `, + ), + }, + } + showResultCmd := resultShowSubCommand(resultsWrapper, scanWrapper, exportWrapper, resultsPdfReportsWrapper, resultsJSONReportsWrapper, + risksOverviewWrapper, scsScanOverviewWrapper, policyWrapper, featureFlagsWrapper, jwtWrapper) + codeBashingCmd := resultCodeBashing(codeBashingWrapper) + bflResultCmd := resultBflSubCommand(bflWrapper) + exitCodeSubcommand := exitCodeSubCommand(scanWrapper) + riskManagementSubCommand := riskManagementSubCommand(riskManagementWrapper, featureFlagsWrapper) + resultCmd.AddCommand( + showResultCmd, bflResultCmd, codeBashingCmd, exitCodeSubcommand, riskManagementSubCommand, + ) + return resultCmd +} + +func exitCodeSubCommand(scanWrapper wrappers.ScansWrapper) *cobra.Command { + exitCodeCmd := &cobra.Command{ + Use: "exit-code", + Short: "Get exit code and details of a scan", + Long: "The exit-code command enables you to get the exit code and failure details of a requested scan in Checkmarx One", + Example: heredoc.Doc( + ` + $ cx results exit-code --scan-id --scan-types + `, + ), + RunE: runGetExitCodeCommand(scanWrapper), + } + + exitCodeCmd.PersistentFlags().String(commonParams.ScanIDFlag, "", "Scan ID") + exitCodeCmd.PersistentFlags().String(commonParams.ScanTypes, "", "Scan types") + + return exitCodeCmd +} +func riskManagementSubCommand(riskManagement wrappers.RiskManagementWrapper, featureFlagsWrapper wrappers.FeatureFlagsWrapper, +) *cobra.Command { + riskManagementCmd := &cobra.Command{ + Use: "risk-management", + Short: "Show risk-management results of a project", + Long: "The risk-management command displays risk management results for a specific project in Checkmarx One", + Example: heredoc.Doc( + ` + $ cx results risk-management --project-id --scan-id --limit (1-50, default: 50) + `, + ), + RunE: runRiskManagementCommand(riskManagement, featureFlagsWrapper), + } + + riskManagementCmd.PersistentFlags().String(commonParams.ProjectIDFlag, "", "Project ID") + riskManagementCmd.PersistentFlags().String(commonParams.ScanIDFlag, "", "Scan ID") + riskManagementCmd.PersistentFlags().Int(commonParams.LimitFlag, -1, "Limit") + + addFormatFlag(riskManagementCmd, printer.FormatJSON, printer.FormatTable, printer.FormatList) + + return riskManagementCmd +} + +func resultShowSubCommand( + resultsWrapper wrappers.ResultsWrapper, + scanWrapper wrappers.ScansWrapper, + exportWrapper wrappers.ExportWrapper, + resultsPdfReportsWrapper wrappers.ResultsPdfWrapper, + resultsJSONReportsWrapper wrappers.ResultsJSONWrapper, + risksOverviewWrapper wrappers.RisksOverviewWrapper, + scsScanOverviewWrapper wrappers.ScanOverviewWrapper, + policyWrapper wrappers.PolicyWrapper, + featureFlagsWrapper wrappers.FeatureFlagsWrapper, + jwtWrapper wrappers.JWTWrapper, +) *cobra.Command { + resultShowCmd := &cobra.Command{ + Use: showSubCommand, + Short: "Show results of a scan", + Long: "The show command enables the ability to show results about a requested scan in Checkmarx One", + Example: heredoc.Doc( + ` + $ cx results show --scan-id + `, + ), + RunE: runGetResultCommand(resultsWrapper, scanWrapper, exportWrapper, resultsPdfReportsWrapper, resultsJSONReportsWrapper, risksOverviewWrapper, scsScanOverviewWrapper, policyWrapper, featureFlagsWrapper, jwtWrapper), + } + addScanIDFlag(resultShowCmd, "ID to report on") + addResultFormatFlag( + resultShowCmd, + printer.FormatJSON, + printer.FormatJSONv2, + printer.FormatSummary, + printer.FormatSummaryConsole, + printer.FormatSarif, + printer.FormatSummaryJSON, + printer.FormatSbom, + printer.FormatPDF, + printer.FormatSummaryMarkdown, + printer.FormatGLSast, + printer.FormatGLSca, + printer.FormatSonar, + ) + resultShowCmd.PersistentFlags().String(commonParams.ReportFormatPdfToEmailFlag, "", pdfToEmailFlagDescription) + resultShowCmd.PersistentFlags().String(commonParams.ReportSbomFormatFlag, services.DefaultSbomOption, sbomReportFlagDescription) + resultShowCmd.PersistentFlags().String(commonParams.ReportFormatPdfOptionsFlag, defaultPdfOptionsDataSections, pdfOptionsFlagDescription) + resultShowCmd.PersistentFlags().String(commonParams.TargetFlag, "cx_result", "Output file") + resultShowCmd.PersistentFlags().String(commonParams.TargetPathFlag, ".", "Output Path") + resultShowCmd.PersistentFlags().StringSlice(commonParams.FilterFlag, []string{}, filterResultsListFlagUsage) + + resultShowCmd.PersistentFlags().IntP( + commonParams.WaitDelayFlag, + "", + commonParams.WaitDelayDefault, + "Polling wait time in seconds", + ) + resultShowCmd.PersistentFlags().Int( + commonParams.PolicyTimeoutFlag, + commonParams.ResultPolicyDefaultTimeout, + "Cancel the policy evaluation and fail after the timeout in minutes", + ) + resultShowCmd.PersistentFlags().Bool(commonParams.IgnorePolicyFlag, false, "Skip policy evaluation. Requires override-policy-management permission.") + resultShowCmd.PersistentFlags().Bool(commonParams.SastRedundancyFlag, false, + "Populate SAST results 'data.redundancy' with values '"+fixLabel+"' (to fix) or '"+redundantLabel+"' (no need to fix)") + resultShowCmd.PersistentFlags().Bool(commonParams.ScaHideDevAndTestDepFlag, false, scaHideDevAndTestDepFlagDescription) + + return resultShowCmd +} + +func resultBflSubCommand(bflWrapper wrappers.BflWrapper) *cobra.Command { + resultBflCmd := &cobra.Command{ + Use: "bfl", + Short: "Show best fix location for a query id within the scan result", + Long: "The bfl command enables the ability to show best fix location for a querid within the scan result", + Example: heredoc.Doc( + ` + $ cx results bfl --scan-id --query-id + `, + ), + RunE: runGetBestFixLocationCommand(bflWrapper), + } + addScanIDFlag(resultBflCmd, "ID to report on") + addQueryIDFlag(resultBflCmd, "Query Id from the result") + addFormatFlag(resultBflCmd, printer.FormatList, printer.FormatJSON) + + markFlagAsRequired(resultBflCmd, commonParams.ScanIDFlag) + markFlagAsRequired(resultBflCmd, commonParams.QueryIDFlag) + + return resultBflCmd +} + +func runGetExitCodeCommand(scanWrapper wrappers.ScansWrapper) func(cmd *cobra.Command, args []string) error { + return func(cmd *cobra.Command, args []string) error { + scanID, _ := cmd.Flags().GetString(commonParams.ScanIDFlag) + if scanID == "" { + return errors.New(errorConstants.ScanIDRequired) + } + scanTypesFlagValue, _ := cmd.Flags().GetString(commonParams.ScanTypes) + results, err := GetScannerResults(scanWrapper, scanID, scanTypesFlagValue) + if err != nil { + return err + } + + if len(results) == 0 { + return nil + } + + return printer.Print(cmd.OutOrStdout(), results, printer.FormatIndentedJSON) + } +} + +func runRiskManagementCommand(riskManagement wrappers.RiskManagementWrapper, featureFlagsWrapper wrappers.FeatureFlagsWrapper, +) func(cmd *cobra.Command, args []string) error { + return func(cmd *cobra.Command, args []string) error { + projectID, _ := cmd.Flags().GetString(commonParams.ProjectIDFlag) + scanID, _ := cmd.Flags().GetString(commonParams.ScanIDFlag) + + limit, _ := cmd.Flags().GetInt(commonParams.LimitFlag) + + flagResponse, _ := wrappers.GetSpecificFeatureFlag(featureFlagsWrapper, wrappers.RiskManagementEnabled) + ASPMEnabled := flagResponse.Status + if !ASPMEnabled { + return errors.Errorf("%s", "Risk management results are currently unavailable for your tenant.") + } + results, err := getRiskManagementResults(riskManagement, projectID, scanID) + if err != nil { + return err + } + results.Results = utils.LimitSlice(results.Results, limit) + err = printByFormat(cmd, results) + return err + } +} + +func getRiskManagementResults(riskManagement wrappers.RiskManagementWrapper, projectID, scanID string) (*wrappers.ASPMResult, error) { + ASPMResult, errorModel, err := riskManagement.GetTopVulnerabilitiesByProjectID(projectID, scanID) + if err != nil { + return nil, errors.Wrapf(err, "%s", failedListingResults) + } + if errorModel != nil { + return nil, errors.Errorf("%s: CODE: %d, %s", failedListingResults, errorModel.Code, errorModel.Message) + } + return ASPMResult, nil +} + +// GetScannerResults returns per-scanner status entries for the given scan, optionally filtered by scan types. +func GetScannerResults(scanWrapper wrappers.ScansWrapper, scanID, scanTypesFlagValue string) ([]ScannerResponse, error) { + scanResponseModel, errorModel, err := scanWrapper.GetByID(scanID) + if err != nil { + return nil, errors.Wrapf(err, "%s", failedGetting) + } + if errorModel != nil { + return nil, errors.Errorf("%s: CODE: %d, %s", failedGettingScan, errorModel.Code, errorModel.Message) + } + results := getScannerResponse(scanTypesFlagValue, scanResponseModel) + return results, nil +} + +func getScannerResponse(scanTypesFlagValue string, scanResponseModel *wrappers.ScanResponseModel) []ScannerResponse { + var results []ScannerResponse + + if scanResponseModel.Status == wrappers.ScanCanceled || + scanResponseModel.Status == wrappers.ScanRunning || + scanResponseModel.Status == wrappers.ScanQueued || + scanResponseModel.Status == wrappers.ScanPartial || + scanResponseModel.Status == wrappers.ScanCompleted { + result := ScannerResponse{ + ScanID: scanResponseModel.ID, + Status: string(scanResponseModel.Status), + } + results = append(results, result) + return results + } + + if scanTypesFlagValue == "" { + results = createAllFailedScannersResponse(scanResponseModel) + } else { + scanTypes := sanitizeScannerNames(scanTypesFlagValue) + results = createRequestedScannersResponse(scanTypes, scanResponseModel) + } + + return results +} + +func createRequestedScannersResponse(scanTypes map[string]string, scanResponseModel *wrappers.ScanResponseModel) []ScannerResponse { + var results []ScannerResponse + for i := range scanResponseModel.StatusDetails { + if _, ok := scanTypes[scanResponseModel.StatusDetails[i].Name]; ok { + results = append(results, createScannerResponse(&scanResponseModel.StatusDetails[i])) + } + } + return results +} + +func createAllFailedScannersResponse(scanResponseModel *wrappers.ScanResponseModel) []ScannerResponse { + var results []ScannerResponse + for i := range scanResponseModel.StatusDetails { + if scanResponseModel.StatusDetails[i].Status == wrappers.ScanFailed { + results = append(results, createScannerResponse(&scanResponseModel.StatusDetails[i])) + } + } + return results +} + +func sanitizeScannerNames(scanTypes string) map[string]string { + scanTypeSlice := strings.Split(scanTypes, ",") + scanTypeMap := make(map[string]string) + for i := range scanTypeSlice { + lowered := strings.ToLower(scanTypeSlice[i]) + scanTypeMap[lowered] = lowered + } + + return scanTypeMap +} + +func createScannerResponse(statusDetails *wrappers.StatusInfo) ScannerResponse { + return ScannerResponse{ + Name: statusDetails.Name, + Status: statusDetails.Status, + Details: statusDetails.Details, + ErrorCode: stringifyErrorCode(statusDetails.ErrorCode), + } +} + +func stringifyErrorCode(errorCode int) string { + if errorCode == 0 { + return "" + } + return strconv.Itoa(errorCode) +} + +func runGetBestFixLocationCommand(bflWrapper wrappers.BflWrapper) func(cmd *cobra.Command, args []string) error { + return func(cmd *cobra.Command, args []string) error { + var bflResponseModel *wrappers.BFLResponseModel + var errorModel *wrappers.WebError + var err error + + scanID, _ := cmd.Flags().GetString(commonParams.ScanIDFlag) + queryID, _ := cmd.Flags().GetString(commonParams.QueryIDFlag) + + scanIds := strings.Split(scanID, ",") + if len(scanIds) > 1 { + return errors.Errorf("%s", "Multiple scan-ids are not allowed.") + } + queryIds := strings.Split(queryID, ",") + if len(queryIds) > 1 { + return errors.Errorf("%s", "Multiple query-ids are not allowed.") + } + + params := make(map[string]string) + params[commonParams.ScanIDQueryParam] = scanID + params[commonParams.QueryIDQueryParam] = queryID + + bflResponseModel, errorModel, err = bflWrapper.GetBflByScanIDAndQueryID(params) + + if err != nil { + return errors.Wrapf(err, "%s", failedGettingBfl) + } + + // Checking the response + if errorModel != nil { + return errors.Errorf("%s: CODE: %d, %s", failedGettingBfl, errorModel.Code, errorModel.Message) + } else if bflResponseModel != nil { + err = printByFormat(cmd, toBflView(*bflResponseModel)) + if err != nil { + return err + } + } + + return nil + } +} + +func toBflView(bflResponseModel wrappers.BFLResponseModel) []wrappers.ScanResultNode { + if (bflResponseModel.TotalCount) > 0 { + views := make([]wrappers.ScanResultNode, bflResponseModel.TotalCount) + + for i := 0; i < bflResponseModel.TotalCount; i++ { + views[i] = wrappers.ScanResultNode{ + Name: bflResponseModel.Trees[i].BFL.Name, + FileName: bflResponseModel.Trees[i].BFL.FileName, + FullName: bflResponseModel.Trees[i].BFL.FullName, + Column: bflResponseModel.Trees[i].BFL.Column, + Length: bflResponseModel.Trees[i].BFL.Length, + Line: bflResponseModel.Trees[i].BFL.Line, + MethodLine: bflResponseModel.Trees[i].BFL.MethodLine, + Method: bflResponseModel.Trees[i].BFL.Method, + DomType: bflResponseModel.Trees[i].BFL.DomType, + } + } + return views + } + views := make([]wrappers.ScanResultNode, 0) + return views +} + +func resultCodeBashing(codeBashingWrapper wrappers.CodeBashingWrapper) *cobra.Command { + // Create a codeBashing wrapper + resultCmd := &cobra.Command{ + Use: "codebashing", + Short: "Get codebashing lesson link", + Long: "The codebashing command enables the ability to retrieve the link about a specific vulnerability", + Example: heredoc.Doc( + ` + $ cx results codebashing --language --vulnerability-type --cwe-id --format + `, + ), + RunE: runGetCodeBashingCommand(codeBashingWrapper), + } + resultCmd.PersistentFlags().String(commonParams.LanguageFlag, "", "Language of the vulnerability") + err := resultCmd.MarkPersistentFlagRequired(commonParams.LanguageFlag) + if err != nil { + log.Fatal(err) + } + resultCmd.PersistentFlags().String(commonParams.VulnerabilityTypeFlag, "", "Vulnerability type") + err = resultCmd.MarkPersistentFlagRequired(commonParams.VulnerabilityTypeFlag) + if err != nil { + log.Fatal(err) + } + resultCmd.PersistentFlags().String(commonParams.CweIDFlag, "", "CWE ID for the vulnerability") + err = resultCmd.MarkPersistentFlagRequired(commonParams.CweIDFlag) + if err != nil { + log.Fatal(err) + } + addFormatFlag(resultCmd, printer.FormatJSON, printer.FormatTable, printer.FormatList) + return resultCmd +} + +func convertScanToResultsSummary(scanInfo *wrappers.ScanResponseModel, resultsWrapper wrappers.ResultsWrapper) (*wrappers.ResultSummary, error) { + if scanInfo == nil { + return nil, errors.New(failedCreatingSummary) + } + + scanInfo.ReplaceMicroEnginesWithSCS() + + sastIssues := 0 + scaIssues := 0 + kicsIssues := 0 + var containersIssues *int + var scsIssues *int + enginesStatusCode := map[string]int{ + commonParams.SastType: 0, + commonParams.ScaType: 0, + commonParams.KicsType: 0, + commonParams.APISecType: 0, + commonParams.ScsType: 0, + commonParams.ContainersType: 0, + } + if wrappers.IsContainersEnabled { + containersIssues = new(int) + *containersIssues = 0 + enginesStatusCode[commonParams.ContainersType] = 0 + } + + scsIssues = new(int) + *scsIssues = 0 + enginesStatusCode[commonParams.ScsType] = 0 + + if len(scanInfo.StatusDetails) > 0 { + applyScanStatusDetails(scanInfo.StatusDetails, &sastIssues, &scaIssues, &kicsIssues, scsIssues, containersIssues, enginesStatusCode) + } + summary := &wrappers.ResultSummary{ + ScanID: scanInfo.ID, + Status: string(scanInfo.Status), + CreatedAt: scanInfo.CreatedAt.Format("2006-01-02, 15:04:05"), + ProjectID: scanInfo.ProjectID, + RiskStyle: "", + RiskMsg: "", + CriticalIssues: 0, + HighIssues: 0, + MediumIssues: 0, + LowIssues: 0, + InfoIssues: 0, + SastIssues: sastIssues, + KicsIssues: kicsIssues, + ScaIssues: scaIssues, + ScsIssues: scsIssues, + ContainersIssues: containersIssues, + Tags: scanInfo.Tags, + ProjectName: scanInfo.ProjectName, + BranchName: scanInfo.Branch, + EnginesEnabled: scanInfo.Engines, + EnginesResult: map[string]*wrappers.EngineResultSummary{ + commonParams.SastType: {StatusCode: enginesStatusCode[commonParams.SastType]}, + commonParams.ScaType: {StatusCode: enginesStatusCode[commonParams.ScaType]}, + commonParams.KicsType: {StatusCode: enginesStatusCode[commonParams.KicsType]}, + commonParams.APISecType: {StatusCode: enginesStatusCode[commonParams.APISecType]}, + commonParams.ContainersType: {StatusCode: enginesStatusCode[commonParams.ContainersType]}, + }, + } + if wrappers.IsContainersEnabled { + summary.EnginesResult[commonParams.ContainersType] = &wrappers.EngineResultSummary{StatusCode: enginesStatusCode[commonParams.ContainersType]} + } + + summary.EnginesResult[commonParams.ScsType] = &wrappers.EngineResultSummary{StatusCode: enginesStatusCode[commonParams.ScsType]} + + baseURI, err := resultsWrapper.GetResultsURL(summary.ProjectID) + if err != nil { + return nil, err + } + + summary.BaseURI = baseURI + summary.BaseURI = generateScanSummaryURL(summary) + if isScanPending(summary.Status) { + summary.ScanInfoMessage = scanPendingMessage + } + + return summary, nil +} + +func applyScanStatusDetails( + statusDetails []wrappers.StatusInfo, + sastIssues, scaIssues, kicsIssues *int, + scsIssues, containersIssues *int, + enginesStatusCode map[string]int, +) { + for _, statusDetailItem := range statusDetails { + if statusDetailItem.Status == wrappers.ScanFailed || statusDetailItem.Status == wrappers.ScanCanceled { + markEngineNotAvailable(statusDetailItem.Name, sastIssues, scaIssues, kicsIssues, scsIssues, containersIssues) + } + switch statusDetailItem.Status { + case wrappers.ScanFailed: + handleScanStatus(statusDetailItem, enginesStatusCode, scanFailedNumber) + case wrappers.ScanCanceled: + handleScanStatus(statusDetailItem, enginesStatusCode, scanCanceledNumber) + } + } +} + +func markEngineNotAvailable(name string, sastIssues, scaIssues, kicsIssues, scsIssues, containersIssues *int) { + switch name { + case commonParams.SastType: + *sastIssues = notAvailableNumber + case commonParams.ScaType: + *scaIssues = notAvailableNumber + case commonParams.KicsType: + *kicsIssues = notAvailableNumber + case commonParams.ScsType: + *scsIssues = notAvailableNumber + case commonParams.ContainersType: + if wrappers.IsContainersEnabled { + *containersIssues = notAvailableNumber + } + } +} + +func handleScanStatus(statusDetailItem wrappers.StatusInfo, targetTypes map[string]int, statusCode int) { + if _, ok := targetTypes[statusDetailItem.Name]; ok { + targetTypes[statusDetailItem.Name] = statusCode + } +} + +func summaryReport( + summary *wrappers.ResultSummary, + policies *wrappers.PolicyResponseModel, + risksOverviewWrapper wrappers.RisksOverviewWrapper, + scsScanOverviewWrapper wrappers.ScanOverviewWrapper, + featureFlagsWrapper wrappers.FeatureFlagsWrapper, + results *wrappers.ScanResultsCollection, + resultsParams map[string]string, +) (*wrappers.ResultSummary, error) { + if summary.HasAPISecurity() { + apiSecFilterRisks, err := getFilterResultsForAPISecScanner(risksOverviewWrapper, summary.ScanID, resultsParams) + if err != nil { + return nil, err + } + if apiSecFilterRisks != nil { + summary.APISecurity = *apiSecFilterRisks + } + apiSecRisks, err := getResultsForAPISecScanner(risksOverviewWrapper, summary.ScanID) + if err != nil { + return nil, err + } + if apiSecRisks != nil { + summary.APISecurity.APICount = apiSecRisks.APICount + } + } + if summary.HasSCS() { + // Getting the base SCS overview. Results counts are overwritten in enhanceWithScanSummary->countResult + SCSOverview, err := getScanOverviewForSCSScanner(scsScanOverviewWrapper, summary.ScanID) + if err != nil { + return nil, err + } + summary.SCSOverview = SCSOverview + } + + if policies != nil { + summary.Policies = filterViolatedRules(*policies) + } + + enhanceWithScanSummary(summary, results, featureFlagsWrapper) + + setNotAvailableNumberIfZero(summary, &summary.SastIssues, commonParams.SastType) + setNotAvailableNumberIfZero(summary, &summary.ScaIssues, commonParams.ScaType) + setNotAvailableNumberIfZero(summary, &summary.KicsIssues, commonParams.KicsType) + setNotAvailableNumberIfZero(summary, summary.ScsIssues, commonParams.ScsType) + + if wrappers.IsContainersEnabled { + setNotAvailableNumberIfZero(summary, summary.ContainersIssues, commonParams.ContainersType) + } + + setRiskMsgAndStyle(summary) + setNotAvailableEnginesStatusCode(summary) + + return summary, nil +} + +func setNotAvailableEnginesStatusCode(summary *wrappers.ResultSummary) { + for engineName, engineResult := range summary.EnginesResult { + setNotAvailableNumberIfZero(summary, &engineResult.StatusCode, engineName) + } +} + +func setRiskMsgAndStyle(summary *wrappers.ResultSummary) { + if summary.CriticalIssues > 0 { + summary.RiskStyle = criticalLabel + summary.RiskMsg = "Critical Risk" + } else if summary.HighIssues > 0 { + summary.RiskStyle = highLabel + summary.RiskMsg = "High Risk" + } else if summary.MediumIssues > 0 { + summary.RiskStyle = mediumLabel + summary.RiskMsg = "Medium Risk" + } else if summary.LowIssues > 0 { + summary.RiskStyle = lowLabel + summary.RiskMsg = "Low Risk" + } else if summary.TotalIssues == 0 { + summary.RiskMsg = "No Risk" + } +} + +func setNotAvailableNumberIfZero(summary *wrappers.ResultSummary, counter *int, engineType string) { + if *counter == 0 && !contains(summary.EnginesEnabled, engineType) { + *counter = notAvailableNumber + } +} + +func enhanceWithScanSummary(summary *wrappers.ResultSummary, results *wrappers.ScanResultsCollection, featureFlagsWrapper wrappers.FeatureFlagsWrapper) { + for _, result := range results.Results { + countResult(summary, result) + } + // Set critical count for a specific engine if critical is disabled + flagResponse, _ := wrappers.GetSpecificFeatureFlag(featureFlagsWrapper, wrappers.CVSSV3Enabled) + criticalEnabled := flagResponse.Status + if summary.HasAPISecurity() { + summary.EnginesResult[commonParams.APISecType].Low = summary.APISecurity.SeverityCount["low"] + summary.EnginesResult[commonParams.APISecType].Medium = summary.APISecurity.SeverityCount["medium"] + summary.EnginesResult[commonParams.APISecType].High = summary.APISecurity.SeverityCount["high"] + if !criticalEnabled { + summary.EnginesResult[commonParams.APISecType].Critical = notAvailableNumber + } else { + summary.EnginesResult[commonParams.APISecType].Critical = summary.APISecurity.SeverityCount["critical"] + } + } + + summary.TotalIssues = summary.SastIssues + summary.ScaIssues + summary.KicsIssues + summary.GetAPISecurityDocumentationTotal() + + if summary.HasSCS() { + // Special case for SCS where status is partial if any microengines failed + if summary.SCSOverview.Status == scanPartialString { + summary.EnginesResult[commonParams.ScsType].StatusCode = scanPartialNumber + } + if !criticalEnabled { + summary.EnginesResult[commonParams.ScsType].Critical = notAvailableNumber + removeCriticalFromSCSOverview(summary) + } + if *summary.ScsIssues >= 0 { + summary.TotalIssues += *summary.ScsIssues + } + } + if wrappers.IsContainersEnabled { + if *summary.ContainersIssues >= 0 { + summary.TotalIssues += *summary.ContainersIssues + } + } + if !criticalEnabled { + summary.EnginesResult[commonParams.SastType].Critical = notAvailableNumber + summary.EnginesResult[commonParams.KicsType].Critical = notAvailableNumber + summary.EnginesResult[commonParams.ScaType].Critical = notAvailableNumber + summary.EnginesResult[commonParams.ContainersType].Critical = notAvailableNumber + } +} + +func removeCriticalFromSCSOverview(summary *wrappers.ResultSummary) { + criticalCount := summary.SCSOverview.RiskSummary[criticalLabel] + summary.SCSOverview.TotalRisksCount -= criticalCount + summary.SCSOverview.RiskSummary[criticalLabel] = notAvailableNumber + for _, microEngineOverview := range summary.SCSOverview.MicroEngineOverviews { + if microEngineOverview.RiskSummary != nil && microEngineOverview.RiskSummary[criticalLabel] != nil { + engineCriticalCount := microEngineOverview.RiskSummary[criticalLabel] + microEngineOverview.TotalRisks -= engineCriticalCount.(int) + microEngineOverview.RiskSummary[criticalLabel] = disabledString + } + } +} + +func writeHTMLSummary(targetFile string, summary *wrappers.ResultSummary) error { + log.Println("Creating Summary Report: ", targetFile) + summaryTemp, err := template.New("summaryTemplate").Parse(wrappers.SummaryTemplate(isScanPending(summary.Status))) + if err == nil { + f, err := os.Create(targetFile) + if err == nil { + _ = summaryTemp.ExecuteTemplate(f, "SummaryTemplate", summary) + _ = f.Close() + } + return err + } + return nil +} +func writeMarkdownSummary(targetFile string, data *wrappers.ResultSummary) error { + log.Println("Creating Markdown Summary Report: ", targetFile) + tmpl, err := template.New(printer.FormatSummaryMarkdown).Parse(wrappers.SummaryMarkdownTemplate(isScanPending(data.Status))) + if err != nil { + return err + } + file, err := os.Create(targetFile) + if err != nil { + return err + } + defer func() { _ = file.Close() }() + + err = tmpl.Execute(file, &data) + if err != nil { + return err + } + return nil +} + +// nolint: whitespace +func writeConsoleSummary(summary *wrappers.ResultSummary, ignorePolicyFlagOmit bool) error { + if !isScanPending(summary.Status) { + fmt.Printf(" Scan Summary: \n") + fmt.Printf(" Created At: %s\n", summary.CreatedAt) + fmt.Printf(" Project Name: %s \n", summary.ProjectName) + fmt.Printf(" Scan ID: %s \n\n", summary.ScanID) + fmt.Printf(" Results Summary: \n") + fmt.Printf( + " Risk Level: %s \n", + summary.RiskMsg, + ) + if summary.Policies != nil && !strings.EqualFold(summary.Policies.Status, policeManagementNoneStatus) { + printPoliciesSummary(summary, ignorePolicyFlagOmit) + } + + printResultsSummaryTable(summary) + + if summary.HasAPISecurity() { + printAPIsSecuritySummary(summary) + } + + if summary.HasSCS() { + printSCSSummary(summary.SCSOverview.MicroEngineOverviews) + } + + 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") + fmt.Printf("For more information: %s\n", summary.BaseURI) + } + return nil +} + +func printPoliciesSummary(summary *wrappers.ResultSummary, ignorePolicyFlagOmit bool) { + hasViolations := false + for _, policy := range summary.Policies.Policies { + if len(policy.RulesViolated) > 0 { + hasViolations = true + break + } + } + if hasViolations { + fmt.Printf(tableLine + "\n") + if ignorePolicyFlagOmit { + printWarningIfIgnorePolicyOmiited() + } + if summary.Policies.BreakBuild { + fmt.Printf(" Policy Management Violation - Break Build Enabled: \n") + } else { + fmt.Printf(" Policy Management Violation: \n") + } + for _, police := range summary.Policies.Policies { + if len(police.RulesViolated) > 0 { + fmt.Printf(" Policy: %s | Break Build: %t | Violated Rules: ", police.Name, police.BreakBuild) + for _, violatedRule := range police.RulesViolated { + fmt.Printf("%s;", violatedRule) + } + } + fmt.Printf("\n") + } + fmt.Printf("\n") + } +} + +func printAPIsSecuritySummary(summary *wrappers.ResultSummary) { + fmt.Printf(" API Security - Total Detected APIs: %d \n", summary.APISecurity.APICount) + fmt.Printf(" APIS WITH RISK: %*d \n", defaultPaddingSize, summary.APISecurity.TotalRisksCount) + if summary.HasAPISecurityDocumentation() { + fmt.Printf(" APIS DOCUMENTATION: %*d \n", defaultPaddingSize, summary.GetAPISecurityDocumentationTotal()) + } + fmt.Printf(tableLine + twoNewLines) +} + +func printTableRow(title string, counts *wrappers.EngineResultSummary, statusNumber int) { + switch statusNumber { + case notAvailableNumber: + fmt.Printf(stringTableResultsFormat, title, notAvailableString, notAvailableString, notAvailableString, notAvailableString, notAvailableString, notAvailableString) + case scanFailedNumber: + fmt.Printf(tableResultsFormat, title, getCountValue(counts.Critical), counts.High, counts.Medium, counts.Low, counts.Info, scanFailedString) + case scanCanceledNumber: + fmt.Printf(tableResultsFormat, title, getCountValue(counts.Critical), counts.High, counts.Medium, counts.Low, counts.Info, scanCanceledString) + case scanPartialNumber: + fmt.Printf(tableResultsFormat, title, getCountValue(counts.Critical), counts.High, counts.Medium, counts.Low, counts.Info, scanPartialString) + default: + fmt.Printf(tableResultsFormat, title, getCountValue(counts.Critical), counts.High, counts.Medium, counts.Low, counts.Info, scanSuccessString) + } +} + +func printSCSSummary(microEngineOverviews []*wrappers.MicroEngineOverview) { + fmt.Printf(" Supply Chain Security Results\n") + fmt.Printf(" -------------------------------------------------------------------------- \n") + fmt.Println(" | Critical High Medium Low Info Status |") + for _, microEngineOverview := range microEngineOverviews { + printSCSTableRow(microEngineOverview) + } + fmt.Printf(" -------------------------------------------------------------------------- \n\n") +} + +func printSCSTableRow(microEngineOverview *wrappers.MicroEngineOverview) { + formatString := " | %-20s %4v %4v %6v %4v %4v %-9s |\n" + notAvailableFormatString := " | %-20s %4v %4s %6s %4s %4s %5s |\n" + + riskSummary := microEngineOverview.RiskSummary + microEngineName := microEngineOverview.FullName + + switch microEngineOverview.Status { + case scsScanUnavailableString: + fmt.Printf(notAvailableFormatString, microEngineName, notAvailableString, notAvailableString, notAvailableString, notAvailableString, notAvailableString, notAvailableString) + default: + fmt.Printf(formatString, microEngineName, riskSummary[criticalLabel], riskSummary[highLabel], riskSummary[mediumLabel], riskSummary[lowLabel], + riskSummary[infoLabel], microEngineOverview.Status) + } +} + +func getCountValue(count int) interface{} { + if count < 0 { + return disabledString + } + return count +} + +func printResultsSummaryTable(summary *wrappers.ResultSummary) { + totalCriticalIssues := summary.EnginesResult.GetCriticalIssues() + totalHighIssues := summary.EnginesResult.GetHighIssues() + totalMediumIssues := summary.EnginesResult.GetMediumIssues() + totalLowIssues := summary.EnginesResult.GetLowIssues() + totalInfoIssues := summary.EnginesResult.GetInfoIssues() + fmt.Printf(tableLine + twoNewLines) + fmt.Printf(" Total Results: %d (Total Results includes only API documentation vulnerabilities\n and does not include API code vulnerabilities.)\n", summary.TotalIssues) + fmt.Println(tableLine) + fmt.Printf(TableTitleFormat, " ", "Critical", "High", "Medium", "Low", "Info", "Status") + + printTableRow("APIs", summary.EnginesResult[commonParams.APISecType], summary.EnginesResult[commonParams.APISecType].StatusCode) + printTableRow("IAC", summary.EnginesResult[commonParams.KicsType], summary.EnginesResult[commonParams.KicsType].StatusCode) + printTableRow("SAST", summary.EnginesResult[commonParams.SastType], summary.EnginesResult[commonParams.SastType].StatusCode) + printTableRow("SCA", summary.EnginesResult[commonParams.ScaType], summary.EnginesResult[commonParams.ScaType].StatusCode) + printTableRow("SCS", summary.EnginesResult[commonParams.ScsType], summary.EnginesResult[commonParams.ScsType].StatusCode) + + if wrappers.IsContainersEnabled { + printTableRow("CONTAINERS", summary.EnginesResult[commonParams.ContainersType], summary.EnginesResult[commonParams.ContainersType].StatusCode) + } + + fmt.Println(tableLine) + fmt.Printf(tableResultsFormat, + "TOTAL", getCountValue(totalCriticalIssues), totalHighIssues, totalMediumIssues, totalLowIssues, totalInfoIssues, summary.Status) + fmt.Printf(tableLine + twoNewLines) +} + +func generateScanSummaryURL(summary *wrappers.ResultSummary) string { + summaryURL := fmt.Sprintf( + strings.Replace(summary.BaseURI, "overview", "scans?id=%s&branch=%s", 1), + summary.ScanID, url.QueryEscape(summary.BranchName), + ) + return summaryURL +} + +func runGetResultCommand( + resultsWrapper wrappers.ResultsWrapper, + scanWrapper wrappers.ScansWrapper, + exportWrapper wrappers.ExportWrapper, + resultsPdfReportsWrapper wrappers.ResultsPdfWrapper, + resultsJSONReportsWrapper wrappers.ResultsJSONWrapper, + risksOverviewWrapper wrappers.RisksOverviewWrapper, + scsScanOverviewWrapper wrappers.ScanOverviewWrapper, + policyWrapper wrappers.PolicyWrapper, + featureFlagsWrapper wrappers.FeatureFlagsWrapper, + jwtWrapper wrappers.JWTWrapper, +) func(cmd *cobra.Command, args []string) error { + return func(cmd *cobra.Command, args []string) error { + targetFile, _ := cmd.Flags().GetString(commonParams.TargetFlag) + targetPath, _ := cmd.Flags().GetString(commonParams.TargetPathFlag) + format, _ := cmd.Flags().GetString(commonParams.TargetFormatFlag) + formatPdfToEmail, _ := cmd.Flags().GetString(commonParams.ReportFormatPdfToEmailFlag) + formatPdfOptions, _ := cmd.Flags().GetString(commonParams.ReportFormatPdfOptionsFlag) + formatSbomOptions, _ := cmd.Flags().GetString(commonParams.ReportSbomFormatFlag) + sastRedundancy, _ := cmd.Flags().GetBool(commonParams.SastRedundancyFlag) + agent, _ := cmd.Flags().GetString(commonParams.AgentFlag) + scaHideDevAndTestDep, _ := cmd.Flags().GetBool(commonParams.ScaHideDevAndTestDepFlag) + ignorePolicy, _ := cmd.Flags().GetBool(commonParams.IgnorePolicyFlag) + // Check if the user has permission to override policy management if --ignore-policy is set + ignorePolicyFlagOmit := false + if ignorePolicy { + overridePolicyManagementPer, err := jwtWrapper.CheckPermissionByAccessToken(OverridePolicyManagement) + if err != nil { + return err + } + if !overridePolicyManagementPer { + ignorePolicyFlagOmit = true + ignorePolicy = false + } + } + waitDelay, _ := cmd.Flags().GetInt(commonParams.WaitDelayFlag) + policyTimeout, _ := cmd.Flags().GetInt(commonParams.PolicyTimeoutFlag) + + scanID, _ := cmd.Flags().GetString(commonParams.ScanIDFlag) + if scanID == "" { + return errors.Errorf("%s: Please provide a scan ID", failedListingResults) + } + + resultsParams, err := getFilters(cmd) + if err != nil { + return errors.Wrapf(err, "%s", failedListingResults) + } + + if scaHideDevAndTestDep { + resultsParams[ScaExcludeResultTypesParam] = ScaDevAndTestExclusionParam + } + + scan, errorModel, scanErr := scanWrapper.GetByID(scanID) + if scanErr != nil { + return errors.Wrapf(scanErr, "%s", failedGetting) + } + if errorModel != nil { + return errors.Errorf("%s: CODE: %d, %s", failedGettingScan, errorModel.Code, errorModel.Message) + } + + var policyResponseModel *wrappers.PolicyResponseModel + if !isScanPending(string(scan.Status)) { + policyResponseModel, err = services.HandlePolicyEvaluation(cmd, policyWrapper, scan, ignorePolicy, agent, waitDelay, policyTimeout) + if err != nil { + return err + } + } else { + logger.PrintIfVerbose("Policy violations aren't returned in the pipeline for scans run in async mode.") + } + + if sastRedundancy { + resultsParams[commonParams.SastRedundancyFlag] = "" + } + + _, err = CreateScanReport(resultsWrapper, risksOverviewWrapper, scsScanOverviewWrapper, exportWrapper, + policyResponseModel, resultsPdfReportsWrapper, resultsJSONReportsWrapper, scan, format, formatPdfToEmail, formatPdfOptions, + formatSbomOptions, targetFile, targetPath, agent, resultsParams, featureFlagsWrapper, ignorePolicyFlagOmit) + return err + } +} + +func runGetCodeBashingCommand( + codeBashingWrapper wrappers.CodeBashingWrapper, +) func(cmd *cobra.Command, args []string) error { + return func(cmd *cobra.Command, args []string) error { + lang, _ := cmd.Flags().GetString(commonParams.LanguageFlag) + cwe, _ := cmd.Flags().GetString(commonParams.CweIDFlag) + vulType, _ := cmd.Flags().GetString(commonParams.VulnerabilityTypeFlag) + params, err := codeBashingWrapper.BuildCodeBashingParams( + []wrappers.CodeBashingParamsCollection{ + { + CweID: "CWE-" + cwe, + Language: lang, + CxQueryName: strings.ReplaceAll(vulType, " ", "_"), + }, + }, + ) + if err != nil { + return err + } + // Fetch the cached token or a new one to obtain the codebashing URL incoded in the jwt token + codeBashingURL, err := codeBashingWrapper.GetCodeBashingURL(codeBashingKey) + if err != nil { + return err + } + // Make the request to the api to obtain the codebashing link and send the codebashing url to enrich the path + CodeBashingModel, webError, err := codeBashingWrapper.GetCodeBashingLinks(params, codeBashingURL) + if err != nil { + return err + } + if webError != nil { + return errors.New(webError.Message) + } + err = printByFormat(cmd, *CodeBashingModel) + if err != nil { + return errors.Wrapf(err, "%s", failedListingCodeBashing) + } + return nil + } +} + +func setIsContainersEnabled(agent string) { + wrappers.IsContainersEnabled = !containsIgnoreCase(containerEngineUnsupportedAgents, agent) +} + +func filterResultsByType(results *wrappers.ScanResultsCollection, excludedTypes map[string]struct{}) *wrappers.ScanResultsCollection { + var filteredResults []*wrappers.ScanResult + + for _, result := range results.Results { + if _, shouldExclude := excludedTypes[result.Type]; shouldExclude { + results.TotalCount-- + } else { + filteredResults = append(filteredResults, result) + } + } + results.Results = filteredResults + return results +} + +func filterScsResultsByAgent(results *wrappers.ScanResultsCollection, agent string) *wrappers.ScanResultsCollection { + unsupportedTypesByAgent := map[string][]string{ + commonParams.VSCodeAgent: {commonParams.SCSScorecardType}, + commonParams.JetbrainsAgent: {commonParams.SCSScorecardType}, + commonParams.EclipseAgent: {commonParams.SCSScorecardType, commonParams.SCSSecretDetectionType}, + commonParams.VisualStudioAgent: {commonParams.SCSScorecardType}, + } + + excludedTypes := make(map[string]struct{}) + + if typesToExclude, exists := unsupportedTypesByAgent[agent]; exists { + for _, excludeType := range typesToExclude { + excludedTypes[excludeType] = struct{}{} + } + } + + results = filterResultsByType(results, excludedTypes) + + return results +} + +// CreateScanReport produces the requested report formats for a scan and writes them to the target path. +func CreateScanReport( + resultsWrapper wrappers.ResultsWrapper, + risksOverviewWrapper wrappers.RisksOverviewWrapper, + scsScanOverviewWrapper wrappers.ScanOverviewWrapper, + exportWrapper wrappers.ExportWrapper, + policyResponseModel *wrappers.PolicyResponseModel, + resultsPdfReportsWrapper wrappers.ResultsPdfWrapper, + resultsJSONReportsWrapper wrappers.ResultsJSONWrapper, + scan *wrappers.ScanResponseModel, + reportTypes, + formatPdfToEmail, + formatPdfOptions, + formatSbomOptions, + targetFile, + targetPath string, + agent string, + resultsParams map[string]string, + featureFlagsWrapper wrappers.FeatureFlagsWrapper, + ignorePolicyFlagOmit bool, +) (*wrappers.ScanResultsCollection, error) { + reportList := strings.Split(reportTypes, ",") + results := &wrappers.ScanResultsCollection{} + setIsContainersEnabled(agent) + summary, err := convertScanToResultsSummary(scan, resultsWrapper) + if err != nil { + return nil, err + } + scanPending := isScanPending(summary.Status) + + err = createDirectory(targetPath) + if err != nil { + return nil, err + } + if !scanPending { + results, err = ReadResults(resultsWrapper, exportWrapper, scan, resultsParams, agent, featureFlagsWrapper) + if err != nil { + return nil, err + } + } + isSummaryNeeded := verifyFormatsByReportList(reportList, summaryFormats...) + if isSummaryNeeded && !scanPending { + summary, err = summaryReport(summary, policyResponseModel, risksOverviewWrapper, scsScanOverviewWrapper, featureFlagsWrapper, results, resultsParams) + if err != nil { + return nil, err + } + } + for _, reportType := range reportList { + err = createReport(reportType, formatPdfToEmail, formatPdfOptions, formatSbomOptions, targetFile, + targetPath, results, summary, exportWrapper, resultsPdfReportsWrapper, resultsJSONReportsWrapper, featureFlagsWrapper, ignorePolicyFlagOmit) + if err != nil { + return nil, err + } + } + return results, nil +} + +func countResult(summary *wrappers.ResultSummary, result *wrappers.ScanResult) { + engineType := strings.TrimSpace(result.Type) + severity := strings.ToLower(result.Severity) + if contains(summary.EnginesEnabled, engineType) && isExploitable(result.State) { + if engineType == commonParams.SastType { + summary.SastIssues++ + summary.TotalIssues++ + } else if engineType == commonParams.ScaType { + summary.ScaIssues++ + summary.TotalIssues++ + } else if engineType == commonParams.KicsType { + summary.KicsIssues++ + summary.TotalIssues++ + } else if engineType == commonParams.ContainersType { + if wrappers.IsContainersEnabled { + *summary.ContainersIssues++ + summary.TotalIssues++ + } else { + return + } + } else if strings.HasPrefix(engineType, commonParams.SscsType) { + addResultToSCSOverview(summary, result) + engineType = commonParams.ScsType + *summary.ScsIssues++ + summary.TotalIssues++ + } else { + return + } + + switch severity { + case criticalLabel: + summary.CriticalIssues++ + case highLabel: + summary.HighIssues++ + case mediumLabel: + summary.MediumIssues++ + case lowLabel: + summary.LowIssues++ + case infoLabel: + summary.InfoIssues++ + } + + summary.UpdateEngineResultSummary(engineType, severity) + } +} + +func addResultToSCSOverview(summary *wrappers.ResultSummary, result *wrappers.ScanResult) { + if engineOverviewName, engineExists := sscsEngineToOverviewEngineMap[result.Type]; engineExists { + for _, microEngineOverview := range summary.SCSOverview.MicroEngineOverviews { + if microEngineOverview.Name == engineOverviewName { + if microEngineOverview.RiskSummary != nil { + severity := strings.ToLower(result.Severity) + if severityCount, exists := microEngineOverview.RiskSummary[severity]; exists { + summary.SCSOverview.RiskSummary[severity]++ + microEngineOverview.TotalRisks++ + summary.SCSOverview.TotalRisksCount++ + microEngineOverview.RiskSummary[severity] = severityCount.(int) + 1 + } + } + } + } + } +} + +func verifyFormatsByReportList(reportFormats []string, formats ...string) bool { + for _, reportFormat := range reportFormats { + for _, format := range formats { + if printer.IsFormat(reportFormat, format) { + return true + } + } + } + return false +} + +func validateEmails(emailString string) ([]string, error) { + re := regexp.MustCompile(`^[a-zA-Z0-9_.+-]+@[a-zA-Z0-9-]+\.[a-zA-Z0-9-.]+$`) + emails := strings.Split(emailString, ",") + var validEmails []string + for _, emailStr := range emails { + email := strings.TrimSpace(emailStr) + if re.MatchString(email) { + validEmails = append(validEmails, email) + } else { + return nil, errors.Errorf("report not sent, invalid email address: %s", email) + } + } + return validEmails, nil +} + +func getResultsForAPISecScanner( + risksOverviewWrapper wrappers.RisksOverviewWrapper, + scanID string, +) (results *wrappers.APISecResult, err error) { + var apiSecResultsModel *wrappers.APISecResult + var errorModel *wrappers.WebError + + apiSecResultsModel, errorModel, err = risksOverviewWrapper.GetAllAPISecRisksByScanID(scanID) + if err != nil { + return nil, errors.Wrapf(err, "%s", failedListingResults) + } + if errorModel != nil { + return nil, errors.Errorf("%s: CODE: %d, %s", failedListingResults, errorModel.Code, errorModel.Message) + } else if apiSecResultsModel != nil { + return apiSecResultsModel, nil + } + return nil, nil +} + +func getScanOverviewForSCSScanner( + scsScanOverviewWrapper wrappers.ScanOverviewWrapper, + scanID string, +) (results *wrappers.SCSOverview, err error) { + var scsOverview *wrappers.SCSOverview + var errorModel *wrappers.WebError + + scsOverview, errorModel, err = scsScanOverviewWrapper.GetSCSOverviewByScanID(scanID) + if err != nil { + return nil, errors.Wrapf(err, "SCS: %s", failedListingResults) + } + if errorModel != nil { + return nil, errors.Errorf("SCS: %s: CODE: %d, %s", failedListingResults, errorModel.Code, errorModel.Message) + } else if scsOverview != nil { + // Setting all counts to 0. Results are recounted in enhanceWithScanSummary->countResult + scsOverview.TotalRisksCount = 0 + for key := range scsOverview.RiskSummary { + scsOverview.RiskSummary[key] = 0 + } + for _, microEngineOverview := range scsOverview.MicroEngineOverviews { + microEngineOverview.TotalRisks = 0 + if microEngineOverview.RiskSummary != nil { + for severity := range microEngineOverview.RiskSummary { + microEngineOverview.RiskSummary[severity] = 0 + } + } + } + return scsOverview, nil + } + return nil, nil +} + +func isScanPending(scanStatus string) bool { + return !strings.EqualFold(scanStatus, statusCompleted) && + !strings.EqualFold(scanStatus, statusPartial) && + !strings.EqualFold(scanStatus, statusFailed) +} + +func createRawReport( + format, targetFile, targetPath string, + results *wrappers.ScanResultsCollection, + summary *wrappers.ResultSummary, + resultsJSONReportsWrapper wrappers.ResultsJSONWrapper, + featureFlagsWrapper wrappers.FeatureFlagsWrapper, +) (handled bool, err error) { + if printer.IsFormat(format, printer.FormatIndentedJSON) { + return true, nil + } + if printer.IsFormat(format, printer.FormatSarif) && isValidScanStatus(summary.Status, printer.FormatSarif) { + sarifRpt := createTargetName(targetFile, targetPath, printer.FormatSarif) + return true, exportSarifResults(sarifRpt, results) + } + if printer.IsFormat(format, printer.FormatSonar) && isValidScanStatus(summary.Status, printer.FormatSonar) { + sonarRpt := createTargetName(fmt.Sprintf("%s%s", targetFile, sonarTypeLabel), targetPath, printer.FormatJSON) + return true, exportSonarResults(sonarRpt, results) + } + if printer.IsFormat(format, printer.FormatJSON) && isValidScanStatus(summary.Status, printer.FormatJSON) { + jsonRpt := createTargetName(targetFile, targetPath, printer.FormatJSON) + return true, exportJSONResults(jsonRpt, results) + } + if printer.IsFormat(format, printer.FormatJSONv2) && isValidScanStatus(summary.Status, printer.FormatJSONv2) { + summaryRpt := createTargetName(targetFile, targetPath, printer.FormatJSON) + return true, exportJSONReportResults(resultsJSONReportsWrapper, summary, summaryRpt, featureFlagsWrapper) + } + if printer.IsFormat(format, printer.FormatGLSast) { + jsonRpt := createTargetName(fmt.Sprintf("%s%s", targetFile, glSastTypeLabel), targetPath, printer.FormatJSON) + return true, exportGlSastResults(jsonRpt, results, summary) + } + if printer.IsFormat(format, printer.FormatGLSca) { + jsonRpt := createTargetName(fmt.Sprintf("%s%s", targetFile, glScaTypeLabel), targetPath, printer.FormatJSON) + return true, exportGlScaResults(jsonRpt, results, summary) + } + return false, nil +} + +func isValidScanStatus(status, format string) bool { + if isScanPending(status) { + log.Printf("Result format file %s not create because scan status is %s", format, status) + return false + } + return true +} + +func createReport(format, + formatPdfToEmail, + formatPdfOptions, + formatSbomOptions, + targetFile, + targetPath string, + results *wrappers.ScanResultsCollection, + summary *wrappers.ResultSummary, + exportWrapper wrappers.ExportWrapper, + resultsPdfReportsWrapper wrappers.ResultsPdfWrapper, + resultsJSONReportsWrapper wrappers.ResultsJSONWrapper, + featureFlagsWrapper wrappers.FeatureFlagsWrapper, + ignorePolicyFlagOmit bool) error { + if handled, err := createRawReport(format, targetFile, targetPath, results, summary, resultsJSONReportsWrapper, featureFlagsWrapper); handled { + return err + } + + if printer.IsFormat(format, printer.FormatSummaryConsole) { + return writeConsoleSummary(summary, ignorePolicyFlagOmit) + } + if printer.IsFormat(format, printer.FormatSummary) { + summaryRpt := createTargetName(targetFile, targetPath, printer.FormatHTML) + convertNotAvailableNumberToZero(summary) + return writeHTMLSummary(summaryRpt, summary) + } + if printer.IsFormat(format, printer.FormatSummaryJSON) { + summaryRpt := createTargetName(targetFile, targetPath, printer.FormatJSON) + convertNotAvailableNumberToZero(summary) + return exportJSONSummaryResults(summaryRpt, summary) + } + if printer.IsFormat(format, printer.FormatPDF) && isValidScanStatus(summary.Status, printer.FormatPDF) { + summaryRpt := createTargetName(targetFile, targetPath, printer.FormatPDF) + return exportPdfResults(resultsPdfReportsWrapper, summary, summaryRpt, formatPdfToEmail, formatPdfOptions, featureFlagsWrapper) + } + if printer.IsFormat(format, printer.FormatSummaryMarkdown) { + summaryRpt := createTargetName(targetFile, targetPath, "md") + convertNotAvailableNumberToZero(summary) + return writeMarkdownSummary(summaryRpt, summary) + } + if printer.IsFormat(format, printer.FormatSbom) && isValidScanStatus(summary.Status, printer.FormatSbom) { + targetType := printer.FormatJSON + if strings.Contains(strings.ToLower(formatSbomOptions), printer.FormatXML) { + targetType = printer.FormatXML + } + summaryRpt := createTargetName(fmt.Sprintf("%s_%s", targetFile, printer.FormatSbom), targetPath, targetType) + convertNotAvailableNumberToZero(summary) + + if !contains(summary.EnginesEnabled, commonParams.ScaType) { + return fmt.Errorf("unable to generate %s report - SCA engine must be enabled on scan summary", printer.FormatSbom) + } + + if summary.ScaIssues == notAvailableNumber { + return fmt.Errorf("unable to generate %s report - SCA engine did not complete successfully", printer.FormatSbom) + } + + return services.ExportSbomResults(exportWrapper, summaryRpt, summary, formatSbomOptions) + } + return fmt.Errorf("bad report format %s", format) +} + +func createTargetName(targetFile, targetPath, targetType string) string { + return filepath.Join(targetPath, targetFile+"."+targetType) +} + +func createDirectory(targetPath string) error { + if _, err := os.Stat(targetPath); os.IsNotExist(err) { + log.Printf("\nOutput path not found: %s\n", targetPath) + log.Printf("Creating directory: %s\n", targetPath) + err = os.Mkdir(targetPath, directoryPermission) + if err != nil { + return err + } + } + return nil +} + +// ReadResults fetches all scan results for the given scan and enriches them with SCA and SCS data as applicable. +func ReadResults( + resultsWrapper wrappers.ResultsWrapper, + exportWrapper wrappers.ExportWrapper, + scan *wrappers.ScanResponseModel, + resultsParams map[string]string, + agent string, featureflagsWrappers wrappers.FeatureFlagsWrapper) (results *wrappers.ScanResultsCollection, err error) { + var resultsModel *wrappers.ScanResultsCollection + var errorModel *wrappers.WebError + + resultsParams[commonParams.ScanIDQueryParam] = scan.ID + _, sastRedundancy := resultsParams[commonParams.SastRedundancyFlag] + + scaHideDevAndTestDep := resultsParams[ScaExcludeResultTypesParam] == ScaDevAndTestExclusionParam + + resultsModel, errorModel, err = resultsWrapper.GetAllResultsByScanID(resultsParams) + + if err != nil { + return nil, errors.Wrapf(err, "%s", failedListingResults) + } + if errorModel != nil { + return nil, errors.Errorf("%s: CODE: %d, %s", failedListingResults, errorModel.Code, errorModel.Message) + } + + if resultsModel != nil { + if slices.Contains(scan.Engines, commonParams.SastType) && sastRedundancy { + // Compute SAST results redundancy + resultsModel = ComputeRedundantSastResults(resultsModel) + } + resultsModel, err = enrichScaResults(exportWrapper, scan, resultsModel, scaHideDevAndTestDep, featureflagsWrappers) + if err != nil { + return nil, err + } + + if slices.Contains(scan.Engines, commonParams.ScsType) { + resultsModel = filterScsResultsByAgent(resultsModel, agent) + } + + resultsModel.ScanID = scan.ID + return resultsModel, nil + } + return nil, nil +} + +func enrichScaResults( + exportWrapper wrappers.ExportWrapper, + scan *wrappers.ScanResponseModel, + resultsModel *wrappers.ScanResultsCollection, + scaHideDevAndTestDep bool, featureflagWrapper wrappers.FeatureFlagsWrapper) (*wrappers.ScanResultsCollection, error) { + if slices.Contains(scan.Engines, commonParams.ScaType) { + scaExportDetails, err := services.GetExportPackage(exportWrapper, scan.ID, scaHideDevAndTestDep, featureflagWrapper) + if err != nil { + return nil, errors.Wrapf(err, "%s", failedListingResults) + } + scaPackageModel := parseScaExportPackage(scaExportDetails.Packages) + scaTypeModel := parseExportScaVulnerability(scaExportDetails.ScaTypes) + if scaPackageModel != nil { + resultsModel = addPackageInformation(resultsModel, scaPackageModel, scaTypeModel) + } + } + if slices.Contains(scan.Engines, commonParams.ContainersType) && !wrappers.IsContainersEnabled { + resultsModel = removeResultsByType(resultsModel, commonParams.ContainersType) + } + return resultsModel, nil +} + +func parseExportScaVulnerability(types []wrappers.ScaType) *[]wrappers.ScaTypeCollection { + var scaTypes []wrappers.ScaTypeCollection + for _, t := range types { + scaTypes = append(scaTypes, wrappers.ScaTypeCollection(t)) + } + return &scaTypes +} + +func parseScaExportPackage(packages []wrappers.ScaPackage) *[]wrappers.ScaPackageCollection { + var scaPackages []wrappers.ScaPackageCollection + for _, pkg := range packages { + pkg := pkg + scaPackages = append(scaPackages, wrappers.ScaPackageCollection{ + ID: pkg.ID, + Locations: pkg.Locations, + DependencyPathArray: parsePackagePathToDependencyPath(&pkg), + Outdated: pkg.Outdated, + IsDirectDependency: pkg.IsDirectDependency, + IsDevelopmentDependency: pkg.IsDevelopmentDependency, + IsTestDependency: pkg.IsTestDependency, + }) + } + return &scaPackages +} + +func parsePackagePathToDependencyPath(pkg *wrappers.ScaPackage) [][]wrappers.DependencyPath { + var dependencyPathArray [][]wrappers.DependencyPath + for _, path := range pkg.PackagePathArray { + var dependencyPath []wrappers.DependencyPath + for _, dep := range path { + dependencyPath = append(dependencyPath, wrappers.DependencyPath{ + ID: dep.ID, + Name: dep.Name, + Version: dep.Version, + }) + } + dependencyPathArray = append(dependencyPathArray, dependencyPath) + } + + // We are doing this to maintain the same structure that was in risk-management api response + // in risk-management, if the length of the dependency path array is 1, it will be the main package + // in export service, if there are no dependencies, the package path array will be empty + if len(dependencyPathArray) == 0 { + appendMainPackageToDependencyPath(&dependencyPathArray, pkg) + } + return dependencyPathArray +} + +func appendMainPackageToDependencyPath(dependencyPathArray *[][]wrappers.DependencyPath, pkg *wrappers.ScaPackage) { + *dependencyPathArray = append(*dependencyPathArray, []wrappers.DependencyPath{{ + ID: pkg.ID, + Locations: pkg.Locations, + Name: pkg.Name, + IsDevelopment: pkg.IsDevelopmentDependency, + }}) +} + +func removeResultsByType(model *wrappers.ScanResultsCollection, resultType string) *wrappers.ScanResultsCollection { + var newResults []*wrappers.ScanResult + for _, result := range model.Results { + isResultType := result.Type == resultType + if resultType == commonParams.SscsType { + isResultType = strings.HasPrefix(result.Type, resultType) + } + if !isResultType { + newResults = append(newResults, result) + } + } + model.Results = newResults + model.TotalCount = uint(len(newResults)) + return model +} + +func exportSarifResults(targetFile string, results *wrappers.ScanResultsCollection) error { + var err error + var resultsJSON []byte + log.Println("Creating SARIF Report: ", targetFile) + var sarifResults = convertCxResultsToSarif(results) + resultsJSON, err = json.Marshal(sarifResults) + if err != nil { + return errors.Wrapf(err, "%s: failed to serialize results response ", failedGettingAll) + } + f, err := os.Create(targetFile) + if err != nil { + return errors.Wrapf(err, "%s: failed to create target file ", failedGettingAll) + } + _, _ = fmt.Fprintln(f, string(resultsJSON)) + _ = f.Close() + return nil +} +func exportGlSastResults(targetFile string, results *wrappers.ScanResultsCollection, summary *wrappers.ResultSummary) error { + log.Println("Creating gl-sast Report: ", targetFile) + var glSast = new(wrappers.GlSastResultsCollection) + glSast.Vulnerabilities = []wrappers.GlVulnerabilities{} + err := addScanToGlSastReport(summary, glSast) + if err != nil { + return errors.Wrapf(err, "%s: failed to add scan to gl-sast report", failedListingResults) + } + convertCxResultToGlSastVulnerability(results, glSast, summary) + resultsJSON, err := json.Marshal(glSast) + if err != nil { + return errors.Wrapf(err, "%s: failed to serialize gl-sast report ", failedListingResults) + } + f, err := os.Create(targetFile) + if err != nil { + return errors.Wrapf(err, "%s: failed to create target file ", failedListingResults) + } + defer func() { _ = f.Close() }() + _, _ = fmt.Fprintln(f, string(resultsJSON)) + return nil +} + +func exportGlScaResults(targetFile string, results *wrappers.ScanResultsCollection, summary *wrappers.ResultSummary) error { + log.Println("Creating Gl-sca Report: ", targetFile) + glScaResult := &wrappers.GlScaResultsCollection{ + Vulnerabilities: []wrappers.GlScaDepVulnerabilities{}, // Initialize arrays to prevent GitLab schema validation errors. + ScaDependencyFiles: []wrappers.ScaDependencyFile{}, + } + err := addScanToGlScaReport(summary, glScaResult) + if err != nil { + return errors.Wrapf(err, "%s: failed to denerate GL-Sca report ", failedListingResults) + } + convertCxResultToGlScaVulnerability(results, glScaResult) + convertCxResultToGlScaFiles(results, glScaResult) + resultsJSON, err := json.Marshal(glScaResult) + if err != nil { + return errors.Wrapf(err, "%s: failed to serialize GL-Sca report ", failedListingResults) + } + f, err := os.Create(targetFile) + if err != nil { + return errors.Wrapf(err, "%s: failed to create target file ", failedListingResults) + } + defer func() { _ = f.Close() }() + _, _ = fmt.Fprintln(f, string(resultsJSON)) + + return nil +} + +func addScanToGlScaReport(summary *wrappers.ResultSummary, glScaResult *wrappers.GlScaResultsCollection) error { + createdAt, err := time.Parse(summaryCreatedAtLayout, summary.CreatedAt) + if err != nil { + return err + } + + glScaResult.Schema = wrappers.ScaSchema + glScaResult.Version = wrappers.SchemaVersion + glScaResult.Scan.Analyzer.VendorGlSCA.VendorGlname = wrappers.AnalyzerScaID + glScaResult.Scan.Analyzer.Name = wrappers.AnalyzerScaID + glScaResult.Scan.Analyzer.Name = wrappers.AnalyzerScaID + glScaResult.Scan.Analyzer.ID = wrappers.ScannerID + glScaResult.Scan.Scanner.ID = wrappers.ScannerID + glScaResult.Scan.Scanner.Name = wrappers.AnalyzerScaID + glScaResult.Scan.Scanner.VendorGlSCA.VendorGlname = wrappers.AnalyzerScaID + glScaResult.Scan.Status = commonParams.Success + glScaResult.Scan.Type = wrappers.ScannerType + glScaResult.Scan.StartTime = createdAt.Format(glTimeFormat) + glScaResult.Scan.EndTime = createdAt.Format(glTimeFormat) + glScaResult.Scan.Scanner.Name = wrappers.AnalyzerScaID + glScaResult.Scan.Scanner.VersionGlSca = commonParams.Version + glScaResult.Scan.Analyzer.VersionGlSca = commonParams.Version + + return nil +} + +func addScanToGlSastReport(summary *wrappers.ResultSummary, glSast *wrappers.GlSastResultsCollection) error { + createdAt, err := time.Parse(summaryCreatedAtLayout, summary.CreatedAt) + if err != nil { + return err + } + + glSast.Scan = wrappers.ScanGlReport{} + glSast.Schema = wrappers.SastSchema + glSast.Version = wrappers.SastSchemaVersion + glSast.Scan.Analyzer.URL = wrappers.AnalyzerURL + glSast.Scan.Analyzer.Name = wrappers.VendorName + glSast.Scan.Analyzer.Vendor.Name = wrappers.VendorName + glSast.Scan.Analyzer.ID = wrappers.AnalyzerID + glSast.Scan.Scanner.ID = wrappers.AnalyzerID + glSast.Scan.Scanner.Name = wrappers.VendorName + glSast.Scan.Status = commonParams.Success + glSast.Scan.Type = commonParams.SastType + glSast.Scan.StartTime = createdAt.Format(glTimeFormat) + glSast.Scan.EndTime = createdAt.Format(glTimeFormat) + glSast.Scan.Scanner.Vendor.Name = wrappers.VendorName + glSast.Scan.Scanner.Version = commonParams.Version + glSast.Scan.Analyzer.Version = commonParams.Version + + return nil +} +func exportSonarResults(targetFile string, results *wrappers.ScanResultsCollection) error { + var err error + var resultsJSON []byte + log.Println("Creating SONAR Report: ", targetFile) + var sonarResults = convertCxResultsToSonar(results) + resultsJSON, err = json.Marshal(sonarResults) + if err != nil { + return errors.Wrapf(err, "%s: failed to serialize results response ", failedGettingAll) + } + f, err := os.Create(targetFile) + if err != nil { + return errors.Wrapf(err, "%s: failed to create target file ", failedGettingAll) + } + _, _ = fmt.Fprintln(f, string(resultsJSON)) + _ = f.Close() + return nil +} + +// Function to decode HTML entities in the ScanResultsCollection +func decodeHTMLEntitiesInResults(results *wrappers.ScanResultsCollection) { + for _, result := range results.Results { + result.Description = html.UnescapeString(result.Description) + result.DescriptionHTML = html.UnescapeString(result.DescriptionHTML) + for _, node := range result.ScanResultData.Nodes { + node.FullName = html.UnescapeString(node.FullName) + node.Name = html.UnescapeString(node.Name) + } + } +} + +func exportJSONResults(targetFile string, results *wrappers.ScanResultsCollection) error { + decodeHTMLEntitiesInResults(results) + var err error + var resultsJSON []byte + log.Println("Creating JSON Report: ", targetFile) + resultsJSON, err = json.Marshal(results) + if err != nil { + return errors.Wrapf(err, "%s: failed to serialize results response ", failedGettingAll) + } + f, err := os.Create(targetFile) + if err != nil { + return errors.Wrapf(err, "%s: failed to create target file ", failedGettingAll) + } + _, _ = fmt.Fprintln(f, string(resultsJSON)) + _ = f.Close() + return nil +} + +func exportJSONReportResults(jsonWrapper wrappers.ResultsJSONWrapper, summary *wrappers.ResultSummary, summaryRpt string, featureFlagsWrapper wrappers.FeatureFlagsWrapper) error { + jsonReportsPayload := &wrappers.JSONReportsPayload{} + pollingResp := &wrappers.JSONPollingResponse{} + jsonReportsPayload.ReportName = reportNameImprovedScanReport + + jsonOptionsSections, jsonOptionsEngines := parseJSONOptions(summary.EnginesEnabled, jsonReportsPayload.ReportName) + + jsonReportsPayload.ReportType = CliType + jsonReportsPayload.FileFormat = printer.FormatJSON + jsonReportsPayload.Data.ScanID = summary.ScanID + jsonReportsPayload.Data.ProjectID = summary.ProjectID + jsonReportsPayload.Data.BranchName = summary.BranchName + jsonReportsPayload.Data.Scanners = jsonOptionsEngines + jsonReportsPayload.Data.Sections = jsonOptionsSections + + jsonReportID, webErr, err := jsonWrapper.GenerateJSONReport(jsonReportsPayload) + if webErr != nil { + return errors.Errorf("Error generating JSON report - %s", webErr.Message) + } + if err != nil { + return errors.Errorf("Error generating JSON report - %s", err.Error()) + } + log.Println("Generating JSON report") + pollingResp.Status = startedStatus + for pollingResp.Status == startedStatus || pollingResp.Status == requestedStatus { + pollingResp, webErr, err = jsonWrapper.CheckJSONReportStatus(jsonReportID.ReportID) + if err != nil || webErr != nil { + return errors.Wrapf(err, "%v", webErr) + } + logger.PrintfIfVerbose("JSON report status: %s", pollingResp.Status) + time.Sleep(delayValueForReport * time.Millisecond) + } + if pollingResp.Status != completedStatus { + return errors.Errorf("JSON generating failed - Current status: %s", pollingResp.Status) + } + + minioEnabled, _ := wrappers.GetSpecificFeatureFlag(featureFlagsWrapper, wrappers.MinioEnabled) + infoPathType := "" + if minioEnabled.Status { + infoPathType = jsonReportID.ReportID + } else { + infoPathType = pollingResp.URL + } + err = jsonWrapper.DownloadJSONReport(infoPathType, summaryRpt, minioEnabled.Status) + if err != nil { + return errors.Wrapf(err, "%s", "Failed downloading JSON report") + } + return nil +} + +func parseJSONOptions(enabledEngines []string, reportName string) (jsonOptionsSections, jsonOptionsEngines []string) { + jsonOptionsSections = []string{ + sectionScanSummary, + sectionExecutiveSummary, + sectionScanResults, + } + + var jsonOptionsEnginesMap = map[string]string{ + commonParams.ScaType: scaEngineLabel, + commonParams.SastType: sastEngineLabel, + commonParams.KicsType: kicsEngineLabel, + commonParams.IacType: kicsEngineLabel, + commonParams.ContainersType: "Containers", + commonParams.ScsType: "Microengines", + } + if jsonOptionsEngines == nil { + for _, engine := range enabledEngines { + if jsonOptionsEnginesMap[engine] != "" { + jsonOptionsEngines = append(jsonOptionsEngines, jsonOptionsEnginesMap[engine]) + } + } + } + + if reportName == reportNameImprovedScanReport { + jsonOptionsSections = translateReportSectionsForImproved(jsonOptionsSections) + } + + return jsonOptionsSections, jsonOptionsEngines +} + +func exportJSONSummaryResults(targetFile string, results *wrappers.ResultSummary) error { + var err error + var resultsJSON []byte + log.Println("Creating summary JSON Report: ", targetFile) + resultsJSON, err = json.Marshal(results) + if err != nil { + return errors.Wrapf(err, "%s: failed to serialize results response ", failedGettingAll) + } + f, err := os.Create(targetFile) + if err != nil { + return errors.Wrapf(err, "%s: failed to create target file ", failedGettingAll) + } + _, _ = fmt.Fprintln(f, string(resultsJSON)) + _ = f.Close() + return nil +} + +func exportPdfResults(pdfWrapper wrappers.ResultsPdfWrapper, summary *wrappers.ResultSummary, summaryRpt, formatPdfToEmail, + pdfOptions string, featureFlagsWrapper wrappers.FeatureFlagsWrapper) error { + pdfReportsPayload := &wrappers.PdfReportsPayload{} + pollingResp := &wrappers.PdfPollingResponse{} + pdfReportsPayload.ReportName = reportNameImprovedScanReport + pdfOptionsSections, pdfOptionsEngines, err := parsePDFOptions(pdfOptions, summary.EnginesEnabled, pdfReportsPayload.ReportName) + if err != nil { + return err + } + pdfReportsPayload.ReportType = CliType + pdfReportsPayload.FileFormat = printer.FormatPDF + pdfReportsPayload.Data.ScanID = summary.ScanID + pdfReportsPayload.Data.ProjectID = summary.ProjectID + pdfReportsPayload.Data.BranchName = summary.BranchName + pdfReportsPayload.Data.Scanners = pdfOptionsEngines + pdfReportsPayload.Data.Sections = pdfOptionsSections + + // will generate pdf report and send it to the email list + // instead of saving it to the file system + if formatPdfToEmail != "" { + emailList, validateErr := validateEmails(formatPdfToEmail) + if validateErr != nil { + return validateErr + } + pdfReportsPayload.ReportType = reportTypeEmail + pdfReportsPayload.Data.Email = emailList + } + pdfReportID, webErr, err := pdfWrapper.GeneratePdfReport(pdfReportsPayload) + if webErr != nil { + return errors.Errorf("Error generating PDF report - %s", webErr.Message) + } + if err != nil { + return errors.Errorf("Error generating PDF report - %s", err.Error()) + } + if pdfReportsPayload.ReportType == reportTypeEmail { + log.Println("Sending PDF report to: ", pdfReportsPayload.Data.Email) + return nil + } + log.Println("Generating PDF report") + pollingResp.Status = startedStatus + for pollingResp.Status == startedStatus || pollingResp.Status == requestedStatus { + pollingResp, webErr, err = pdfWrapper.CheckPdfReportStatus(pdfReportID.ReportID) + if err != nil || webErr != nil { + return errors.Wrapf(err, "%v", webErr) + } + logger.PrintfIfVerbose("PDF report status: %s", pollingResp.Status) + time.Sleep(delayValueForReport * time.Millisecond) + } + if pollingResp.Status != completedStatus { + return errors.Errorf("PDF generating failed - Current status: %s", pollingResp.Status) + } + + minioEnabled, _ := wrappers.GetSpecificFeatureFlag(featureFlagsWrapper, wrappers.MinioEnabled) + infoPathType := "" + if minioEnabled.Status { + infoPathType = pdfReportID.ReportID + } else { + infoPathType = pollingResp.URL + } + err = pdfWrapper.DownloadPdfReport(infoPathType, summaryRpt, minioEnabled.Status) + if err != nil { + return errors.Wrapf(err, "%s", "Failed downloading PDF report") + } + return nil +} + +func parsePDFOptions(pdfOptions string, enabledEngines []string, reportName string) (pdfOptionsSections, pdfOptionsEngines []string, err error) { + var pdfOptionsSectionsMap = map[string]string{ + "scansummary": sectionScanSummary, + "executivesummary": sectionExecutiveSummary, + "scanresults": sectionScanResults, + } + + var pdfOptionsEnginesMap = map[string]string{ + commonParams.ScaType: scaEngineLabel, + commonParams.SastType: sastEngineLabel, + commonParams.KicsType: kicsEngineLabel, + commonParams.IacType: kicsEngineLabel, + } + + pdfOptions = strings.ToLower(strings.ReplaceAll(pdfOptions, " ", "")) + options := strings.Split(strings.ReplaceAll(pdfOptions, "\n", ""), ",") + for _, s := range options { + if pdfOptionsEnginesMap[s] != "" { + pdfOptionsEngines = append(pdfOptionsEngines, pdfOptionsEnginesMap[s]) + } else if pdfOptionsSectionsMap[s] != "" { + pdfOptionsSections = append(pdfOptionsSections, pdfOptionsSectionsMap[s]) + } else { + return nil, nil, errors.Errorf("report option \"%s\" unavailable", s) + } + } + if pdfOptionsEngines == nil { + for _, engine := range enabledEngines { + if pdfOptionsEnginesMap[engine] != "" { + pdfOptionsEngines = append(pdfOptionsEngines, pdfOptionsEnginesMap[engine]) + } + } + } + + if reportName == reportNameImprovedScanReport { + pdfOptionsSections = translateReportSectionsForImproved(pdfOptionsSections) + } + + return pdfOptionsSections, pdfOptionsEngines, nil +} + +func translateReportSectionsForImproved(sections []string) []string { + var resultSections = make([]string, 0) + + var pdfOptionsSectionsImprovedTranslation = map[string][]string{ + sectionScanSummary: {"scan-information"}, + sectionExecutiveSummary: {"results-overview"}, + sectionScanResults: {"scan-results", "categories", "resolved-results", "vulnerability-details"}, + } + + for _, section := range sections { + if translatedSections := pdfOptionsSectionsImprovedTranslation[section]; translatedSections != nil { + resultSections = append(resultSections, translatedSections...) + } + } + + return resultSections +} + +func convertCxResultsToSarif(results *wrappers.ScanResultsCollection) *wrappers.SarifResultsCollection { + var sarif = new(wrappers.SarifResultsCollection) + sarif.Schema = "https://raw.githubusercontent.com/oasis-tcs/sarif-spec/master/Schemata/sarif-schema-2.1.0.json" + sarif.Version = "2.1.0" + sarif.Runs = []wrappers.SarifRun{} + sarif.Runs = append(sarif.Runs, createSarifRun(results)) + return sarif +} + +func convertCxResultToGlSastVulnerability(results *wrappers.ScanResultsCollection, glSast *wrappers.GlSastResultsCollection, summary *wrappers.ResultSummary) { + for _, result := range results.Results { + if strings.TrimSpace(result.Type) == commonParams.SastType { + glSast = parseGlSastVulnerability(result, glSast, summary) + } + } +} + +func convertCxResultToGlScaVulnerability(results *wrappers.ScanResultsCollection, glScaResult *wrappers.GlScaResultsCollection) { + for _, result := range results.Results { + if strings.TrimSpace(result.Type) == commonParams.ScaType { + glScaResult = parseGlscaVulnerability(result, glScaResult) + } + } +} + +func convertCxResultToGlScaFiles(results *wrappers.ScanResultsCollection, glScaResult *wrappers.GlScaResultsCollection) { + for _, result := range results.Results { + if strings.TrimSpace(result.Type) == commonParams.ScaType { + glScaResult = parseGlScaFiles(result, glScaResult) + } + } +} +func parseGlSastVulnerability(result *wrappers.ScanResult, glSast *wrappers.GlSastResultsCollection, summary *wrappers.ResultSummary) *wrappers.GlSastResultsCollection { + hostName := parseURI(summary.BaseURI) + + queryName := result.ScanResultData.QueryName + fileName := result.ScanResultData.Nodes[0].FileName + lineNumber := strconv.FormatUint(uint64(result.ScanResultData.Nodes[0].Line), 10) + startLine := result.ScanResultData.Nodes[0].Line + endLine := result.ScanResultData.Nodes[0].Line + result.ScanResultData.Nodes[0].Length + ID := fmt.Sprintf("%s:%s:%s", queryName, fileName, lineNumber) + category := fmt.Sprintf("%s-%s", wrappers.VendorName, result.Type) + message := fmt.Sprintf("%s@%s:%s", queryName, fileName, lineNumber) + QueryDescriptionLink := fmt.Sprintf("%s/results/%s/%s/sast/description/%s/%s", hostName, summary.ScanID, summary.ProjectID, result.VulnerabilityDetails.CweID, result.ScanResultData.QueryID) + + glSast.Vulnerabilities = append(glSast.Vulnerabilities, wrappers.GlVulnerabilities{ + ID: ID, + Category: category, + Name: queryName, + Message: message, + Description: result.Description + " \n" + QueryDescriptionLink, + CVE: ID, + Severity: cases.Title(language.English).String(result.Severity), + Confidence: cases.Title(language.English).String(result.Severity), + Solution: "", + + Scanner: wrappers.GlScanner{ + ID: category, + Name: category, + }, + Identifiers: []wrappers.Identifier{ + { + Type: "cxOneScan", + Name: "CxOne Scan", + URL: summary.BaseURI, + Value: result.ID, + }, + }, + Links: make([]string, 0), + Tracking: wrappers.Tracking{ + Type: "source", + Items: []wrappers.Item{ + { + Signatures: []wrappers.Signature{{Algorithm: result.Type + "-Algorithm ", Value: notAvailableValue}}, + File: fileName, + EndLine: endLine, + StartLine: startLine, + }, + }, + }, + Flags: make([]wrappers.Flag, 0), + Location: wrappers.Location{ + File: fileName, + StartLine: startLine, + EndLine: endLine, + }, + }) + return glSast +} +func parseGlscaVulnerability(result *wrappers.ScanResult, glDependencyResult *wrappers.GlScaResultsCollection) *wrappers.GlScaResultsCollection { + if result.ScanResultData.ScaPackageCollection != nil { + glDependencyResult.Vulnerabilities = append(glDependencyResult.Vulnerabilities, wrappers.GlScaDepVulnerabilities{ + ID: result.ID, + Name: result.VulnerabilityDetails.CveName, + Description: result.Description, + Severity: cases.Title(language.English).String(result.Severity), + Solution: result.ScanResultData.RecommendedVersion, + Identifiers: collectScaPackageData(result), + Links: collectScaPackageLinks(result), + TrackingDep: wrappers.TrackingDep{ + Items: collectScaPackageItemsDep(result), + }, + Flags: make([]string, 0), + LocationDep: wrappers.GlScaDepVulnerabilityLocation{ + File: parseGlDependencyLocation(result), + Dependency: wrappers.ScaDependencyLocation{ + Package: wrappers.PackageName{Name: result.ScanResultData.PackageIdentifier}, + ScaDependencyLocationVersion: "", + Direct: result.ScanResultData.ScaPackageCollection.IsDirectDependency, + ScaDependencyPath: result.ScanResultData.Line, + }, + }, + }) + } + return glDependencyResult +} +func parseGlDependencyLocation(result *wrappers.ScanResult) string { + var location string + if result != nil && result.ScanResultData.ScaPackageCollection != nil && result.ScanResultData.ScaPackageCollection.Locations != nil { + location = *result.ScanResultData.ScaPackageCollection.Locations[0] + } else { + location = "" + } + return location +} +func parseGlScaFiles(result *wrappers.ScanResult, glScaResult *wrappers.GlScaResultsCollection) *wrappers.GlScaResultsCollection { + if result.ScanResultData.ScaPackageCollection != nil && result.ScanResultData.ScaPackageCollection.Locations != nil { + glScaResult.ScaDependencyFiles = append(glScaResult.ScaDependencyFiles, wrappers.ScaDependencyFile{ + Path: *result.ScanResultData.ScaPackageCollection.Locations[0], + PackageManager: result.ScanResultData.ScaPackageCollection.ID, + Dependencies: collectScaFileLocations(result), + }) + } + return glScaResult +} +func collectScaFileLocations(result *wrappers.ScanResult) []wrappers.ScaDependencyLocation { + allScaIdentifierLocations := []wrappers.ScaDependencyLocation{} + for _, packageInfo := range result.ScanResultData.PackageData { + allScaIdentifierLocations = append(allScaIdentifierLocations, wrappers.ScaDependencyLocation{ + Package: wrappers.PackageName{ + Name: packageInfo.Type, + }, + ScaDependencyLocationVersion: packageInfo.URL, + Direct: true, + ScaDependencyPath: result.ScanResultData.Line, + }) + } + return allScaIdentifierLocations +} +func collectScaPackageItemsDep(result *wrappers.ScanResult) []wrappers.ItemDep { + allScaPackageItemDep := []wrappers.ItemDep{} + allScaPackageItemDep = append(allScaPackageItemDep, wrappers.ItemDep{ + Signature: []wrappers.SignatureDep{{Algorithm: "SCA-Algorithm ", Value: notAvailableValue}}, + File: result.VulnerabilityDetails.CveName, + EndLine: 0, + StartLine: 0, + }) + return allScaPackageItemDep +} +func collectScaPackageLinks(result *wrappers.ScanResult) []wrappers.LinkDep { + allScaPackageLinks := []wrappers.LinkDep{} + for _, packageInfo := range result.ScanResultData.PackageData { + allScaPackageLinks = append(allScaPackageLinks, wrappers.LinkDep{ + Name: packageInfo.Type, + URL: packageInfo.URL, + }) + } + return allScaPackageLinks +} +func collectScaPackageData(result *wrappers.ScanResult) []wrappers.IdentifierDep { + allIdentifierDep := []wrappers.IdentifierDep{} + for _, packageInfo := range result.ScanResultData.PackageData { + allIdentifierDep = append(allIdentifierDep, wrappers.IdentifierDep{ + Type: packageInfo.Type, + Value: packageInfo.URL, + Name: packageInfo.URL, + }) + } + return allIdentifierDep +} + +func convertCxResultsToSonar(results *wrappers.ScanResultsCollection) *wrappers.ScanResultsSonar { + var sonar = new(wrappers.ScanResultsSonar) + sonar.Issues, sonar.Rules = parseSonar(results) + return sonar +} + +func createSarifRun(results *wrappers.ScanResultsCollection) wrappers.SarifRun { + var sarifRun wrappers.SarifRun + sarifRun.Tool.Driver.Name = wrappers.SarifName + sarifRun.Tool.Driver.Version = wrappers.SarifVersion + sarifRun.Tool.Driver.InformationURI = wrappers.SarifInformationURI + sarifRun.Tool.Driver.Rules, sarifRun.Results = parseResults(results) + return sarifRun +} + +func parseResults(results *wrappers.ScanResultsCollection) ([]wrappers.SarifDriverRule, []wrappers.SarifScanResult) { + var sarifRules = make([]wrappers.SarifDriverRule, 0) + var sarifResults = make([]wrappers.SarifScanResult, 0) + if results != nil { + ruleIds := map[interface{}]bool{} + for _, result := range results.Results { + if rule := findRule(ruleIds, result); rule != nil { + sarifRules = append(sarifRules, *rule) + } + if sarifResult := findResult(result); sarifResult != nil { + sarifResults = append(sarifResults, sarifResult...) + } + } + } + return sarifRules, sarifResults +} + +func parseSonar(results *wrappers.ScanResultsCollection) ([]wrappers.SonarIssues, []wrappers.SonarRules) { + var sonarIssues []wrappers.SonarIssues + var sonarRules []wrappers.SonarRules + seenRuleIDs := make(map[string]bool) // Track already added rule IDs + + if results != nil { + for _, result := range results.Results { + var auxRules = initSonarRules(result) + var auxIssue = initSonarIssue(result) + + if !seenRuleIDs[auxRules.ID] { + sonarRules = append(sonarRules, auxRules) + seenRuleIDs[auxRules.ID] = true + } + + engineType := strings.TrimSpace(result.Type) + + if engineType == commonParams.SastType { + auxIssue.PrimaryLocation = parseSonarPrimaryLocation(result) + auxIssue.SecondaryLocations = parseSonarSecondaryLocations(result) + sonarIssues = append(sonarIssues, auxIssue) + } else if engineType == commonParams.KicsType { + auxIssue.PrimaryLocation = parseLocationKics(result) + sonarIssues = append(sonarIssues, auxIssue) + } else if engineType == commonParams.ScaType { + sonarIssuesByLocation := parseScaSonarLocations(result) + sonarIssues = append(sonarIssues, sonarIssuesByLocation...) + } else if wrappers.IsContainersEnabled && engineType == commonParams.ContainersType { + auxIssue.PrimaryLocation = parseContainersSonar(result) + sonarIssues = append(sonarIssues, auxIssue) + } else if strings.HasPrefix(engineType, commonParams.SscsType) { + sscsSonarIssue := parseSscsSonar(result, &auxIssue) + sonarIssues = append(sonarIssues, sscsSonarIssue) + } + } + } + return sonarIssues, sonarRules +} + +func parseContainersSonar(result *wrappers.ScanResult) wrappers.SonarLocation { + var auxLocation wrappers.SonarLocation + auxLocation.FilePath = result.ScanResultData.ImageFilePath + auxLocation.Message = html.UnescapeString(result.Description) + var textRange wrappers.SonarTextRange + textRange.StartColumn = 1 + textRange.EndColumn = 2 + textRange.StartLine = 1 + textRange.EndLine = 2 + auxLocation.TextRange = textRange + return auxLocation +} + +func parseSscsSonar(result *wrappers.ScanResult, sonarIssue *wrappers.SonarIssues) wrappers.SonarIssues { + sonarIssue.PrimaryLocation.FilePath = result.ScanResultData.Filename + + sonarIssue.PrimaryLocation.Message = html.UnescapeString(result.ScanResultData.Remediation) + var textRange wrappers.SonarTextRange + textRange.StartColumn = 1 + textRange.EndColumn = 2 + textRange.StartLine = result.ScanResultData.Line + sonarIssue.PrimaryLocation.TextRange = textRange + return *sonarIssue +} + +func initSonarIssue(result *wrappers.ScanResult) wrappers.SonarIssues { + var sonarIssue wrappers.SonarIssues + engineType := strings.TrimSpace(result.Type) + if engineType == commonParams.SastType { + sonarIssue.RuleID = result.ScanResultData.LanguageName + " - " + result.ScanResultData.QueryName + } else if engineType == commonParams.KicsType { + sonarIssue.RuleID = result.ScanResultData.QueryName + } else if engineType == commonParams.ScaType { + sonarIssue.RuleID = result.ID + } else if wrappers.IsContainersEnabled && engineType == commonParams.ContainersType { + sonarIssue.RuleID = result.ID + } else if strings.HasPrefix(engineType, commonParams.SscsType) { + sonarIssue.RuleID = result.ID + } + + sonarIssue.PrimaryLocation.Message = html.UnescapeString(result.Description) + sonarIssue.EffortMinutes = 0 + + return sonarIssue +} + +func initSonarRules(result *wrappers.ScanResult) wrappers.SonarRules { + var sonarRules wrappers.SonarRules + var sonarImpacts wrappers.SonarImpacts + + sonarImpacts.Severity = sonarSeverities[result.Severity] + sonarImpacts.SoftwareQuality = vulnerabilitySonar + + sonarRules.EngineID = result.Type + sonarRules.CleanCodeAttribute = cleanCodeAttribute + + engineType := strings.TrimSpace(result.Type) + if engineType == commonParams.SastType { + sonarRules.Name = result.ScanResultData.QueryName + sonarRules.Description = html.UnescapeString(result.Description) + sonarRules.ID = result.ScanResultData.LanguageName + " - " + result.ScanResultData.QueryName + } else if engineType == commonParams.KicsType { + sonarRules.Name = result.ScanResultData.QueryName + sonarRules.Description = html.UnescapeString(result.Description) + sonarRules.ID = result.ScanResultData.QueryName + } else if engineType == commonParams.ScaType { + sonarRules.Name = result.ScanResultData.PackageIdentifier + sonarRules.Description = html.UnescapeString(result.Description) + sonarRules.ID = result.ID + } else if wrappers.IsContainersEnabled && engineType == commonParams.ContainersType { + sonarRules.Name = result.ScanResultData.ImageTag + sonarRules.Description = html.UnescapeString(result.Description) + sonarRules.ID = result.ID + } else if strings.HasPrefix(engineType, commonParams.SscsType) { + sonarRules.Name = result.ScanResultData.RuleName + sonarRules.Description = html.UnescapeString(result.ScanResultData.RuleDescription) + sonarRules.ID = result.ID + } + + sonarRules.Impacts = []wrappers.SonarImpacts{sonarImpacts} + + return sonarRules +} + +func parseScaSonarLocations(result *wrappers.ScanResult) []wrappers.SonarIssues { + if result == nil || result.ScanResultData.ScaPackageCollection == nil || result.ScanResultData.ScaPackageCollection.Locations == nil { + return []wrappers.SonarIssues{} + } + + var issuesByLocation []wrappers.SonarIssues + + for _, location := range result.ScanResultData.ScaPackageCollection.Locations { + issueByLocation := initSonarIssue(result) + + var primaryLocation wrappers.SonarLocation + + primaryLocation.FilePath = *location + _, _, primaryLocation.Message = findRuleID(result) + + var textRange wrappers.SonarTextRange + textRange.StartColumn = 1 + textRange.EndColumn = 2 + textRange.StartLine = 1 + textRange.EndLine = 2 + + primaryLocation.TextRange = textRange + + issueByLocation.PrimaryLocation = primaryLocation + + issuesByLocation = append(issuesByLocation, issueByLocation) + } + + return issuesByLocation +} + +func parseLocationKics(results *wrappers.ScanResult) wrappers.SonarLocation { + var auxLocation wrappers.SonarLocation + auxLocation.FilePath = strings.TrimLeft(results.ScanResultData.Filename, "/") + auxLocation.Message = html.UnescapeString(results.ScanResultData.Value) + var auxTextRange wrappers.SonarTextRange + auxTextRange.StartLine = results.ScanResultData.Line + auxTextRange.StartColumn = 0 + auxTextRange.EndColumn = 1 + auxLocation.TextRange = auxTextRange + return auxLocation +} + +func parseSonarPrimaryLocation(results *wrappers.ScanResult) wrappers.SonarLocation { + var auxLocation wrappers.SonarLocation + // fill the details in the primary Location + if len(results.ScanResultData.Nodes) > 0 { + auxLocation.FilePath = strings.TrimLeft(results.ScanResultData.Nodes[0].FileName, "/") + auxLocation.Message = html.UnescapeString(strings.ReplaceAll(results.ScanResultData.QueryName, "_", " ")) + auxLocation.TextRange = parseSonarTextRange(results.ScanResultData.Nodes[0]) + } + return auxLocation +} + +func parseSonarSecondaryLocations(results *wrappers.ScanResult) []wrappers.SonarLocation { + var auxSecondaryLocations []wrappers.SonarLocation + // Traverse all the rest of the scan result nodes into secondary location of sonar + if len(results.ScanResultData.Nodes) >= 1 { + for _, node := range results.ScanResultData.Nodes[1:] { + var auxSecondaryLocation wrappers.SonarLocation + auxSecondaryLocation.FilePath = strings.TrimLeft(node.FileName, "/") + auxSecondaryLocation.Message = html.UnescapeString(strings.ReplaceAll(results.ScanResultData.QueryName, "_", " ")) + auxSecondaryLocation.TextRange = parseSonarTextRange(node) + auxSecondaryLocations = append(auxSecondaryLocations, auxSecondaryLocation) + } + } + return auxSecondaryLocations +} + +func parseSonarTextRange(results *wrappers.ScanResultNode) wrappers.SonarTextRange { + var auxTextRange wrappers.SonarTextRange + auxTextRange.StartLine = results.Line + startColumn := getSastStartColumn(results.Column) + + auxTextRange.StartColumn = startColumn + auxTextRange.EndColumn = startColumn + results.Length + + if auxTextRange.StartColumn == auxTextRange.EndColumn { + auxTextRange.EndColumn++ + } + + return auxTextRange +} + +func findRule(ruleIds map[interface{}]bool, result *wrappers.ScanResult) *wrappers.SarifDriverRule { + var sarifRule wrappers.SarifDriverRule + sarifRule.ID, sarifRule.Name, _ = findRuleID(result) + sarifRule.FullDescription = findFullDescription(result) + sarifRule.Help = findHelp(result) + sarifRule.HelpURI = findHelpURI(result) + sarifRule.Properties = findProperties(result) + + if !ruleIds[sarifRule.ID] { + ruleIds[sarifRule.ID] = true + return &sarifRule + } + + return nil +} + +func getSastStartColumn(column uint) uint { + if column == 0 { + return 0 + } + return column - 1 +} + +func findRuleID(result *wrappers.ScanResult) (ruleID, ruleName, shortMessage string) { + caser := cases.Title(language.English) + + if result.ScanResultData.QueryID == nil && result.ScanResultData.RuleID == nil { + return fmt.Sprintf("%s (%s)", result.ID, result.Type), + caser.String(strings.ToLower(strings.ReplaceAll(result.ID, "-", ""))), + html.UnescapeString(fmt.Sprintf("%s (%s)", result.ScanResultData.PackageIdentifier, result.ID)) + } + + if result.ScanResultData.RuleID != nil { + ruleName = strings.ReplaceAll(result.ScanResultData.RuleName, "_", " ") + return fmt.Sprintf("%s - %s (%s)", ruleName, *result.ScanResultData.RuleID, result.Type), + ruleName, + ruleName + } + + ruleName = strings.ReplaceAll(result.ScanResultData.QueryName, "_", " ") + return fmt.Sprintf("%v - %s (%s)", ruleName, result.ScanResultData.QueryID, result.Type), + ruleName, + ruleName +} + +func findFullDescription(result *wrappers.ScanResult) wrappers.SarifDescription { + var sarifDescription wrappers.SarifDescription + sarifDescription.Text = findDescriptionText(result) + return sarifDescription +} + +func findHelp(result *wrappers.ScanResult) wrappers.SarifHelp { + var sarifHelp wrappers.SarifHelp + sarifHelp.Text = findHelpText(result) + sarifHelp.Markdown = findHelpMarkdownText(result) + + return sarifHelp +} + +func findHelpURI(result *wrappers.ScanResult) string { + if strings.HasPrefix(result.Type, commonParams.SscsType) { + if result.ScanResultData.RemediationLink != "" { + return result.ScanResultData.RemediationLink + } + } + + return wrappers.SarifInformationURI +} + +func findDescriptionText(result *wrappers.ScanResult) string { + if result.Type == commonParams.KicsType { + return fmt.Sprintf( + "%s Value: %s Excepted value: %s", + result.Description, result.ScanResultData.Value, result.ScanResultData.ExpectedValue, + ) + } else if strings.HasPrefix(result.Type, commonParams.SscsType) { + return result.ScanResultData.RuleDescription + } + + return result.Description +} + +func findHelpText(result *wrappers.ScanResult) string { + if strings.HasPrefix(result.Type, commonParams.SscsType) { + return findHelpMarkdownText(result) + } + + return findDescriptionText(result) +} + +func findHelpMarkdownText(result *wrappers.ScanResult) string { + if result.Type == commonParams.KicsType { + return fmt.Sprintf( + "%s

Value: %s
Excepted value: %s", + result.Description, result.ScanResultData.Value, result.ScanResultData.ExpectedValue, + ) + } else if strings.HasPrefix(result.Type, commonParams.SscsType) { + return result.ScanResultData.Remediation + } + + return result.Description +} + +func findProperties(result *wrappers.ScanResult) wrappers.SarifProperties { + var sarifProperties wrappers.SarifProperties + sarifProperties.ID, sarifProperties.Name, _ = findRuleID(result) + sarifProperties.Description = findDescriptionText(result) + sarifProperties.SecuritySeverity = securities[result.Severity] + sarifProperties.Tags = []string{"security", "checkmarx", result.Type} + return sarifProperties +} + +func findSarifLevel(result *wrappers.ScanResult) string { + level := map[string]string{ + infoCx: infoLowSarif, + lowCx: infoLowSarif, + mediumCx: mediumSarif, + highCx: highSarif, + criticalCx: highSarif, + } + return level[result.Severity] +} + +func initSarifResult(result *wrappers.ScanResult) wrappers.SarifScanResult { + var scanResult wrappers.SarifScanResult + scanResult.RuleID, _, scanResult.Message.Text = findRuleID(result) + scanResult.Level = findSarifLevel(result) + scanResult.Locations = []wrappers.SarifLocation{} + + return scanResult +} + +func findResult(result *wrappers.ScanResult) []wrappers.SarifScanResult { + var scanResults []wrappers.SarifScanResult + + if len(result.ScanResultData.Nodes) > 0 { + scanResults = parseSarifResultSast(result, scanResults) + } else if result.Type == commonParams.KicsType { + scanResults = parseSarifResultKics(result, scanResults) + } else if result.Type == commonParams.ScaType { + scanResults = parseSarifResultsSca(result, scanResults) + } else if result.Type == commonParams.ContainersType && wrappers.IsContainersEnabled { + scanResults = parseSarifResultsContainers(result, scanResults) + } else if strings.HasPrefix(result.Type, commonParams.SscsType) { + scanResults = parseSarifResultsSscs(result, scanResults) + } + + if len(scanResults) > 0 { + return scanResults + } + return nil +} + +func parseSarifResultsContainers(result *wrappers.ScanResult, scanResults []wrappers.SarifScanResult) []wrappers.SarifScanResult { + var scanResult = initSarifResult(result) + var scanLocation wrappers.SarifLocation + + scanLocation.PhysicalLocation.ArtifactLocation.URI = result.ScanResultData.ImageFilePath + scanLocation.PhysicalLocation.Region = &wrappers.SarifRegion{} + scanLocation.PhysicalLocation.Region.StartLine = 1 + scanLocation.PhysicalLocation.Region.StartColumn = 1 + scanLocation.PhysicalLocation.Region.EndColumn = 2 + scanResult.Locations = append(scanResult.Locations, scanLocation) + + scanResults = append(scanResults, scanResult) + return scanResults +} + +func parseSarifResultsSca(result *wrappers.ScanResult, scanResults []wrappers.SarifScanResult) []wrappers.SarifScanResult { + if result == nil || result.ScanResultData.ScaPackageCollection == nil || result.ScanResultData.ScaPackageCollection.Locations == nil { + return scanResults + } + for _, location := range result.ScanResultData.ScaPackageCollection.Locations { + var scanResult = initSarifResult(result) + + var scanLocation wrappers.SarifLocation + scanLocation.PhysicalLocation.ArtifactLocation.URI = *location + scanLocation.PhysicalLocation.Region = &wrappers.SarifRegion{} + scanLocation.PhysicalLocation.Region.StartLine = 1 + scanLocation.PhysicalLocation.Region.StartColumn = 1 + scanLocation.PhysicalLocation.Region.EndColumn = 2 + scanResult.Locations = append(scanResult.Locations, scanLocation) + + scanResults = append(scanResults, scanResult) + } + return scanResults +} + +func parseSarifResultKics(result *wrappers.ScanResult, scanResults []wrappers.SarifScanResult) []wrappers.SarifScanResult { + var scanResult = initSarifResult(result) + var scanLocation wrappers.SarifLocation + + scanLocation.PhysicalLocation.ArtifactLocation.URI = strings.Replace( + result.ScanResultData.Filename, + "/", + "", + 1, + ) + scanLocation.PhysicalLocation.Region = &wrappers.SarifRegion{} + scanLocation.PhysicalLocation.Region.StartLine = result.ScanResultData.Line + scanLocation.PhysicalLocation.Region.StartColumn = 1 + scanLocation.PhysicalLocation.Region.EndColumn = 2 + scanResult.Locations = append(scanResult.Locations, scanLocation) + + scanResults = append(scanResults, scanResult) + return scanResults +} + +func parseSarifResultSast(result *wrappers.ScanResult, scanResults []wrappers.SarifScanResult) []wrappers.SarifScanResult { + if result == nil || result.ScanResultData.Nodes == nil { + return scanResults + } + var scanResult = initSarifResult(result) + + var allLocations []wrappers.SarifLocation + for _, node := range result.ScanResultData.Nodes { + var scanLocation wrappers.SarifLocation + if len(node.FileName) >= sarifNodeFileLength { + scanLocation.PhysicalLocation.ArtifactLocation.URI = node.FileName[1:] + if node.Line <= 0 { + continue + } + scanLocation.PhysicalLocation.Region = &wrappers.SarifRegion{} + scanLocation.PhysicalLocation.Region.StartLine = node.Line + column := node.Column + length := node.Length + scanLocation.PhysicalLocation.Region.StartColumn = column + scanLocation.PhysicalLocation.Region.EndColumn = column + length + + allLocations = append(allLocations, scanLocation) + } + } + + if len(allLocations) > 0 { + var threadFlowLocations []wrappers.SarifThreadFlowLocation + for _, loc := range allLocations { + threadFlowLocations = append(threadFlowLocations, wrappers.SarifThreadFlowLocation{Location: loc}) + } + scanResult.CodeFlows = []wrappers.SarifCodeFlow{ + { + ThreadFlows: []wrappers.SarifThreadFlow{ + { + Locations: threadFlowLocations, + }, + }, + }, + } + } + + scanResults = append(scanResults, scanResult) + return scanResults +} + +func parseSarifResultsSscs(result *wrappers.ScanResult, scanResults []wrappers.SarifScanResult) []wrappers.SarifScanResult { + var scanResult = initSarifResult(result) + scanResult.Message.Text = result.Description + + var scanLocation wrappers.SarifLocation + + trimOsSeparatorFromFileName(result) + if result.Type == commonParams.SCSScorecardType && result.ScanResultData.Filename == noFileForScorecardResultString { + scanLocation.PhysicalLocation.ArtifactLocation.URI = artifactLocationURIString + scanLocation.PhysicalLocation.ArtifactLocation.Description = &wrappers.SarifMessage{} + scanLocation.PhysicalLocation.ArtifactLocation.Description.Text = result.ScanResultData.Filename + } else { + scanLocation.PhysicalLocation.ArtifactLocation.URI = result.ScanResultData.Filename + } + + scanLocation.PhysicalLocation.Region = &wrappers.SarifRegion{} + scanLocation.PhysicalLocation.Region.StartLine = result.ScanResultData.Line + scanLocation.PhysicalLocation.Region.StartColumn = 1 + scanLocation.PhysicalLocation.Region.EndColumn = 2 + if result.ScanResultData.Snippet != "" { + scanLocation.PhysicalLocation.Region.Snippet = &wrappers.SarifSnippet{} + scanLocation.PhysicalLocation.Region.Snippet.Text = result.ScanResultData.Snippet + } + + scanResult.Locations = append(scanResult.Locations, scanLocation) + + var properties wrappers.SarifResultProperties + properties.Severity = result.Severity + properties.Validity = result.ScanResultData.Validity + properties.IsInSource = result.ScanResultData.IsInSource + properties.CommitURL = result.ScanResultData.CommitURL + scanResult.Properties = &properties + + scanResults = append(scanResults, scanResult) + return scanResults +} + +func convertNotAvailableNumberToZero(summary *wrappers.ResultSummary) { + if summary.KicsIssues == notAvailableNumber { + summary.KicsIssues = 0 + } else if summary.SastIssues == notAvailableNumber { + summary.SastIssues = 0 + } else if summary.ScaIssues == notAvailableNumber { + summary.ScaIssues = 0 + } else if wrappers.IsContainersEnabled && *summary.ContainersIssues == notAvailableNumber { + *summary.ContainersIssues = 0 + } +} + +func buildAuxiliaryScaMaps(resultsModel *wrappers.ScanResultsCollection, scaPackageModel *[]wrappers.ScaPackageCollection, + scaTypeModel *[]wrappers.ScaTypeCollection) (locationsByID map[string][]*string, typesByCVE map[string]wrappers.ScaTypeCollection) { + locationsByID = make(map[string][]*string) + typesByCVE = make(map[string]wrappers.ScaTypeCollection) + // Create map to be used to populate locations for each package path + for _, result := range resultsModel.Results { + if result.Type == commonParams.ScaType { + for i := range *scaPackageModel { + pkg := &(*scaPackageModel)[i] + locationsByID[pkg.ID] = pkg.Locations + } + for _, types := range *scaTypeModel { + identifier := fmt.Sprintf("%s:%s", types.ID, types.PackageID) + typesByCVE[identifier] = types + } + } + } + return locationsByID, typesByCVE +} + +func buildScaType(typesByCVE map[string]wrappers.ScaTypeCollection, result *wrappers.ScanResult) string { + identifier := buildVulnerabilityIdentifier(result) + types, ok := typesByCVE[identifier] + if ok && types.Type == "SupplyChain" { + return "Supply Chain" + } + return "Vulnerability" +} + +func buildScaState(typesByCVE map[string]wrappers.ScaTypeCollection, result *wrappers.ScanResult) string { + identifier := buildVulnerabilityIdentifier(result) + types, ok := typesByCVE[identifier] + if ok && types.IsIgnored { + return notExploitable + } + return result.State +} + +func buildVulnerabilityIdentifier(result *wrappers.ScanResult) string { + return fmt.Sprintf("%s:%s", result.ID, result.ScanResultData.PackageIdentifier) +} + +func addPackageInformation( + resultsModel *wrappers.ScanResultsCollection, + scaPackageModel *[]wrappers.ScaPackageCollection, + scaTypeModel *[]wrappers.ScaTypeCollection, +) *wrappers.ScanResultsCollection { + locationsByID, typesByCVE := buildAuxiliaryScaMaps(resultsModel, scaPackageModel, scaTypeModel) + scaPackageMap := buildScaPackageMap(*scaPackageModel) + + for _, result := range resultsModel.Results { + if result.Type == commonParams.ScaType { + processResult(result, locationsByID, typesByCVE, scaPackageMap) + } + } + + return resultsModel +} + +func processResult( + result *wrappers.ScanResult, + locationsByID map[string][]*string, + typesByCVE map[string]wrappers.ScaTypeCollection, + scaPackageMap map[string]wrappers.ScaPackageCollection, // Updated parameter +) { + const precision = 1 + + currentID := result.ScanResultData.PackageIdentifier + result.VulnerabilityDetails.CvssScore = util.RoundFloat(result.VulnerabilityDetails.CvssScore, precision) + result.ScaType = buildScaType(typesByCVE, result) + result.State = buildScaState(typesByCVE, result) + + updatePackages(result, scaPackageMap, locationsByID, currentID) +} + +func updatePackages( + result *wrappers.ScanResult, + scaPackageMap map[string]wrappers.ScaPackageCollection, + locationsByID map[string][]*string, + currentID string, +) { + packages, found := scaPackageMap[currentID] + if !found { + return + } + + updateDependencyPaths(packages.DependencyPathArray, locationsByID) + if !packages.SupportsQuickFix { + packages.SupportsQuickFix = hasQuickFix(packages.DependencyPathArray) + } + + if packages.IsDirectDependency { + packages.TypeOfDependency = directDependencyType + } else { + packages.TypeOfDependency = indirectDependencyType + } + + packages.FixLink = buildFixLink(result) + result.ScanResultData.ScaPackageCollection = &packages +} + +func hasQuickFix(dependencyPaths [][]wrappers.DependencyPath) bool { + for i := range dependencyPaths { + head := &dependencyPaths[i][0] + if head.SupportsQuickFix { + return true + } + } + return false +} + +func buildScaPackageMap(scaPackageModel []wrappers.ScaPackageCollection) map[string]wrappers.ScaPackageCollection { + scaPackageMap := make(map[string]wrappers.ScaPackageCollection) + for i := range scaPackageModel { + scaPackageMap[scaPackageModel[i].ID] = scaPackageModel[i] + } + return scaPackageMap +} + +func updateDependencyPaths(dependencyPaths [][]wrappers.DependencyPath, locationsByID map[string][]*string) { + for i := range dependencyPaths { + head := &dependencyPaths[i][0] + head.Locations = locationsByID[head.ID] + head.SupportsQuickFix = len(dependencyPaths[i]) == 1 + + for _, location := range locationsByID[head.ID] { + head.SupportsQuickFix = head.SupportsQuickFix && util.IsPackageFileSupported(*location) + } + } +} + +func buildFixLink(result *wrappers.ScanResult) string { + if result.ID != "" { + return fmt.Sprint(fixLinkPrefix, result.ID) + } + return "" +} + +func filterViolatedRules(policyModel wrappers.PolicyResponseModel) *wrappers.PolicyResponseModel { + i := 0 + for _, policy := range policyModel.Policies { + if len(policy.RulesViolated) > 0 { + policyModel.Policies[i] = policy + i++ + } + } + policyModel.Policies = policyModel.Policies[:i] + return &policyModel +} + +func trimOsSeparatorFromFileName(result *wrappers.ScanResult) { + if result.ScanResultData.Filename != "" { + result.ScanResultData.Filename = strings.TrimPrefix(result.ScanResultData.Filename, "/") + result.ScanResultData.Filename = strings.TrimPrefix(result.ScanResultData.Filename, "\\") + } +} + +// ScannerResponse is the per-scanner status info returned by the results exit-code subcommand. +type ScannerResponse struct { + ScanID string `json:"ScanID,omitempty"` + Name string `json:"Name,omitempty"` + Status string `json:"Status,omitempty"` + Details string `json:"Details,omitempty"` + ErrorCode string `json:"ErrorCode,omitempty"` +} + +func parseURI(summaryBaseURI string) (hostName string) { + parsedURL, err := url.Parse(summaryBaseURI) + if err != nil { + return "" + } + hostName = fmt.Sprintf("%s://%s", parsedURL.Scheme, parsedURL.Host) + + return hostName +} + +func printWarningIfIgnorePolicyOmiited() { + fmt.Printf("\n Warning: The --ignore-policy flag was not implemented because you do not have the required permission.\n Only users with 'override-policy-management' permission can use this flag. \n\n") +} + +func getFilterResultsForAPISecScanner(risksOverviewWrapper wrappers.RisksOverviewWrapper, scanID string, resultsParams map[string]string) (aPISecSeveritySummary *wrappers.APISecFilteredResult, err error) { + var apiSecRiskEntriesResult wrappers.APISecRiskEntriesResult + var errorModel *wrappers.WebError + + apiSecRiskEntriesResult, errorModel, err = risksOverviewWrapper.GetFilterResultForAPISecByScanID(scanID, resultsParams) + if err != nil { + return nil, errors.Wrapf(err, "%s", failedListingResults) + } + if errorModel != nil { + return nil, errors.Errorf("%s: CODE: %d, %s", failedListingResults, errorModel.Code, errorModel.Message) + } + if len(apiSecRiskEntriesResult.Entries) > 0 { + entries := apiSecRiskEntriesResult.Entries + severityCount := make(map[string]int) + originCount := make(map[string]int) + totalRecords := 0 + for i := range entries { + entry := &entries[i] + if !isExploitable(entry.State) { + continue + } + sev := strings.ToLower(entry.Severity) + severityCount[sev]++ + orig := strings.ToLower(entry.Origin) + originCount[orig]++ + totalRecords++ + } + var riskDistribution []wrappers.RiskDistributionEntry + if originCount[originCode] > 0 { + riskDistribution = append(riskDistribution, wrappers.RiskDistributionEntry{Origin: originCode, Total: originCount[originCode]}) + } + if originCount[originDocumentation] > 0 { + riskDistribution = append(riskDistribution, wrappers.RiskDistributionEntry{Origin: originDocumentation, Total: originCount[originDocumentation]}) + } + return &wrappers.APISecFilteredResult{ + SeverityCount: severityCount, + RiskDistribution: riskDistribution, + TotalRisksCount: totalRecords, + }, nil + } + return nil, nil +} diff --git a/internal/commands/result_test.go b/internal/commands/result_test.go index dc0063351..5bd0fe670 100644 --- a/internal/commands/result_test.go +++ b/internal/commands/result_test.go @@ -1591,7 +1591,8 @@ func TestIgnorePolicyWithNoPermission(t *testing.T) { t.Fatalf("failed to copy output: %v", err) // Handle the error if io.Copy fails } output := buf.String() - assert.Assert(t, strings.Contains(output, "Warning: The --ignore-policy flag was not implemented because you don’t have the required permission."), "'Ignore Policy flag omitted because you dont have permission' should not be present in the output") + expectedWarning := "Warning: The --ignore-policy flag was not implemented because you do not have the required permission." + assert.Assert(t, strings.Contains(output, expectedWarning), "’Ignore Policy flag omitted because you dont have permission’ should not be present in the output") } func TestIgnorePolicyWithPermission(t *testing.T) { @@ -1625,7 +1626,8 @@ func TestIgnorePolicyWithPermission(t *testing.T) { t.Fatalf("failed to copy output: %v", err) // Handle the error if io.Copy fails } output := buf.String() - assert.Assert(t, !strings.Contains(output, "Warning: The --ignore-policy flag was not implemented because you don’t have the required permission."), "'Ignore Policy flag omitted because you dont have permission' should not be present in the output") + expectedWarning := "Warning: The --ignore-policy flag was not implemented because you do not have the required permission." + assert.Assert(t, !strings.Contains(output, expectedWarning), "’Ignore Policy flag omitted because you dont have permission’ should not be present in the output") } func TestParseGlSastVulnerability_QueryDescriptionLink_Succeed(t *testing.T) { From f2eb1ad48a3abe453c3bcd6161bc05d48a0f3baa Mon Sep 17 00:00:00 2001 From: atishj99 <141334503+cx-atish-jadhav@users.noreply.github.com> Date: Thu, 28 May 2026 21:06:27 +0530 Subject: [PATCH 11/27] Fix CVE vulnerabilities and lint issues - Upgrade golang.org/x/image to v0.39.0 (CVE-2026-33813) - Upgrade github.com/go-jose/go-jose/v3 to v3.0.5 (CVE-2026-34986) - Upgrade github.com/opencontainers/runc to v1.3.4 (CVE-2025-52881) - Extract repeated string to constant in result_test.go (goconst lint fix) --- go.mod | 17 ++++++++++ go.sum | 54 ++++++++++++++++++++++++++++++++ internal/commands/result_test.go | 25 +++++++-------- 3 files changed, 83 insertions(+), 13 deletions(-) diff --git a/go.mod b/go.mod index 593b653b0..6e8afd8c1 100644 --- a/go.mod +++ b/go.mod @@ -45,6 +45,7 @@ require ( cloud.google.com/go/iam v1.5.3 // indirect cloud.google.com/go/monitoring v1.24.3 // indirect cloud.google.com/go/storage v1.61.3 // indirect + cyphar.com/go-pathrs v0.2.1 // indirect github.com/GoogleCloudPlatform/opentelemetry-operations-go/detectors/gcp v1.31.0 // indirect github.com/GoogleCloudPlatform/opentelemetry-operations-go/exporter/metric v0.55.0 // indirect github.com/GoogleCloudPlatform/opentelemetry-operations-go/internal/resourcemapping v0.55.0 // indirect @@ -78,17 +79,24 @@ require ( github.com/bodgit/sevenzip v1.6.1 // indirect github.com/bodgit/windows v1.0.1 // indirect github.com/cespare/xxhash/v2 v2.3.0 // indirect + github.com/checkpoint-restore/go-criu/v6 v6.3.0 // indirect + github.com/cilium/ebpf v0.17.3 // indirect github.com/clipperhouse/displaywidth v0.10.0 // indirect github.com/clipperhouse/uax29/v2 v2.6.0 // indirect github.com/cncf/xds/go v0.0.0-20251210132809-ee656c7534f5 // indirect + github.com/containerd/console v1.0.5 // indirect github.com/containerd/containerd/v2 v2.3.1 // indirect github.com/containerd/plugin v1.1.0 // indirect + github.com/coreos/go-systemd/v22 v22.7.0 // indirect + github.com/cpuguy83/go-md2man/v2 v2.0.7 // indirect github.com/diskfs/go-diskfs v1.7.0 // indirect github.com/distribution/distribution/v3 v3.1.1 // indirect github.com/envoyproxy/go-control-plane/envoy v1.36.0 // indirect github.com/envoyproxy/protoc-gen-validate v1.3.0 // indirect + github.com/go-jose/go-jose/v3 v3.0.5 // indirect github.com/go-jose/go-jose/v4 v4.1.4 // indirect github.com/goccy/go-yaml v1.19.2 // indirect + github.com/godbus/dbus/v5 v5.1.0 // indirect github.com/gohugoio/hashstructure v0.6.0 // indirect github.com/google/s2a-go v0.1.9 // indirect github.com/googleapis/enterprise-certificate-proxy v0.3.14 // indirect @@ -106,17 +114,26 @@ require ( github.com/minio/minlz v1.0.1 // indirect github.com/moby/moby/api v1.54.1 // indirect github.com/moby/moby/client v0.4.0 // indirect + github.com/moby/sys/capability v0.4.0 // indirect + github.com/mrunalp/fileutils v0.5.1 // indirect github.com/nix-community/go-nix v0.0.0-20250101154619-4bdde671e0a1 // indirect github.com/nwaples/rardecode/v2 v2.2.0 // indirect github.com/olekukonko/cat v0.0.0-20250911104152-50322a0618f6 // indirect github.com/olekukonko/errors v1.2.0 // indirect github.com/olekukonko/ll v0.1.6 // indirect + github.com/opencontainers/cgroups v0.0.4 // indirect + github.com/opencontainers/runc v1.3.4 // indirect + github.com/opencontainers/selinux v1.13.1 // indirect github.com/pkg/xattr v0.4.9 // indirect github.com/planetscale/vtprotobuf v0.6.1-0.20240319094008-0393e58bdf10 // indirect github.com/prometheus/procfs v0.20.1 // indirect + github.com/seccomp/libseccomp-golang v0.10.0 // indirect github.com/smallnest/ringbuffer v0.0.0-20241116012123-461381446e3d // indirect github.com/sorairolake/lzip-go v0.3.8 // indirect github.com/spiffe/go-spiffe/v2 v2.6.0 // indirect + github.com/urfave/cli v1.22.16 // indirect + github.com/vishvananda/netlink v1.3.1 // indirect + github.com/vishvananda/netns v0.0.5 // indirect go.opentelemetry.io/contrib/detectors/gcp v1.39.0 // indirect go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.68.0 // indirect go.opentelemetry.io/otel/exporters/stdout/stdoutmetric v1.42.0 // indirect diff --git a/go.sum b/go.sum index 0a4e739f9..cdf0a48f3 100644 --- a/go.sum +++ b/go.sum @@ -67,6 +67,8 @@ cloud.google.com/go/storage v1.61.3 h1:VS//ZfBuPGDvakfD9xyPW1RGF1Vy3BWUoVZXgW1KM cloud.google.com/go/storage v1.61.3/go.mod h1:JtqK8BBB7TWv0HVGHubtUdzYYrakOQIsMLffZ2Z/HWk= cloud.google.com/go/trace v1.11.7 h1:kDNDX8JkaAG3R2nq1lIdkb7FCSi1rCmsEtKVsty7p+U= cloud.google.com/go/trace v1.11.7/go.mod h1:TNn9d5V3fQVf6s4SCveVMIBS2LJUqo73GACmq/Tky0s= +cyphar.com/go-pathrs v0.2.1 h1:9nx1vOgwVvX1mNBWDu93+vaceedpbsDqo+XuBGL40b8= +cyphar.com/go-pathrs v0.2.1/go.mod h1:y8f1EMG7r+hCuFf/rXsKqMJrJAUoADZGNh5/vZPKcGc= dario.cat/mergo v1.0.2 h1:85+piFYR1tMbRrLcDwR18y4UKJ3aH1Tbzi24VRW1TK8= dario.cat/mergo v1.0.2/go.mod h1:E/hbnu0NxMFBjpMIE34DRGLWqDy0g5FuKDhCb31ngxA= dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU= @@ -80,6 +82,7 @@ github.com/BobuSumisu/aho-corasick v1.0.3 h1:uuf+JHwU9CHP2Vx+wAy6jcksJThhJS9ehR8 github.com/BobuSumisu/aho-corasick v1.0.3/go.mod h1:hm4jLcvZKI2vRF2WDU1N4p/jpWtpOzp3nLmi9AzX/XE= github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= github.com/BurntSushi/toml v0.4.1/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbicEuybxQ= +github.com/BurntSushi/toml v1.4.0/go.mod h1:ukJfTF/6rtPPRCnwkur4qwRxa8vTRFBF0uk2lLoLwho= github.com/BurntSushi/toml v1.6.0 h1:dRaEfpa2VI55EwlIW72hMRHdWouJeRF7TPYhI+AUQjk= github.com/BurntSushi/toml v1.6.0/go.mod h1:ukJfTF/6rtPPRCnwkur4qwRxa8vTRFBF0uk2lLoLwho= github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo= @@ -297,6 +300,8 @@ github.com/charmbracelet/x/term v0.2.2 h1:xVRT/S2ZcKdhhOuSP4t5cLi5o+JxklsoEObBSg github.com/charmbracelet/x/term v0.2.2/go.mod h1:kF8CY5RddLWrsgVwpw4kAa6TESp6EB5y3uxGLeCqzAI= github.com/checkmarx/2ms/v3 v3.21.0 h1:EcabeDypNMsSidISQbziZ062HjMZQ+Hm/uOJ5AOxK8o= github.com/checkmarx/2ms/v3 v3.21.0/go.mod h1:e8f4F94MZ+iCetR/G3aw7nXdPe6TgPI92Zzk/NG1l0o= +github.com/checkpoint-restore/go-criu/v6 v6.3.0 h1:mIdrSO2cPNWQY1truPg6uHLXyKHk3Z5Odx4wjKOASzA= +github.com/checkpoint-restore/go-criu/v6 v6.3.0/go.mod h1:rrRTN/uSwY2X+BPRl/gkulo9gsKOSAeVp9/K2tv7xZI= github.com/chromedp/cdproto v0.0.0-20230802225258-3cf4e6d46a89/go.mod h1:GKljq0VrfU4D5yc+2qA6OVr8pmO/MBbPEWqWQ/oqGEs= github.com/chromedp/chromedp v0.9.2/go.mod h1:LkSXJKONWTCHAfQasKFUZI+mxqS4tZqhmtGzzhLsnLs= github.com/chromedp/sysutil v1.0.0/go.mod h1:kgWmDdq8fTzXYcKIBqIYvRRTnYb9aNS9moAV0xufSww= @@ -306,6 +311,8 @@ github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5P github.com/chzyer/readline v1.5.1/go.mod h1:Eh+b79XXUwfKfcPLepksvw2tcLE/Ct21YObkaSkeBlk= github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU= github.com/chzyer/test v1.0.0/go.mod h1:2JlltgoNkt4TW/z9V/IzDdFaMTM2JPIi26O1pF38GC8= +github.com/cilium/ebpf v0.17.3 h1:FnP4r16PWYSE4ux6zN+//jMcW4nMVRvuTLVTvCjyyjg= +github.com/cilium/ebpf v0.17.3/go.mod h1:G5EDHij8yiLzaqn0WjyfJHvRa+3aDlReIaLVRMvOyJk= github.com/circonus-labs/circonus-gometrics v2.3.1+incompatible/go.mod h1:nmEj6Dob7S7YxXgwXpfOuvO54S+tGdZdw9fuRZt25Ag= github.com/circonus-labs/circonusllhist v0.1.3/go.mod h1:kMXHVDlOchFAehlya5ePtbp5jckzBHf4XRpQvBOLI+I= github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= @@ -329,6 +336,8 @@ github.com/cncf/xds/go v0.0.0-20251210132809-ee656c7534f5 h1:6xNmx7iTtyBRev0+D/T github.com/cncf/xds/go v0.0.0-20251210132809-ee656c7534f5/go.mod h1:KdCmV+x/BuvyMxRnYBlmVaq4OLiKW6iRQfvC62cvdkI= github.com/containerd/cgroups/v3 v3.1.3 h1:eUNflyMddm18+yrDmZPn3jI7C5hJ9ahABE5q6dyLYXQ= github.com/containerd/cgroups/v3 v3.1.3/go.mod h1:PKZ2AcWmSBsY/tJUVhtS/rluX0b1uq1GmPO1ElCmbOw= +github.com/containerd/console v1.0.5 h1:R0ymNeydRqH2DmakFNdmjR2k0t7UPuiOV/N/27/qqsc= +github.com/containerd/console v1.0.5/go.mod h1:YynlIjWYF8myEu6sdkwKIvGQq+cOckRm6So2avqoYAk= github.com/containerd/containerd v1.7.32 h1:S54xuVcPxeLaYgaRABtpJ2VyVUVsy0IGf7qHBs+sbY8= github.com/containerd/containerd v1.7.32/go.mod h1:jdwD6s/BhV4XVJGrvtziNPVA+83n66TwptVaPKprq4E= github.com/containerd/containerd/api v1.11.1 h1:h8nfoDW9+fNsC/9TwiAHj8B1GzXKtR4eFtkhi/X5RLU= @@ -361,7 +370,11 @@ github.com/coreos/go-systemd/v22 v22.5.0/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSV github.com/coreos/go-systemd/v22 v22.7.0 h1:LAEzFkke61DFROc7zNLX/WA2i5J8gYqe0rSj9KI28KA= github.com/coreos/go-systemd/v22 v22.7.0/go.mod h1:xNUYtjHu2EDXbsxz1i41wouACIwT7Ybq9o0BQhMwD0w= github.com/cpuguy83/go-md2man/v2 v2.0.1/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= +github.com/cpuguy83/go-md2man/v2 v2.0.2/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= +github.com/cpuguy83/go-md2man/v2 v2.0.5/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= github.com/cpuguy83/go-md2man/v2 v2.0.6/go.mod h1:oOW0eioCTA6cOiMLiUPZOpcVxMig6NIQQ7OS05n1F4g= +github.com/cpuguy83/go-md2man/v2 v2.0.7 h1:zbFlGlXEAKlwXpmvle3d8Oe3YnkKIK4xSRTd3sHPnBo= +github.com/cpuguy83/go-md2man/v2 v2.0.7/go.mod h1:oOW0eioCTA6cOiMLiUPZOpcVxMig6NIQQ7OS05n1F4g= github.com/creack/pty v1.1.24 h1:bJrF4RRfyJnbTJqzRLHzcGaZK1NeM5kTC9jGgovnR1s= github.com/creack/pty v1.1.24/go.mod h1:08sCNb52WyoAwi2QDyzUCTgcvVFhUzewun7wtTfvcwE= github.com/cyphar/filepath-securejoin v0.6.1 h1:5CeZ1jPXEiYt3+Z6zqprSAgSWiggmpVyciv8syjIpVE= @@ -495,6 +508,8 @@ github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2 github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= github.com/go-gorp/gorp/v3 v3.1.0 h1:ItKF/Vbuj31dmV4jxA1qblpSwkl9g1typ24xoe70IGs= github.com/go-gorp/gorp/v3 v3.1.0/go.mod h1:dLEjIyyRNiXvNZ8PSmzpt1GsWAUK8kjVhEpjH8TixEw= +github.com/go-jose/go-jose/v3 v3.0.5 h1:BLLJWbC4nMZOfuPVxoZIxeYsn6Nl2r1fITaJ78UQlVQ= +github.com/go-jose/go-jose/v3 v3.0.5/go.mod h1:5b+7YgP7ZICgJDBdfjZaIt+H/9L9T/YQrVfLAMboGkQ= github.com/go-jose/go-jose/v4 v4.1.4 h1:moDMcTHmvE6Groj34emNPLs/qtYXRVcd6S7NHbHz3kA= github.com/go-jose/go-jose/v4 v4.1.4/go.mod h1:x4oUasVrzR7071A4TnHLGSPpNOm2a21K9Kf04k1rs08= github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= @@ -534,6 +549,8 @@ github.com/gobwas/ws v1.2.1/go.mod h1:hRKAFb8wOxFROYNsT1bqfWnhX+b5MFeJM9r2ZSwg/K github.com/goccy/go-yaml v1.19.2 h1:PmFC1S6h8ljIz6gMRBopkjP1TVT7xuwrButHID66PoM= github.com/goccy/go-yaml v1.19.2/go.mod h1:XBurs7gK8ATbW4ZPGKgcbrY1Br56PdM69F7LkFRi1kA= github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= +github.com/godbus/dbus/v5 v5.1.0 h1:4KLkAxT3aOY8Li4FRJe/KvhoNFFxo0m6fNuFUO8QJUk= +github.com/godbus/dbus/v5 v5.1.0/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= github.com/gofrs/flock v0.13.0 h1:95JolYOvGMqeH31+FC7D2+uULf6mG61mEZ/A8dRYMzw= github.com/gofrs/flock v0.13.0/go.mod h1:jxeyy9R1auM5S6JYDBhDt+E2TCo7DkratH4Pgi8P+Z0= github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= @@ -599,6 +616,7 @@ github.com/google/go-cmp v0.5.3/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/ github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8= github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU= github.com/google/go-containerregistry v0.21.5 h1:KTJG9Pn/jC0VdZR6ctV3/jcN+q6/Iqlx0sTVz3ywZlM= @@ -873,6 +891,8 @@ github.com/moby/moby/api v1.54.1 h1:TqVzuJkOLsgLDDwNLmYqACUuTehOHRGKiPhvH8V3Nn4= github.com/moby/moby/api v1.54.1/go.mod h1:+RQ6wluLwtYaTd1WnPLykIDPekkuyD/ROWQClE83pzs= github.com/moby/moby/client v0.4.0 h1:S+2XegzHQrrvTCvF6s5HFzcrywWQmuVnhOXe2kiWjIw= github.com/moby/moby/client v0.4.0/go.mod h1:QWPbvWchQbxBNdaLSpoKpCdf5E+WxFAgNHogCWDoa7g= +github.com/moby/sys/capability v0.4.0 h1:4D4mI6KlNtWMCM1Z/K0i7RV1FkX+DBDHKVJpCndZoHk= +github.com/moby/sys/capability v0.4.0/go.mod h1:4g9IK291rVkms3LKCDOoYlnV8xKwoDTpIrNEE35Wq0I= github.com/moby/sys/mountinfo v0.7.2 h1:1shs6aH5s4o5H2zQLn796ADW1wMrIwHsyJ2v9KouLrg= github.com/moby/sys/mountinfo v0.7.2/go.mod h1:1YOa8w8Ih7uW0wALDUgT1dTTSBrZ+HiBLGws92L2RU4= github.com/moby/sys/sequential v0.6.0 h1:qrx7XFUd/5DxtqcoH1h438hF5TmOvzC/lspjy7zgvCU= @@ -895,6 +915,8 @@ github.com/modern-go/reflect2 v1.0.3-0.20250322232337-35a7c28c31ee h1:W5t00kpgFd github.com/modern-go/reflect2 v1.0.3-0.20250322232337-35a7c28c31ee/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk= github.com/monochromegane/go-gitignore v0.0.0-20200626010858-205db1a8cc00 h1:n6/2gBQ3RWajuToeY6ZtZTIKv2v7ThUy5KKusIT0yc0= github.com/monochromegane/go-gitignore v0.0.0-20200626010858-205db1a8cc00/go.mod h1:Pm3mSP3c5uWn86xMLZ5Sa7JB9GsEZySvHYXCTK4E9q4= +github.com/mrunalp/fileutils v0.5.1 h1:F+S7ZlNKnrwHfSwdlgNSkKo67ReVf8o9fel6C3dkm/Q= +github.com/mrunalp/fileutils v0.5.1/go.mod h1:M1WthSahJixYnrXQl/DFQuteStB1weuxD2QJNHXfbSQ= github.com/mssola/user_agent v0.6.0 h1:uwPR4rtWlCHRFyyP9u2KOV0u8iQXmS7Z7feTrstQwk4= github.com/mssola/user_agent v0.6.0/go.mod h1:TTPno8LPY3wAIEKRpAtkdMT0f8SE24pLRGPahjCH4uw= github.com/muesli/ansi v0.0.0-20230316100256-276c6243b2f6 h1:ZK8zHtRHOkbHy6Mmr5D264iyp3TiX5OmNcI5cIARiQI= @@ -926,12 +948,18 @@ github.com/onsi/ginkgo/v2 v2.28.1 h1:S4hj+HbZp40fNKuLUQOYLDgZLwNUVn19N3Atb98NCyI github.com/onsi/ginkgo/v2 v2.28.1/go.mod h1:CLtbVInNckU3/+gC8LzkGUb9oF+e8W8TdUsxPwvdOgE= github.com/onsi/gomega v1.39.1 h1:1IJLAad4zjPn2PsnhH70V4DKRFlrCzGBNrNaru+Vf28= github.com/onsi/gomega v1.39.1/go.mod h1:hL6yVALoTOxeWudERyfppUcZXjMwIMLnuSfruD2lcfg= +github.com/opencontainers/cgroups v0.0.4 h1:XVj8P/IHVms/j+7eh8ggdkTLAxjz84ZzuFyGoE28DR4= +github.com/opencontainers/cgroups v0.0.4/go.mod h1:s8lktyhlGUqM7OSRL5P7eAW6Wb+kWPNvt4qvVfzA5vs= github.com/opencontainers/go-digest v1.0.0 h1:apOUWs51W5PlhuyGyz9FCeeBIOUDA/6nW8Oi/yOhh5U= github.com/opencontainers/go-digest v1.0.0/go.mod h1:0JzlMkj0TRzQZfJkVvzbP0HBR3IKzErnv2BNG4W4MAM= github.com/opencontainers/image-spec v1.1.1 h1:y0fUlFfIZhPF1W537XOLg0/fcx6zcHCJwooC2xJA040= github.com/opencontainers/image-spec v1.1.1/go.mod h1:qpqAh3Dmcf36wStyyWU+kCeDgrGnAve2nCC8+7h8Q0M= +github.com/opencontainers/runc v1.3.4 h1:+lwmPUTzbgv0JFqu8zBU2WtHYbm+JPPS9hxB/PvWd30= +github.com/opencontainers/runc v1.3.4/go.mod h1:o1wyv76EDlTkcf0KTFgN8bMWLPvgF/HfX709lDv+rr4= github.com/opencontainers/runtime-spec v1.3.0 h1:YZupQUdctfhpZy3TM39nN9Ika5CBWT5diQ8ibYCRkxg= github.com/opencontainers/runtime-spec v1.3.0/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0= +github.com/opencontainers/selinux v1.13.0 h1:Zza88GWezyT7RLql12URvoxsbLfjFx988+LGaWfbL84= +github.com/opencontainers/selinux v1.13.0/go.mod h1:XxWTed+A/s5NNq4GmYScVy+9jzXhGBVEOAyucdRUY8s= github.com/orisano/pixelmatch v0.0.0-20220722002657-fb0b55479cde/go.mod h1:nZgzbfBr3hhjoZnS66nKrHmduYNpc34ny7RK4z5/HM0= github.com/pascaldekloe/goe v0.0.0-20180627143212-57f6aae5913c/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc= github.com/pascaldekloe/goe v0.1.0/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc= @@ -1033,6 +1061,8 @@ github.com/scylladb/go-set v1.0.3-0.20200225121959-cc7b2070d91e/go.mod h1:DkpGd7 github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529/go.mod h1:DxrIzT+xaE7yg65j358z/aeFdxmN0P9QXhEzd20vsDc= github.com/sebdah/goldie/v2 v2.8.0 h1:dZb9wR8q5++oplmEiJT+U/5KyotVD+HNGCAc5gNr8rc= github.com/sebdah/goldie/v2 v2.8.0/go.mod h1:oZ9fp0+se1eapSRjfYbsV/0Hqhbuu3bJVvKI/NNtssI= +github.com/seccomp/libseccomp-golang v0.10.0 h1:aA4bp+/Zzi0BnWZ2F1wgNBs5gTpm+na2rWM6M9YjLpY= +github.com/seccomp/libseccomp-golang v0.10.0/go.mod h1:JA8cRccbGaA1s33RQf7Y1+q9gHmZX1yB/z9WDN1C6fg= github.com/sergi/go-diff v1.1.0/go.mod h1:STckp+ISIX8hZLjrqAeVduY0gWCT9IjLuqbuNXdaHfM= github.com/sergi/go-diff v1.2.0/go.mod h1:STckp+ISIX8hZLjrqAeVduY0gWCT9IjLuqbuNXdaHfM= github.com/sergi/go-diff v1.4.0 h1:n/SP9D5ad1fORl+llWyN+D6qoUETXNZARKjyY2/KVCw= @@ -1069,6 +1099,7 @@ github.com/spf13/cast v1.4.1/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkU github.com/spf13/cast v1.10.0 h1:h2x0u2shc1QuLHfxi+cTJvs30+ZAHOGRic8uyGTDWxY= github.com/spf13/cast v1.10.0/go.mod h1:jNfB8QC9IA6ZuY2ZjDp0KtFO2LZZlg4S/7bzP6qqeHo= github.com/spf13/cobra v1.3.0/go.mod h1:BrRVncBjOJa/eUcVVm9CE+oC6as8k+VYr4NY7WCi9V4= +github.com/spf13/cobra v1.5.0/go.mod h1:dWXEIy2H428czQCjInthrTRUg7yKbok+2Qi/yBIJoUM= github.com/spf13/cobra v1.10.2 h1:DMTTonx5m65Ic0GOoRY2c16WCbHxOOw6xxezuLaBpcU= github.com/spf13/cobra v1.10.2/go.mod h1:7C1pvHqHw5A4vrJfjNwvOdzYu0Gml16OCs2GRiTUUS4= github.com/spf13/jwalterweatherman v1.1.0/go.mod h1:aNWZUN0dPAAO/Ljvb5BEdw96iTZ0EXowPYD95IqWIGo= @@ -1096,6 +1127,8 @@ github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/ github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= +github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= +github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= github.com/stretchr/testify v1.11.1 h1:7s2iGBzp5EwR7/aIZr8ao5+dra3wiQyKjjFuvgVKu7U= github.com/stretchr/testify v1.11.1/go.mod h1:wZwfW3scLgRK+23gO65QZefKpKQRnfz6sD981Nm4B6U= github.com/subosito/gotenv v1.2.0/go.mod h1:N0PQaV/YGNqwC0u51sEeR/aUtSLEXKX9iv69rRypqCw= @@ -1123,12 +1156,18 @@ github.com/tv42/httpunix v0.0.0-20150427012821-b75d8614f926/go.mod h1:9ESjWnEqri github.com/ulikunitz/xz v0.5.8/go.mod h1:nbz6k7qbPmH4IRqmfOplQw/tblSgqTqBwxkY0oWt/14= github.com/ulikunitz/xz v0.5.15 h1:9DNdB5s+SgV3bQ2ApL10xRc35ck0DuIX/isZvIk+ubY= github.com/ulikunitz/xz v0.5.15/go.mod h1:nbz6k7qbPmH4IRqmfOplQw/tblSgqTqBwxkY0oWt/14= +github.com/urfave/cli v1.22.16 h1:MH0k6uJxdwdeWQTwhSO42Pwr4YLrNLwBtg1MRgTqPdQ= +github.com/urfave/cli v1.22.16/go.mod h1:EeJR6BKodywf4zciqrdw6hpCPk68JO9z5LazXZMn5Po= github.com/vbatts/go-mtree v0.7.0 h1:ytmOc3MTRidZiBi9VBCyZ2BHe4fZS47L5v7BVXDWW4E= github.com/vbatts/go-mtree v0.7.0/go.mod h1:EjdpFC+LZy1TXbRGNa1MKKgjQ+7ew3foMFJK8o4/TdY= github.com/vbatts/tar-split v0.12.2 h1:w/Y6tjxpeiFMR47yzZPlPj/FcPLpXbTUi/9H7d3CPa4= github.com/vbatts/tar-split v0.12.2/go.mod h1:eF6B6i6ftWQcDqEn3/iGFRFRo8cBIMSJVOpnNdfTMFA= github.com/vifraa/gopom v1.0.0 h1:L9XlKbyvid8PAIK8nr0lihMApJQg/12OBvMA28BcWh0= github.com/vifraa/gopom v1.0.0/go.mod h1:oPa1dcrGrtlO37WPDBm5SqHAT+wTgF8An1Q71Z6Vv4o= +github.com/vishvananda/netlink v1.3.1 h1:3AEMt62VKqz90r0tmNhog0r/PpWKmrEShJU0wJW6bV0= +github.com/vishvananda/netlink v1.3.1/go.mod h1:ARtKouGSTGchR8aMwmkzC0qiNPrrWO5JS/XMVl45+b4= +github.com/vishvananda/netns v0.0.5 h1:DfiHV+j8bA32MFM7bfEunvT8IAqQ/NzSJHtcmW5zdEY= +github.com/vishvananda/netns v0.0.5/go.mod h1:SpkAiCQRtJ6TvvxPnOSyH3BMl6unz3xZlaprSwhNNJM= github.com/wagoodman/go-partybus v0.0.0-20230516145632-8ccac152c651 h1:jIVmlAFIqV3d+DOxazTR9v+zgj8+VYuQBzPgBZvWBHA= github.com/wagoodman/go-partybus v0.0.0-20230516145632-8ccac152c651/go.mod h1:b26F2tHLqaoRQf8DywqzVaV1MQ9yvjb0OMcNl7Nxu20= github.com/wagoodman/go-progress v0.0.0-20260303201901-10176f79b2c0 h1:EHsPe0Q0ANoLOZff1dBLAyeWLTA4sbPTpGI+2zb0FnM= @@ -1256,6 +1295,7 @@ golang.org/x/crypto v0.0.0-20210817164053-32db794688a5/go.mod h1:GvvjBRRGRdwPK5y golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/crypto v0.0.0-20220622213112-05595931fe9d/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= golang.org/x/crypto v0.6.0/go.mod h1:OFC/31mSvZgRz0V1QTNCzfAI1aIRzbiufJtkMIlEp58= +golang.org/x/crypto v0.19.0/go.mod h1:Iy9bg/ha4yyC70EfRS8jz+B6ybOBKMaSxLj6P6oBDfU= golang.org/x/crypto v0.50.0 h1:zO47/JPrL6vsNkINmLoo/PH1gcxpls50DNogFvB5ZGI= golang.org/x/crypto v0.50.0/go.mod h1:3muZ7vA7PBCE6xgPX7nkzzjiUq87kRItoJQM1Yo8S+Q= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= @@ -1297,6 +1337,7 @@ golang.org/x/mod v0.4.1/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.5.0/go.mod h1:5OXOZSfqPIIbmVBIIKWRFfZjPR0E5r58TLhUjH0a2Ro= golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= +golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= golang.org/x/mod v0.35.0 h1:Ww1D637e6Pg+Zb2KrWfHQUnH2dQRLBQyAtpr/haaJeM= golang.org/x/mod v0.35.0/go.mod h1:+GwiRhIInF8wPm+4AoT6L0FA1QWAad3OMdTRx4tFYlU= golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= @@ -1344,6 +1385,7 @@ golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qx golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= golang.org/x/net v0.7.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= +golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg= golang.org/x/net v0.53.0 h1:d+qAbo5L0orcWAr0a9JweQpjXF19LMXJE8Ey7hwOdUA= golang.org/x/net v0.53.0/go.mod h1:JvMuJH7rrdiCfbeHoo3fCQU24Lf5JJwT9W3sJFulfgs= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= @@ -1377,6 +1419,7 @@ golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJ golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.20.0 h1:e0PTpb7pjO8GAtTs2dQ6jYa5BWYlMuX047Dco/pItO4= golang.org/x/sync v0.20.0/go.mod h1:9xrNwdLfx4jkKbNva9FpL6vEN7evnE43NNNJQ2LF3+0= golang.org/x/sys v0.0.0-20180823144017-11551d06cbcc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= @@ -1452,14 +1495,21 @@ golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.2.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.10.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.17.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/sys v0.43.0 h1:Rlag2XtaFTxp19wS8MXlJwTvoh8ArU6ezoyFsMyCTNI= golang.org/x/sys v0.43.0/go.mod h1:4GL1E5IUh+htKOUEOaiffhrAeqysfVGipDYzABqnCmw= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k= +golang.org/x/term v0.8.0/go.mod h1:xPskH00ivmX89bAKVGSKKtLOWNx2+17Eiy94tnKShWo= +golang.org/x/term v0.17.0/go.mod h1:lLRBjIVuehSbZlaOtGMbcMncT+aqLLLmKrsjNrUguwk= golang.org/x/term v0.42.0 h1:UiKe+zDFmJobeJ5ggPwOshJIVt6/Ft0rcfrXZDLWAWY= golang.org/x/term v0.42.0/go.mod h1:Dq/D+snpsbazcBG5+F9Q1n2rXV8Ma+71xEjTRufARgY= golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= @@ -1472,6 +1522,8 @@ golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= +golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= +golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= golang.org/x/text v0.36.0 h1:JfKh3XmcRPqZPKevfXVpI1wXPTqbkE5f7JA92a55Yxg= golang.org/x/text v0.36.0/go.mod h1:NIdBknypM8iqVmPiuco0Dh6P5Jcdk8lJL0CUebqK164= golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= @@ -1534,6 +1586,7 @@ golang.org/x/tools v0.1.3/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= golang.org/x/tools v0.1.4/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= golang.org/x/tools v0.1.5/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= +golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU= golang.org/x/tools v0.44.0 h1:UP4ajHPIcuMjT1GqzDWRlalUEoY+uzoZKnhOjbIPD2c= golang.org/x/tools v0.44.0/go.mod h1:KA0AfVErSdxRZIsOVipbv3rQhVXTnlU6UhKxHd1seDI= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= @@ -1697,6 +1750,7 @@ google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlba google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= google.golang.org/protobuf v1.27.1/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= +google.golang.org/protobuf v1.28.1/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= google.golang.org/protobuf v1.36.12-0.20260120151049-f2248ac996af h1:+5/Sw3GsDNlEmu7TfklWKPdQ0Ykja5VEmq2i817+jbI= google.golang.org/protobuf v1.36.12-0.20260120151049-f2248ac996af/go.mod h1:HTf+CrKn2C3g5S8VImy6tdcUvCska2kB7j23XfzDpco= gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw= diff --git a/internal/commands/result_test.go b/internal/commands/result_test.go index 5bd0fe670..ed634427c 100644 --- a/internal/commands/result_test.go +++ b/internal/commands/result_test.go @@ -27,15 +27,16 @@ import ( const fileName = "cx_result" const ( - resultsCommand = "results" - codeBashingCommand = "codebashing" - vulnerabilityValue = "Reflected XSS All Clients" - languageValue = "PHP" - cweValue = "79" - jsonValue = "json" - tableValue = "table" - listValue = "list" - secretDetectionLine = "| Secret Detection 0 1 1 0 0 Completed |" + resultsCommand = "results" + codeBashingCommand = "codebashing" + vulnerabilityValue = "Reflected XSS All Clients" + languageValue = "PHP" + cweValue = "79" + jsonValue = "json" + tableValue = "table" + listValue = "list" + secretDetectionLine = "| Secret Detection 0 1 1 0 0 Completed |" + ignorePolicyWarningMessage = "Warning: The --ignore-policy flag was not implemented because you do not have the required permission." ) func flag(f string) string { @@ -1591,8 +1592,7 @@ func TestIgnorePolicyWithNoPermission(t *testing.T) { t.Fatalf("failed to copy output: %v", err) // Handle the error if io.Copy fails } output := buf.String() - expectedWarning := "Warning: The --ignore-policy flag was not implemented because you do not have the required permission." - assert.Assert(t, strings.Contains(output, expectedWarning), "’Ignore Policy flag omitted because you dont have permission’ should not be present in the output") + assert.Assert(t, strings.Contains(output, ignorePolicyWarningMessage), "’Ignore Policy flag omitted because you dont have permission’ should not be present in the output") } func TestIgnorePolicyWithPermission(t *testing.T) { @@ -1626,8 +1626,7 @@ func TestIgnorePolicyWithPermission(t *testing.T) { t.Fatalf("failed to copy output: %v", err) // Handle the error if io.Copy fails } output := buf.String() - expectedWarning := "Warning: The --ignore-policy flag was not implemented because you do not have the required permission." - assert.Assert(t, !strings.Contains(output, expectedWarning), "’Ignore Policy flag omitted because you dont have permission’ should not be present in the output") + assert.Assert(t, !strings.Contains(output, ignorePolicyWarningMessage), "’Ignore Policy flag omitted because you dont have permission’ should not be present in the output") } func TestParseGlSastVulnerability_QueryDescriptionLink_Succeed(t *testing.T) { From 129ef8c8e88b60193f67d6e5619d38e9ef62107f Mon Sep 17 00:00:00 2001 From: atishj99 <141334503+cx-atish-jadhav@users.noreply.github.com> Date: Fri, 29 May 2026 12:24:10 +0530 Subject: [PATCH 12/27] Override transitive golang.org/x/image and update config - Add explicit requirement for golang.org/x/image v0.39.0 to override gonum.org/v1/gonum's transitive requirement of v0.25.0 (CVE-2026-33813) - Update result_test.go constant alignment - Add cx_config_file_path to integration config --- go.mod | 1 + go.sum | 2 ++ internal/commands/result_test.go | 20 ++++++++++---------- test/integration/data/config.yaml | 1 + 4 files changed, 14 insertions(+), 10 deletions(-) diff --git a/go.mod b/go.mod index 6e8afd8c1..6951e7fe2 100644 --- a/go.mod +++ b/go.mod @@ -140,6 +140,7 @@ require ( go.opentelemetry.io/otel/sdk v1.43.0 // indirect go.opentelemetry.io/otel/sdk/metric v1.43.0 // indirect go4.org v0.0.0-20230225012048-214862532bf5 // indirect + golang.org/x/image v0.39.0 // indirect gonum.org/v1/gonum v0.17.0 // indirect google.golang.org/api v0.271.0 // indirect google.golang.org/genproto/googleapis/api v0.0.0-20260401024825-9d38bb4040a9 // indirect diff --git a/go.sum b/go.sum index cdf0a48f3..c5165419b 100644 --- a/go.sum +++ b/go.sum @@ -1312,6 +1312,8 @@ golang.org/x/exp v0.0.0-20260410095643-746e56fc9e2f h1:W3F4c+6OLc6H2lb//N1q4WpJk golang.org/x/exp v0.0.0-20260410095643-746e56fc9e2f/go.mod h1:J1xhfL/vlindoeF/aINzNzt2Bket5bjo9sdOYzOsU80= golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js= golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= +golang.org/x/image v0.39.0 h1:skVYidAEVKgn8lZ602XO75asgXBgLj9G/FE3RbuPFww= +golang.org/x/image v0.39.0/go.mod h1:sIbmppfU+xFLPIG0FoVUTvyBMmgng1/XAMhQ2ft0hpA= golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU= golang.org/x/lint v0.0.0-20190301231843-5614ed5bae6f/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= diff --git a/internal/commands/result_test.go b/internal/commands/result_test.go index ed634427c..133d90516 100644 --- a/internal/commands/result_test.go +++ b/internal/commands/result_test.go @@ -27,16 +27,16 @@ import ( const fileName = "cx_result" const ( - resultsCommand = "results" - codeBashingCommand = "codebashing" - vulnerabilityValue = "Reflected XSS All Clients" - languageValue = "PHP" - cweValue = "79" - jsonValue = "json" - tableValue = "table" - listValue = "list" - secretDetectionLine = "| Secret Detection 0 1 1 0 0 Completed |" - ignorePolicyWarningMessage = "Warning: The --ignore-policy flag was not implemented because you do not have the required permission." + resultsCommand = "results" + codeBashingCommand = "codebashing" + vulnerabilityValue = "Reflected XSS All Clients" + languageValue = "PHP" + cweValue = "79" + jsonValue = "json" + tableValue = "table" + listValue = "list" + secretDetectionLine = "| Secret Detection 0 1 1 0 0 Completed |" + ignorePolicyWarningMessage = "Warning: The --ignore-policy flag was not implemented because you do not have the required permission." ) func flag(f string) string { diff --git a/test/integration/data/config.yaml b/test/integration/data/config.yaml index b01de3ac2..6d6b4c836 100644 --- a/test/integration/data/config.yaml +++ b/test/integration/data/config.yaml @@ -18,6 +18,7 @@ cx_byor_path: api/byor cx_client_id: example_client_id cx_client_secret: example_client_secret cx_codebashing_path: api/codebashing/lessons +cx_config_file_path: data/config.yaml cx_create_oath2_client_path: auth/realms/organization/pip/clients cx_custom_states_path: api/custom-states cx_descriptions_path: api/queries/descriptions From b791438a16bc7d11148b3eaeb8daf047adba73f5 Mon Sep 17 00:00:00 2001 From: "stepsecurity-app[bot]" <188008098+stepsecurity-app[bot]@users.noreply.github.com> Date: Fri, 29 May 2026 21:28:30 -0400 Subject: [PATCH 13/27] [StepSecurity] Apply security best practices (#1495) Signed-off-by: StepSecurity Bot Co-authored-by: stepsecurity-app[bot] <188008098+stepsecurity-app[bot]@users.noreply.github.com> --- .github/workflows/ci-tests.yml | 2 +- .github/workflows/dependabot-auto-merge.yml | 4 ++-- .github/workflows/release.yml | 6 +++--- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/.github/workflows/ci-tests.yml b/.github/workflows/ci-tests.yml index adb7c1794..e9b47b4a2 100644 --- a/.github/workflows/ci-tests.yml +++ b/.github/workflows/ci-tests.yml @@ -133,7 +133,7 @@ jobs: - run: go version - run: go mod tidy - name: golangci-lint - uses: golangci/golangci-lint-action@1e7e51e771db61008b38414a730f564565cf7c20 #v9.2.0 + uses: step-security/golangci-lint-action@1797facf9ea427614d729a4e9cab0fae1a7852d9 # v9.2.0 with: skip-pkg-cache: true version: v2.11.3 diff --git a/.github/workflows/dependabot-auto-merge.yml b/.github/workflows/dependabot-auto-merge.yml index 736fd17e9..a048a3ec6 100644 --- a/.github/workflows/dependabot-auto-merge.yml +++ b/.github/workflows/dependabot-auto-merge.yml @@ -11,7 +11,7 @@ jobs: steps: - name: Dependabot metadata id: metadata - uses: dependabot/fetch-metadata@bfac3fa29cc6834ca2e3fd659343da191a65d971 # v1.3.1 + uses: step-security/dependabot-fetch-metadata@bf8fb6e0be0a711c669dc236de6e7f7374ba626e # v3.1.0 with: github-token: "${{ secrets.GH_TOKEN }}" - name: Enable auto-merge for Dependabot PRs @@ -20,6 +20,6 @@ jobs: GITHUB_TOKEN: ${{secrets.GH_TOKEN}} run: gh pr merge --auto --merge "$PR_URL" - name: Auto approve dependabot PRs - uses: hmarr/auto-approve-action@7782c7e2bdf62b4d79bdcded8332808fd2f179cd #v2 + uses: step-security/auto-approve-action@0c28339628c8e79ab2f6813291e7e6cd584b4d30 # v4.0.0 with: github-token: ${{ secrets.PERSONAL_ACCESS_TOKEN }} diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 296cd29e1..5ed3bb8d1 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -81,14 +81,14 @@ jobs: docker info - name: Login to Docker Hub if: inputs.dev == false - uses: docker/login-action@4907a6ddec9925e35a0a9e82d7399ccc52663121 #v4.1.0 + uses: step-security/docker-login-action@870af644803bf9f204aed474adbad2958fec048b # v4.1.0 with: username: ${{ secrets.DOCKER_USERNAME }} password: ${{ secrets.DOCKER_PASSWORD }} - name: Install Cosign if: inputs.dev == false - uses: sigstore/cosign-installer@1fc5bd396d372bee37d608f955b336615edf79c8 #v3.2.0 + uses: step-security/cosign-installer@8c02650536457a1c912424ab6cb9734aa3eceb56 # v4.1.1 - name: Configure AWS Credentials uses: aws-actions/configure-aws-credentials@5fd3084fc36e372ff1fff382a39b10d03659f355 #v2 @@ -115,7 +115,7 @@ jobs: - name: Echo GoReleaser Args run: echo ${{ env.GR_ARGS }} - name: Run GoReleaser - uses: goreleaser/goreleaser-action@b508e2e3ef3b19d4e4146d4f8fb3ba9db644a757 #v3 + uses: step-security/goreleaser-action@1472c46ac6e641f2b929f1a893354288b3a6b6b6 # v7.2.1 with: version: v1.18.2 args: ${{ env.GR_ARGS }} From 1095e956635870aba52b8055be8a0455e2a1268d Mon Sep 17 00:00:00 2001 From: Atish Jadhav <141334503+cx-atish-jadhav@users.noreply.github.com> Date: Tue, 26 May 2026 14:01:21 +0530 Subject: [PATCH 14/27] Fix KICS container shutdown race condition and add OneAssist license support - Create kicsshutdown package with thread-safe container name management - Update signal handler to read container name from kicsshutdown instead of viper - Prevents race conditions during SIGTERM cleanup - Add support for OneAssist license in addition to Developer Assist - Update GetUniqueID() to check both license types --- cmd/main.go | 12 +++++---- internal/commands/scan.go | 5 +++- internal/kicsshutdown/container_name.go | 25 +++++++++++++++++++ .../iacrealtime/container-manager.go | 2 ++ .../iacrealtime/container-manager_test.go | 14 +++++++++++ internal/wrappers/jwt-helper.go | 11 ++++++-- internal/wrappers/jwt-helper_test.go | 4 +-- 7 files changed, 63 insertions(+), 10 deletions(-) create mode 100644 internal/kicsshutdown/container_name.go diff --git a/cmd/main.go b/cmd/main.go index 53d2ae664..ae5d46ceb 100644 --- a/cmd/main.go +++ b/cmd/main.go @@ -9,6 +9,7 @@ import ( "syscall" "github.com/checkmarx/ast-cli/internal/commands" + "github.com/checkmarx/ast-cli/internal/kicsshutdown" "github.com/checkmarx/ast-cli/internal/logger" "github.com/checkmarx/ast-cli/internal/params" "github.com/checkmarx/ast-cli/internal/wrappers" @@ -191,10 +192,6 @@ func exitListener() { } func signalHandler(signalChanel chan os.Signal) { - kicsRunArgs := []string{ - killCommand, - viper.GetString(params.KicsContainerNameKey), - } for { s := <-signalChanel switch s { @@ -204,7 +201,12 @@ func signalHandler(signalChanel chan os.Signal) { os.Exit(failureExitCode) } logger.PrintIfVerbose(string(out)) - if strings.Contains(string(out), viper.GetString(params.KicsContainerNameKey)) { + kicsContainerName := kicsshutdown.GetKicsContainerName() + if kicsContainerName != "" && strings.Contains(string(out), kicsContainerName) { + kicsRunArgs := []string{ + killCommand, + kicsContainerName, + } out, err = exec.Command("docker", kicsRunArgs...).CombinedOutput() logger.PrintIfVerbose(string(out)) if err != nil { diff --git a/internal/commands/scan.go b/internal/commands/scan.go index b0d346a6d..777632c6a 100644 --- a/internal/commands/scan.go +++ b/internal/commands/scan.go @@ -35,6 +35,7 @@ import ( "github.com/pkg/errors" "github.com/MakeNowJust/heredoc" + "github.com/checkmarx/ast-cli/internal/kicsshutdown" commonParams "github.com/checkmarx/ast-cli/internal/params" "github.com/checkmarx/ast-cli/internal/wrappers" "github.com/mssola/user_agent" @@ -279,7 +280,9 @@ func NewScanCommand( func scanRealtimeSubCommand() *cobra.Command { kicsContainerID := uuid.New() - viper.Set(commonParams.KicsContainerNameKey, kicsContainerPrefixName+kicsContainerID.String()) + kicsName := kicsContainerPrefixName + kicsContainerID.String() + viper.Set(commonParams.KicsContainerNameKey, kicsName) + kicsshutdown.SetKicsContainerName(kicsName) realtimeScanCmd := &cobra.Command{ Use: "kics-realtime", Short: "Create and run kics scan", diff --git a/internal/kicsshutdown/container_name.go b/internal/kicsshutdown/container_name.go new file mode 100644 index 000000000..274858b64 --- /dev/null +++ b/internal/kicsshutdown/container_name.go @@ -0,0 +1,25 @@ +// Package kicsshutdown holds the current KICS Docker container name for SIGTERM cleanup. +// It is updated alongside viper wherever KicsContainerNameKey is set so the signal handler +// can read the latest name without concurrent access to viper. +package kicsshutdown + +import "sync" + +var ( + mu sync.RWMutex + name string +) + +// SetKicsContainerName records the container name used for shutdown handling. +func SetKicsContainerName(n string) { + mu.Lock() + defer mu.Unlock() + name = n +} + +// GetKicsContainerName returns the last recorded container name. +func GetKicsContainerName() string { + mu.RLock() + defer mu.RUnlock() + return name +} diff --git a/internal/services/realtimeengine/iacrealtime/container-manager.go b/internal/services/realtimeengine/iacrealtime/container-manager.go index 77a833b8b..0a8fcae62 100644 --- a/internal/services/realtimeengine/iacrealtime/container-manager.go +++ b/internal/services/realtimeengine/iacrealtime/container-manager.go @@ -7,6 +7,7 @@ import ( "strings" "github.com/checkmarx/ast-cli/internal/commands/util" + "github.com/checkmarx/ast-cli/internal/kicsshutdown" "github.com/checkmarx/ast-cli/internal/logger" commonParams "github.com/checkmarx/ast-cli/internal/params" "github.com/google/uuid" @@ -32,6 +33,7 @@ func (dm *ContainerManager) GenerateContainerID() string { containerID := uuid.New().String() containerName := KicsContainerPrefix + containerID viper.Set(commonParams.KicsContainerNameKey, containerName) + kicsshutdown.SetKicsContainerName(containerName) return containerName } diff --git a/internal/services/realtimeengine/iacrealtime/container-manager_test.go b/internal/services/realtimeengine/iacrealtime/container-manager_test.go index 2a2261121..7f19ac42c 100644 --- a/internal/services/realtimeengine/iacrealtime/container-manager_test.go +++ b/internal/services/realtimeengine/iacrealtime/container-manager_test.go @@ -7,6 +7,7 @@ import ( "strings" "testing" + "github.com/checkmarx/ast-cli/internal/kicsshutdown" commonParams "github.com/checkmarx/ast-cli/internal/params" "github.com/google/uuid" "github.com/spf13/viper" @@ -46,6 +47,7 @@ func (m *MockContainerManager) GenerateContainerID() string { containerName := KicsContainerPrefix + containerID m.GeneratedContainerIDs = append(m.GeneratedContainerIDs, containerName) viper.Set(commonParams.KicsContainerNameKey, containerName) + kicsshutdown.SetKicsContainerName(containerName) return containerName } @@ -102,6 +104,7 @@ func TestMockContainerManager_GenerateContainerID(t *testing.T) { // Clear any existing value viper.Set(commonParams.KicsContainerNameKey, "") + kicsshutdown.SetKicsContainerName("") containerName := dm.GenerateContainerID() @@ -125,6 +128,9 @@ func TestMockContainerManager_GenerateContainerID(t *testing.T) { if viperValue != containerName { t.Errorf("Viper should be set to '%s', got '%s'", containerName, viperValue) } + if kicsshutdown.GetKicsContainerName() != containerName { + t.Errorf("kicsshutdown should be set to '%s', got '%s'", containerName, kicsshutdown.GetKicsContainerName()) + } // Test that mock recorded the generated ID if len(dm.GeneratedContainerIDs) != 1 { @@ -164,6 +170,7 @@ func TestMockContainerManager_RunKicsContainer(t *testing.T) { // Set up test parameters containerName := "test-container" viper.Set(commonParams.KicsContainerNameKey, containerName) + kicsshutdown.SetKicsContainerName(containerName) tests := []struct { name string @@ -263,6 +270,9 @@ func TestMockContainerManager_Integration(t *testing.T) { if viper.GetString(commonParams.KicsContainerNameKey) != containerName { t.Error("Container name should be set in viper after generation") } + if kicsshutdown.GetKicsContainerName() != containerName { + t.Error("Container name should be set in kicsshutdown after generation") + } // Test running container err := dm.RunKicsContainer("docker", "/tmp:/path") @@ -379,6 +389,7 @@ func TestContainerManager_GenerateContainerID(t *testing.T) { // Clear any existing value viper.Set(commonParams.KicsContainerNameKey, "") + kicsshutdown.SetKicsContainerName("") containerName := cm.GenerateContainerID() @@ -402,6 +413,9 @@ func TestContainerManager_GenerateContainerID(t *testing.T) { if viperValue != containerName { t.Errorf("Viper should be set to '%s', got '%s'", containerName, viperValue) } + if kicsshutdown.GetKicsContainerName() != containerName { + t.Errorf("kicsshutdown should be set to '%s', got '%s'", containerName, kicsshutdown.GetKicsContainerName()) + } // Test that subsequent calls generate different IDs containerName2 := cm.GenerateContainerID() diff --git a/internal/wrappers/jwt-helper.go b/internal/wrappers/jwt-helper.go index 63b1defb5..8393c6b43 100644 --- a/internal/wrappers/jwt-helper.go +++ b/internal/wrappers/jwt-helper.go @@ -203,12 +203,19 @@ func GetUniqueID() string { var uniqueID string // Check License first jwtWrapper := NewJwtWrapper() - isAllowed, err := jwtWrapper.IsAllowedEngine(commonParams.CheckmarxDevAssistType) + devAssistAllowed, err := jwtWrapper.IsAllowedEngine(commonParams.CheckmarxDevAssistType) if err != nil { logger.PrintIfVerbose("Failed to check engine allowance: " + err.Error()) return "" } - if !isAllowed { + + oneAssistAllowed, err := jwtWrapper.IsAllowedEngine(commonParams.CheckmarxOneAssistType) + if err != nil { + logger.PrintIfVerbose("Failed to check engine allowance: " + err.Error()) + return "" + } + + if !devAssistAllowed && !oneAssistAllowed { return "" } diff --git a/internal/wrappers/jwt-helper_test.go b/internal/wrappers/jwt-helper_test.go index ea01fb041..9356921ef 100644 --- a/internal/wrappers/jwt-helper_test.go +++ b/internal/wrappers/jwt-helper_test.go @@ -90,7 +90,7 @@ func TestGetUniqueID(t *testing.T) { if result != "" { assert.Equal(t, existingID, result) } else { - t.Skip("Requires valid auth and 'Checkmarx Developer Assist' license") + t.Skip("Requires valid auth and 'Checkmarx Developer Assist' or 'Checkmarx OneAssist' license") } }) @@ -101,7 +101,7 @@ func TestGetUniqueID(t *testing.T) { result := GetUniqueID() if result == "" { - t.Skip("Requires valid auth and 'Checkmarx Developer Assist' license") + t.Skip("Requires valid auth and 'Checkmarx Developer Assist' or 'Checkmarx OneAssist' license") return } From ad9ed063d3213a3ef00fba9a814fac54e141fcec Mon Sep 17 00:00:00 2001 From: Atish Jadhav <141334503+cx-atish-jadhav@users.noreply.github.com> Date: Tue, 26 May 2026 18:13:06 +0530 Subject: [PATCH 15/27] Integrate file updates: SARIF enhancements, filters expansion, and project/application management improvements - Add CodeFlow and ThreadFlow support to SARIF result structures with new types - Extend BaseIncludeFilters with 41 additional file type patterns - Enhance applications.go with project association polling and duplicate prevention - Update result.go with CodeFlow handling in SARIF serialization - Add IsInSource and CommitURL fields to SarifResultProperties - Fix projects.go verifyApplicationAssociationDone and UpsertProjectGroups functions - Change IaCS and KICS filter flags from String to StringSlice in scan.go Co-Authored-By: Claude Haiku 4.5 --- internal/commands/result.go | 5901 ++++++++++---------- internal/commands/scan.go | 4 +- internal/params/filters.go | 41 + internal/services/applications.go | 18 +- internal/services/applications_test.go | 10 +- internal/services/projects.go | 1 - internal/wrappers/mock/application-mock.go | 4 +- internal/wrappers/results-sarif.go | 13 + 8 files changed, 3035 insertions(+), 2957 deletions(-) diff --git a/internal/commands/result.go b/internal/commands/result.go index f37c5e46b..34320193c 100644 --- a/internal/commands/result.go +++ b/internal/commands/result.go @@ -1,2942 +1,2959 @@ -package commands - -import ( - "encoding/json" - "fmt" - "html" - "log" - "net/url" - "os" - "path/filepath" - "regexp" - "slices" - "strconv" - "strings" - "text/template" - "time" - - "github.com/MakeNowJust/heredoc" - "github.com/checkmarx/ast-cli/internal/commands/util" - "github.com/checkmarx/ast-cli/internal/commands/util/printer" - errorConstants "github.com/checkmarx/ast-cli/internal/constants/errors" - "github.com/checkmarx/ast-cli/internal/logger" - "github.com/checkmarx/ast-cli/internal/services" - "github.com/checkmarx/ast-cli/internal/wrappers" - "github.com/checkmarx/ast-cli/internal/wrappers/utils" - "golang.org/x/text/cases" - "golang.org/x/text/language" - - commonParams "github.com/checkmarx/ast-cli/internal/params" - - "github.com/pkg/errors" - "github.com/spf13/cobra" -) - -const ( - failedCreatingSummary = "Failed creating summary" - failedGettingScan = "Failed getting scan" - failedListingResults = "Failed listing results" - failedListingCodeBashing = "Failed codebashing link" - mediumLabel = "medium" - criticalLabel = "critical" - highLabel = "high" - lowLabel = "low" - infoLabel = "info" - sonarTypeLabel = "_sonar" - glSastTypeLabel = ".gl-sast-report" - glScaTypeLabel = ".gl-sca-report" - directoryPermission = 0700 - infoSonar = "INFO" - lowSonar = "LOW" - mediumSonar = "MEDIUM" - highSonar = "HIGH" - criticalSonar = "BLOCKER" - infoLowSarif = "note" - mediumSarif = "warning" - highSarif = "error" - vulnerabilitySonar = "SECURITY" - cleanCodeAttribute = "FORMATTED" - infoCx = "INFO" - lowCx = "LOW" - mediumCx = "MEDIUM" - highCx = "HIGH" - criticalCx = "CRITICAL" - tableResultsFormat = " | %-10s %6v %5d %6d %5d %4d %-9s |\n" - stringTableResultsFormat = " | %-10s %5s %6s %6s %5s %4s %5s |\n" - TableTitleFormat = " | %-11s %4s %4s %6s %4s %4s %6s |\n" - twoNewLines = "\n\n" - tableLine = " --------------------------------------------------------------------- " - codeBashingKey = "cb-url" - failedGettingBfl = "Failed getting BFL" - notAvailableString = "-" - disabledString = "N/A" - scanFailedString = "Failed " - scanCanceledString = "Canceled" - scanSuccessString = "Completed" - scanPartialString = "Partial" - scsScanUnavailableString = "" - notAvailableNumber = -1 - scanFailedNumber = -2 - scanCanceledNumber = -3 - scanPartialNumber = -4 - defaultPaddingSize = -13 - scanPendingMessage = "Scan triggered in asynchronous mode or still running. Click more details to get the full status." - directDependencyType = "Direct Dependency" - indirectDependencyType = "Transitive Dependency" - startedStatus = "started" - requestedStatus = "requested" - completedStatus = "completed" - pdfToEmailFlagDescription = "Send the PDF report to the specified email address." + - " Use \",\" as the delimiter for multiple emails" - pdfOptionsFlagDescription = "Sections to generate PDF report. Available options: Iac-Security,Sast,Sca," + - defaultPdfOptionsDataSections - sbomReportFlagDescription = "Sections to generate SBOM report. Available options: CycloneDxJson,CycloneDxXml,SpdxJson" - reportNameScanReport = "scan-report" - reportNameImprovedScanReport = "improved-scan-report" - reportTypeEmail = "email" - defaultPdfOptionsDataSections = "ScanSummary,ExecutiveSummary,ScanResults" - exploitablePathFlagDescription = "Enable or disable exploitable path in scan. Available options: true,false" - scaLastScanTimeFlagDescription = "SCA last scan time. Available options: integer above 1" - projectPrivatePackageFlagDescription = "Enable or disable project private package. Available options: true,false" - scaPrivatePackageVersionFlagDescription = "SCA project private package version. Example: 0.1.1" - scaHideDevAndTestDepFlagDescription = "Filter SCA results to exclude dev and test dependencies" - policeManagementNoneStatus = "none" - apiDocumentationFlagDescription = "Swagger folder/file filter for API-Security scan. Example: ./swagger.json" - summaryCreatedAtLayout = "2006-01-02, 15:04:05" - glTimeFormat = "2006-01-02T15:04:05" - sarifNodeFileLength = 2 - fixLabel = "fix" - redundantLabel = "redundant" - delayValueForReport = 10 - fixLinkPrefix = "https://devhub.checkmarx.com/cve-details/" - ScaDevAndTestExclusionParam = "DEV_AND_TEST" - ScaExcludeResultTypesParam = "exclude-result-types" - noFileForScorecardResultString = "Issue Found in your GitHub repository" - CliType = "cli" - artifactLocationURIString = "This alert has no associated file" -) - -var ( - summaryFormats = []string{ - printer.FormatSummaryConsole, - printer.FormatSummary, - printer.FormatSummaryJSON, - printer.FormatPDF, - printer.FormatSummaryMarkdown, - printer.FormatSbom, - printer.FormatGLSast, - printer.FormatGLSca, - printer.FormatSonar, - } - - filterResultsListFlagUsage = fmt.Sprintf( - "Filter the list of results. Use ';' as the delimiter for arrays. Available filters are: %s", - strings.Join( - []string{ - commonParams.ScanIDQueryParam, - commonParams.LimitQueryParam, - commonParams.OffsetQueryParam, - commonParams.SortQueryParam, - commonParams.IncludeNodesQueryParam, - commonParams.NodeIDsQueryParam, - commonParams.QueryQueryParam, - commonParams.GroupQueryParam, - commonParams.StatusQueryParam, - commonParams.SeverityQueryParam, - commonParams.StateQueryParam, - }, ",", - ), - ) - - // Follows: over 9.0 is critical, 7.0 to 8.9 is high, 4.0 to 6.9 is medium and 3.9 or less is low. - securities = map[string]string{ - infoCx: "1.0", - lowCx: "2.0", - mediumCx: "4.0", - highCx: "7.0", - criticalCx: "9.0", - } - - // Match cx severity with sonar severity - sonarSeverities = map[string]string{ - infoCx: infoSonar, - lowCx: lowSonar, - mediumCx: mediumSonar, - highCx: highSonar, - criticalCx: criticalSonar, - } - - containerEngineUnsupportedAgents = []string{ - commonParams.JetbrainsAgent, commonParams.VSCodeAgent, commonParams.VisualStudioAgent, commonParams.EclipseAgent, - } - - sscsEngineToOverviewEngineMap = map[string]string{ - commonParams.SCSScorecardType: commonParams.SCSScorecardOverviewType, - commonParams.SCSSecretDetectionType: commonParams.SCSSecretDetectionOverviewType, - } -) - -func NewResultsCommand( - resultsWrapper wrappers.ResultsWrapper, - scanWrapper wrappers.ScansWrapper, - exportWrapper wrappers.ExportWrapper, - resultsPdfReportsWrapper wrappers.ResultsPdfWrapper, - resultsJSONReportsWrapper wrappers.ResultsJSONWrapper, - codeBashingWrapper wrappers.CodeBashingWrapper, - bflWrapper wrappers.BflWrapper, - risksOverviewWrapper wrappers.RisksOverviewWrapper, - riskManagementWrapper wrappers.RiskManagementWrapper, - scsScanOverviewWrapper wrappers.ScanOverviewWrapper, - policyWrapper wrappers.PolicyWrapper, - featureFlagsWrapper wrappers.FeatureFlagsWrapper, - jwtWrapper wrappers.JWTWrapper, -) *cobra.Command { - resultCmd := &cobra.Command{ - Use: "results", - Short: "Retrieve results", - Annotations: map[string]string{ - "command:doc": heredoc.Doc( - ` - https://checkmarx.com/resource/documents/en/34965-68640-results.html - `, - ), - }, - } - showResultCmd := resultShowSubCommand(resultsWrapper, scanWrapper, exportWrapper, resultsPdfReportsWrapper, resultsJSONReportsWrapper, - risksOverviewWrapper, scsScanOverviewWrapper, policyWrapper, featureFlagsWrapper, jwtWrapper) - codeBashingCmd := resultCodeBashing(codeBashingWrapper) - bflResultCmd := resultBflSubCommand(bflWrapper) - exitCodeSubcommand := exitCodeSubCommand(scanWrapper) - riskManagementSubCommand := riskManagementSubCommand(riskManagementWrapper, featureFlagsWrapper) - resultCmd.AddCommand( - showResultCmd, bflResultCmd, codeBashingCmd, exitCodeSubcommand, riskManagementSubCommand, - ) - return resultCmd -} - -func exitCodeSubCommand(scanWrapper wrappers.ScansWrapper) *cobra.Command { - exitCodeCmd := &cobra.Command{ - Use: "exit-code", - Short: "Get exit code and details of a scan", - Long: "The exit-code command enables you to get the exit code and failure details of a requested scan in Checkmarx One", - Example: heredoc.Doc( - ` - $ cx results exit-code --scan-id --scan-types - `, - ), - RunE: runGetExitCodeCommand(scanWrapper), - } - - exitCodeCmd.PersistentFlags().String(commonParams.ScanIDFlag, "", "Scan ID") - exitCodeCmd.PersistentFlags().String(commonParams.ScanTypes, "", "Scan types") - - return exitCodeCmd -} -func riskManagementSubCommand(riskManagement wrappers.RiskManagementWrapper, featureFlagsWrapper wrappers.FeatureFlagsWrapper, -) *cobra.Command { - riskManagementCmd := &cobra.Command{ - Use: "risk-management", - Short: "Show risk-management results of a project", - Long: "The risk-management command displays risk management results for a specific project in Checkmarx One", - Example: heredoc.Doc( - ` - $ cx results risk-management --project-id --scan-id --limit (1-50, default: 50) - `, - ), - RunE: runRiskManagementCommand(riskManagement, featureFlagsWrapper), - } - - riskManagementCmd.PersistentFlags().String(commonParams.ProjectIDFlag, "", "Project ID") - riskManagementCmd.PersistentFlags().String(commonParams.ScanIDFlag, "", "Scan ID") - riskManagementCmd.PersistentFlags().Int(commonParams.LimitFlag, -1, "Limit") - - addFormatFlag(riskManagementCmd, printer.FormatJSON, printer.FormatTable, printer.FormatList) - - return riskManagementCmd -} - -func resultShowSubCommand( - resultsWrapper wrappers.ResultsWrapper, - scanWrapper wrappers.ScansWrapper, - exportWrapper wrappers.ExportWrapper, - resultsPdfReportsWrapper wrappers.ResultsPdfWrapper, - resultsJSONReportsWrapper wrappers.ResultsJSONWrapper, - risksOverviewWrapper wrappers.RisksOverviewWrapper, - scsScanOverviewWrapper wrappers.ScanOverviewWrapper, - policyWrapper wrappers.PolicyWrapper, - featureFlagsWrapper wrappers.FeatureFlagsWrapper, - jwtWrapper wrappers.JWTWrapper, -) *cobra.Command { - resultShowCmd := &cobra.Command{ - Use: "show", - Short: "Show results of a scan", - Long: "The show command enables the ability to show results about a requested scan in Checkmarx One", - Example: heredoc.Doc( - ` - $ cx results show --scan-id - `, - ), - RunE: runGetResultCommand(resultsWrapper, scanWrapper, exportWrapper, resultsPdfReportsWrapper, resultsJSONReportsWrapper, risksOverviewWrapper, scsScanOverviewWrapper, policyWrapper, featureFlagsWrapper, jwtWrapper), - } - addScanIDFlag(resultShowCmd, "ID to report on") - addResultFormatFlag( - resultShowCmd, - printer.FormatJSON, - printer.FormatJSONv2, - printer.FormatSummary, - printer.FormatSummaryConsole, - printer.FormatSarif, - printer.FormatSummaryJSON, - printer.FormatSbom, - printer.FormatPDF, - printer.FormatSummaryMarkdown, - printer.FormatGLSast, - printer.FormatGLSca, - printer.FormatSonar, - ) - resultShowCmd.PersistentFlags().String(commonParams.ReportFormatPdfToEmailFlag, "", pdfToEmailFlagDescription) - resultShowCmd.PersistentFlags().String(commonParams.ReportSbomFormatFlag, services.DefaultSbomOption, sbomReportFlagDescription) - resultShowCmd.PersistentFlags().String(commonParams.ReportFormatPdfOptionsFlag, defaultPdfOptionsDataSections, pdfOptionsFlagDescription) - resultShowCmd.PersistentFlags().String(commonParams.TargetFlag, "cx_result", "Output file") - resultShowCmd.PersistentFlags().String(commonParams.TargetPathFlag, ".", "Output Path") - resultShowCmd.PersistentFlags().StringSlice(commonParams.FilterFlag, []string{}, filterResultsListFlagUsage) - - resultShowCmd.PersistentFlags().IntP( - commonParams.WaitDelayFlag, - "", - commonParams.WaitDelayDefault, - "Polling wait time in seconds", - ) - resultShowCmd.PersistentFlags().Int( - commonParams.PolicyTimeoutFlag, - commonParams.ResultPolicyDefaultTimeout, - "Cancel the policy evaluation and fail after the timeout in minutes", - ) - resultShowCmd.PersistentFlags().Bool(commonParams.IgnorePolicyFlag, false, "Skip policy evaluation. Requires override-policy-management permission.") - resultShowCmd.PersistentFlags().Bool(commonParams.SastRedundancyFlag, false, - "Populate SAST results 'data.redundancy' with values '"+fixLabel+"' (to fix) or '"+redundantLabel+"' (no need to fix)") - resultShowCmd.PersistentFlags().Bool(commonParams.ScaHideDevAndTestDepFlag, false, scaHideDevAndTestDepFlagDescription) - - return resultShowCmd -} - -func resultBflSubCommand(bflWrapper wrappers.BflWrapper) *cobra.Command { - resultBflCmd := &cobra.Command{ - Use: "bfl", - Short: "Show best fix location for a query id within the scan result", - Long: "The bfl command enables the ability to show best fix location for a querid within the scan result", - Example: heredoc.Doc( - ` - $ cx results bfl --scan-id --query-id - `, - ), - RunE: runGetBestFixLocationCommand(bflWrapper), - } - addScanIDFlag(resultBflCmd, "ID to report on") - addQueryIDFlag(resultBflCmd, "Query Id from the result") - addFormatFlag(resultBflCmd, printer.FormatList, printer.FormatJSON) - - markFlagAsRequired(resultBflCmd, commonParams.ScanIDFlag) - markFlagAsRequired(resultBflCmd, commonParams.QueryIDFlag) - - return resultBflCmd -} - -func runGetExitCodeCommand(scanWrapper wrappers.ScansWrapper) func(cmd *cobra.Command, args []string) error { - return func(cmd *cobra.Command, args []string) error { - scanID, _ := cmd.Flags().GetString(commonParams.ScanIDFlag) - if scanID == "" { - return errors.New(errorConstants.ScanIDRequired) - } - scanTypesFlagValue, _ := cmd.Flags().GetString(commonParams.ScanTypes) - results, err := GetScannerResults(scanWrapper, scanID, scanTypesFlagValue) - if err != nil { - return err - } - - if len(results) == 0 { - return nil - } - - return printer.Print(cmd.OutOrStdout(), results, printer.FormatIndentedJSON) - } -} - -func runRiskManagementCommand(riskManagement wrappers.RiskManagementWrapper, featureFlagsWrapper wrappers.FeatureFlagsWrapper, -) func(cmd *cobra.Command, args []string) error { - return func(cmd *cobra.Command, args []string) error { - projectID, _ := cmd.Flags().GetString(commonParams.ProjectIDFlag) - scanID, _ := cmd.Flags().GetString(commonParams.ScanIDFlag) - - limit, _ := cmd.Flags().GetInt(commonParams.LimitFlag) - - flagResponse, _ := wrappers.GetSpecificFeatureFlag(featureFlagsWrapper, wrappers.RiskManagementEnabled) - ASPMEnabled := flagResponse.Status - if !ASPMEnabled { - return errors.Errorf("%s", "Risk management results are currently unavailable for your tenant.") - } - results, err := getRiskManagementResults(riskManagement, projectID, scanID) - if err != nil { - return err - } - results.Results = utils.LimitSlice(results.Results, limit) - err = printByFormat(cmd, results) - return err - } -} - -func getRiskManagementResults(riskManagement wrappers.RiskManagementWrapper, projectID, scanID string) (*wrappers.ASPMResult, error) { - ASPMResult, errorModel, err := riskManagement.GetTopVulnerabilitiesByProjectID(projectID, scanID) - if err != nil { - return nil, errors.Wrapf(err, "%s", failedListingResults) - } - if errorModel != nil { - return nil, errors.Errorf("%s: CODE: %d, %s", failedListingResults, errorModel.Code, errorModel.Message) - } - return ASPMResult, nil -} - -func GetScannerResults(scanWrapper wrappers.ScansWrapper, scanID, scanTypesFlagValue string) ([]ScannerResponse, error) { - scanResponseModel, errorModel, err := scanWrapper.GetByID(scanID) - if err != nil { - return nil, errors.Wrapf(err, "%s", failedGetting) - } - if errorModel != nil { - return nil, errors.Errorf("%s: CODE: %d, %s", failedGettingScan, errorModel.Code, errorModel.Message) - } - results := getScannerResponse(scanTypesFlagValue, scanResponseModel) - return results, nil -} - -func getScannerResponse(scanTypesFlagValue string, scanResponseModel *wrappers.ScanResponseModel) []ScannerResponse { - var results []ScannerResponse - - if scanResponseModel.Status == wrappers.ScanCanceled || - scanResponseModel.Status == wrappers.ScanRunning || - scanResponseModel.Status == wrappers.ScanQueued || - scanResponseModel.Status == wrappers.ScanPartial || - scanResponseModel.Status == wrappers.ScanCompleted { - result := ScannerResponse{ - ScanID: scanResponseModel.ID, - Status: string(scanResponseModel.Status), - } - results = append(results, result) - return results - } - - if scanTypesFlagValue == "" { - results = createAllFailedScannersResponse(scanResponseModel) - } else { - scanTypes := sanitizeScannerNames(scanTypesFlagValue) - results = createRequestedScannersResponse(scanTypes, scanResponseModel) - } - - return results -} - -func createRequestedScannersResponse(scanTypes map[string]string, scanResponseModel *wrappers.ScanResponseModel) []ScannerResponse { - var results []ScannerResponse - for i := range scanResponseModel.StatusDetails { - if _, ok := scanTypes[scanResponseModel.StatusDetails[i].Name]; ok { - results = append(results, createScannerResponse(&scanResponseModel.StatusDetails[i])) - } - } - return results -} - -func createAllFailedScannersResponse(scanResponseModel *wrappers.ScanResponseModel) []ScannerResponse { - var results []ScannerResponse - for i := range scanResponseModel.StatusDetails { - if scanResponseModel.StatusDetails[i].Status == wrappers.ScanFailed { - results = append(results, createScannerResponse(&scanResponseModel.StatusDetails[i])) - } - } - return results -} - -func sanitizeScannerNames(scanTypes string) map[string]string { - scanTypeSlice := strings.Split(scanTypes, ",") - scanTypeMap := make(map[string]string) - for i := range scanTypeSlice { - lowered := strings.ToLower(scanTypeSlice[i]) - scanTypeMap[lowered] = lowered - } - - return scanTypeMap -} - -func createScannerResponse(statusDetails *wrappers.StatusInfo) ScannerResponse { - return ScannerResponse{ - Name: statusDetails.Name, - Status: statusDetails.Status, - Details: statusDetails.Details, - ErrorCode: stringifyErrorCode(statusDetails.ErrorCode), - } -} - -func stringifyErrorCode(errorCode int) string { - if errorCode == 0 { - return "" - } - return strconv.Itoa(errorCode) -} - -func runGetBestFixLocationCommand(bflWrapper wrappers.BflWrapper) func(cmd *cobra.Command, args []string) error { - return func(cmd *cobra.Command, args []string) error { - var bflResponseModel *wrappers.BFLResponseModel - var errorModel *wrappers.WebError - var err error - - scanID, _ := cmd.Flags().GetString(commonParams.ScanIDFlag) - queryID, _ := cmd.Flags().GetString(commonParams.QueryIDFlag) - - scanIds := strings.Split(scanID, ",") - if len(scanIds) > 1 { - return errors.Errorf("%s", "Multiple scan-ids are not allowed.") - } - queryIds := strings.Split(queryID, ",") - if len(queryIds) > 1 { - return errors.Errorf("%s", "Multiple query-ids are not allowed.") - } - - params := make(map[string]string) - params[commonParams.ScanIDQueryParam] = scanID - params[commonParams.QueryIDQueryParam] = queryID - - bflResponseModel, errorModel, err = bflWrapper.GetBflByScanIDAndQueryID(params) - - if err != nil { - return errors.Wrapf(err, "%s", failedGettingBfl) - } - - // Checking the response - if errorModel != nil { - return errors.Errorf("%s: CODE: %d, %s", failedGettingBfl, errorModel.Code, errorModel.Message) - } else if bflResponseModel != nil { - err = printByFormat(cmd, toBflView(*bflResponseModel)) - if err != nil { - return err - } - } - - return nil - } -} - -func toBflView(bflResponseModel wrappers.BFLResponseModel) []wrappers.ScanResultNode { - if (bflResponseModel.TotalCount) > 0 { - views := make([]wrappers.ScanResultNode, bflResponseModel.TotalCount) - - for i := 0; i < bflResponseModel.TotalCount; i++ { - views[i] = wrappers.ScanResultNode{ - Name: bflResponseModel.Trees[i].BFL.Name, - FileName: bflResponseModel.Trees[i].BFL.FileName, - FullName: bflResponseModel.Trees[i].BFL.FullName, - Column: bflResponseModel.Trees[i].BFL.Column, - Length: bflResponseModel.Trees[i].BFL.Length, - Line: bflResponseModel.Trees[i].BFL.Line, - MethodLine: bflResponseModel.Trees[i].BFL.MethodLine, - Method: bflResponseModel.Trees[i].BFL.Method, - DomType: bflResponseModel.Trees[i].BFL.DomType, - } - } - return views - } - views := make([]wrappers.ScanResultNode, 0) - return views -} - -func resultCodeBashing(codeBashingWrapper wrappers.CodeBashingWrapper) *cobra.Command { - // Create a codeBashing wrapper - resultCmd := &cobra.Command{ - Use: "codebashing", - Short: "Get codebashing lesson link", - Long: "The codebashing command enables the ability to retrieve the link about a specific vulnerability", - Example: heredoc.Doc( - ` - $ cx results codebashing --language --vulnerability-type --cwe-id --format - `, - ), - RunE: runGetCodeBashingCommand(codeBashingWrapper), - } - resultCmd.PersistentFlags().String(commonParams.LanguageFlag, "", "Language of the vulnerability") - err := resultCmd.MarkPersistentFlagRequired(commonParams.LanguageFlag) - if err != nil { - log.Fatal(err) - } - resultCmd.PersistentFlags().String(commonParams.VulnerabilityTypeFlag, "", "Vulnerability type") - err = resultCmd.MarkPersistentFlagRequired(commonParams.VulnerabilityTypeFlag) - if err != nil { - log.Fatal(err) - } - resultCmd.PersistentFlags().String(commonParams.CweIDFlag, "", "CWE ID for the vulnerability") - err = resultCmd.MarkPersistentFlagRequired(commonParams.CweIDFlag) - if err != nil { - log.Fatal(err) - } - addFormatFlag(resultCmd, printer.FormatJSON, printer.FormatTable, printer.FormatList) - return resultCmd -} - -func convertScanToResultsSummary(scanInfo *wrappers.ScanResponseModel, resultsWrapper wrappers.ResultsWrapper) (*wrappers.ResultSummary, error) { - if scanInfo == nil { - return nil, errors.New(failedCreatingSummary) - } - - scanInfo.ReplaceMicroEnginesWithSCS() - - sastIssues := 0 - scaIssues := 0 - kicsIssues := 0 - var containersIssues *int - var scsIssues *int - enginesStatusCode := map[string]int{ - commonParams.SastType: 0, - commonParams.ScaType: 0, - commonParams.KicsType: 0, - commonParams.APISecType: 0, - commonParams.ScsType: 0, - commonParams.ContainersType: 0, - } - if wrappers.IsContainersEnabled { - containersIssues = new(int) - *containersIssues = 0 - enginesStatusCode[commonParams.ContainersType] = 0 - } - - scsIssues = new(int) - *scsIssues = 0 - enginesStatusCode[commonParams.ScsType] = 0 - - if len(scanInfo.StatusDetails) > 0 { - for _, statusDetailItem := range scanInfo.StatusDetails { - if statusDetailItem.Status == wrappers.ScanFailed || statusDetailItem.Status == wrappers.ScanCanceled { - if statusDetailItem.Name == commonParams.SastType { - sastIssues = notAvailableNumber - } else if statusDetailItem.Name == commonParams.ScaType { - scaIssues = notAvailableNumber - } else if statusDetailItem.Name == commonParams.KicsType { - kicsIssues = notAvailableNumber - } else if statusDetailItem.Name == commonParams.ScsType { - *scsIssues = notAvailableNumber - } else if statusDetailItem.Name == commonParams.ContainersType && wrappers.IsContainersEnabled { - *containersIssues = notAvailableNumber - } - } - switch statusDetailItem.Status { - case wrappers.ScanFailed: - handleScanStatus(statusDetailItem, enginesStatusCode, scanFailedNumber) - case wrappers.ScanCanceled: - handleScanStatus(statusDetailItem, enginesStatusCode, scanCanceledNumber) - } - } - } - summary := &wrappers.ResultSummary{ - ScanID: scanInfo.ID, - Status: string(scanInfo.Status), - CreatedAt: scanInfo.CreatedAt.Format("2006-01-02, 15:04:05"), - ProjectID: scanInfo.ProjectID, - RiskStyle: "", - RiskMsg: "", - CriticalIssues: 0, - HighIssues: 0, - MediumIssues: 0, - LowIssues: 0, - InfoIssues: 0, - SastIssues: sastIssues, - KicsIssues: kicsIssues, - ScaIssues: scaIssues, - ScsIssues: scsIssues, - ContainersIssues: containersIssues, - Tags: scanInfo.Tags, - ProjectName: scanInfo.ProjectName, - BranchName: scanInfo.Branch, - EnginesEnabled: scanInfo.Engines, - EnginesResult: map[string]*wrappers.EngineResultSummary{ - commonParams.SastType: {StatusCode: enginesStatusCode[commonParams.SastType]}, - commonParams.ScaType: {StatusCode: enginesStatusCode[commonParams.ScaType]}, - commonParams.KicsType: {StatusCode: enginesStatusCode[commonParams.KicsType]}, - commonParams.APISecType: {StatusCode: enginesStatusCode[commonParams.APISecType]}, - commonParams.ContainersType: {StatusCode: enginesStatusCode[commonParams.ContainersType]}, - }, - } - if wrappers.IsContainersEnabled { - summary.EnginesResult[commonParams.ContainersType] = &wrappers.EngineResultSummary{StatusCode: enginesStatusCode[commonParams.ContainersType]} - } - - summary.EnginesResult[commonParams.ScsType] = &wrappers.EngineResultSummary{StatusCode: enginesStatusCode[commonParams.ScsType]} - - baseURI, err := resultsWrapper.GetResultsURL(summary.ProjectID) - if err != nil { - return nil, err - } - - summary.BaseURI = baseURI - summary.BaseURI = generateScanSummaryURL(summary) - if isScanPending(summary.Status) { - summary.ScanInfoMessage = scanPendingMessage - } - - return summary, nil -} - -func handleScanStatus(statusDetailItem wrappers.StatusInfo, targetTypes map[string]int, statusCode int) { - if _, ok := targetTypes[statusDetailItem.Name]; ok { - targetTypes[statusDetailItem.Name] = statusCode - } -} - -func summaryReport( - summary *wrappers.ResultSummary, - policies *wrappers.PolicyResponseModel, - risksOverviewWrapper wrappers.RisksOverviewWrapper, - scsScanOverviewWrapper wrappers.ScanOverviewWrapper, - featureFlagsWrapper wrappers.FeatureFlagsWrapper, - results *wrappers.ScanResultsCollection, - resultsParams map[string]string, -) (*wrappers.ResultSummary, error) { - if summary.HasAPISecurity() { - apiSecFilterRisks, err := getFilterResultsForAPISecScanner(risksOverviewWrapper, summary.ScanID, resultsParams) - if err != nil { - return nil, err - } - if apiSecFilterRisks != nil { - summary.APISecurity = *apiSecFilterRisks - } - apiSecRisks, err := getResultsForAPISecScanner(risksOverviewWrapper, summary.ScanID) - if err != nil { - return nil, err - } - if apiSecRisks != nil { - summary.APISecurity.APICount = apiSecRisks.APICount - } - } - if summary.HasSCS() { - // Getting the base SCS overview. Results counts are overwritten in enhanceWithScanSummary->countResult - SCSOverview, err := getScanOverviewForSCSScanner(scsScanOverviewWrapper, summary.ScanID) - if err != nil { - return nil, err - } - summary.SCSOverview = SCSOverview - } - - if policies != nil { - summary.Policies = filterViolatedRules(*policies) - } - - enhanceWithScanSummary(summary, results, featureFlagsWrapper) - - setNotAvailableNumberIfZero(summary, &summary.SastIssues, commonParams.SastType) - setNotAvailableNumberIfZero(summary, &summary.ScaIssues, commonParams.ScaType) - setNotAvailableNumberIfZero(summary, &summary.KicsIssues, commonParams.KicsType) - setNotAvailableNumberIfZero(summary, summary.ScsIssues, commonParams.ScsType) - - if wrappers.IsContainersEnabled { - setNotAvailableNumberIfZero(summary, summary.ContainersIssues, commonParams.ContainersType) - } - - setRiskMsgAndStyle(summary) - setNotAvailableEnginesStatusCode(summary) - - return summary, nil -} - -func setNotAvailableEnginesStatusCode(summary *wrappers.ResultSummary) { - for engineName, engineResult := range summary.EnginesResult { - setNotAvailableNumberIfZero(summary, &engineResult.StatusCode, engineName) - } -} - -func setRiskMsgAndStyle(summary *wrappers.ResultSummary) { - if summary.CriticalIssues > 0 { - summary.RiskStyle = criticalLabel - summary.RiskMsg = "Critical Risk" - } else if summary.HighIssues > 0 { - summary.RiskStyle = highLabel - summary.RiskMsg = "High Risk" - } else if summary.MediumIssues > 0 { - summary.RiskStyle = mediumLabel - summary.RiskMsg = "Medium Risk" - } else if summary.LowIssues > 0 { - summary.RiskStyle = lowLabel - summary.RiskMsg = "Low Risk" - } else if summary.TotalIssues == 0 { - summary.RiskMsg = "No Risk" - } -} - -func setNotAvailableNumberIfZero(summary *wrappers.ResultSummary, counter *int, engineType string) { - if *counter == 0 && !contains(summary.EnginesEnabled, engineType) { - *counter = notAvailableNumber - } -} - -func enhanceWithScanSummary(summary *wrappers.ResultSummary, results *wrappers.ScanResultsCollection, featureFlagsWrapper wrappers.FeatureFlagsWrapper) { - for _, result := range results.Results { - countResult(summary, result) - } - // Set critical count for a specific engine if critical is disabled - flagResponse, _ := wrappers.GetSpecificFeatureFlag(featureFlagsWrapper, wrappers.CVSSV3Enabled) - criticalEnabled := flagResponse.Status - if summary.HasAPISecurity() { - summary.EnginesResult[commonParams.APISecType].Low = summary.APISecurity.SeverityCount["low"] - summary.EnginesResult[commonParams.APISecType].Medium = summary.APISecurity.SeverityCount["medium"] - summary.EnginesResult[commonParams.APISecType].High = summary.APISecurity.SeverityCount["high"] - if !criticalEnabled { - summary.EnginesResult[commonParams.APISecType].Critical = notAvailableNumber - } else { - summary.EnginesResult[commonParams.APISecType].Critical = summary.APISecurity.SeverityCount["critical"] - } - } - - summary.TotalIssues = summary.SastIssues + summary.ScaIssues + summary.KicsIssues + summary.GetAPISecurityDocumentationTotal() - - if summary.HasSCS() { - // Special case for SCS where status is partial if any microengines failed - if summary.SCSOverview.Status == scanPartialString { - summary.EnginesResult[commonParams.ScsType].StatusCode = scanPartialNumber - } - if !criticalEnabled { - summary.EnginesResult[commonParams.ScsType].Critical = notAvailableNumber - removeCriticalFromSCSOverview(summary) - } - if *summary.ScsIssues >= 0 { - summary.TotalIssues += *summary.ScsIssues - } - } - if wrappers.IsContainersEnabled { - if *summary.ContainersIssues >= 0 { - summary.TotalIssues += *summary.ContainersIssues - } - } - if !criticalEnabled { - summary.EnginesResult[commonParams.SastType].Critical = notAvailableNumber - summary.EnginesResult[commonParams.KicsType].Critical = notAvailableNumber - summary.EnginesResult[commonParams.ScaType].Critical = notAvailableNumber - summary.EnginesResult[commonParams.ContainersType].Critical = notAvailableNumber - } -} - -func removeCriticalFromSCSOverview(summary *wrappers.ResultSummary) { - criticalCount := summary.SCSOverview.RiskSummary[criticalLabel] - summary.SCSOverview.TotalRisksCount -= criticalCount - summary.SCSOverview.RiskSummary[criticalLabel] = notAvailableNumber - for _, microEngineOverview := range summary.SCSOverview.MicroEngineOverviews { - if microEngineOverview.RiskSummary != nil && microEngineOverview.RiskSummary[criticalLabel] != nil { - engineCriticalCount := microEngineOverview.RiskSummary[criticalLabel] - microEngineOverview.TotalRisks -= engineCriticalCount.(int) - microEngineOverview.RiskSummary[criticalLabel] = disabledString - } - } -} - -func writeHTMLSummary(targetFile string, summary *wrappers.ResultSummary) error { - log.Println("Creating Summary Report: ", targetFile) - summaryTemp, err := template.New("summaryTemplate").Parse(wrappers.SummaryTemplate(isScanPending(summary.Status))) - if err == nil { - f, err := os.Create(targetFile) - if err == nil { - _ = summaryTemp.ExecuteTemplate(f, "SummaryTemplate", summary) - _ = f.Close() - } - return err - } - return nil -} -func writeMarkdownSummary(targetFile string, data *wrappers.ResultSummary) error { - log.Println("Creating Markdown Summary Report: ", targetFile) - tmpl, err := template.New(printer.FormatSummaryMarkdown).Parse(wrappers.SummaryMarkdownTemplate(isScanPending(data.Status))) - if err != nil { - return err - } - file, err := os.Create(targetFile) - if err != nil { - return err - } - defer file.Close() - - err = tmpl.Execute(file, &data) - if err != nil { - return err - } - return nil -} - -// nolint: whitespace -func writeConsoleSummary(summary *wrappers.ResultSummary, featureFlagsWrapper wrappers.FeatureFlagsWrapper, ignorePolicyFlagOmit bool) error { - if !isScanPending(summary.Status) { - fmt.Printf(" Scan Summary: \n") - fmt.Printf(" Created At: %s\n", summary.CreatedAt) - fmt.Printf(" Project Name: %s \n", summary.ProjectName) - fmt.Printf(" Scan ID: %s \n\n", summary.ScanID) - fmt.Printf(" Results Summary: \n") - fmt.Printf( - " Risk Level: %s \n", - summary.RiskMsg, - ) - if summary.Policies != nil && !strings.EqualFold(summary.Policies.Status, policeManagementNoneStatus) { - printPoliciesSummary(summary, ignorePolicyFlagOmit) - } - - printResultsSummaryTable(summary) - - if summary.HasAPISecurity() { - printAPIsSecuritySummary(summary) - } - - if summary.HasSCS() { - printSCSSummary(summary.SCSOverview.MicroEngineOverviews, featureFlagsWrapper) - } - - 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") - fmt.Printf("For more information: %s\n", summary.BaseURI) - } - return nil -} - -func printPoliciesSummary(summary *wrappers.ResultSummary, ignorePolicyFlagOmit bool) { - hasViolations := false - for _, policy := range summary.Policies.Policies { - if len(policy.RulesViolated) > 0 { - hasViolations = true - break - } - } - if hasViolations { - fmt.Printf(tableLine + "\n") - if ignorePolicyFlagOmit { - printWarningIfIgnorePolicyOmiited() - } - if summary.Policies.BreakBuild { - fmt.Printf(" Policy Management Violation - Break Build Enabled: \n") - } else { - fmt.Printf(" Policy Management Violation: \n") - } - for _, police := range summary.Policies.Policies { - if len(police.RulesViolated) > 0 { - fmt.Printf(" Policy: %s | Break Build: %t | Violated Rules: ", police.Name, police.BreakBuild) - for _, violatedRule := range police.RulesViolated { - fmt.Printf("%s;", violatedRule) - } - } - fmt.Printf("\n") - } - fmt.Printf("\n") - } -} - -func printAPIsSecuritySummary(summary *wrappers.ResultSummary) { - fmt.Printf(" API Security - Total Detected APIs: %d \n", summary.APISecurity.APICount) - fmt.Printf(" APIS WITH RISK: %*d \n", defaultPaddingSize, summary.APISecurity.TotalRisksCount) - if summary.HasAPISecurityDocumentation() { - fmt.Printf(" APIS DOCUMENTATION: %*d \n", defaultPaddingSize, summary.GetAPISecurityDocumentationTotal()) - } - fmt.Printf(tableLine + twoNewLines) -} - -func printTableRow(title string, counts *wrappers.EngineResultSummary, statusNumber int) { - switch statusNumber { - case notAvailableNumber: - fmt.Printf(stringTableResultsFormat, title, notAvailableString, notAvailableString, notAvailableString, notAvailableString, notAvailableString, notAvailableString) - case scanFailedNumber: - fmt.Printf(tableResultsFormat, title, getCountValue(counts.Critical), counts.High, counts.Medium, counts.Low, counts.Info, scanFailedString) - case scanCanceledNumber: - fmt.Printf(tableResultsFormat, title, getCountValue(counts.Critical), counts.High, counts.Medium, counts.Low, counts.Info, scanCanceledString) - case scanPartialNumber: - fmt.Printf(tableResultsFormat, title, getCountValue(counts.Critical), counts.High, counts.Medium, counts.Low, counts.Info, scanPartialString) - default: - fmt.Printf(tableResultsFormat, title, getCountValue(counts.Critical), counts.High, counts.Medium, counts.Low, counts.Info, scanSuccessString) - } -} - -func printSCSSummary(microEngineOverviews []*wrappers.MicroEngineOverview, featureFlagsWrapper wrappers.FeatureFlagsWrapper) { - fmt.Printf(" Supply Chain Security Results\n") - fmt.Printf(" -------------------------------------------------------------------------- \n") - fmt.Println(" | Critical High Medium Low Info Status |") - for _, microEngineOverview := range microEngineOverviews { - printSCSTableRow(microEngineOverview, featureFlagsWrapper) - } - fmt.Printf(" -------------------------------------------------------------------------- \n\n") -} - -func printSCSTableRow(microEngineOverview *wrappers.MicroEngineOverview, featureFlagsWrapper wrappers.FeatureFlagsWrapper) { - formatString := " | %-20s %4v %4v %6v %4v %4v %-9s |\n" - notAvailableFormatString := " | %-20s %4v %4s %6s %4s %4s %5s |\n" - - riskSummary := microEngineOverview.RiskSummary - microEngineName := microEngineOverview.FullName - - switch microEngineOverview.Status { - case scsScanUnavailableString: - fmt.Printf(notAvailableFormatString, microEngineName, notAvailableString, notAvailableString, notAvailableString, notAvailableString, notAvailableString, notAvailableString) - default: - fmt.Printf(formatString, microEngineName, riskSummary[criticalLabel], riskSummary[highLabel], riskSummary[mediumLabel], riskSummary[lowLabel], - riskSummary[infoLabel], microEngineOverview.Status) - } -} - -func getCountValue(count int) interface{} { - if count < 0 { - return disabledString - } - return count -} - -func printResultsSummaryTable(summary *wrappers.ResultSummary) { - totalCriticalIssues := summary.EnginesResult.GetCriticalIssues() - totalHighIssues := summary.EnginesResult.GetHighIssues() - totalMediumIssues := summary.EnginesResult.GetMediumIssues() - totalLowIssues := summary.EnginesResult.GetLowIssues() - totalInfoIssues := summary.EnginesResult.GetInfoIssues() - fmt.Printf(tableLine + twoNewLines) - fmt.Printf(" Total Results: %d (Total Results includes only API documentation vulnerabilities\n and does not include API code vulnerabilities.)\n", summary.TotalIssues) - fmt.Println(tableLine) - fmt.Printf(TableTitleFormat, " ", "Critical", "High", "Medium", "Low", "Info", "Status") - - printTableRow("APIs", summary.EnginesResult[commonParams.APISecType], summary.EnginesResult[commonParams.APISecType].StatusCode) - printTableRow("IAC", summary.EnginesResult[commonParams.KicsType], summary.EnginesResult[commonParams.KicsType].StatusCode) - printTableRow("SAST", summary.EnginesResult[commonParams.SastType], summary.EnginesResult[commonParams.SastType].StatusCode) - printTableRow("SCA", summary.EnginesResult[commonParams.ScaType], summary.EnginesResult[commonParams.ScaType].StatusCode) - printTableRow("SCS", summary.EnginesResult[commonParams.ScsType], summary.EnginesResult[commonParams.ScsType].StatusCode) - - if wrappers.IsContainersEnabled { - printTableRow("CONTAINERS", summary.EnginesResult[commonParams.ContainersType], summary.EnginesResult[commonParams.ContainersType].StatusCode) - } - - fmt.Println(tableLine) - fmt.Printf(tableResultsFormat, - "TOTAL", getCountValue(totalCriticalIssues), totalHighIssues, totalMediumIssues, totalLowIssues, totalInfoIssues, summary.Status) - fmt.Printf(tableLine + twoNewLines) -} - -func generateScanSummaryURL(summary *wrappers.ResultSummary) string { - summaryURL := fmt.Sprintf( - strings.Replace(summary.BaseURI, "overview", "scans?id=%s&branch=%s", 1), - summary.ScanID, url.QueryEscape(summary.BranchName), - ) - return summaryURL -} - -func runGetResultCommand( - resultsWrapper wrappers.ResultsWrapper, - scanWrapper wrappers.ScansWrapper, - exportWrapper wrappers.ExportWrapper, - resultsPdfReportsWrapper wrappers.ResultsPdfWrapper, - resultsJSONReportsWrapper wrappers.ResultsJSONWrapper, - risksOverviewWrapper wrappers.RisksOverviewWrapper, - scsScanOverviewWrapper wrappers.ScanOverviewWrapper, - policyWrapper wrappers.PolicyWrapper, - featureFlagsWrapper wrappers.FeatureFlagsWrapper, - jwtWrapper wrappers.JWTWrapper, -) func(cmd *cobra.Command, args []string) error { - return func(cmd *cobra.Command, args []string) error { - targetFile, _ := cmd.Flags().GetString(commonParams.TargetFlag) - targetPath, _ := cmd.Flags().GetString(commonParams.TargetPathFlag) - format, _ := cmd.Flags().GetString(commonParams.TargetFormatFlag) - formatPdfToEmail, _ := cmd.Flags().GetString(commonParams.ReportFormatPdfToEmailFlag) - formatPdfOptions, _ := cmd.Flags().GetString(commonParams.ReportFormatPdfOptionsFlag) - formatSbomOptions, _ := cmd.Flags().GetString(commonParams.ReportSbomFormatFlag) - sastRedundancy, _ := cmd.Flags().GetBool(commonParams.SastRedundancyFlag) - agent, _ := cmd.Flags().GetString(commonParams.AgentFlag) - scaHideDevAndTestDep, _ := cmd.Flags().GetBool(commonParams.ScaHideDevAndTestDepFlag) - ignorePolicy, _ := cmd.Flags().GetBool(commonParams.IgnorePolicyFlag) - // Check if the user has permission to override policy management if --ignore-policy is set - ignorePolicyFlagOmit := false - if ignorePolicy { - overridePolicyManagementPer, err := jwtWrapper.CheckPermissionByAccessToken(OverridePolicyManagement) - if err != nil { - return err - } - if !overridePolicyManagementPer { - ignorePolicyFlagOmit = true - ignorePolicy = false - } - } - waitDelay, _ := cmd.Flags().GetInt(commonParams.WaitDelayFlag) - policyTimeout, _ := cmd.Flags().GetInt(commonParams.PolicyTimeoutFlag) - - scanID, _ := cmd.Flags().GetString(commonParams.ScanIDFlag) - if scanID == "" { - return errors.Errorf("%s: Please provide a scan ID", failedListingResults) - } - - resultsParams, err := getFilters(cmd) - if err != nil { - return errors.Wrapf(err, "%s", failedListingResults) - } - - if scaHideDevAndTestDep { - resultsParams[ScaExcludeResultTypesParam] = ScaDevAndTestExclusionParam - } - - scan, errorModel, scanErr := scanWrapper.GetByID(scanID) - if scanErr != nil { - return errors.Wrapf(scanErr, "%s", failedGetting) - } - if errorModel != nil { - return errors.Errorf("%s: CODE: %d, %s", failedGettingScan, errorModel.Code, errorModel.Message) - } - - var policyResponseModel *wrappers.PolicyResponseModel - if !isScanPending(string(scan.Status)) { - policyResponseModel, err = services.HandlePolicyEvaluation(cmd, policyWrapper, scan, ignorePolicy, agent, waitDelay, policyTimeout) - if err != nil { - return err - } - } else { - logger.PrintIfVerbose("Policy violations aren't returned in the pipeline for scans run in async mode.") - } - - if sastRedundancy { - resultsParams[commonParams.SastRedundancyFlag] = "" - } - - _, err = CreateScanReport(resultsWrapper, risksOverviewWrapper, scsScanOverviewWrapper, exportWrapper, - policyResponseModel, resultsPdfReportsWrapper, resultsJSONReportsWrapper, scan, format, formatPdfToEmail, formatPdfOptions, - formatSbomOptions, targetFile, targetPath, agent, resultsParams, featureFlagsWrapper, ignorePolicyFlagOmit) - return err - } -} - -func runGetCodeBashingCommand( - codeBashingWrapper wrappers.CodeBashingWrapper, -) func(cmd *cobra.Command, args []string) error { - return func(cmd *cobra.Command, args []string) error { - language, _ := cmd.Flags().GetString(commonParams.LanguageFlag) - cwe, _ := cmd.Flags().GetString(commonParams.CweIDFlag) - vulType, _ := cmd.Flags().GetString(commonParams.VulnerabilityTypeFlag) - params, err := codeBashingWrapper.BuildCodeBashingParams( - []wrappers.CodeBashingParamsCollection{ - { - CweID: "CWE-" + cwe, - Language: language, - CxQueryName: strings.ReplaceAll(vulType, " ", "_"), - }, - }, - ) - if err != nil { - return err - } - // Fetch the cached token or a new one to obtain the codebashing URL incoded in the jwt token - codeBashingURL, err := codeBashingWrapper.GetCodeBashingURL(codeBashingKey) - if err != nil { - return err - } - // Make the request to the api to obtain the codebashing link and send the codebashing url to enrich the path - CodeBashingModel, webError, err := codeBashingWrapper.GetCodeBashingLinks(params, codeBashingURL) - if err != nil { - return err - } - if webError != nil { - return errors.New(webError.Message) - } - err = printByFormat(cmd, *CodeBashingModel) - if err != nil { - return errors.Wrapf(err, "%s", failedListingCodeBashing) - } - return nil - } -} - -func setIsContainersEnabled(agent string) { - wrappers.IsContainersEnabled = !containsIgnoreCase(containerEngineUnsupportedAgents, agent) -} - -func filterResultsByType(results *wrappers.ScanResultsCollection, excludedTypes map[string]struct{}) *wrappers.ScanResultsCollection { - var filteredResults []*wrappers.ScanResult - - for _, result := range results.Results { - if _, shouldExclude := excludedTypes[result.Type]; shouldExclude { - results.TotalCount-- - } else { - filteredResults = append(filteredResults, result) - } - } - results.Results = filteredResults - return results -} - -func filterScsResultsByAgent(results *wrappers.ScanResultsCollection, agent string) *wrappers.ScanResultsCollection { - unsupportedTypesByAgent := map[string][]string{ - commonParams.VSCodeAgent: {commonParams.SCSScorecardType}, - commonParams.JetbrainsAgent: {commonParams.SCSScorecardType}, - commonParams.EclipseAgent: {commonParams.SCSScorecardType, commonParams.SCSSecretDetectionType}, - commonParams.VisualStudioAgent: {commonParams.SCSScorecardType}, - } - - excludedTypes := make(map[string]struct{}) - - if typesToExclude, exists := unsupportedTypesByAgent[agent]; exists { - for _, excludeType := range typesToExclude { - excludedTypes[excludeType] = struct{}{} - } - } - - results = filterResultsByType(results, excludedTypes) - - return results -} - -func CreateScanReport( - resultsWrapper wrappers.ResultsWrapper, - risksOverviewWrapper wrappers.RisksOverviewWrapper, - scsScanOverviewWrapper wrappers.ScanOverviewWrapper, - exportWrapper wrappers.ExportWrapper, - policyResponseModel *wrappers.PolicyResponseModel, - resultsPdfReportsWrapper wrappers.ResultsPdfWrapper, - resultsJSONReportsWrapper wrappers.ResultsJSONWrapper, - scan *wrappers.ScanResponseModel, - reportTypes, - formatPdfToEmail, - formatPdfOptions, - formatSbomOptions, - targetFile, - targetPath string, - agent string, - resultsParams map[string]string, - featureFlagsWrapper wrappers.FeatureFlagsWrapper, - ignorePolicyFlagOmit bool, -) (*wrappers.ScanResultsCollection, error) { - reportList := strings.Split(reportTypes, ",") - results := &wrappers.ScanResultsCollection{} - setIsContainersEnabled(agent) - summary, err := convertScanToResultsSummary(scan, resultsWrapper) - if err != nil { - return nil, err - } - scanPending := isScanPending(summary.Status) - - err = createDirectory(targetPath) - if err != nil { - return nil, err - } - if !scanPending { - results, err = ReadResults(resultsWrapper, exportWrapper, scan, resultsParams, agent, featureFlagsWrapper) - if err != nil { - return nil, err - } - } - isSummaryNeeded := verifyFormatsByReportList(reportList, summaryFormats...) - if isSummaryNeeded && !scanPending { - summary, err = summaryReport(summary, policyResponseModel, risksOverviewWrapper, scsScanOverviewWrapper, featureFlagsWrapper, results, resultsParams) - if err != nil { - return nil, err - } - } - for _, reportType := range reportList { - err = createReport(reportType, formatPdfToEmail, formatPdfOptions, formatSbomOptions, targetFile, - targetPath, results, summary, exportWrapper, resultsPdfReportsWrapper, resultsJSONReportsWrapper, featureFlagsWrapper, ignorePolicyFlagOmit) - if err != nil { - return nil, err - } - } - return results, nil -} - -func countResult(summary *wrappers.ResultSummary, result *wrappers.ScanResult) { - engineType := strings.TrimSpace(result.Type) - severity := strings.ToLower(result.Severity) - if contains(summary.EnginesEnabled, engineType) && isExploitable(result.State) { - if engineType == commonParams.SastType { - summary.SastIssues++ - summary.TotalIssues++ - } else if engineType == commonParams.ScaType { - summary.ScaIssues++ - summary.TotalIssues++ - } else if engineType == commonParams.KicsType { - summary.KicsIssues++ - summary.TotalIssues++ - } else if engineType == commonParams.ContainersType { - if wrappers.IsContainersEnabled { - *summary.ContainersIssues++ - summary.TotalIssues++ - } else { - return - } - } else if strings.HasPrefix(engineType, commonParams.SscsType) { - addResultToSCSOverview(summary, result) - engineType = commonParams.ScsType - *summary.ScsIssues++ - summary.TotalIssues++ - } else { - return - } - - switch severity { - case criticalLabel: - summary.CriticalIssues++ - case highLabel: - summary.HighIssues++ - case mediumLabel: - summary.MediumIssues++ - case lowLabel: - summary.LowIssues++ - case infoLabel: - summary.InfoIssues++ - } - - summary.UpdateEngineResultSummary(engineType, severity) - } -} - -func addResultToSCSOverview(summary *wrappers.ResultSummary, result *wrappers.ScanResult) { - if engineOverviewName, engineExists := sscsEngineToOverviewEngineMap[result.Type]; engineExists { - for _, microEngineOverview := range summary.SCSOverview.MicroEngineOverviews { - if microEngineOverview.Name == engineOverviewName { - if microEngineOverview.RiskSummary != nil { - severity := strings.ToLower(result.Severity) - if severityCount, exists := microEngineOverview.RiskSummary[severity]; exists { - summary.SCSOverview.RiskSummary[severity]++ - microEngineOverview.TotalRisks++ - summary.SCSOverview.TotalRisksCount++ - microEngineOverview.RiskSummary[severity] = severityCount.(int) + 1 - } - } - } - } - } -} - -func verifyFormatsByReportList(reportFormats []string, formats ...string) bool { - for _, reportFormat := range reportFormats { - for _, format := range formats { - if printer.IsFormat(reportFormat, format) { - return true - } - } - } - return false -} - -func validateEmails(emailString string) ([]string, error) { - re := regexp.MustCompile(`^[a-zA-Z0-9_.+-]+@[a-zA-Z0-9-]+\.[a-zA-Z0-9-.]+$`) - emails := strings.Split(emailString, ",") - var validEmails []string - for _, emailStr := range emails { - email := strings.TrimSpace(emailStr) - if re.MatchString(email) { - validEmails = append(validEmails, email) - } else { - return nil, errors.Errorf("report not sent, invalid email address: %s", email) - } - } - return validEmails, nil -} - -func getResultsForAPISecScanner( - risksOverviewWrapper wrappers.RisksOverviewWrapper, - scanID string, -) (results *wrappers.APISecResult, err error) { - var apiSecResultsModel *wrappers.APISecResult - var errorModel *wrappers.WebError - - apiSecResultsModel, errorModel, err = risksOverviewWrapper.GetAllAPISecRisksByScanID(scanID) - if err != nil { - return nil, errors.Wrapf(err, "%s", failedListingResults) - } - if errorModel != nil { - return nil, errors.Errorf("%s: CODE: %d, %s", failedListingResults, errorModel.Code, errorModel.Message) - } else if apiSecResultsModel != nil { - return apiSecResultsModel, nil - } - return nil, nil -} - -func getScanOverviewForSCSScanner( - scsScanOverviewWrapper wrappers.ScanOverviewWrapper, - scanID string, -) (results *wrappers.SCSOverview, err error) { - var scsOverview *wrappers.SCSOverview - var errorModel *wrappers.WebError - - scsOverview, errorModel, err = scsScanOverviewWrapper.GetSCSOverviewByScanID(scanID) - if err != nil { - return nil, errors.Wrapf(err, "SCS: %s", failedListingResults) - } - if errorModel != nil { - return nil, errors.Errorf("SCS: %s: CODE: %d, %s", failedListingResults, errorModel.Code, errorModel.Message) - } else if scsOverview != nil { - // Setting all counts to 0. Results are recounted in enhanceWithScanSummary->countResult - scsOverview.TotalRisksCount = 0 - for key := range scsOverview.RiskSummary { - scsOverview.RiskSummary[key] = 0 - } - for _, microEngineOverview := range scsOverview.MicroEngineOverviews { - microEngineOverview.TotalRisks = 0 - if microEngineOverview.RiskSummary != nil { - for severity := range microEngineOverview.RiskSummary { - microEngineOverview.RiskSummary[severity] = 0 - } - } - } - return scsOverview, nil - } - return nil, nil -} - -func isScanPending(scanStatus string) bool { - return !(strings.EqualFold(scanStatus, "Completed") || strings.EqualFold( - scanStatus, - "Partial", - ) || strings.EqualFold(scanStatus, "Failed")) -} - -func isValidScanStatus(status, format string) bool { - if isScanPending(status) { - log.Printf("Result format file %s not create because scan status is %s", format, status) - return false - } - return true -} - -func createReport(format, - formatPdfToEmail, - formatPdfOptions, - formatSbomOptions, - targetFile, - targetPath string, - results *wrappers.ScanResultsCollection, - summary *wrappers.ResultSummary, - exportWrapper wrappers.ExportWrapper, - resultsPdfReportsWrapper wrappers.ResultsPdfWrapper, - resultsJSONReportsWrapper wrappers.ResultsJSONWrapper, - featureFlagsWrapper wrappers.FeatureFlagsWrapper, - ignorePolicyFlagOmit bool) error { - if printer.IsFormat(format, printer.FormatIndentedJSON) { - return nil - } - if printer.IsFormat(format, printer.FormatSarif) && isValidScanStatus(summary.Status, printer.FormatSarif) { - sarifRpt := createTargetName(targetFile, targetPath, printer.FormatSarif) - return exportSarifResults(sarifRpt, results) - } - if printer.IsFormat(format, printer.FormatSonar) && isValidScanStatus(summary.Status, printer.FormatSonar) { - sonarRpt := createTargetName(fmt.Sprintf("%s%s", targetFile, sonarTypeLabel), targetPath, printer.FormatJSON) - return exportSonarResults(sonarRpt, results) - } - if printer.IsFormat(format, printer.FormatJSON) && isValidScanStatus(summary.Status, printer.FormatJSON) { - jsonRpt := createTargetName(targetFile, targetPath, printer.FormatJSON) - return exportJSONResults(jsonRpt, results) - } - if printer.IsFormat(format, printer.FormatJSONv2) && isValidScanStatus(summary.Status, printer.FormatJSONv2) { - summaryRpt := createTargetName(targetFile, targetPath, printer.FormatJSON) - return exportJSONReportResults(resultsJSONReportsWrapper, summary, summaryRpt, featureFlagsWrapper) - } - if printer.IsFormat(format, printer.FormatGLSast) { - jsonRpt := createTargetName(fmt.Sprintf("%s%s", targetFile, glSastTypeLabel), targetPath, printer.FormatJSON) - return exportGlSastResults(jsonRpt, results, summary) - } - if printer.IsFormat(format, printer.FormatGLSca) { - jsonRpt := createTargetName(fmt.Sprintf("%s%s", targetFile, glScaTypeLabel), targetPath, printer.FormatJSON) - return exportGlScaResults(jsonRpt, results, summary) - } - - if printer.IsFormat(format, printer.FormatSummaryConsole) { - return writeConsoleSummary(summary, featureFlagsWrapper, ignorePolicyFlagOmit) - } - if printer.IsFormat(format, printer.FormatSummary) { - summaryRpt := createTargetName(targetFile, targetPath, printer.FormatHTML) - convertNotAvailableNumberToZero(summary) - return writeHTMLSummary(summaryRpt, summary) - } - if printer.IsFormat(format, printer.FormatSummaryJSON) { - summaryRpt := createTargetName(targetFile, targetPath, printer.FormatJSON) - convertNotAvailableNumberToZero(summary) - return exportJSONSummaryResults(summaryRpt, summary) - } - if printer.IsFormat(format, printer.FormatPDF) && isValidScanStatus(summary.Status, printer.FormatPDF) { - summaryRpt := createTargetName(targetFile, targetPath, printer.FormatPDF) - return exportPdfResults(resultsPdfReportsWrapper, summary, summaryRpt, formatPdfToEmail, formatPdfOptions, featureFlagsWrapper) - } - if printer.IsFormat(format, printer.FormatSummaryMarkdown) { - summaryRpt := createTargetName(targetFile, targetPath, "md") - convertNotAvailableNumberToZero(summary) - return writeMarkdownSummary(summaryRpt, summary) - } - if printer.IsFormat(format, printer.FormatSbom) && isValidScanStatus(summary.Status, printer.FormatSbom) { - targetType := printer.FormatJSON - if strings.Contains(strings.ToLower(formatSbomOptions), printer.FormatXML) { - targetType = printer.FormatXML - } - summaryRpt := createTargetName(fmt.Sprintf("%s_%s", targetFile, printer.FormatSbom), targetPath, targetType) - convertNotAvailableNumberToZero(summary) - - if !contains(summary.EnginesEnabled, commonParams.ScaType) { - return fmt.Errorf("unable to generate %s report - SCA engine must be enabled on scan summary", printer.FormatSbom) - } - - if summary.ScaIssues == notAvailableNumber { - return fmt.Errorf("unable to generate %s report - SCA engine did not complete successfully", printer.FormatSbom) - } - - return services.ExportSbomResults(exportWrapper, summaryRpt, summary, formatSbomOptions) - } - return fmt.Errorf("bad report format %s", format) -} - -func createTargetName(targetFile, targetPath, targetType string) string { - return filepath.Join(targetPath, targetFile+"."+targetType) -} - -func createDirectory(targetPath string) error { - if _, err := os.Stat(targetPath); os.IsNotExist(err) { - log.Printf("\nOutput path not found: %s\n", targetPath) - log.Printf("Creating directory: %s\n", targetPath) - err = os.Mkdir(targetPath, directoryPermission) - if err != nil { - return err - } - } - return nil -} - -func ReadResults( - resultsWrapper wrappers.ResultsWrapper, - exportWrapper wrappers.ExportWrapper, - scan *wrappers.ScanResponseModel, - resultsParams map[string]string, - agent string, featureflagsWrappers wrappers.FeatureFlagsWrapper) (results *wrappers.ScanResultsCollection, err error) { - var resultsModel *wrappers.ScanResultsCollection - var errorModel *wrappers.WebError - - resultsParams[commonParams.ScanIDQueryParam] = scan.ID - _, sastRedundancy := resultsParams[commonParams.SastRedundancyFlag] - - scaHideDevAndTestDep := resultsParams[ScaExcludeResultTypesParam] == ScaDevAndTestExclusionParam - - resultsModel, errorModel, err = resultsWrapper.GetAllResultsByScanID(resultsParams) - - if err != nil { - return nil, errors.Wrapf(err, "%s", failedListingResults) - } - if errorModel != nil { - return nil, errors.Errorf("%s: CODE: %d, %s", failedListingResults, errorModel.Code, errorModel.Message) - } - - if resultsModel != nil { - if slices.Contains(scan.Engines, commonParams.SastType) && sastRedundancy { - // Compute SAST results redundancy - resultsModel = ComputeRedundantSastResults(resultsModel) - } - resultsModel, err = enrichScaResults(exportWrapper, scan, resultsModel, scaHideDevAndTestDep, featureflagsWrappers) - if err != nil { - return nil, err - } - - if slices.Contains(scan.Engines, commonParams.ScsType) { - resultsModel = filterScsResultsByAgent(resultsModel, agent) - } - - resultsModel.ScanID = scan.ID - return resultsModel, nil - } - return nil, nil -} - -func enrichScaResults( - exportWrapper wrappers.ExportWrapper, - scan *wrappers.ScanResponseModel, - resultsModel *wrappers.ScanResultsCollection, - scaHideDevAndTestDep bool, featureflagWrapper wrappers.FeatureFlagsWrapper) (*wrappers.ScanResultsCollection, error) { - if slices.Contains(scan.Engines, commonParams.ScaType) { - scaExportDetails, err := services.GetExportPackage(exportWrapper, scan.ID, scaHideDevAndTestDep, featureflagWrapper) - if err != nil { - return nil, errors.Wrapf(err, "%s", failedListingResults) - } - scaPackageModel := parseScaExportPackage(scaExportDetails.Packages) - scaTypeModel := parseExportScaVulnerability(scaExportDetails.ScaTypes) - if scaPackageModel != nil { - resultsModel = addPackageInformation(resultsModel, scaPackageModel, scaTypeModel) - } - } - if slices.Contains(scan.Engines, commonParams.ContainersType) && !wrappers.IsContainersEnabled { - resultsModel = removeResultsByType(resultsModel, commonParams.ContainersType) - } - return resultsModel, nil -} - -func parseExportScaVulnerability(types []wrappers.ScaType) *[]wrappers.ScaTypeCollection { - var scaTypes []wrappers.ScaTypeCollection - for _, t := range types { - scaTypes = append(scaTypes, wrappers.ScaTypeCollection(t)) - } - return &scaTypes -} - -func parseScaExportPackage(packages []wrappers.ScaPackage) *[]wrappers.ScaPackageCollection { - var scaPackages []wrappers.ScaPackageCollection - for _, pkg := range packages { - pkg := pkg - scaPackages = append(scaPackages, wrappers.ScaPackageCollection{ - ID: pkg.ID, - Locations: pkg.Locations, - DependencyPathArray: parsePackagePathToDependencyPath(&pkg), - Outdated: pkg.Outdated, - IsDirectDependency: pkg.IsDirectDependency, - IsDevelopmentDependency: pkg.IsDevelopmentDependency, - IsTestDependency: pkg.IsTestDependency, - }) - } - return &scaPackages -} - -func parsePackagePathToDependencyPath(pkg *wrappers.ScaPackage) [][]wrappers.DependencyPath { - var dependencyPathArray [][]wrappers.DependencyPath - for _, path := range pkg.PackagePathArray { - var dependencyPath []wrappers.DependencyPath - for _, dep := range path { - dependencyPath = append(dependencyPath, wrappers.DependencyPath{ - ID: dep.ID, - Name: dep.Name, - Version: dep.Version, - }) - } - dependencyPathArray = append(dependencyPathArray, dependencyPath) - } - - // We are doing this to maintain the same structure that was in risk-management api response - // in risk-management, if the length of the dependency path array is 1, it will be the main package - // in export service, if there are no dependencies, the package path array will be empty - if len(dependencyPathArray) == 0 { - appendMainPackageToDependencyPath(&dependencyPathArray, pkg) - } - return dependencyPathArray -} - -func appendMainPackageToDependencyPath(dependencyPathArray *[][]wrappers.DependencyPath, pkg *wrappers.ScaPackage) { - *dependencyPathArray = append(*dependencyPathArray, []wrappers.DependencyPath{{ - ID: pkg.ID, - Locations: pkg.Locations, - Name: pkg.Name, - IsDevelopment: pkg.IsDevelopmentDependency, - }}) -} - -func removeResultsByType(model *wrappers.ScanResultsCollection, resultType string) *wrappers.ScanResultsCollection { - var newResults []*wrappers.ScanResult - for _, result := range model.Results { - isResultType := result.Type == resultType - if resultType == commonParams.SscsType { - isResultType = strings.HasPrefix(result.Type, resultType) - } - if !isResultType { - newResults = append(newResults, result) - } - } - model.Results = newResults - model.TotalCount = uint(len(newResults)) - return model -} - -func exportSarifResults(targetFile string, results *wrappers.ScanResultsCollection) error { - var err error - var resultsJSON []byte - log.Println("Creating SARIF Report: ", targetFile) - var sarifResults = convertCxResultsToSarif(results) - resultsJSON, err = json.Marshal(sarifResults) - if err != nil { - return errors.Wrapf(err, "%s: failed to serialize results response ", failedGettingAll) - } - f, err := os.Create(targetFile) - if err != nil { - return errors.Wrapf(err, "%s: failed to create target file ", failedGettingAll) - } - _, _ = fmt.Fprintln(f, string(resultsJSON)) - _ = f.Close() - return nil -} -func exportGlSastResults(targetFile string, results *wrappers.ScanResultsCollection, summary *wrappers.ResultSummary) error { - log.Println("Creating gl-sast Report: ", targetFile) - var glSast = new(wrappers.GlSastResultsCollection) - glSast.Vulnerabilities = []wrappers.GlVulnerabilities{} - err := addScanToGlSastReport(summary, glSast) - if err != nil { - return errors.Wrapf(err, "%s: failed to add scan to gl-sast report", failedListingResults) - } - convertCxResultToGlSastVulnerability(results, glSast, summary) - resultsJSON, err := json.Marshal(glSast) - if err != nil { - return errors.Wrapf(err, "%s: failed to serialize gl-sast report ", failedListingResults) - } - f, err := os.Create(targetFile) - if err != nil { - return errors.Wrapf(err, "%s: failed to create target file ", failedListingResults) - } - defer f.Close() - _, _ = fmt.Fprintln(f, string(resultsJSON)) - return nil -} - -func exportGlScaResults(targetFile string, results *wrappers.ScanResultsCollection, summary *wrappers.ResultSummary) error { - log.Println("Creating Gl-sca Report: ", targetFile) - glScaResult := &wrappers.GlScaResultsCollection{ - Vulnerabilities: []wrappers.GlScaDepVulnerabilities{}, // Initialize arrays to prevent GitLab schema validation errors. - ScaDependencyFiles: []wrappers.ScaDependencyFile{}, - } - err := addScanToGlScaReport(summary, glScaResult) - if err != nil { - return errors.Wrapf(err, "%s: failed to denerate GL-Sca report ", failedListingResults) - } - convertCxResultToGlScaVulnerability(results, glScaResult) - convertCxResultToGlScaFiles(results, glScaResult) - resultsJSON, err := json.Marshal(glScaResult) - if err != nil { - return errors.Wrapf(err, "%s: failed to serialize GL-Sca report ", failedListingResults) - } - f, err := os.Create(targetFile) - if err != nil { - return errors.Wrapf(err, "%s: failed to create target file ", failedListingResults) - } - _, _ = fmt.Fprintln(f, string(resultsJSON)) - defer f.Close() - - return nil -} - -func addScanToGlScaReport(summary *wrappers.ResultSummary, glScaResult *wrappers.GlScaResultsCollection) error { - createdAt, err := time.Parse(summaryCreatedAtLayout, summary.CreatedAt) - if err != nil { - return err - } - - glScaResult.Schema = wrappers.ScaSchema - glScaResult.Version = wrappers.SchemaVersion - glScaResult.Scan.Analyzer.VendorGlSCA.VendorGlname = wrappers.AnalyzerScaID - glScaResult.Scan.Analyzer.Name = wrappers.AnalyzerScaID - glScaResult.Scan.Analyzer.Name = wrappers.AnalyzerScaID - glScaResult.Scan.Analyzer.ID = wrappers.ScannerID - glScaResult.Scan.Scanner.ID = wrappers.ScannerID - glScaResult.Scan.Scanner.Name = wrappers.AnalyzerScaID - glScaResult.Scan.Scanner.VendorGlSCA.VendorGlname = wrappers.AnalyzerScaID - glScaResult.Scan.Status = commonParams.Success - glScaResult.Scan.Type = wrappers.ScannerType - glScaResult.Scan.StartTime = createdAt.Format(glTimeFormat) - glScaResult.Scan.EndTime = createdAt.Format(glTimeFormat) - glScaResult.Scan.Scanner.Name = wrappers.AnalyzerScaID - glScaResult.Scan.Scanner.VersionGlSca = commonParams.Version - glScaResult.Scan.Analyzer.VersionGlSca = commonParams.Version - - return nil -} - -func addScanToGlSastReport(summary *wrappers.ResultSummary, glSast *wrappers.GlSastResultsCollection) error { - createdAt, err := time.Parse(summaryCreatedAtLayout, summary.CreatedAt) - if err != nil { - return err - } - - glSast.Scan = wrappers.ScanGlReport{} - glSast.Schema = wrappers.SastSchema - glSast.Version = wrappers.SastSchemaVersion - glSast.Scan.Analyzer.URL = wrappers.AnalyzerURL - glSast.Scan.Analyzer.Name = wrappers.VendorName - glSast.Scan.Analyzer.Vendor.Name = wrappers.VendorName - glSast.Scan.Analyzer.ID = wrappers.AnalyzerID - glSast.Scan.Scanner.ID = wrappers.AnalyzerID - glSast.Scan.Scanner.Name = wrappers.VendorName - glSast.Scan.Status = commonParams.Success - glSast.Scan.Type = commonParams.SastType - glSast.Scan.StartTime = createdAt.Format(glTimeFormat) - glSast.Scan.EndTime = createdAt.Format(glTimeFormat) - glSast.Scan.Scanner.Vendor.Name = wrappers.VendorName - glSast.Scan.Scanner.Version = commonParams.Version - glSast.Scan.Analyzer.Version = commonParams.Version - - return nil -} -func exportSonarResults(targetFile string, results *wrappers.ScanResultsCollection) error { - var err error - var resultsJSON []byte - log.Println("Creating SONAR Report: ", targetFile) - var sonarResults = convertCxResultsToSonar(results) - resultsJSON, err = json.Marshal(sonarResults) - if err != nil { - return errors.Wrapf(err, "%s: failed to serialize results response ", failedGettingAll) - } - f, err := os.Create(targetFile) - if err != nil { - return errors.Wrapf(err, "%s: failed to create target file ", failedGettingAll) - } - _, _ = fmt.Fprintln(f, string(resultsJSON)) - _ = f.Close() - return nil -} - -// Function to decode HTML entities in the ScanResultsCollection -func decodeHTMLEntitiesInResults(results *wrappers.ScanResultsCollection) { - for _, result := range results.Results { - result.Description = html.UnescapeString(result.Description) - result.DescriptionHTML = html.UnescapeString(result.DescriptionHTML) - for _, node := range result.ScanResultData.Nodes { - node.FullName = html.UnescapeString(node.FullName) - node.Name = html.UnescapeString(node.Name) - } - } -} - -func exportJSONResults(targetFile string, results *wrappers.ScanResultsCollection) error { - decodeHTMLEntitiesInResults(results) - var err error - var resultsJSON []byte - log.Println("Creating JSON Report: ", targetFile) - resultsJSON, err = json.Marshal(results) - if err != nil { - return errors.Wrapf(err, "%s: failed to serialize results response ", failedGettingAll) - } - f, err := os.Create(targetFile) - if err != nil { - return errors.Wrapf(err, "%s: failed to create target file ", failedGettingAll) - } - _, _ = fmt.Fprintln(f, string(resultsJSON)) - _ = f.Close() - return nil -} - -func exportJSONReportResults(jsonWrapper wrappers.ResultsJSONWrapper, summary *wrappers.ResultSummary, summaryRpt string, featureFlagsWrapper wrappers.FeatureFlagsWrapper) error { - jsonReportsPayload := &wrappers.JSONReportsPayload{} - pollingResp := &wrappers.JSONPollingResponse{} - jsonReportsPayload.ReportName = reportNameImprovedScanReport - - jsonOptionsSections, jsonOptionsEngines := parseJSONOptions(summary.EnginesEnabled, jsonReportsPayload.ReportName) - - jsonReportsPayload.ReportType = CliType - jsonReportsPayload.FileFormat = printer.FormatJSON - jsonReportsPayload.Data.ScanID = summary.ScanID - jsonReportsPayload.Data.ProjectID = summary.ProjectID - jsonReportsPayload.Data.BranchName = summary.BranchName - jsonReportsPayload.Data.Scanners = jsonOptionsEngines - jsonReportsPayload.Data.Sections = jsonOptionsSections - - jsonReportID, webErr, err := jsonWrapper.GenerateJSONReport(jsonReportsPayload) - if webErr != nil { - return errors.Errorf("Error generating JSON report - %s", webErr.Message) - } - if err != nil { - return errors.Errorf("Error generating JSON report - %s", err.Error()) - } - log.Println("Generating JSON report") - pollingResp.Status = startedStatus - for pollingResp.Status == startedStatus || pollingResp.Status == requestedStatus { - pollingResp, webErr, err = jsonWrapper.CheckJSONReportStatus(jsonReportID.ReportID) - if err != nil || webErr != nil { - return errors.Wrapf(err, "%v", webErr) - } - logger.PrintfIfVerbose("JSON report status: %s", pollingResp.Status) - time.Sleep(delayValueForReport * time.Millisecond) - } - if pollingResp.Status != completedStatus { - return errors.Errorf("JSON generating failed - Current status: %s", pollingResp.Status) - } - - minioEnabled, _ := wrappers.GetSpecificFeatureFlag(featureFlagsWrapper, wrappers.MinioEnabled) - infoPathType := "" - if minioEnabled.Status { - infoPathType = jsonReportID.ReportID - } else { - infoPathType = pollingResp.URL - } - err = jsonWrapper.DownloadJSONReport(infoPathType, summaryRpt, minioEnabled.Status) - if err != nil { - return errors.Wrapf(err, "%s", "Failed downloading JSON report") - } - return nil -} - -func parseJSONOptions(enabledEngines []string, reportName string) (jsonOptionsSections, jsonOptionsEngines []string) { - jsonOptionsSections = []string{ - "ScanSummary", - "ExecutiveSummary", - "ScanResults", - } - - var jsonOptionsEnginesMap = map[string]string{ - commonParams.ScaType: "SCA", - commonParams.SastType: "SAST", - commonParams.KicsType: "KICS", - commonParams.IacType: "KICS", - commonParams.ContainersType: "Containers", - commonParams.ScsType: "Microengines", - } - if jsonOptionsEngines == nil { - for _, engine := range enabledEngines { - if jsonOptionsEnginesMap[engine] != "" { - jsonOptionsEngines = append(jsonOptionsEngines, jsonOptionsEnginesMap[engine]) - } - } - } - - if reportName == reportNameImprovedScanReport { - jsonOptionsSections = translateReportSectionsForImproved(jsonOptionsSections) - } - - return jsonOptionsSections, jsonOptionsEngines -} - -func exportJSONSummaryResults(targetFile string, results *wrappers.ResultSummary) error { - var err error - var resultsJSON []byte - log.Println("Creating summary JSON Report: ", targetFile) - resultsJSON, err = json.Marshal(results) - if err != nil { - return errors.Wrapf(err, "%s: failed to serialize results response ", failedGettingAll) - } - f, err := os.Create(targetFile) - if err != nil { - return errors.Wrapf(err, "%s: failed to create target file ", failedGettingAll) - } - _, _ = fmt.Fprintln(f, string(resultsJSON)) - _ = f.Close() - return nil -} - -func exportPdfResults(pdfWrapper wrappers.ResultsPdfWrapper, summary *wrappers.ResultSummary, summaryRpt, formatPdfToEmail, - pdfOptions string, featureFlagsWrapper wrappers.FeatureFlagsWrapper) error { - pdfReportsPayload := &wrappers.PdfReportsPayload{} - pollingResp := &wrappers.PdfPollingResponse{} - pdfReportsPayload.ReportName = reportNameImprovedScanReport - pdfOptionsSections, pdfOptionsEngines, err := parsePDFOptions(pdfOptions, summary.EnginesEnabled, pdfReportsPayload.ReportName) - if err != nil { - return err - } - pdfReportsPayload.ReportType = CliType - pdfReportsPayload.FileFormat = printer.FormatPDF - pdfReportsPayload.Data.ScanID = summary.ScanID - pdfReportsPayload.Data.ProjectID = summary.ProjectID - pdfReportsPayload.Data.BranchName = summary.BranchName - pdfReportsPayload.Data.Scanners = pdfOptionsEngines - pdfReportsPayload.Data.Sections = pdfOptionsSections - - // will generate pdf report and send it to the email list - // instead of saving it to the file system - if len(formatPdfToEmail) > 0 { - emailList, validateErr := validateEmails(formatPdfToEmail) - if validateErr != nil { - return validateErr - } - pdfReportsPayload.ReportType = reportTypeEmail - pdfReportsPayload.Data.Email = emailList - } - pdfReportID, webErr, err := pdfWrapper.GeneratePdfReport(pdfReportsPayload) - if webErr != nil { - return errors.Errorf("Error generating PDF report - %s", webErr.Message) - } - if err != nil { - return errors.Errorf("Error generating PDF report - %s", err.Error()) - } - if pdfReportsPayload.ReportType == reportTypeEmail { - log.Println("Sending PDF report to: ", pdfReportsPayload.Data.Email) - return nil - } - log.Println("Generating PDF report") - pollingResp.Status = startedStatus - for pollingResp.Status == startedStatus || pollingResp.Status == requestedStatus { - pollingResp, webErr, err = pdfWrapper.CheckPdfReportStatus(pdfReportID.ReportID) - if err != nil || webErr != nil { - return errors.Wrapf(err, "%v", webErr) - } - logger.PrintfIfVerbose("PDF report status: %s", pollingResp.Status) - time.Sleep(delayValueForReport * time.Millisecond) - } - if pollingResp.Status != completedStatus { - return errors.Errorf("PDF generating failed - Current status: %s", pollingResp.Status) - } - - minioEnabled, _ := wrappers.GetSpecificFeatureFlag(featureFlagsWrapper, wrappers.MinioEnabled) - infoPathType := "" - if minioEnabled.Status { - infoPathType = pdfReportID.ReportID - } else { - infoPathType = pollingResp.URL - } - err = pdfWrapper.DownloadPdfReport(infoPathType, summaryRpt, minioEnabled.Status) - if err != nil { - return errors.Wrapf(err, "%s", "Failed downloading PDF report") - } - return nil -} - -func parsePDFOptions(pdfOptions string, enabledEngines []string, reportName string) (pdfOptionsSections, pdfOptionsEngines []string, err error) { - var pdfOptionsSectionsMap = map[string]string{ - "scansummary": "ScanSummary", - "executivesummary": "ExecutiveSummary", - "scanresults": "ScanResults", - } - - var pdfOptionsEnginesMap = map[string]string{ - commonParams.ScaType: "SCA", - commonParams.SastType: "SAST", - commonParams.KicsType: "KICS", - commonParams.IacType: "KICS", - } - - pdfOptions = strings.ToLower(strings.ReplaceAll(pdfOptions, " ", "")) - options := strings.Split(strings.ReplaceAll(pdfOptions, "\n", ""), ",") - for _, s := range options { - if pdfOptionsEnginesMap[s] != "" { - pdfOptionsEngines = append(pdfOptionsEngines, pdfOptionsEnginesMap[s]) - } else if pdfOptionsSectionsMap[s] != "" { - pdfOptionsSections = append(pdfOptionsSections, pdfOptionsSectionsMap[s]) - } else { - return nil, nil, errors.Errorf("report option \"%s\" unavailable", s) - } - } - if pdfOptionsEngines == nil { - for _, engine := range enabledEngines { - if pdfOptionsEnginesMap[engine] != "" { - pdfOptionsEngines = append(pdfOptionsEngines, pdfOptionsEnginesMap[engine]) - } - } - } - - if reportName == reportNameImprovedScanReport { - pdfOptionsSections = translateReportSectionsForImproved(pdfOptionsSections) - } - - return pdfOptionsSections, pdfOptionsEngines, nil -} - -func translateReportSectionsForImproved(sections []string) []string { - var resultSections = make([]string, 0) - - var pdfOptionsSectionsImprovedTranslation = map[string][]string{ - "ScanSummary": {"scan-information"}, - "ExecutiveSummary": {"results-overview"}, - "ScanResults": {"scan-results", "categories", "resolved-results", "vulnerability-details"}, - } - - for _, section := range sections { - if translatedSections := pdfOptionsSectionsImprovedTranslation[section]; translatedSections != nil { - resultSections = append(resultSections, translatedSections...) - } - } - - return resultSections -} - -func convertCxResultsToSarif(results *wrappers.ScanResultsCollection) *wrappers.SarifResultsCollection { - var sarif = new(wrappers.SarifResultsCollection) - sarif.Schema = "https://raw.githubusercontent.com/oasis-tcs/sarif-spec/master/Schemata/sarif-schema-2.1.0.json" - sarif.Version = "2.1.0" - sarif.Runs = []wrappers.SarifRun{} - sarif.Runs = append(sarif.Runs, createSarifRun(results)) - return sarif -} - -func convertCxResultToGlSastVulnerability(results *wrappers.ScanResultsCollection, glSast *wrappers.GlSastResultsCollection, summary *wrappers.ResultSummary) { - for _, result := range results.Results { - if strings.TrimSpace(result.Type) == commonParams.SastType { - glSast = parseGlSastVulnerability(result, glSast, summary) - } - } -} - -func convertCxResultToGlScaVulnerability(results *wrappers.ScanResultsCollection, glScaResult *wrappers.GlScaResultsCollection) { - for _, result := range results.Results { - if strings.TrimSpace(result.Type) == commonParams.ScaType { - glScaResult = parseGlscaVulnerability(result, glScaResult) - } - } -} - -func convertCxResultToGlScaFiles(results *wrappers.ScanResultsCollection, glScaResult *wrappers.GlScaResultsCollection) { - for _, result := range results.Results { - if strings.TrimSpace(result.Type) == commonParams.ScaType { - glScaResult = parseGlScaFiles(result, glScaResult) - } - } -} -func parseGlSastVulnerability(result *wrappers.ScanResult, glSast *wrappers.GlSastResultsCollection, summary *wrappers.ResultSummary) *wrappers.GlSastResultsCollection { - hostName := parseURI(summary.BaseURI) - - queryName := result.ScanResultData.QueryName - fileName := result.ScanResultData.Nodes[0].FileName - lineNumber := strconv.FormatUint(uint64(result.ScanResultData.Nodes[0].Line), 10) - startLine := result.ScanResultData.Nodes[0].Line - endLine := result.ScanResultData.Nodes[0].Line + result.ScanResultData.Nodes[0].Length - ID := fmt.Sprintf("%s:%s:%s", queryName, fileName, lineNumber) - category := fmt.Sprintf("%s-%s", wrappers.VendorName, result.Type) - message := fmt.Sprintf("%s@%s:%s", queryName, fileName, lineNumber) - QueryDescriptionLink := fmt.Sprintf("%s/results/%s/%s/sast/description/%s/%s", hostName, summary.ScanID, summary.ProjectID, result.VulnerabilityDetails.CweID, result.ScanResultData.QueryID) - - glSast.Vulnerabilities = append(glSast.Vulnerabilities, wrappers.GlVulnerabilities{ - ID: ID, - Category: category, - Name: queryName, - Message: message, - Description: result.Description + " \n" + QueryDescriptionLink, - CVE: ID, - Severity: cases.Title(language.English).String(result.Severity), - Confidence: cases.Title(language.English).String(result.Severity), - Solution: "", - - Scanner: wrappers.GlScanner{ - ID: category, - Name: category, - }, - Identifiers: []wrappers.Identifier{ - { - Type: "cxOneScan", - Name: "CxOne Scan", - URL: summary.BaseURI, - Value: result.ID, - }, - }, - Links: make([]string, 0), - Tracking: wrappers.Tracking{ - Type: "source", - Items: []wrappers.Item{ - { - Signatures: []wrappers.Signature{{Algorithm: result.Type + "-Algorithm ", Value: "NA"}}, - File: fileName, - EndLine: endLine, - StartLine: startLine, - }, - }, - }, - Flags: make([]wrappers.Flag, 0), - Location: wrappers.Location{ - File: fileName, - StartLine: startLine, - EndLine: endLine, - }, - }) - return glSast -} -func parseGlscaVulnerability(result *wrappers.ScanResult, glDependencyResult *wrappers.GlScaResultsCollection) *wrappers.GlScaResultsCollection { - if result.ScanResultData.ScaPackageCollection != nil { - glDependencyResult.Vulnerabilities = append(glDependencyResult.Vulnerabilities, wrappers.GlScaDepVulnerabilities{ - ID: result.ID, - Name: result.VulnerabilityDetails.CveName, - Description: result.Description, - Severity: cases.Title(language.English).String(result.Severity), - Solution: result.ScanResultData.RecommendedVersion, - Identifiers: collectScaPackageData(result), - Links: collectScaPackageLinks(result), - TrackingDep: wrappers.TrackingDep{ - Items: collectScaPackageItemsDep(result), - }, - Flags: make([]string, 0), - LocationDep: wrappers.GlScaDepVulnerabilityLocation{ - File: parseGlDependencyLocation(result), - Dependency: wrappers.ScaDependencyLocation{ - Package: wrappers.PackageName{Name: result.ScanResultData.PackageIdentifier}, - ScaDependencyLocationVersion: "", - Direct: result.ScanResultData.ScaPackageCollection.IsDirectDependency, - ScaDependencyPath: result.ScanResultData.Line, - }, - }, - }) - } - return glDependencyResult -} -func parseGlDependencyLocation(result *wrappers.ScanResult) string { - var location string - if result != nil && result.ScanResultData.ScaPackageCollection != nil && result.ScanResultData.ScaPackageCollection.Locations != nil { - location = *result.ScanResultData.ScaPackageCollection.Locations[0] - } else { - location = "" - } - return location -} -func parseGlScaFiles(result *wrappers.ScanResult, glScaResult *wrappers.GlScaResultsCollection) *wrappers.GlScaResultsCollection { - if result.ScanResultData.ScaPackageCollection != nil && result.ScanResultData.ScaPackageCollection.Locations != nil { - glScaResult.ScaDependencyFiles = append(glScaResult.ScaDependencyFiles, wrappers.ScaDependencyFile{ - Path: *result.ScanResultData.ScaPackageCollection.Locations[0], - PackageManager: result.ScanResultData.ScaPackageCollection.ID, - Dependencies: collectScaFileLocations(result), - }) - } - return glScaResult -} -func collectScaFileLocations(result *wrappers.ScanResult) []wrappers.ScaDependencyLocation { - allScaIdentifierLocations := []wrappers.ScaDependencyLocation{} - for _, packageInfo := range result.ScanResultData.PackageData { - allScaIdentifierLocations = append(allScaIdentifierLocations, wrappers.ScaDependencyLocation{ - Package: wrappers.PackageName{ - Name: packageInfo.Type, - }, - ScaDependencyLocationVersion: packageInfo.URL, - Direct: true, - ScaDependencyPath: result.ScanResultData.Line, - }) - } - return allScaIdentifierLocations -} -func collectScaPackageItemsDep(result *wrappers.ScanResult) []wrappers.ItemDep { - allScaPackageItemDep := []wrappers.ItemDep{} - allScaPackageItemDep = append(allScaPackageItemDep, wrappers.ItemDep{ - Signature: []wrappers.SignatureDep{{Algorithm: "SCA-Algorithm ", Value: "NA"}}, - File: result.VulnerabilityDetails.CveName, - EndLine: 0, - StartLine: 0, - }) - return allScaPackageItemDep -} -func collectScaPackageLinks(result *wrappers.ScanResult) []wrappers.LinkDep { - allScaPackageLinks := []wrappers.LinkDep{} - for _, packageInfo := range result.ScanResultData.PackageData { - allScaPackageLinks = append(allScaPackageLinks, wrappers.LinkDep{ - Name: packageInfo.Type, - URL: packageInfo.URL, - }) - } - return allScaPackageLinks -} -func collectScaPackageData(result *wrappers.ScanResult) []wrappers.IdentifierDep { - allIdentifierDep := []wrappers.IdentifierDep{} - for _, packageInfo := range result.ScanResultData.PackageData { - allIdentifierDep = append(allIdentifierDep, wrappers.IdentifierDep{ - Type: packageInfo.Type, - Value: packageInfo.URL, - Name: packageInfo.URL, - }) - } - return allIdentifierDep -} - -func convertCxResultsToSonar(results *wrappers.ScanResultsCollection) *wrappers.ScanResultsSonar { - var sonar = new(wrappers.ScanResultsSonar) - sonar.Issues, sonar.Rules = parseSonar(results) - return sonar -} - -func createSarifRun(results *wrappers.ScanResultsCollection) wrappers.SarifRun { - var sarifRun wrappers.SarifRun - sarifRun.Tool.Driver.Name = wrappers.SarifName - sarifRun.Tool.Driver.Version = wrappers.SarifVersion - sarifRun.Tool.Driver.InformationURI = wrappers.SarifInformationURI - sarifRun.Tool.Driver.Rules, sarifRun.Results = parseResults(results) - return sarifRun -} - -func parseResults(results *wrappers.ScanResultsCollection) ([]wrappers.SarifDriverRule, []wrappers.SarifScanResult) { - var sarifRules = make([]wrappers.SarifDriverRule, 0) - var sarifResults = make([]wrappers.SarifScanResult, 0) - if results != nil { - ruleIds := map[interface{}]bool{} - for _, result := range results.Results { - if rule := findRule(ruleIds, result); rule != nil { - sarifRules = append(sarifRules, *rule) - } - if sarifResult := findResult(result); sarifResult != nil { - sarifResults = append(sarifResults, sarifResult...) - } - } - } - return sarifRules, sarifResults -} - -func parseSonar(results *wrappers.ScanResultsCollection) ([]wrappers.SonarIssues, []wrappers.SonarRules) { - var sonarIssues []wrappers.SonarIssues - var sonarRules []wrappers.SonarRules - seenRuleIDs := make(map[string]bool) // Track already added rule IDs - - if results != nil { - for _, result := range results.Results { - var auxRules = initSonarRules(result) - var auxIssue = initSonarIssue(result) - - if !seenRuleIDs[auxRules.ID] { - sonarRules = append(sonarRules, auxRules) - seenRuleIDs[auxRules.ID] = true - } - - engineType := strings.TrimSpace(result.Type) - - if engineType == commonParams.SastType { - auxIssue.PrimaryLocation = parseSonarPrimaryLocation(result) - auxIssue.SecondaryLocations = parseSonarSecondaryLocations(result) - sonarIssues = append(sonarIssues, auxIssue) - } else if engineType == commonParams.KicsType { - auxIssue.PrimaryLocation = parseLocationKics(result) - sonarIssues = append(sonarIssues, auxIssue) - } else if engineType == commonParams.ScaType { - sonarIssuesByLocation := parseScaSonarLocations(result) - sonarIssues = append(sonarIssues, sonarIssuesByLocation...) - } else if wrappers.IsContainersEnabled && engineType == commonParams.ContainersType { - auxIssue.PrimaryLocation = parseContainersSonar(result) - sonarIssues = append(sonarIssues, auxIssue) - } else if strings.HasPrefix(engineType, commonParams.SscsType) { - sscsSonarIssue := parseSscsSonar(result, &auxIssue) - sonarIssues = append(sonarIssues, sscsSonarIssue) - } - } - } - return sonarIssues, sonarRules -} - -func parseContainersSonar(result *wrappers.ScanResult) wrappers.SonarLocation { - var auxLocation wrappers.SonarLocation - auxLocation.FilePath = result.ScanResultData.ImageFilePath - auxLocation.Message = html.UnescapeString(result.Description) - var textRange wrappers.SonarTextRange - textRange.StartColumn = 1 - textRange.EndColumn = 2 - textRange.StartLine = 1 - textRange.EndLine = 2 - auxLocation.TextRange = textRange - return auxLocation -} - -func parseSscsSonar(result *wrappers.ScanResult, sonarIssue *wrappers.SonarIssues) wrappers.SonarIssues { - sonarIssue.PrimaryLocation.FilePath = result.ScanResultData.Filename - - sonarIssue.PrimaryLocation.Message = html.UnescapeString(result.ScanResultData.Remediation) - var textRange wrappers.SonarTextRange - textRange.StartColumn = 1 - textRange.EndColumn = 2 - textRange.StartLine = result.ScanResultData.Line - sonarIssue.PrimaryLocation.TextRange = textRange - return *sonarIssue -} - -func initSonarIssue(result *wrappers.ScanResult) wrappers.SonarIssues { - var sonarIssue wrappers.SonarIssues - engineType := strings.TrimSpace(result.Type) - if engineType == commonParams.SastType { - sonarIssue.RuleID = result.ScanResultData.LanguageName + " - " + result.ScanResultData.QueryName - } else if engineType == commonParams.KicsType { - sonarIssue.RuleID = result.ScanResultData.QueryName - } else if engineType == commonParams.ScaType { - sonarIssue.RuleID = result.ID - } else if wrappers.IsContainersEnabled && engineType == commonParams.ContainersType { - sonarIssue.RuleID = result.ID - } else if strings.HasPrefix(engineType, commonParams.SscsType) { - sonarIssue.RuleID = result.ID - } - - sonarIssue.PrimaryLocation.Message = html.UnescapeString(result.Description) - sonarIssue.EffortMinutes = 0 - - return sonarIssue -} - -func initSonarRules(result *wrappers.ScanResult) wrappers.SonarRules { - var sonarRules wrappers.SonarRules - var sonarImpacts wrappers.SonarImpacts - - sonarImpacts.Severity = sonarSeverities[result.Severity] - sonarImpacts.SoftwareQuality = vulnerabilitySonar - - sonarRules.EngineID = result.Type - sonarRules.CleanCodeAttribute = cleanCodeAttribute - - engineType := strings.TrimSpace(result.Type) - if engineType == commonParams.SastType { - sonarRules.Name = result.ScanResultData.QueryName - sonarRules.Description = html.UnescapeString(result.Description) - sonarRules.ID = result.ScanResultData.LanguageName + " - " + result.ScanResultData.QueryName - } else if engineType == commonParams.KicsType { - sonarRules.Name = result.ScanResultData.QueryName - sonarRules.Description = html.UnescapeString(result.Description) - sonarRules.ID = result.ScanResultData.QueryName - } else if engineType == commonParams.ScaType { - sonarRules.Name = result.ScanResultData.PackageIdentifier - sonarRules.Description = html.UnescapeString(result.Description) - sonarRules.ID = result.ID - } else if wrappers.IsContainersEnabled && engineType == commonParams.ContainersType { - sonarRules.Name = result.ScanResultData.ImageTag - sonarRules.Description = html.UnescapeString(result.Description) - sonarRules.ID = result.ID - } else if strings.HasPrefix(engineType, commonParams.SscsType) { - sonarRules.Name = result.ScanResultData.RuleName - sonarRules.Description = html.UnescapeString(result.ScanResultData.RuleDescription) - sonarRules.ID = result.ID - } - - sonarRules.Impacts = []wrappers.SonarImpacts{sonarImpacts} - - return sonarRules -} - -func parseScaSonarLocations(result *wrappers.ScanResult) []wrappers.SonarIssues { - if result == nil || result.ScanResultData.ScaPackageCollection == nil || result.ScanResultData.ScaPackageCollection.Locations == nil { - return []wrappers.SonarIssues{} - } - - var issuesByLocation []wrappers.SonarIssues - - for _, location := range result.ScanResultData.ScaPackageCollection.Locations { - issueByLocation := initSonarIssue(result) - - var primaryLocation wrappers.SonarLocation - - primaryLocation.FilePath = *location - _, _, primaryLocation.Message = findRuleID(result) - - var textRange wrappers.SonarTextRange - textRange.StartColumn = 1 - textRange.EndColumn = 2 - textRange.StartLine = 1 - textRange.EndLine = 2 - - primaryLocation.TextRange = textRange - - issueByLocation.PrimaryLocation = primaryLocation - - issuesByLocation = append(issuesByLocation, issueByLocation) - } - - return issuesByLocation -} - -func parseLocationKics(results *wrappers.ScanResult) wrappers.SonarLocation { - var auxLocation wrappers.SonarLocation - auxLocation.FilePath = strings.TrimLeft(results.ScanResultData.Filename, "/") - auxLocation.Message = html.UnescapeString(results.ScanResultData.Value) - var auxTextRange wrappers.SonarTextRange - auxTextRange.StartLine = results.ScanResultData.Line - auxTextRange.StartColumn = 0 - auxTextRange.EndColumn = 1 - auxLocation.TextRange = auxTextRange - return auxLocation -} - -func parseSonarPrimaryLocation(results *wrappers.ScanResult) wrappers.SonarLocation { - var auxLocation wrappers.SonarLocation - // fill the details in the primary Location - if len(results.ScanResultData.Nodes) > 0 { - auxLocation.FilePath = strings.TrimLeft(results.ScanResultData.Nodes[0].FileName, "/") - auxLocation.Message = html.UnescapeString(strings.ReplaceAll(results.ScanResultData.QueryName, "_", " ")) - auxLocation.TextRange = parseSonarTextRange(results.ScanResultData.Nodes[0]) - } - return auxLocation -} - -func parseSonarSecondaryLocations(results *wrappers.ScanResult) []wrappers.SonarLocation { - var auxSecondaryLocations []wrappers.SonarLocation - // Traverse all the rest of the scan result nodes into secondary location of sonar - if len(results.ScanResultData.Nodes) >= 1 { - for _, node := range results.ScanResultData.Nodes[1:] { - var auxSecondaryLocation wrappers.SonarLocation - auxSecondaryLocation.FilePath = strings.TrimLeft(node.FileName, "/") - auxSecondaryLocation.Message = html.UnescapeString(strings.ReplaceAll(results.ScanResultData.QueryName, "_", " ")) - auxSecondaryLocation.TextRange = parseSonarTextRange(node) - auxSecondaryLocations = append(auxSecondaryLocations, auxSecondaryLocation) - } - } - return auxSecondaryLocations -} - -func parseSonarTextRange(results *wrappers.ScanResultNode) wrappers.SonarTextRange { - var auxTextRange wrappers.SonarTextRange - auxTextRange.StartLine = results.Line - startColumn := getSastStartColumn(results.Column) - - auxTextRange.StartColumn = startColumn - auxTextRange.EndColumn = startColumn + results.Length - - if auxTextRange.StartColumn == auxTextRange.EndColumn { - auxTextRange.EndColumn++ - } - - return auxTextRange -} - -func findRule(ruleIds map[interface{}]bool, result *wrappers.ScanResult) *wrappers.SarifDriverRule { - var sarifRule wrappers.SarifDriverRule - sarifRule.ID, sarifRule.Name, _ = findRuleID(result) - sarifRule.FullDescription = findFullDescription(result) - sarifRule.Help = findHelp(result) - sarifRule.HelpURI = findHelpURI(result) - sarifRule.Properties = findProperties(result) - - if !ruleIds[sarifRule.ID] { - ruleIds[sarifRule.ID] = true - return &sarifRule - } - - return nil -} - -func getSastStartColumn(column uint) uint { - if column == 0 { - return 0 - } - return column - 1 -} - -func findRuleID(result *wrappers.ScanResult) (ruleID, ruleName, shortMessage string) { - caser := cases.Title(language.English) - - if result.ScanResultData.QueryID == nil && result.ScanResultData.RuleID == nil { - return fmt.Sprintf("%s (%s)", result.ID, result.Type), - caser.String(strings.ToLower(strings.ReplaceAll(result.ID, "-", ""))), - html.UnescapeString(fmt.Sprintf("%s (%s)", result.ScanResultData.PackageIdentifier, result.ID)) - } - - if result.ScanResultData.RuleID != nil { - ruleName = strings.ReplaceAll(result.ScanResultData.RuleName, "_", " ") - return fmt.Sprintf("%s - %s (%s)", ruleName, *result.ScanResultData.RuleID, result.Type), - ruleName, - ruleName - } - - ruleName = strings.ReplaceAll(result.ScanResultData.QueryName, "_", " ") - return fmt.Sprintf("%v - %s (%s)", ruleName, result.ScanResultData.QueryID, result.Type), - ruleName, - ruleName -} - -func findFullDescription(result *wrappers.ScanResult) wrappers.SarifDescription { - var sarifDescription wrappers.SarifDescription - sarifDescription.Text = findDescriptionText(result) - return sarifDescription -} - -func findHelp(result *wrappers.ScanResult) wrappers.SarifHelp { - var sarifHelp wrappers.SarifHelp - sarifHelp.Text = findHelpText(result) - sarifHelp.Markdown = findHelpMarkdownText(result) - - return sarifHelp -} - -func findHelpURI(result *wrappers.ScanResult) string { - if strings.HasPrefix(result.Type, commonParams.SscsType) { - if result.ScanResultData.RemediationLink != "" { - return result.ScanResultData.RemediationLink - } - } - - return wrappers.SarifInformationURI -} - -func findDescriptionText(result *wrappers.ScanResult) string { - if result.Type == commonParams.KicsType { - return fmt.Sprintf( - "%s Value: %s Excepted value: %s", - result.Description, result.ScanResultData.Value, result.ScanResultData.ExpectedValue, - ) - } else if strings.HasPrefix(result.Type, commonParams.SscsType) { - return result.ScanResultData.RuleDescription - } - - return result.Description -} - -func findHelpText(result *wrappers.ScanResult) string { - if strings.HasPrefix(result.Type, commonParams.SscsType) { - return findHelpMarkdownText(result) - } - - return findDescriptionText(result) -} - -func findHelpMarkdownText(result *wrappers.ScanResult) string { - if result.Type == commonParams.KicsType { - return fmt.Sprintf( - "%s

Value: %s
Excepted value: %s", - result.Description, result.ScanResultData.Value, result.ScanResultData.ExpectedValue, - ) - } else if strings.HasPrefix(result.Type, commonParams.SscsType) { - return result.ScanResultData.Remediation - } - - return result.Description -} - -func findProperties(result *wrappers.ScanResult) wrappers.SarifProperties { - var sarifProperties wrappers.SarifProperties - sarifProperties.ID, sarifProperties.Name, _ = findRuleID(result) - sarifProperties.Description = findDescriptionText(result) - sarifProperties.SecuritySeverity = securities[result.Severity] - sarifProperties.Tags = []string{"security", "checkmarx", result.Type} - return sarifProperties -} - -func findSarifLevel(result *wrappers.ScanResult) string { - level := map[string]string{ - infoCx: infoLowSarif, - lowCx: infoLowSarif, - mediumCx: mediumSarif, - highCx: highSarif, - criticalCx: highSarif, - } - return level[result.Severity] -} - -func initSarifResult(result *wrappers.ScanResult) wrappers.SarifScanResult { - var scanResult wrappers.SarifScanResult - scanResult.RuleID, _, scanResult.Message.Text = findRuleID(result) - scanResult.Level = findSarifLevel(result) - scanResult.Locations = []wrappers.SarifLocation{} - - return scanResult -} - -func findResult(result *wrappers.ScanResult) []wrappers.SarifScanResult { - var scanResults []wrappers.SarifScanResult - - if len(result.ScanResultData.Nodes) > 0 { - scanResults = parseSarifResultSast(result, scanResults) - } else if result.Type == commonParams.KicsType { - scanResults = parseSarifResultKics(result, scanResults) - } else if result.Type == commonParams.ScaType { - scanResults = parseSarifResultsSca(result, scanResults) - } else if result.Type == commonParams.ContainersType && wrappers.IsContainersEnabled { - scanResults = parseSarifResultsContainers(result, scanResults) - } else if strings.HasPrefix(result.Type, commonParams.SscsType) { - scanResults = parseSarifResultsSscs(result, scanResults) - } - - if len(scanResults) > 0 { - return scanResults - } - return nil -} - -func parseSarifResultsContainers(result *wrappers.ScanResult, scanResults []wrappers.SarifScanResult) []wrappers.SarifScanResult { - var scanResult = initSarifResult(result) - var scanLocation wrappers.SarifLocation - - scanLocation.PhysicalLocation.ArtifactLocation.URI = result.ScanResultData.ImageFilePath - scanLocation.PhysicalLocation.Region = &wrappers.SarifRegion{} - scanLocation.PhysicalLocation.Region.StartLine = 1 - scanLocation.PhysicalLocation.Region.StartColumn = 1 - scanLocation.PhysicalLocation.Region.EndColumn = 2 - scanResult.Locations = append(scanResult.Locations, scanLocation) - - scanResults = append(scanResults, scanResult) - return scanResults -} - -func parseSarifResultsSca(result *wrappers.ScanResult, scanResults []wrappers.SarifScanResult) []wrappers.SarifScanResult { - if result == nil || result.ScanResultData.ScaPackageCollection == nil || result.ScanResultData.ScaPackageCollection.Locations == nil { - return scanResults - } - for _, location := range result.ScanResultData.ScaPackageCollection.Locations { - var scanResult = initSarifResult(result) - - var scanLocation wrappers.SarifLocation - scanLocation.PhysicalLocation.ArtifactLocation.URI = *location - scanLocation.PhysicalLocation.Region = &wrappers.SarifRegion{} - scanLocation.PhysicalLocation.Region.StartLine = 1 - scanLocation.PhysicalLocation.Region.StartColumn = 1 - scanLocation.PhysicalLocation.Region.EndColumn = 2 - scanResult.Locations = append(scanResult.Locations, scanLocation) - - scanResults = append(scanResults, scanResult) - } - return scanResults -} - -func parseSarifResultKics(result *wrappers.ScanResult, scanResults []wrappers.SarifScanResult) []wrappers.SarifScanResult { - var scanResult = initSarifResult(result) - var scanLocation wrappers.SarifLocation - - scanLocation.PhysicalLocation.ArtifactLocation.URI = strings.Replace( - result.ScanResultData.Filename, - "/", - "", - 1, - ) - scanLocation.PhysicalLocation.Region = &wrappers.SarifRegion{} - scanLocation.PhysicalLocation.Region.StartLine = result.ScanResultData.Line - scanLocation.PhysicalLocation.Region.StartColumn = 1 - scanLocation.PhysicalLocation.Region.EndColumn = 2 - scanResult.Locations = append(scanResult.Locations, scanLocation) - - scanResults = append(scanResults, scanResult) - return scanResults -} - -func parseSarifResultSast(result *wrappers.ScanResult, scanResults []wrappers.SarifScanResult) []wrappers.SarifScanResult { - if result == nil || result.ScanResultData.Nodes == nil { - return scanResults - } - var scanResult = initSarifResult(result) - - for _, node := range result.ScanResultData.Nodes { - var scanLocation wrappers.SarifLocation - if len(node.FileName) >= sarifNodeFileLength { - scanLocation.PhysicalLocation.ArtifactLocation.URI = node.FileName[1:] - if node.Line <= 0 { - continue - } - scanLocation.PhysicalLocation.Region = &wrappers.SarifRegion{} - scanLocation.PhysicalLocation.Region.StartLine = node.Line - column := node.Column - length := node.Length - scanLocation.PhysicalLocation.Region.StartColumn = column - scanLocation.PhysicalLocation.Region.EndColumn = column + length - - scanResult.Locations = append(scanResult.Locations, scanLocation) - } - } - - scanResults = append(scanResults, scanResult) - return scanResults -} - -func parseSarifResultsSscs(result *wrappers.ScanResult, scanResults []wrappers.SarifScanResult) []wrappers.SarifScanResult { - var scanResult = initSarifResult(result) - scanResult.Message.Text = result.Description - - var scanLocation wrappers.SarifLocation - - trimOsSeparatorFromFileName(result) - if result.Type == commonParams.SCSScorecardType && result.ScanResultData.Filename == noFileForScorecardResultString { - scanLocation.PhysicalLocation.ArtifactLocation.URI = artifactLocationURIString - scanLocation.PhysicalLocation.ArtifactLocation.Description = &wrappers.SarifMessage{} - scanLocation.PhysicalLocation.ArtifactLocation.Description.Text = result.ScanResultData.Filename - } else { - scanLocation.PhysicalLocation.ArtifactLocation.URI = result.ScanResultData.Filename - } - - scanLocation.PhysicalLocation.Region = &wrappers.SarifRegion{} - scanLocation.PhysicalLocation.Region.StartLine = result.ScanResultData.Line - scanLocation.PhysicalLocation.Region.StartColumn = 1 - scanLocation.PhysicalLocation.Region.EndColumn = 2 - if result.ScanResultData.Snippet != "" { - scanLocation.PhysicalLocation.Region.Snippet = &wrappers.SarifSnippet{} - scanLocation.PhysicalLocation.Region.Snippet.Text = result.ScanResultData.Snippet - } - - scanResult.Locations = append(scanResult.Locations, scanLocation) - - var properties wrappers.SarifResultProperties - properties.Severity = result.Severity - properties.Validity = result.ScanResultData.Validity - properties.IsInSource = result.ScanResultData.IsInSource - properties.CommitURL = result.ScanResultData.CommitURL - scanResult.Properties = &properties - - scanResults = append(scanResults, scanResult) - return scanResults -} - -func convertNotAvailableNumberToZero(summary *wrappers.ResultSummary) { - if summary.KicsIssues == notAvailableNumber { - summary.KicsIssues = 0 - } else if summary.SastIssues == notAvailableNumber { - summary.SastIssues = 0 - } else if summary.ScaIssues == notAvailableNumber { - summary.ScaIssues = 0 - } else if wrappers.IsContainersEnabled && *summary.ContainersIssues == notAvailableNumber { - *summary.ContainersIssues = 0 - } -} - -func buildAuxiliaryScaMaps(resultsModel *wrappers.ScanResultsCollection, scaPackageModel *[]wrappers.ScaPackageCollection, - scaTypeModel *[]wrappers.ScaTypeCollection) (locationsByID map[string][]*string, typesByCVE map[string]wrappers.ScaTypeCollection) { - locationsByID = make(map[string][]*string) - typesByCVE = make(map[string]wrappers.ScaTypeCollection) - // Create map to be used to populate locations for each package path - for _, result := range resultsModel.Results { - if result.Type == commonParams.ScaType { - for _, packages := range *scaPackageModel { - currentPackage := packages - locationsByID[packages.ID] = currentPackage.Locations - } - for _, types := range *scaTypeModel { - identifier := fmt.Sprintf("%s:%s", types.ID, types.PackageID) - typesByCVE[identifier] = types - } - } - } - return locationsByID, typesByCVE -} - -func buildScaType(typesByCVE map[string]wrappers.ScaTypeCollection, result *wrappers.ScanResult) string { - identifier := buildVulnerabilityIdentifier(result) - types, ok := typesByCVE[identifier] - if ok && types.Type == "SupplyChain" { - return "Supply Chain" - } - return "Vulnerability" -} - -func buildScaState(typesByCVE map[string]wrappers.ScaTypeCollection, result *wrappers.ScanResult) string { - identifier := buildVulnerabilityIdentifier(result) - types, ok := typesByCVE[identifier] - if ok && types.IsIgnored { - return notExploitable - } - return result.State -} - -func buildVulnerabilityIdentifier(result *wrappers.ScanResult) string { - return fmt.Sprintf("%s:%s", result.ID, result.ScanResultData.PackageIdentifier) -} - -func addPackageInformation( - resultsModel *wrappers.ScanResultsCollection, - scaPackageModel *[]wrappers.ScaPackageCollection, - scaTypeModel *[]wrappers.ScaTypeCollection, -) *wrappers.ScanResultsCollection { - locationsByID, typesByCVE := buildAuxiliaryScaMaps(resultsModel, scaPackageModel, scaTypeModel) - scaPackageMap := buildScaPackageMap(*scaPackageModel) - - for _, result := range resultsModel.Results { - if result.Type == commonParams.ScaType { - processResult(result, locationsByID, typesByCVE, scaPackageMap) - } - } - - return resultsModel -} - -func processResult( - result *wrappers.ScanResult, - locationsByID map[string][]*string, - typesByCVE map[string]wrappers.ScaTypeCollection, - scaPackageMap map[string]wrappers.ScaPackageCollection, // Updated parameter -) { - const precision = 1 - - currentID := result.ScanResultData.PackageIdentifier - result.VulnerabilityDetails.CvssScore = util.RoundFloat(result.VulnerabilityDetails.CvssScore, precision) - result.ScaType = buildScaType(typesByCVE, result) - result.State = buildScaState(typesByCVE, result) - - updatePackages(result, scaPackageMap, locationsByID, currentID) -} - -func updatePackages( - result *wrappers.ScanResult, - scaPackageMap map[string]wrappers.ScaPackageCollection, - locationsByID map[string][]*string, - currentID string, -) { - packages, found := scaPackageMap[currentID] - if !found { - return - } - - updateDependencyPaths(packages.DependencyPathArray, locationsByID) - if !packages.SupportsQuickFix { - packages.SupportsQuickFix = hasQuickFix(packages.DependencyPathArray) - } - - if packages.IsDirectDependency { - packages.TypeOfDependency = directDependencyType - } else { - packages.TypeOfDependency = indirectDependencyType - } - - packages.FixLink = buildFixLink(result) - result.ScanResultData.ScaPackageCollection = &packages -} - -func hasQuickFix(dependencyPaths [][]wrappers.DependencyPath) bool { - for i := range dependencyPaths { - head := &dependencyPaths[i][0] - if head.SupportsQuickFix { - return true - } - } - return false -} - -func buildScaPackageMap(scaPackageModel []wrappers.ScaPackageCollection) map[string]wrappers.ScaPackageCollection { - scaPackageMap := make(map[string]wrappers.ScaPackageCollection) - for i := range scaPackageModel { - scaPackageMap[scaPackageModel[i].ID] = scaPackageModel[i] - } - return scaPackageMap -} - -func updateDependencyPaths(dependencyPaths [][]wrappers.DependencyPath, locationsByID map[string][]*string) { - for i := range dependencyPaths { - head := &dependencyPaths[i][0] - head.Locations = locationsByID[head.ID] - head.SupportsQuickFix = len(dependencyPaths[i]) == 1 - - for _, location := range locationsByID[head.ID] { - head.SupportsQuickFix = head.SupportsQuickFix && util.IsPackageFileSupported(*location) - } - } -} - -func buildFixLink(result *wrappers.ScanResult) string { - if result.ID != "" { - return fmt.Sprint(fixLinkPrefix, result.ID) - } - return "" -} - -func filterViolatedRules(policyModel wrappers.PolicyResponseModel) *wrappers.PolicyResponseModel { - i := 0 - for _, policy := range policyModel.Policies { - if len(policy.RulesViolated) > 0 { - policyModel.Policies[i] = policy - i++ - } - } - policyModel.Policies = policyModel.Policies[:i] - return &policyModel -} - -func trimOsSeparatorFromFileName(result *wrappers.ScanResult) { - if result.ScanResultData.Filename != "" { - result.ScanResultData.Filename = strings.TrimPrefix(result.ScanResultData.Filename, "/") - result.ScanResultData.Filename = strings.TrimPrefix(result.ScanResultData.Filename, "\\") - } -} - -type ScannerResponse struct { - ScanID string `json:"ScanID,omitempty"` - Name string `json:"Name,omitempty"` - Status string `json:"Status,omitempty"` - Details string `json:"Details,omitempty"` - ErrorCode string `json:"ErrorCode,omitempty"` -} - -func parseURI(summaryBaseURI string) (hostName string) { - parsedURL, err := url.Parse(summaryBaseURI) - if err != nil { - return "" - } - hostName = fmt.Sprintf("%s://%s", parsedURL.Scheme, parsedURL.Host) - - return hostName -} - -func printWarningIfIgnorePolicyOmiited() { - fmt.Printf("\n Warning: The --ignore-policy flag was not implemented because you don’t have the required permission.\n Only users with 'override-policy-management' permission can use this flag. \n\n") -} - -func getFilterResultsForAPISecScanner(risksOverviewWrapper wrappers.RisksOverviewWrapper, scanID string, resultsParams map[string]string) (aPISecSeveritySummary *wrappers.APISecFilteredResult, err error) { - var apiSecRiskEntriesResult wrappers.APISecRiskEntriesResult - var errorModel *wrappers.WebError - - apiSecRiskEntriesResult, errorModel, err = risksOverviewWrapper.GetFilterResultForAPISecByScanID(scanID, resultsParams) - if err != nil { - return nil, errors.Wrapf(err, "%s", failedListingResults) - } - if errorModel != nil { - return nil, errors.Errorf("%s: CODE: %d, %s", failedListingResults, errorModel.Code, errorModel.Message) - } - if len(apiSecRiskEntriesResult.Entries) > 0 { - entries := apiSecRiskEntriesResult.Entries - severityCount := make(map[string]int) - originCount := make(map[string]int) - totalRecords := 0 - for i := range entries { - entry := &entries[i] - if !isExploitable(entry.State) { - continue - } - sev := strings.ToLower(entry.Severity) - severityCount[sev]++ - orig := strings.ToLower(entry.Origin) - originCount[orig]++ - totalRecords++ - } - var riskDistribution []wrappers.RiskDistributionEntry - if originCount["code"] > 0 { - riskDistribution = append(riskDistribution, wrappers.RiskDistributionEntry{Origin: "code", Total: originCount["code"]}) - } - if originCount["documentation"] > 0 { - riskDistribution = append(riskDistribution, wrappers.RiskDistributionEntry{Origin: "documentation", Total: originCount["documentation"]}) - } - return &wrappers.APISecFilteredResult{ - SeverityCount: severityCount, - RiskDistribution: riskDistribution, - TotalRisksCount: totalRecords, - }, nil - } - return nil, nil -} +package commands + +import ( + "encoding/json" + "fmt" + "html" + "log" + "net/url" + "os" + "path/filepath" + "regexp" + "slices" + "strconv" + "strings" + "text/template" + "time" + + "github.com/MakeNowJust/heredoc" + "github.com/checkmarx/ast-cli/internal/commands/util" + "github.com/checkmarx/ast-cli/internal/commands/util/printer" + errorConstants "github.com/checkmarx/ast-cli/internal/constants/errors" + "github.com/checkmarx/ast-cli/internal/logger" + "github.com/checkmarx/ast-cli/internal/services" + "github.com/checkmarx/ast-cli/internal/wrappers" + "github.com/checkmarx/ast-cli/internal/wrappers/utils" + "golang.org/x/text/cases" + "golang.org/x/text/language" + + commonParams "github.com/checkmarx/ast-cli/internal/params" + + "github.com/pkg/errors" + "github.com/spf13/cobra" +) + +const ( + failedCreatingSummary = "Failed creating summary" + failedGettingScan = "Failed getting scan" + failedListingResults = "Failed listing results" + failedListingCodeBashing = "Failed codebashing link" + mediumLabel = "medium" + criticalLabel = "critical" + highLabel = "high" + lowLabel = "low" + infoLabel = "info" + sonarTypeLabel = "_sonar" + glSastTypeLabel = ".gl-sast-report" + glScaTypeLabel = ".gl-sca-report" + directoryPermission = 0700 + infoSonar = "INFO" + lowSonar = "LOW" + mediumSonar = "MEDIUM" + highSonar = "HIGH" + criticalSonar = "BLOCKER" + infoLowSarif = "note" + mediumSarif = "warning" + highSarif = "error" + vulnerabilitySonar = "SECURITY" + cleanCodeAttribute = "FORMATTED" + infoCx = "INFO" + lowCx = "LOW" + mediumCx = "MEDIUM" + highCx = "HIGH" + criticalCx = "CRITICAL" + tableResultsFormat = " | %-10s %6v %5d %6d %5d %4d %-9s |\n" + stringTableResultsFormat = " | %-10s %5s %6s %6s %5s %4s %5s |\n" + TableTitleFormat = " | %-11s %4s %4s %6s %4s %4s %6s |\n" + twoNewLines = "\n\n" + tableLine = " --------------------------------------------------------------------- " + codeBashingKey = "cb-url" + failedGettingBfl = "Failed getting BFL" + notAvailableString = "-" + disabledString = "N/A" + scanFailedString = "Failed " + scanCanceledString = "Canceled" + scanSuccessString = "Completed" + scanPartialString = "Partial" + scsScanUnavailableString = "" + notAvailableNumber = -1 + scanFailedNumber = -2 + scanCanceledNumber = -3 + scanPartialNumber = -4 + defaultPaddingSize = -13 + scanPendingMessage = "Scan triggered in asynchronous mode or still running. Click more details to get the full status." + directDependencyType = "Direct Dependency" + indirectDependencyType = "Transitive Dependency" + startedStatus = "started" + requestedStatus = "requested" + completedStatus = "completed" + pdfToEmailFlagDescription = "Send the PDF report to the specified email address." + + " Use \",\" as the delimiter for multiple emails" + pdfOptionsFlagDescription = "Sections to generate PDF report. Available options: Iac-Security,Sast,Sca," + + defaultPdfOptionsDataSections + sbomReportFlagDescription = "Sections to generate SBOM report. Available options: CycloneDxJson,CycloneDxXml,SpdxJson" + reportNameScanReport = "scan-report" + reportNameImprovedScanReport = "improved-scan-report" + reportTypeEmail = "email" + defaultPdfOptionsDataSections = "ScanSummary,ExecutiveSummary,ScanResults" + exploitablePathFlagDescription = "Enable or disable exploitable path in scan. Available options: true,false" + scaLastScanTimeFlagDescription = "SCA last scan time. Available options: integer above 1" + projectPrivatePackageFlagDescription = "Enable or disable project private package. Available options: true,false" + scaPrivatePackageVersionFlagDescription = "SCA project private package version. Example: 0.1.1" + scaHideDevAndTestDepFlagDescription = "Filter SCA results to exclude dev and test dependencies" + policeManagementNoneStatus = "none" + apiDocumentationFlagDescription = "Swagger folder/file filter for API-Security scan. Example: ./swagger.json" + summaryCreatedAtLayout = "2006-01-02, 15:04:05" + glTimeFormat = "2006-01-02T15:04:05" + sarifNodeFileLength = 2 + fixLabel = "fix" + redundantLabel = "redundant" + delayValueForReport = 10 + fixLinkPrefix = "https://devhub.checkmarx.com/cve-details/" + ScaDevAndTestExclusionParam = "DEV_AND_TEST" + ScaExcludeResultTypesParam = "exclude-result-types" + noFileForScorecardResultString = "Issue Found in your GitHub repository" + CliType = "cli" + artifactLocationURIString = "This alert has no associated file" +) + +var ( + summaryFormats = []string{ + printer.FormatSummaryConsole, + printer.FormatSummary, + printer.FormatSummaryJSON, + printer.FormatPDF, + printer.FormatSummaryMarkdown, + printer.FormatSbom, + printer.FormatGLSast, + printer.FormatGLSca, + printer.FormatSonar, + } + + filterResultsListFlagUsage = fmt.Sprintf( + "Filter the list of results. Use ';' as the delimiter for arrays. Available filters are: %s", + strings.Join( + []string{ + commonParams.ScanIDQueryParam, + commonParams.LimitQueryParam, + commonParams.OffsetQueryParam, + commonParams.SortQueryParam, + commonParams.IncludeNodesQueryParam, + commonParams.NodeIDsQueryParam, + commonParams.QueryQueryParam, + commonParams.GroupQueryParam, + commonParams.StatusQueryParam, + commonParams.SeverityQueryParam, + commonParams.StateQueryParam, + }, ",", + ), + ) + + // Follows: over 9.0 is critical, 7.0 to 8.9 is high, 4.0 to 6.9 is medium and 3.9 or less is low. + securities = map[string]string{ + infoCx: "1.0", + lowCx: "2.0", + mediumCx: "4.0", + highCx: "7.0", + criticalCx: "9.0", + } + + // Match cx severity with sonar severity + sonarSeverities = map[string]string{ + infoCx: infoSonar, + lowCx: lowSonar, + mediumCx: mediumSonar, + highCx: highSonar, + criticalCx: criticalSonar, + } + + containerEngineUnsupportedAgents = []string{ + commonParams.JetbrainsAgent, commonParams.VSCodeAgent, commonParams.VisualStudioAgent, commonParams.EclipseAgent, + } + + sscsEngineToOverviewEngineMap = map[string]string{ + commonParams.SCSScorecardType: commonParams.SCSScorecardOverviewType, + commonParams.SCSSecretDetectionType: commonParams.SCSSecretDetectionOverviewType, + } +) + +func NewResultsCommand( + resultsWrapper wrappers.ResultsWrapper, + scanWrapper wrappers.ScansWrapper, + exportWrapper wrappers.ExportWrapper, + resultsPdfReportsWrapper wrappers.ResultsPdfWrapper, + resultsJSONReportsWrapper wrappers.ResultsJSONWrapper, + codeBashingWrapper wrappers.CodeBashingWrapper, + bflWrapper wrappers.BflWrapper, + risksOverviewWrapper wrappers.RisksOverviewWrapper, + riskManagementWrapper wrappers.RiskManagementWrapper, + scsScanOverviewWrapper wrappers.ScanOverviewWrapper, + policyWrapper wrappers.PolicyWrapper, + featureFlagsWrapper wrappers.FeatureFlagsWrapper, + jwtWrapper wrappers.JWTWrapper, +) *cobra.Command { + resultCmd := &cobra.Command{ + Use: "results", + Short: "Retrieve results", + Annotations: map[string]string{ + "command:doc": heredoc.Doc( + ` + https://checkmarx.com/resource/documents/en/34965-68640-results.html + `, + ), + }, + } + showResultCmd := resultShowSubCommand(resultsWrapper, scanWrapper, exportWrapper, resultsPdfReportsWrapper, resultsJSONReportsWrapper, + risksOverviewWrapper, scsScanOverviewWrapper, policyWrapper, featureFlagsWrapper, jwtWrapper) + codeBashingCmd := resultCodeBashing(codeBashingWrapper) + bflResultCmd := resultBflSubCommand(bflWrapper) + exitCodeSubcommand := exitCodeSubCommand(scanWrapper) + riskManagementSubCommand := riskManagementSubCommand(riskManagementWrapper, featureFlagsWrapper) + resultCmd.AddCommand( + showResultCmd, bflResultCmd, codeBashingCmd, exitCodeSubcommand, riskManagementSubCommand, + ) + return resultCmd +} + +func exitCodeSubCommand(scanWrapper wrappers.ScansWrapper) *cobra.Command { + exitCodeCmd := &cobra.Command{ + Use: "exit-code", + Short: "Get exit code and details of a scan", + Long: "The exit-code command enables you to get the exit code and failure details of a requested scan in Checkmarx One", + Example: heredoc.Doc( + ` + $ cx results exit-code --scan-id --scan-types + `, + ), + RunE: runGetExitCodeCommand(scanWrapper), + } + + exitCodeCmd.PersistentFlags().String(commonParams.ScanIDFlag, "", "Scan ID") + exitCodeCmd.PersistentFlags().String(commonParams.ScanTypes, "", "Scan types") + + return exitCodeCmd +} +func riskManagementSubCommand(riskManagement wrappers.RiskManagementWrapper, featureFlagsWrapper wrappers.FeatureFlagsWrapper, +) *cobra.Command { + riskManagementCmd := &cobra.Command{ + Use: "risk-management", + Short: "Show risk-management results of a project", + Long: "The risk-management command displays risk management results for a specific project in Checkmarx One", + Example: heredoc.Doc( + ` + $ cx results risk-management --project-id --scan-id --limit (1-50, default: 50) + `, + ), + RunE: runRiskManagementCommand(riskManagement, featureFlagsWrapper), + } + + riskManagementCmd.PersistentFlags().String(commonParams.ProjectIDFlag, "", "Project ID") + riskManagementCmd.PersistentFlags().String(commonParams.ScanIDFlag, "", "Scan ID") + riskManagementCmd.PersistentFlags().Int(commonParams.LimitFlag, -1, "Limit") + + addFormatFlag(riskManagementCmd, printer.FormatJSON, printer.FormatTable, printer.FormatList) + + return riskManagementCmd +} + +func resultShowSubCommand( + resultsWrapper wrappers.ResultsWrapper, + scanWrapper wrappers.ScansWrapper, + exportWrapper wrappers.ExportWrapper, + resultsPdfReportsWrapper wrappers.ResultsPdfWrapper, + resultsJSONReportsWrapper wrappers.ResultsJSONWrapper, + risksOverviewWrapper wrappers.RisksOverviewWrapper, + scsScanOverviewWrapper wrappers.ScanOverviewWrapper, + policyWrapper wrappers.PolicyWrapper, + featureFlagsWrapper wrappers.FeatureFlagsWrapper, + jwtWrapper wrappers.JWTWrapper, +) *cobra.Command { + resultShowCmd := &cobra.Command{ + Use: "show", + Short: "Show results of a scan", + Long: "The show command enables the ability to show results about a requested scan in Checkmarx One", + Example: heredoc.Doc( + ` + $ cx results show --scan-id + `, + ), + RunE: runGetResultCommand(resultsWrapper, scanWrapper, exportWrapper, resultsPdfReportsWrapper, resultsJSONReportsWrapper, risksOverviewWrapper, scsScanOverviewWrapper, policyWrapper, featureFlagsWrapper, jwtWrapper), + } + addScanIDFlag(resultShowCmd, "ID to report on") + addResultFormatFlag( + resultShowCmd, + printer.FormatJSON, + printer.FormatJSONv2, + printer.FormatSummary, + printer.FormatSummaryConsole, + printer.FormatSarif, + printer.FormatSummaryJSON, + printer.FormatSbom, + printer.FormatPDF, + printer.FormatSummaryMarkdown, + printer.FormatGLSast, + printer.FormatGLSca, + printer.FormatSonar, + ) + resultShowCmd.PersistentFlags().String(commonParams.ReportFormatPdfToEmailFlag, "", pdfToEmailFlagDescription) + resultShowCmd.PersistentFlags().String(commonParams.ReportSbomFormatFlag, services.DefaultSbomOption, sbomReportFlagDescription) + resultShowCmd.PersistentFlags().String(commonParams.ReportFormatPdfOptionsFlag, defaultPdfOptionsDataSections, pdfOptionsFlagDescription) + resultShowCmd.PersistentFlags().String(commonParams.TargetFlag, "cx_result", "Output file") + resultShowCmd.PersistentFlags().String(commonParams.TargetPathFlag, ".", "Output Path") + resultShowCmd.PersistentFlags().StringSlice(commonParams.FilterFlag, []string{}, filterResultsListFlagUsage) + + resultShowCmd.PersistentFlags().IntP( + commonParams.WaitDelayFlag, + "", + commonParams.WaitDelayDefault, + "Polling wait time in seconds", + ) + resultShowCmd.PersistentFlags().Int( + commonParams.PolicyTimeoutFlag, + commonParams.ResultPolicyDefaultTimeout, + "Cancel the policy evaluation and fail after the timeout in minutes", + ) + resultShowCmd.PersistentFlags().Bool(commonParams.IgnorePolicyFlag, false, "Skip policy evaluation. Requires override-policy-management permission.") + resultShowCmd.PersistentFlags().Bool(commonParams.SastRedundancyFlag, false, + "Populate SAST results 'data.redundancy' with values '"+fixLabel+"' (to fix) or '"+redundantLabel+"' (no need to fix)") + resultShowCmd.PersistentFlags().Bool(commonParams.ScaHideDevAndTestDepFlag, false, scaHideDevAndTestDepFlagDescription) + + return resultShowCmd +} + +func resultBflSubCommand(bflWrapper wrappers.BflWrapper) *cobra.Command { + resultBflCmd := &cobra.Command{ + Use: "bfl", + Short: "Show best fix location for a query id within the scan result", + Long: "The bfl command enables the ability to show best fix location for a querid within the scan result", + Example: heredoc.Doc( + ` + $ cx results bfl --scan-id --query-id + `, + ), + RunE: runGetBestFixLocationCommand(bflWrapper), + } + addScanIDFlag(resultBflCmd, "ID to report on") + addQueryIDFlag(resultBflCmd, "Query Id from the result") + addFormatFlag(resultBflCmd, printer.FormatList, printer.FormatJSON) + + markFlagAsRequired(resultBflCmd, commonParams.ScanIDFlag) + markFlagAsRequired(resultBflCmd, commonParams.QueryIDFlag) + + return resultBflCmd +} + +func runGetExitCodeCommand(scanWrapper wrappers.ScansWrapper) func(cmd *cobra.Command, args []string) error { + return func(cmd *cobra.Command, args []string) error { + scanID, _ := cmd.Flags().GetString(commonParams.ScanIDFlag) + if scanID == "" { + return errors.New(errorConstants.ScanIDRequired) + } + scanTypesFlagValue, _ := cmd.Flags().GetString(commonParams.ScanTypes) + results, err := GetScannerResults(scanWrapper, scanID, scanTypesFlagValue) + if err != nil { + return err + } + + if len(results) == 0 { + return nil + } + + return printer.Print(cmd.OutOrStdout(), results, printer.FormatIndentedJSON) + } +} + +func runRiskManagementCommand(riskManagement wrappers.RiskManagementWrapper, featureFlagsWrapper wrappers.FeatureFlagsWrapper, +) func(cmd *cobra.Command, args []string) error { + return func(cmd *cobra.Command, args []string) error { + projectID, _ := cmd.Flags().GetString(commonParams.ProjectIDFlag) + scanID, _ := cmd.Flags().GetString(commonParams.ScanIDFlag) + + limit, _ := cmd.Flags().GetInt(commonParams.LimitFlag) + + flagResponse, _ := wrappers.GetSpecificFeatureFlag(featureFlagsWrapper, wrappers.RiskManagementEnabled) + ASPMEnabled := flagResponse.Status + if !ASPMEnabled { + return errors.Errorf("%s", "Risk management results are currently unavailable for your tenant.") + } + results, err := getRiskManagementResults(riskManagement, projectID, scanID) + if err != nil { + return err + } + results.Results = utils.LimitSlice(results.Results, limit) + err = printByFormat(cmd, results) + return err + } +} + +func getRiskManagementResults(riskManagement wrappers.RiskManagementWrapper, projectID, scanID string) (*wrappers.ASPMResult, error) { + ASPMResult, errorModel, err := riskManagement.GetTopVulnerabilitiesByProjectID(projectID, scanID) + if err != nil { + return nil, errors.Wrapf(err, "%s", failedListingResults) + } + if errorModel != nil { + return nil, errors.Errorf("%s: CODE: %d, %s", failedListingResults, errorModel.Code, errorModel.Message) + } + return ASPMResult, nil +} + +func GetScannerResults(scanWrapper wrappers.ScansWrapper, scanID, scanTypesFlagValue string) ([]ScannerResponse, error) { + scanResponseModel, errorModel, err := scanWrapper.GetByID(scanID) + if err != nil { + return nil, errors.Wrapf(err, "%s", failedGetting) + } + if errorModel != nil { + return nil, errors.Errorf("%s: CODE: %d, %s", failedGettingScan, errorModel.Code, errorModel.Message) + } + results := getScannerResponse(scanTypesFlagValue, scanResponseModel) + return results, nil +} + +func getScannerResponse(scanTypesFlagValue string, scanResponseModel *wrappers.ScanResponseModel) []ScannerResponse { + var results []ScannerResponse + + if scanResponseModel.Status == wrappers.ScanCanceled || + scanResponseModel.Status == wrappers.ScanRunning || + scanResponseModel.Status == wrappers.ScanQueued || + scanResponseModel.Status == wrappers.ScanPartial || + scanResponseModel.Status == wrappers.ScanCompleted { + result := ScannerResponse{ + ScanID: scanResponseModel.ID, + Status: string(scanResponseModel.Status), + } + results = append(results, result) + return results + } + + if scanTypesFlagValue == "" { + results = createAllFailedScannersResponse(scanResponseModel) + } else { + scanTypes := sanitizeScannerNames(scanTypesFlagValue) + results = createRequestedScannersResponse(scanTypes, scanResponseModel) + } + + return results +} + +func createRequestedScannersResponse(scanTypes map[string]string, scanResponseModel *wrappers.ScanResponseModel) []ScannerResponse { + var results []ScannerResponse + for i := range scanResponseModel.StatusDetails { + if _, ok := scanTypes[scanResponseModel.StatusDetails[i].Name]; ok { + results = append(results, createScannerResponse(&scanResponseModel.StatusDetails[i])) + } + } + return results +} + +func createAllFailedScannersResponse(scanResponseModel *wrappers.ScanResponseModel) []ScannerResponse { + var results []ScannerResponse + for i := range scanResponseModel.StatusDetails { + if scanResponseModel.StatusDetails[i].Status == wrappers.ScanFailed { + results = append(results, createScannerResponse(&scanResponseModel.StatusDetails[i])) + } + } + return results +} + +func sanitizeScannerNames(scanTypes string) map[string]string { + scanTypeSlice := strings.Split(scanTypes, ",") + scanTypeMap := make(map[string]string) + for i := range scanTypeSlice { + lowered := strings.ToLower(scanTypeSlice[i]) + scanTypeMap[lowered] = lowered + } + + return scanTypeMap +} + +func createScannerResponse(statusDetails *wrappers.StatusInfo) ScannerResponse { + return ScannerResponse{ + Name: statusDetails.Name, + Status: statusDetails.Status, + Details: statusDetails.Details, + ErrorCode: stringifyErrorCode(statusDetails.ErrorCode), + } +} + +func stringifyErrorCode(errorCode int) string { + if errorCode == 0 { + return "" + } + return strconv.Itoa(errorCode) +} + +func runGetBestFixLocationCommand(bflWrapper wrappers.BflWrapper) func(cmd *cobra.Command, args []string) error { + return func(cmd *cobra.Command, args []string) error { + var bflResponseModel *wrappers.BFLResponseModel + var errorModel *wrappers.WebError + var err error + + scanID, _ := cmd.Flags().GetString(commonParams.ScanIDFlag) + queryID, _ := cmd.Flags().GetString(commonParams.QueryIDFlag) + + scanIds := strings.Split(scanID, ",") + if len(scanIds) > 1 { + return errors.Errorf("%s", "Multiple scan-ids are not allowed.") + } + queryIds := strings.Split(queryID, ",") + if len(queryIds) > 1 { + return errors.Errorf("%s", "Multiple query-ids are not allowed.") + } + + params := make(map[string]string) + params[commonParams.ScanIDQueryParam] = scanID + params[commonParams.QueryIDQueryParam] = queryID + + bflResponseModel, errorModel, err = bflWrapper.GetBflByScanIDAndQueryID(params) + + if err != nil { + return errors.Wrapf(err, "%s", failedGettingBfl) + } + + // Checking the response + if errorModel != nil { + return errors.Errorf("%s: CODE: %d, %s", failedGettingBfl, errorModel.Code, errorModel.Message) + } else if bflResponseModel != nil { + err = printByFormat(cmd, toBflView(*bflResponseModel)) + if err != nil { + return err + } + } + + return nil + } +} + +func toBflView(bflResponseModel wrappers.BFLResponseModel) []wrappers.ScanResultNode { + if (bflResponseModel.TotalCount) > 0 { + views := make([]wrappers.ScanResultNode, bflResponseModel.TotalCount) + + for i := 0; i < bflResponseModel.TotalCount; i++ { + views[i] = wrappers.ScanResultNode{ + Name: bflResponseModel.Trees[i].BFL.Name, + FileName: bflResponseModel.Trees[i].BFL.FileName, + FullName: bflResponseModel.Trees[i].BFL.FullName, + Column: bflResponseModel.Trees[i].BFL.Column, + Length: bflResponseModel.Trees[i].BFL.Length, + Line: bflResponseModel.Trees[i].BFL.Line, + MethodLine: bflResponseModel.Trees[i].BFL.MethodLine, + Method: bflResponseModel.Trees[i].BFL.Method, + DomType: bflResponseModel.Trees[i].BFL.DomType, + } + } + return views + } + views := make([]wrappers.ScanResultNode, 0) + return views +} + +func resultCodeBashing(codeBashingWrapper wrappers.CodeBashingWrapper) *cobra.Command { + // Create a codeBashing wrapper + resultCmd := &cobra.Command{ + Use: "codebashing", + Short: "Get codebashing lesson link", + Long: "The codebashing command enables the ability to retrieve the link about a specific vulnerability", + Example: heredoc.Doc( + ` + $ cx results codebashing --language --vulnerability-type --cwe-id --format + `, + ), + RunE: runGetCodeBashingCommand(codeBashingWrapper), + } + resultCmd.PersistentFlags().String(commonParams.LanguageFlag, "", "Language of the vulnerability") + err := resultCmd.MarkPersistentFlagRequired(commonParams.LanguageFlag) + if err != nil { + log.Fatal(err) + } + resultCmd.PersistentFlags().String(commonParams.VulnerabilityTypeFlag, "", "Vulnerability type") + err = resultCmd.MarkPersistentFlagRequired(commonParams.VulnerabilityTypeFlag) + if err != nil { + log.Fatal(err) + } + resultCmd.PersistentFlags().String(commonParams.CweIDFlag, "", "CWE ID for the vulnerability") + err = resultCmd.MarkPersistentFlagRequired(commonParams.CweIDFlag) + if err != nil { + log.Fatal(err) + } + addFormatFlag(resultCmd, printer.FormatJSON, printer.FormatTable, printer.FormatList) + return resultCmd +} + +func convertScanToResultsSummary(scanInfo *wrappers.ScanResponseModel, resultsWrapper wrappers.ResultsWrapper) (*wrappers.ResultSummary, error) { + if scanInfo == nil { + return nil, errors.New(failedCreatingSummary) + } + + scanInfo.ReplaceMicroEnginesWithSCS() + + sastIssues := 0 + scaIssues := 0 + kicsIssues := 0 + var containersIssues *int + var scsIssues *int + enginesStatusCode := map[string]int{ + commonParams.SastType: 0, + commonParams.ScaType: 0, + commonParams.KicsType: 0, + commonParams.APISecType: 0, + commonParams.ScsType: 0, + commonParams.ContainersType: 0, + } + if wrappers.IsContainersEnabled { + containersIssues = new(int) + *containersIssues = 0 + enginesStatusCode[commonParams.ContainersType] = 0 + } + + scsIssues = new(int) + *scsIssues = 0 + enginesStatusCode[commonParams.ScsType] = 0 + + if len(scanInfo.StatusDetails) > 0 { + for _, statusDetailItem := range scanInfo.StatusDetails { + if statusDetailItem.Status == wrappers.ScanFailed || statusDetailItem.Status == wrappers.ScanCanceled { + if statusDetailItem.Name == commonParams.SastType { + sastIssues = notAvailableNumber + } else if statusDetailItem.Name == commonParams.ScaType { + scaIssues = notAvailableNumber + } else if statusDetailItem.Name == commonParams.KicsType { + kicsIssues = notAvailableNumber + } else if statusDetailItem.Name == commonParams.ScsType { + *scsIssues = notAvailableNumber + } else if statusDetailItem.Name == commonParams.ContainersType && wrappers.IsContainersEnabled { + *containersIssues = notAvailableNumber + } + } + switch statusDetailItem.Status { + case wrappers.ScanFailed: + handleScanStatus(statusDetailItem, enginesStatusCode, scanFailedNumber) + case wrappers.ScanCanceled: + handleScanStatus(statusDetailItem, enginesStatusCode, scanCanceledNumber) + } + } + } + summary := &wrappers.ResultSummary{ + ScanID: scanInfo.ID, + Status: string(scanInfo.Status), + CreatedAt: scanInfo.CreatedAt.Format("2006-01-02, 15:04:05"), + ProjectID: scanInfo.ProjectID, + RiskStyle: "", + RiskMsg: "", + CriticalIssues: 0, + HighIssues: 0, + MediumIssues: 0, + LowIssues: 0, + InfoIssues: 0, + SastIssues: sastIssues, + KicsIssues: kicsIssues, + ScaIssues: scaIssues, + ScsIssues: scsIssues, + ContainersIssues: containersIssues, + Tags: scanInfo.Tags, + ProjectName: scanInfo.ProjectName, + BranchName: scanInfo.Branch, + EnginesEnabled: scanInfo.Engines, + EnginesResult: map[string]*wrappers.EngineResultSummary{ + commonParams.SastType: {StatusCode: enginesStatusCode[commonParams.SastType]}, + commonParams.ScaType: {StatusCode: enginesStatusCode[commonParams.ScaType]}, + commonParams.KicsType: {StatusCode: enginesStatusCode[commonParams.KicsType]}, + commonParams.APISecType: {StatusCode: enginesStatusCode[commonParams.APISecType]}, + commonParams.ContainersType: {StatusCode: enginesStatusCode[commonParams.ContainersType]}, + }, + } + if wrappers.IsContainersEnabled { + summary.EnginesResult[commonParams.ContainersType] = &wrappers.EngineResultSummary{StatusCode: enginesStatusCode[commonParams.ContainersType]} + } + + summary.EnginesResult[commonParams.ScsType] = &wrappers.EngineResultSummary{StatusCode: enginesStatusCode[commonParams.ScsType]} + + baseURI, err := resultsWrapper.GetResultsURL(summary.ProjectID) + if err != nil { + return nil, err + } + + summary.BaseURI = baseURI + summary.BaseURI = generateScanSummaryURL(summary) + if isScanPending(summary.Status) { + summary.ScanInfoMessage = scanPendingMessage + } + + return summary, nil +} + +func handleScanStatus(statusDetailItem wrappers.StatusInfo, targetTypes map[string]int, statusCode int) { + if _, ok := targetTypes[statusDetailItem.Name]; ok { + targetTypes[statusDetailItem.Name] = statusCode + } +} + +func summaryReport( + summary *wrappers.ResultSummary, + policies *wrappers.PolicyResponseModel, + risksOverviewWrapper wrappers.RisksOverviewWrapper, + scsScanOverviewWrapper wrappers.ScanOverviewWrapper, + featureFlagsWrapper wrappers.FeatureFlagsWrapper, + results *wrappers.ScanResultsCollection, + resultsParams map[string]string, +) (*wrappers.ResultSummary, error) { + if summary.HasAPISecurity() { + apiSecFilterRisks, err := getFilterResultsForAPISecScanner(risksOverviewWrapper, summary.ScanID, resultsParams) + if err != nil { + return nil, err + } + if apiSecFilterRisks != nil { + summary.APISecurity = *apiSecFilterRisks + } + apiSecRisks, err := getResultsForAPISecScanner(risksOverviewWrapper, summary.ScanID) + if err != nil { + return nil, err + } + if apiSecRisks != nil { + summary.APISecurity.APICount = apiSecRisks.APICount + } + } + if summary.HasSCS() { + // Getting the base SCS overview. Results counts are overwritten in enhanceWithScanSummary->countResult + SCSOverview, err := getScanOverviewForSCSScanner(scsScanOverviewWrapper, summary.ScanID) + if err != nil { + return nil, err + } + summary.SCSOverview = SCSOverview + } + + if policies != nil { + summary.Policies = filterViolatedRules(*policies) + } + + enhanceWithScanSummary(summary, results, featureFlagsWrapper) + + setNotAvailableNumberIfZero(summary, &summary.SastIssues, commonParams.SastType) + setNotAvailableNumberIfZero(summary, &summary.ScaIssues, commonParams.ScaType) + setNotAvailableNumberIfZero(summary, &summary.KicsIssues, commonParams.KicsType) + setNotAvailableNumberIfZero(summary, summary.ScsIssues, commonParams.ScsType) + + if wrappers.IsContainersEnabled { + setNotAvailableNumberIfZero(summary, summary.ContainersIssues, commonParams.ContainersType) + } + + setRiskMsgAndStyle(summary) + setNotAvailableEnginesStatusCode(summary) + + return summary, nil +} + +func setNotAvailableEnginesStatusCode(summary *wrappers.ResultSummary) { + for engineName, engineResult := range summary.EnginesResult { + setNotAvailableNumberIfZero(summary, &engineResult.StatusCode, engineName) + } +} + +func setRiskMsgAndStyle(summary *wrappers.ResultSummary) { + if summary.CriticalIssues > 0 { + summary.RiskStyle = criticalLabel + summary.RiskMsg = "Critical Risk" + } else if summary.HighIssues > 0 { + summary.RiskStyle = highLabel + summary.RiskMsg = "High Risk" + } else if summary.MediumIssues > 0 { + summary.RiskStyle = mediumLabel + summary.RiskMsg = "Medium Risk" + } else if summary.LowIssues > 0 { + summary.RiskStyle = lowLabel + summary.RiskMsg = "Low Risk" + } else if summary.TotalIssues == 0 { + summary.RiskMsg = "No Risk" + } +} + +func setNotAvailableNumberIfZero(summary *wrappers.ResultSummary, counter *int, engineType string) { + if *counter == 0 && !contains(summary.EnginesEnabled, engineType) { + *counter = notAvailableNumber + } +} + +func enhanceWithScanSummary(summary *wrappers.ResultSummary, results *wrappers.ScanResultsCollection, featureFlagsWrapper wrappers.FeatureFlagsWrapper) { + for _, result := range results.Results { + countResult(summary, result) + } + // Set critical count for a specific engine if critical is disabled + flagResponse, _ := wrappers.GetSpecificFeatureFlag(featureFlagsWrapper, wrappers.CVSSV3Enabled) + criticalEnabled := flagResponse.Status + if summary.HasAPISecurity() { + summary.EnginesResult[commonParams.APISecType].Low = summary.APISecurity.SeverityCount["low"] + summary.EnginesResult[commonParams.APISecType].Medium = summary.APISecurity.SeverityCount["medium"] + summary.EnginesResult[commonParams.APISecType].High = summary.APISecurity.SeverityCount["high"] + if !criticalEnabled { + summary.EnginesResult[commonParams.APISecType].Critical = notAvailableNumber + } else { + summary.EnginesResult[commonParams.APISecType].Critical = summary.APISecurity.SeverityCount["critical"] + } + } + + summary.TotalIssues = summary.SastIssues + summary.ScaIssues + summary.KicsIssues + summary.GetAPISecurityDocumentationTotal() + + if summary.HasSCS() { + // Special case for SCS where status is partial if any microengines failed + if summary.SCSOverview.Status == scanPartialString { + summary.EnginesResult[commonParams.ScsType].StatusCode = scanPartialNumber + } + if !criticalEnabled { + summary.EnginesResult[commonParams.ScsType].Critical = notAvailableNumber + removeCriticalFromSCSOverview(summary) + } + if *summary.ScsIssues >= 0 { + summary.TotalIssues += *summary.ScsIssues + } + } + if wrappers.IsContainersEnabled { + if *summary.ContainersIssues >= 0 { + summary.TotalIssues += *summary.ContainersIssues + } + } + if !criticalEnabled { + summary.EnginesResult[commonParams.SastType].Critical = notAvailableNumber + summary.EnginesResult[commonParams.KicsType].Critical = notAvailableNumber + summary.EnginesResult[commonParams.ScaType].Critical = notAvailableNumber + summary.EnginesResult[commonParams.ContainersType].Critical = notAvailableNumber + } +} + +func removeCriticalFromSCSOverview(summary *wrappers.ResultSummary) { + criticalCount := summary.SCSOverview.RiskSummary[criticalLabel] + summary.SCSOverview.TotalRisksCount -= criticalCount + summary.SCSOverview.RiskSummary[criticalLabel] = notAvailableNumber + for _, microEngineOverview := range summary.SCSOverview.MicroEngineOverviews { + if microEngineOverview.RiskSummary != nil && microEngineOverview.RiskSummary[criticalLabel] != nil { + engineCriticalCount := microEngineOverview.RiskSummary[criticalLabel] + microEngineOverview.TotalRisks -= engineCriticalCount.(int) + microEngineOverview.RiskSummary[criticalLabel] = disabledString + } + } +} + +func writeHTMLSummary(targetFile string, summary *wrappers.ResultSummary) error { + log.Println("Creating Summary Report: ", targetFile) + summaryTemp, err := template.New("summaryTemplate").Parse(wrappers.SummaryTemplate(isScanPending(summary.Status))) + if err == nil { + f, err := os.Create(targetFile) + if err == nil { + _ = summaryTemp.ExecuteTemplate(f, "SummaryTemplate", summary) + _ = f.Close() + } + return err + } + return nil +} +func writeMarkdownSummary(targetFile string, data *wrappers.ResultSummary) error { + log.Println("Creating Markdown Summary Report: ", targetFile) + tmpl, err := template.New(printer.FormatSummaryMarkdown).Parse(wrappers.SummaryMarkdownTemplate(isScanPending(data.Status))) + if err != nil { + return err + } + file, err := os.Create(targetFile) + if err != nil { + return err + } + defer file.Close() + + err = tmpl.Execute(file, &data) + if err != nil { + return err + } + return nil +} + +// nolint: whitespace +func writeConsoleSummary(summary *wrappers.ResultSummary, featureFlagsWrapper wrappers.FeatureFlagsWrapper, ignorePolicyFlagOmit bool) error { + if !isScanPending(summary.Status) { + fmt.Printf(" Scan Summary: \n") + fmt.Printf(" Created At: %s\n", summary.CreatedAt) + fmt.Printf(" Project Name: %s \n", summary.ProjectName) + fmt.Printf(" Scan ID: %s \n\n", summary.ScanID) + fmt.Printf(" Results Summary: \n") + fmt.Printf( + " Risk Level: %s \n", + summary.RiskMsg, + ) + if summary.Policies != nil && !strings.EqualFold(summary.Policies.Status, policeManagementNoneStatus) { + printPoliciesSummary(summary, ignorePolicyFlagOmit) + } + + printResultsSummaryTable(summary) + + if summary.HasAPISecurity() { + printAPIsSecuritySummary(summary) + } + + if summary.HasSCS() { + printSCSSummary(summary.SCSOverview.MicroEngineOverviews, featureFlagsWrapper) + } + + 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") + fmt.Printf("For more information: %s\n", summary.BaseURI) + } + return nil +} + +func printPoliciesSummary(summary *wrappers.ResultSummary, ignorePolicyFlagOmit bool) { + hasViolations := false + for _, policy := range summary.Policies.Policies { + if len(policy.RulesViolated) > 0 { + hasViolations = true + break + } + } + if hasViolations { + fmt.Printf(tableLine + "\n") + if ignorePolicyFlagOmit { + printWarningIfIgnorePolicyOmiited() + } + if summary.Policies.BreakBuild { + fmt.Printf(" Policy Management Violation - Break Build Enabled: \n") + } else { + fmt.Printf(" Policy Management Violation: \n") + } + for _, police := range summary.Policies.Policies { + if len(police.RulesViolated) > 0 { + fmt.Printf(" Policy: %s | Break Build: %t | Violated Rules: ", police.Name, police.BreakBuild) + for _, violatedRule := range police.RulesViolated { + fmt.Printf("%s;", violatedRule) + } + } + fmt.Printf("\n") + } + fmt.Printf("\n") + } +} + +func printAPIsSecuritySummary(summary *wrappers.ResultSummary) { + fmt.Printf(" API Security - Total Detected APIs: %d \n", summary.APISecurity.APICount) + fmt.Printf(" APIS WITH RISK: %*d \n", defaultPaddingSize, summary.APISecurity.TotalRisksCount) + if summary.HasAPISecurityDocumentation() { + fmt.Printf(" APIS DOCUMENTATION: %*d \n", defaultPaddingSize, summary.GetAPISecurityDocumentationTotal()) + } + fmt.Printf(tableLine + twoNewLines) +} + +func printTableRow(title string, counts *wrappers.EngineResultSummary, statusNumber int) { + switch statusNumber { + case notAvailableNumber: + fmt.Printf(stringTableResultsFormat, title, notAvailableString, notAvailableString, notAvailableString, notAvailableString, notAvailableString, notAvailableString) + case scanFailedNumber: + fmt.Printf(tableResultsFormat, title, getCountValue(counts.Critical), counts.High, counts.Medium, counts.Low, counts.Info, scanFailedString) + case scanCanceledNumber: + fmt.Printf(tableResultsFormat, title, getCountValue(counts.Critical), counts.High, counts.Medium, counts.Low, counts.Info, scanCanceledString) + case scanPartialNumber: + fmt.Printf(tableResultsFormat, title, getCountValue(counts.Critical), counts.High, counts.Medium, counts.Low, counts.Info, scanPartialString) + default: + fmt.Printf(tableResultsFormat, title, getCountValue(counts.Critical), counts.High, counts.Medium, counts.Low, counts.Info, scanSuccessString) + } +} + +func printSCSSummary(microEngineOverviews []*wrappers.MicroEngineOverview, featureFlagsWrapper wrappers.FeatureFlagsWrapper) { + fmt.Printf(" Supply Chain Security Results\n") + fmt.Printf(" -------------------------------------------------------------------------- \n") + fmt.Println(" | Critical High Medium Low Info Status |") + for _, microEngineOverview := range microEngineOverviews { + printSCSTableRow(microEngineOverview, featureFlagsWrapper) + } + fmt.Printf(" -------------------------------------------------------------------------- \n\n") +} + +func printSCSTableRow(microEngineOverview *wrappers.MicroEngineOverview, featureFlagsWrapper wrappers.FeatureFlagsWrapper) { + formatString := " | %-20s %4v %4v %6v %4v %4v %-9s |\n" + notAvailableFormatString := " | %-20s %4v %4s %6s %4s %4s %5s |\n" + + riskSummary := microEngineOverview.RiskSummary + microEngineName := microEngineOverview.FullName + + switch microEngineOverview.Status { + case scsScanUnavailableString: + fmt.Printf(notAvailableFormatString, microEngineName, notAvailableString, notAvailableString, notAvailableString, notAvailableString, notAvailableString, notAvailableString) + default: + fmt.Printf(formatString, microEngineName, riskSummary[criticalLabel], riskSummary[highLabel], riskSummary[mediumLabel], riskSummary[lowLabel], + riskSummary[infoLabel], microEngineOverview.Status) + } +} + +func getCountValue(count int) interface{} { + if count < 0 { + return disabledString + } + return count +} + +func printResultsSummaryTable(summary *wrappers.ResultSummary) { + totalCriticalIssues := summary.EnginesResult.GetCriticalIssues() + totalHighIssues := summary.EnginesResult.GetHighIssues() + totalMediumIssues := summary.EnginesResult.GetMediumIssues() + totalLowIssues := summary.EnginesResult.GetLowIssues() + totalInfoIssues := summary.EnginesResult.GetInfoIssues() + fmt.Printf(tableLine + twoNewLines) + fmt.Printf(" Total Results: %d (Total Results includes only API documentation vulnerabilities\n and does not include API code vulnerabilities.)\n", summary.TotalIssues) + fmt.Println(tableLine) + fmt.Printf(TableTitleFormat, " ", "Critical", "High", "Medium", "Low", "Info", "Status") + + printTableRow("APIs", summary.EnginesResult[commonParams.APISecType], summary.EnginesResult[commonParams.APISecType].StatusCode) + printTableRow("IAC", summary.EnginesResult[commonParams.KicsType], summary.EnginesResult[commonParams.KicsType].StatusCode) + printTableRow("SAST", summary.EnginesResult[commonParams.SastType], summary.EnginesResult[commonParams.SastType].StatusCode) + printTableRow("SCA", summary.EnginesResult[commonParams.ScaType], summary.EnginesResult[commonParams.ScaType].StatusCode) + printTableRow("SCS", summary.EnginesResult[commonParams.ScsType], summary.EnginesResult[commonParams.ScsType].StatusCode) + + if wrappers.IsContainersEnabled { + printTableRow("CONTAINERS", summary.EnginesResult[commonParams.ContainersType], summary.EnginesResult[commonParams.ContainersType].StatusCode) + } + + fmt.Println(tableLine) + fmt.Printf(tableResultsFormat, + "TOTAL", getCountValue(totalCriticalIssues), totalHighIssues, totalMediumIssues, totalLowIssues, totalInfoIssues, summary.Status) + fmt.Printf(tableLine + twoNewLines) +} + +func generateScanSummaryURL(summary *wrappers.ResultSummary) string { + summaryURL := fmt.Sprintf( + strings.Replace(summary.BaseURI, "overview", "scans?id=%s&branch=%s", 1), + summary.ScanID, url.QueryEscape(summary.BranchName), + ) + return summaryURL +} + +func runGetResultCommand( + resultsWrapper wrappers.ResultsWrapper, + scanWrapper wrappers.ScansWrapper, + exportWrapper wrappers.ExportWrapper, + resultsPdfReportsWrapper wrappers.ResultsPdfWrapper, + resultsJSONReportsWrapper wrappers.ResultsJSONWrapper, + risksOverviewWrapper wrappers.RisksOverviewWrapper, + scsScanOverviewWrapper wrappers.ScanOverviewWrapper, + policyWrapper wrappers.PolicyWrapper, + featureFlagsWrapper wrappers.FeatureFlagsWrapper, + jwtWrapper wrappers.JWTWrapper, +) func(cmd *cobra.Command, args []string) error { + return func(cmd *cobra.Command, args []string) error { + targetFile, _ := cmd.Flags().GetString(commonParams.TargetFlag) + targetPath, _ := cmd.Flags().GetString(commonParams.TargetPathFlag) + format, _ := cmd.Flags().GetString(commonParams.TargetFormatFlag) + formatPdfToEmail, _ := cmd.Flags().GetString(commonParams.ReportFormatPdfToEmailFlag) + formatPdfOptions, _ := cmd.Flags().GetString(commonParams.ReportFormatPdfOptionsFlag) + formatSbomOptions, _ := cmd.Flags().GetString(commonParams.ReportSbomFormatFlag) + sastRedundancy, _ := cmd.Flags().GetBool(commonParams.SastRedundancyFlag) + agent, _ := cmd.Flags().GetString(commonParams.AgentFlag) + scaHideDevAndTestDep, _ := cmd.Flags().GetBool(commonParams.ScaHideDevAndTestDepFlag) + ignorePolicy, _ := cmd.Flags().GetBool(commonParams.IgnorePolicyFlag) + // Check if the user has permission to override policy management if --ignore-policy is set + ignorePolicyFlagOmit := false + if ignorePolicy { + overridePolicyManagementPer, err := jwtWrapper.CheckPermissionByAccessToken(OverridePolicyManagement) + if err != nil { + return err + } + if !overridePolicyManagementPer { + ignorePolicyFlagOmit = true + ignorePolicy = false + } + } + waitDelay, _ := cmd.Flags().GetInt(commonParams.WaitDelayFlag) + policyTimeout, _ := cmd.Flags().GetInt(commonParams.PolicyTimeoutFlag) + + scanID, _ := cmd.Flags().GetString(commonParams.ScanIDFlag) + if scanID == "" { + return errors.Errorf("%s: Please provide a scan ID", failedListingResults) + } + + resultsParams, err := getFilters(cmd) + if err != nil { + return errors.Wrapf(err, "%s", failedListingResults) + } + + if scaHideDevAndTestDep { + resultsParams[ScaExcludeResultTypesParam] = ScaDevAndTestExclusionParam + } + + scan, errorModel, scanErr := scanWrapper.GetByID(scanID) + if scanErr != nil { + return errors.Wrapf(scanErr, "%s", failedGetting) + } + if errorModel != nil { + return errors.Errorf("%s: CODE: %d, %s", failedGettingScan, errorModel.Code, errorModel.Message) + } + + var policyResponseModel *wrappers.PolicyResponseModel + if !isScanPending(string(scan.Status)) { + policyResponseModel, err = services.HandlePolicyEvaluation(cmd, policyWrapper, scan, ignorePolicy, agent, waitDelay, policyTimeout) + if err != nil { + return err + } + } else { + logger.PrintIfVerbose("Policy violations aren't returned in the pipeline for scans run in async mode.") + } + + if sastRedundancy { + resultsParams[commonParams.SastRedundancyFlag] = "" + } + + _, err = CreateScanReport(resultsWrapper, risksOverviewWrapper, scsScanOverviewWrapper, exportWrapper, + policyResponseModel, resultsPdfReportsWrapper, resultsJSONReportsWrapper, scan, format, formatPdfToEmail, formatPdfOptions, + formatSbomOptions, targetFile, targetPath, agent, resultsParams, featureFlagsWrapper, ignorePolicyFlagOmit) + return err + } +} + +func runGetCodeBashingCommand( + codeBashingWrapper wrappers.CodeBashingWrapper, +) func(cmd *cobra.Command, args []string) error { + return func(cmd *cobra.Command, args []string) error { + language, _ := cmd.Flags().GetString(commonParams.LanguageFlag) + cwe, _ := cmd.Flags().GetString(commonParams.CweIDFlag) + vulType, _ := cmd.Flags().GetString(commonParams.VulnerabilityTypeFlag) + params, err := codeBashingWrapper.BuildCodeBashingParams( + []wrappers.CodeBashingParamsCollection{ + { + CweID: "CWE-" + cwe, + Language: language, + CxQueryName: strings.ReplaceAll(vulType, " ", "_"), + }, + }, + ) + if err != nil { + return err + } + // Fetch the cached token or a new one to obtain the codebashing URL incoded in the jwt token + codeBashingURL, err := codeBashingWrapper.GetCodeBashingURL(codeBashingKey) + if err != nil { + return err + } + // Make the request to the api to obtain the codebashing link and send the codebashing url to enrich the path + CodeBashingModel, webError, err := codeBashingWrapper.GetCodeBashingLinks(params, codeBashingURL) + if err != nil { + return err + } + if webError != nil { + return errors.New(webError.Message) + } + err = printByFormat(cmd, *CodeBashingModel) + if err != nil { + return errors.Wrapf(err, "%s", failedListingCodeBashing) + } + return nil + } +} + +func setIsContainersEnabled(agent string) { + wrappers.IsContainersEnabled = !containsIgnoreCase(containerEngineUnsupportedAgents, agent) +} + +func filterResultsByType(results *wrappers.ScanResultsCollection, excludedTypes map[string]struct{}) *wrappers.ScanResultsCollection { + var filteredResults []*wrappers.ScanResult + + for _, result := range results.Results { + if _, shouldExclude := excludedTypes[result.Type]; shouldExclude { + results.TotalCount-- + } else { + filteredResults = append(filteredResults, result) + } + } + results.Results = filteredResults + return results +} + +func filterScsResultsByAgent(results *wrappers.ScanResultsCollection, agent string) *wrappers.ScanResultsCollection { + unsupportedTypesByAgent := map[string][]string{ + commonParams.VSCodeAgent: {commonParams.SCSScorecardType}, + commonParams.JetbrainsAgent: {commonParams.SCSScorecardType}, + commonParams.EclipseAgent: {commonParams.SCSScorecardType, commonParams.SCSSecretDetectionType}, + commonParams.VisualStudioAgent: {commonParams.SCSScorecardType}, + } + + excludedTypes := make(map[string]struct{}) + + if typesToExclude, exists := unsupportedTypesByAgent[agent]; exists { + for _, excludeType := range typesToExclude { + excludedTypes[excludeType] = struct{}{} + } + } + + results = filterResultsByType(results, excludedTypes) + + return results +} + +func CreateScanReport( + resultsWrapper wrappers.ResultsWrapper, + risksOverviewWrapper wrappers.RisksOverviewWrapper, + scsScanOverviewWrapper wrappers.ScanOverviewWrapper, + exportWrapper wrappers.ExportWrapper, + policyResponseModel *wrappers.PolicyResponseModel, + resultsPdfReportsWrapper wrappers.ResultsPdfWrapper, + resultsJSONReportsWrapper wrappers.ResultsJSONWrapper, + scan *wrappers.ScanResponseModel, + reportTypes, + formatPdfToEmail, + formatPdfOptions, + formatSbomOptions, + targetFile, + targetPath string, + agent string, + resultsParams map[string]string, + featureFlagsWrapper wrappers.FeatureFlagsWrapper, + ignorePolicyFlagOmit bool, +) (*wrappers.ScanResultsCollection, error) { + reportList := strings.Split(reportTypes, ",") + results := &wrappers.ScanResultsCollection{} + setIsContainersEnabled(agent) + summary, err := convertScanToResultsSummary(scan, resultsWrapper) + if err != nil { + return nil, err + } + scanPending := isScanPending(summary.Status) + + err = createDirectory(targetPath) + if err != nil { + return nil, err + } + if !scanPending { + results, err = ReadResults(resultsWrapper, exportWrapper, scan, resultsParams, agent, featureFlagsWrapper) + if err != nil { + return nil, err + } + } + isSummaryNeeded := verifyFormatsByReportList(reportList, summaryFormats...) + if isSummaryNeeded && !scanPending { + summary, err = summaryReport(summary, policyResponseModel, risksOverviewWrapper, scsScanOverviewWrapper, featureFlagsWrapper, results, resultsParams) + if err != nil { + return nil, err + } + } + for _, reportType := range reportList { + err = createReport(reportType, formatPdfToEmail, formatPdfOptions, formatSbomOptions, targetFile, + targetPath, results, summary, exportWrapper, resultsPdfReportsWrapper, resultsJSONReportsWrapper, featureFlagsWrapper, ignorePolicyFlagOmit) + if err != nil { + return nil, err + } + } + return results, nil +} + +func countResult(summary *wrappers.ResultSummary, result *wrappers.ScanResult) { + engineType := strings.TrimSpace(result.Type) + severity := strings.ToLower(result.Severity) + if contains(summary.EnginesEnabled, engineType) && isExploitable(result.State) { + if engineType == commonParams.SastType { + summary.SastIssues++ + summary.TotalIssues++ + } else if engineType == commonParams.ScaType { + summary.ScaIssues++ + summary.TotalIssues++ + } else if engineType == commonParams.KicsType { + summary.KicsIssues++ + summary.TotalIssues++ + } else if engineType == commonParams.ContainersType { + if wrappers.IsContainersEnabled { + *summary.ContainersIssues++ + summary.TotalIssues++ + } else { + return + } + } else if strings.HasPrefix(engineType, commonParams.SscsType) { + addResultToSCSOverview(summary, result) + engineType = commonParams.ScsType + *summary.ScsIssues++ + summary.TotalIssues++ + } else { + return + } + + switch severity { + case criticalLabel: + summary.CriticalIssues++ + case highLabel: + summary.HighIssues++ + case mediumLabel: + summary.MediumIssues++ + case lowLabel: + summary.LowIssues++ + case infoLabel: + summary.InfoIssues++ + } + + summary.UpdateEngineResultSummary(engineType, severity) + } +} + +func addResultToSCSOverview(summary *wrappers.ResultSummary, result *wrappers.ScanResult) { + if engineOverviewName, engineExists := sscsEngineToOverviewEngineMap[result.Type]; engineExists { + for _, microEngineOverview := range summary.SCSOverview.MicroEngineOverviews { + if microEngineOverview.Name == engineOverviewName { + if microEngineOverview.RiskSummary != nil { + severity := strings.ToLower(result.Severity) + if severityCount, exists := microEngineOverview.RiskSummary[severity]; exists { + summary.SCSOverview.RiskSummary[severity]++ + microEngineOverview.TotalRisks++ + summary.SCSOverview.TotalRisksCount++ + microEngineOverview.RiskSummary[severity] = severityCount.(int) + 1 + } + } + } + } + } +} + +func verifyFormatsByReportList(reportFormats []string, formats ...string) bool { + for _, reportFormat := range reportFormats { + for _, format := range formats { + if printer.IsFormat(reportFormat, format) { + return true + } + } + } + return false +} + +func validateEmails(emailString string) ([]string, error) { + re := regexp.MustCompile(`^[a-zA-Z0-9_.+-]+@[a-zA-Z0-9-]+\.[a-zA-Z0-9-.]+$`) + emails := strings.Split(emailString, ",") + var validEmails []string + for _, emailStr := range emails { + email := strings.TrimSpace(emailStr) + if re.MatchString(email) { + validEmails = append(validEmails, email) + } else { + return nil, errors.Errorf("report not sent, invalid email address: %s", email) + } + } + return validEmails, nil +} + +func getResultsForAPISecScanner( + risksOverviewWrapper wrappers.RisksOverviewWrapper, + scanID string, +) (results *wrappers.APISecResult, err error) { + var apiSecResultsModel *wrappers.APISecResult + var errorModel *wrappers.WebError + + apiSecResultsModel, errorModel, err = risksOverviewWrapper.GetAllAPISecRisksByScanID(scanID) + if err != nil { + return nil, errors.Wrapf(err, "%s", failedListingResults) + } + if errorModel != nil { + return nil, errors.Errorf("%s: CODE: %d, %s", failedListingResults, errorModel.Code, errorModel.Message) + } else if apiSecResultsModel != nil { + return apiSecResultsModel, nil + } + return nil, nil +} + +func getScanOverviewForSCSScanner( + scsScanOverviewWrapper wrappers.ScanOverviewWrapper, + scanID string, +) (results *wrappers.SCSOverview, err error) { + var scsOverview *wrappers.SCSOverview + var errorModel *wrappers.WebError + + scsOverview, errorModel, err = scsScanOverviewWrapper.GetSCSOverviewByScanID(scanID) + if err != nil { + return nil, errors.Wrapf(err, "SCS: %s", failedListingResults) + } + if errorModel != nil { + return nil, errors.Errorf("SCS: %s: CODE: %d, %s", failedListingResults, errorModel.Code, errorModel.Message) + } else if scsOverview != nil { + // Setting all counts to 0. Results are recounted in enhanceWithScanSummary->countResult + scsOverview.TotalRisksCount = 0 + for key := range scsOverview.RiskSummary { + scsOverview.RiskSummary[key] = 0 + } + for _, microEngineOverview := range scsOverview.MicroEngineOverviews { + microEngineOverview.TotalRisks = 0 + if microEngineOverview.RiskSummary != nil { + for severity := range microEngineOverview.RiskSummary { + microEngineOverview.RiskSummary[severity] = 0 + } + } + } + return scsOverview, nil + } + return nil, nil +} + +func isScanPending(scanStatus string) bool { + return !(strings.EqualFold(scanStatus, "Completed") || strings.EqualFold( + scanStatus, + "Partial", + ) || strings.EqualFold(scanStatus, "Failed")) +} + +func isValidScanStatus(status, format string) bool { + if isScanPending(status) { + log.Printf("Result format file %s not create because scan status is %s", format, status) + return false + } + return true +} + +func createReport(format, + formatPdfToEmail, + formatPdfOptions, + formatSbomOptions, + targetFile, + targetPath string, + results *wrappers.ScanResultsCollection, + summary *wrappers.ResultSummary, + exportWrapper wrappers.ExportWrapper, + resultsPdfReportsWrapper wrappers.ResultsPdfWrapper, + resultsJSONReportsWrapper wrappers.ResultsJSONWrapper, + featureFlagsWrapper wrappers.FeatureFlagsWrapper, + ignorePolicyFlagOmit bool) error { + if printer.IsFormat(format, printer.FormatIndentedJSON) { + return nil + } + if printer.IsFormat(format, printer.FormatSarif) && isValidScanStatus(summary.Status, printer.FormatSarif) { + sarifRpt := createTargetName(targetFile, targetPath, printer.FormatSarif) + return exportSarifResults(sarifRpt, results) + } + if printer.IsFormat(format, printer.FormatSonar) && isValidScanStatus(summary.Status, printer.FormatSonar) { + sonarRpt := createTargetName(fmt.Sprintf("%s%s", targetFile, sonarTypeLabel), targetPath, printer.FormatJSON) + return exportSonarResults(sonarRpt, results) + } + if printer.IsFormat(format, printer.FormatJSON) && isValidScanStatus(summary.Status, printer.FormatJSON) { + jsonRpt := createTargetName(targetFile, targetPath, printer.FormatJSON) + return exportJSONResults(jsonRpt, results) + } + if printer.IsFormat(format, printer.FormatJSONv2) && isValidScanStatus(summary.Status, printer.FormatJSONv2) { + summaryRpt := createTargetName(targetFile, targetPath, printer.FormatJSON) + return exportJSONReportResults(resultsJSONReportsWrapper, summary, summaryRpt, featureFlagsWrapper) + } + if printer.IsFormat(format, printer.FormatGLSast) { + jsonRpt := createTargetName(fmt.Sprintf("%s%s", targetFile, glSastTypeLabel), targetPath, printer.FormatJSON) + return exportGlSastResults(jsonRpt, results, summary) + } + if printer.IsFormat(format, printer.FormatGLSca) { + jsonRpt := createTargetName(fmt.Sprintf("%s%s", targetFile, glScaTypeLabel), targetPath, printer.FormatJSON) + return exportGlScaResults(jsonRpt, results, summary) + } + + if printer.IsFormat(format, printer.FormatSummaryConsole) { + return writeConsoleSummary(summary, featureFlagsWrapper, ignorePolicyFlagOmit) + } + if printer.IsFormat(format, printer.FormatSummary) { + summaryRpt := createTargetName(targetFile, targetPath, printer.FormatHTML) + convertNotAvailableNumberToZero(summary) + return writeHTMLSummary(summaryRpt, summary) + } + if printer.IsFormat(format, printer.FormatSummaryJSON) { + summaryRpt := createTargetName(targetFile, targetPath, printer.FormatJSON) + convertNotAvailableNumberToZero(summary) + return exportJSONSummaryResults(summaryRpt, summary) + } + if printer.IsFormat(format, printer.FormatPDF) && isValidScanStatus(summary.Status, printer.FormatPDF) { + summaryRpt := createTargetName(targetFile, targetPath, printer.FormatPDF) + return exportPdfResults(resultsPdfReportsWrapper, summary, summaryRpt, formatPdfToEmail, formatPdfOptions, featureFlagsWrapper) + } + if printer.IsFormat(format, printer.FormatSummaryMarkdown) { + summaryRpt := createTargetName(targetFile, targetPath, "md") + convertNotAvailableNumberToZero(summary) + return writeMarkdownSummary(summaryRpt, summary) + } + if printer.IsFormat(format, printer.FormatSbom) && isValidScanStatus(summary.Status, printer.FormatSbom) { + targetType := printer.FormatJSON + if strings.Contains(strings.ToLower(formatSbomOptions), printer.FormatXML) { + targetType = printer.FormatXML + } + summaryRpt := createTargetName(fmt.Sprintf("%s_%s", targetFile, printer.FormatSbom), targetPath, targetType) + convertNotAvailableNumberToZero(summary) + + if !contains(summary.EnginesEnabled, commonParams.ScaType) { + return fmt.Errorf("unable to generate %s report - SCA engine must be enabled on scan summary", printer.FormatSbom) + } + + if summary.ScaIssues == notAvailableNumber { + return fmt.Errorf("unable to generate %s report - SCA engine did not complete successfully", printer.FormatSbom) + } + + return services.ExportSbomResults(exportWrapper, summaryRpt, summary, formatSbomOptions) + } + return fmt.Errorf("bad report format %s", format) +} + +func createTargetName(targetFile, targetPath, targetType string) string { + return filepath.Join(targetPath, targetFile+"."+targetType) +} + +func createDirectory(targetPath string) error { + if _, err := os.Stat(targetPath); os.IsNotExist(err) { + log.Printf("\nOutput path not found: %s\n", targetPath) + log.Printf("Creating directory: %s\n", targetPath) + err = os.Mkdir(targetPath, directoryPermission) + if err != nil { + return err + } + } + return nil +} + +func ReadResults( + resultsWrapper wrappers.ResultsWrapper, + exportWrapper wrappers.ExportWrapper, + scan *wrappers.ScanResponseModel, + resultsParams map[string]string, + agent string, featureflagsWrappers wrappers.FeatureFlagsWrapper) (results *wrappers.ScanResultsCollection, err error) { + var resultsModel *wrappers.ScanResultsCollection + var errorModel *wrappers.WebError + + resultsParams[commonParams.ScanIDQueryParam] = scan.ID + _, sastRedundancy := resultsParams[commonParams.SastRedundancyFlag] + + scaHideDevAndTestDep := resultsParams[ScaExcludeResultTypesParam] == ScaDevAndTestExclusionParam + + resultsModel, errorModel, err = resultsWrapper.GetAllResultsByScanID(resultsParams) + + if err != nil { + return nil, errors.Wrapf(err, "%s", failedListingResults) + } + if errorModel != nil { + return nil, errors.Errorf("%s: CODE: %d, %s", failedListingResults, errorModel.Code, errorModel.Message) + } + + if resultsModel != nil { + if slices.Contains(scan.Engines, commonParams.SastType) && sastRedundancy { + // Compute SAST results redundancy + resultsModel = ComputeRedundantSastResults(resultsModel) + } + resultsModel, err = enrichScaResults(exportWrapper, scan, resultsModel, scaHideDevAndTestDep, featureflagsWrappers) + if err != nil { + return nil, err + } + + if slices.Contains(scan.Engines, commonParams.ScsType) { + resultsModel = filterScsResultsByAgent(resultsModel, agent) + } + + resultsModel.ScanID = scan.ID + return resultsModel, nil + } + return nil, nil +} + +func enrichScaResults( + exportWrapper wrappers.ExportWrapper, + scan *wrappers.ScanResponseModel, + resultsModel *wrappers.ScanResultsCollection, + scaHideDevAndTestDep bool, featureflagWrapper wrappers.FeatureFlagsWrapper) (*wrappers.ScanResultsCollection, error) { + if slices.Contains(scan.Engines, commonParams.ScaType) { + scaExportDetails, err := services.GetExportPackage(exportWrapper, scan.ID, scaHideDevAndTestDep, featureflagWrapper) + if err != nil { + return nil, errors.Wrapf(err, "%s", failedListingResults) + } + scaPackageModel := parseScaExportPackage(scaExportDetails.Packages) + scaTypeModel := parseExportScaVulnerability(scaExportDetails.ScaTypes) + if scaPackageModel != nil { + resultsModel = addPackageInformation(resultsModel, scaPackageModel, scaTypeModel) + } + } + if slices.Contains(scan.Engines, commonParams.ContainersType) && !wrappers.IsContainersEnabled { + resultsModel = removeResultsByType(resultsModel, commonParams.ContainersType) + } + return resultsModel, nil +} + +func parseExportScaVulnerability(types []wrappers.ScaType) *[]wrappers.ScaTypeCollection { + var scaTypes []wrappers.ScaTypeCollection + for _, t := range types { + scaTypes = append(scaTypes, wrappers.ScaTypeCollection(t)) + } + return &scaTypes +} + +func parseScaExportPackage(packages []wrappers.ScaPackage) *[]wrappers.ScaPackageCollection { + var scaPackages []wrappers.ScaPackageCollection + for _, pkg := range packages { + pkg := pkg + scaPackages = append(scaPackages, wrappers.ScaPackageCollection{ + ID: pkg.ID, + Locations: pkg.Locations, + DependencyPathArray: parsePackagePathToDependencyPath(&pkg), + Outdated: pkg.Outdated, + IsDirectDependency: pkg.IsDirectDependency, + IsDevelopmentDependency: pkg.IsDevelopmentDependency, + IsTestDependency: pkg.IsTestDependency, + }) + } + return &scaPackages +} + +func parsePackagePathToDependencyPath(pkg *wrappers.ScaPackage) [][]wrappers.DependencyPath { + var dependencyPathArray [][]wrappers.DependencyPath + for _, path := range pkg.PackagePathArray { + var dependencyPath []wrappers.DependencyPath + for _, dep := range path { + dependencyPath = append(dependencyPath, wrappers.DependencyPath{ + ID: dep.ID, + Name: dep.Name, + Version: dep.Version, + }) + } + dependencyPathArray = append(dependencyPathArray, dependencyPath) + } + + // We are doing this to maintain the same structure that was in risk-management api response + // in risk-management, if the length of the dependency path array is 1, it will be the main package + // in export service, if there are no dependencies, the package path array will be empty + if len(dependencyPathArray) == 0 { + appendMainPackageToDependencyPath(&dependencyPathArray, pkg) + } + return dependencyPathArray +} + +func appendMainPackageToDependencyPath(dependencyPathArray *[][]wrappers.DependencyPath, pkg *wrappers.ScaPackage) { + *dependencyPathArray = append(*dependencyPathArray, []wrappers.DependencyPath{{ + ID: pkg.ID, + Locations: pkg.Locations, + Name: pkg.Name, + IsDevelopment: pkg.IsDevelopmentDependency, + }}) +} + +func removeResultsByType(model *wrappers.ScanResultsCollection, resultType string) *wrappers.ScanResultsCollection { + var newResults []*wrappers.ScanResult + for _, result := range model.Results { + isResultType := result.Type == resultType + if resultType == commonParams.SscsType { + isResultType = strings.HasPrefix(result.Type, resultType) + } + if !isResultType { + newResults = append(newResults, result) + } + } + model.Results = newResults + model.TotalCount = uint(len(newResults)) + return model +} + +func exportSarifResults(targetFile string, results *wrappers.ScanResultsCollection) error { + var err error + var resultsJSON []byte + log.Println("Creating SARIF Report: ", targetFile) + var sarifResults = convertCxResultsToSarif(results) + resultsJSON, err = json.Marshal(sarifResults) + if err != nil { + return errors.Wrapf(err, "%s: failed to serialize results response ", failedGettingAll) + } + f, err := os.Create(targetFile) + if err != nil { + return errors.Wrapf(err, "%s: failed to create target file ", failedGettingAll) + } + _, _ = fmt.Fprintln(f, string(resultsJSON)) + _ = f.Close() + return nil +} +func exportGlSastResults(targetFile string, results *wrappers.ScanResultsCollection, summary *wrappers.ResultSummary) error { + log.Println("Creating gl-sast Report: ", targetFile) + var glSast = new(wrappers.GlSastResultsCollection) + glSast.Vulnerabilities = []wrappers.GlVulnerabilities{} + err := addScanToGlSastReport(summary, glSast) + if err != nil { + return errors.Wrapf(err, "%s: failed to add scan to gl-sast report", failedListingResults) + } + convertCxResultToGlSastVulnerability(results, glSast, summary) + resultsJSON, err := json.Marshal(glSast) + if err != nil { + return errors.Wrapf(err, "%s: failed to serialize gl-sast report ", failedListingResults) + } + f, err := os.Create(targetFile) + if err != nil { + return errors.Wrapf(err, "%s: failed to create target file ", failedListingResults) + } + defer f.Close() + _, _ = fmt.Fprintln(f, string(resultsJSON)) + return nil +} + +func exportGlScaResults(targetFile string, results *wrappers.ScanResultsCollection, summary *wrappers.ResultSummary) error { + log.Println("Creating Gl-sca Report: ", targetFile) + glScaResult := &wrappers.GlScaResultsCollection{ + Vulnerabilities: []wrappers.GlScaDepVulnerabilities{}, // Initialize arrays to prevent GitLab schema validation errors. + ScaDependencyFiles: []wrappers.ScaDependencyFile{}, + } + err := addScanToGlScaReport(summary, glScaResult) + if err != nil { + return errors.Wrapf(err, "%s: failed to denerate GL-Sca report ", failedListingResults) + } + convertCxResultToGlScaVulnerability(results, glScaResult) + convertCxResultToGlScaFiles(results, glScaResult) + resultsJSON, err := json.Marshal(glScaResult) + if err != nil { + return errors.Wrapf(err, "%s: failed to serialize GL-Sca report ", failedListingResults) + } + f, err := os.Create(targetFile) + if err != nil { + return errors.Wrapf(err, "%s: failed to create target file ", failedListingResults) + } + _, _ = fmt.Fprintln(f, string(resultsJSON)) + defer f.Close() + + return nil +} + +func addScanToGlScaReport(summary *wrappers.ResultSummary, glScaResult *wrappers.GlScaResultsCollection) error { + createdAt, err := time.Parse(summaryCreatedAtLayout, summary.CreatedAt) + if err != nil { + return err + } + + glScaResult.Schema = wrappers.ScaSchema + glScaResult.Version = wrappers.SchemaVersion + glScaResult.Scan.Analyzer.VendorGlSCA.VendorGlname = wrappers.AnalyzerScaID + glScaResult.Scan.Analyzer.Name = wrappers.AnalyzerScaID + glScaResult.Scan.Analyzer.Name = wrappers.AnalyzerScaID + glScaResult.Scan.Analyzer.ID = wrappers.ScannerID + glScaResult.Scan.Scanner.ID = wrappers.ScannerID + glScaResult.Scan.Scanner.Name = wrappers.AnalyzerScaID + glScaResult.Scan.Scanner.VendorGlSCA.VendorGlname = wrappers.AnalyzerScaID + glScaResult.Scan.Status = commonParams.Success + glScaResult.Scan.Type = wrappers.ScannerType + glScaResult.Scan.StartTime = createdAt.Format(glTimeFormat) + glScaResult.Scan.EndTime = createdAt.Format(glTimeFormat) + glScaResult.Scan.Scanner.Name = wrappers.AnalyzerScaID + glScaResult.Scan.Scanner.VersionGlSca = commonParams.Version + glScaResult.Scan.Analyzer.VersionGlSca = commonParams.Version + + return nil +} + +func addScanToGlSastReport(summary *wrappers.ResultSummary, glSast *wrappers.GlSastResultsCollection) error { + createdAt, err := time.Parse(summaryCreatedAtLayout, summary.CreatedAt) + if err != nil { + return err + } + + glSast.Scan = wrappers.ScanGlReport{} + glSast.Schema = wrappers.SastSchema + glSast.Version = wrappers.SastSchemaVersion + glSast.Scan.Analyzer.URL = wrappers.AnalyzerURL + glSast.Scan.Analyzer.Name = wrappers.VendorName + glSast.Scan.Analyzer.Vendor.Name = wrappers.VendorName + glSast.Scan.Analyzer.ID = wrappers.AnalyzerID + glSast.Scan.Scanner.ID = wrappers.AnalyzerID + glSast.Scan.Scanner.Name = wrappers.VendorName + glSast.Scan.Status = commonParams.Success + glSast.Scan.Type = commonParams.SastType + glSast.Scan.StartTime = createdAt.Format(glTimeFormat) + glSast.Scan.EndTime = createdAt.Format(glTimeFormat) + glSast.Scan.Scanner.Vendor.Name = wrappers.VendorName + glSast.Scan.Scanner.Version = commonParams.Version + glSast.Scan.Analyzer.Version = commonParams.Version + + return nil +} +func exportSonarResults(targetFile string, results *wrappers.ScanResultsCollection) error { + var err error + var resultsJSON []byte + log.Println("Creating SONAR Report: ", targetFile) + var sonarResults = convertCxResultsToSonar(results) + resultsJSON, err = json.Marshal(sonarResults) + if err != nil { + return errors.Wrapf(err, "%s: failed to serialize results response ", failedGettingAll) + } + f, err := os.Create(targetFile) + if err != nil { + return errors.Wrapf(err, "%s: failed to create target file ", failedGettingAll) + } + _, _ = fmt.Fprintln(f, string(resultsJSON)) + _ = f.Close() + return nil +} + +// Function to decode HTML entities in the ScanResultsCollection +func decodeHTMLEntitiesInResults(results *wrappers.ScanResultsCollection) { + for _, result := range results.Results { + result.Description = html.UnescapeString(result.Description) + result.DescriptionHTML = html.UnescapeString(result.DescriptionHTML) + for _, node := range result.ScanResultData.Nodes { + node.FullName = html.UnescapeString(node.FullName) + node.Name = html.UnescapeString(node.Name) + } + } +} + +func exportJSONResults(targetFile string, results *wrappers.ScanResultsCollection) error { + decodeHTMLEntitiesInResults(results) + var err error + var resultsJSON []byte + log.Println("Creating JSON Report: ", targetFile) + resultsJSON, err = json.Marshal(results) + if err != nil { + return errors.Wrapf(err, "%s: failed to serialize results response ", failedGettingAll) + } + f, err := os.Create(targetFile) + if err != nil { + return errors.Wrapf(err, "%s: failed to create target file ", failedGettingAll) + } + _, _ = fmt.Fprintln(f, string(resultsJSON)) + _ = f.Close() + return nil +} + +func exportJSONReportResults(jsonWrapper wrappers.ResultsJSONWrapper, summary *wrappers.ResultSummary, summaryRpt string, featureFlagsWrapper wrappers.FeatureFlagsWrapper) error { + jsonReportsPayload := &wrappers.JSONReportsPayload{} + pollingResp := &wrappers.JSONPollingResponse{} + jsonReportsPayload.ReportName = reportNameImprovedScanReport + + jsonOptionsSections, jsonOptionsEngines := parseJSONOptions(summary.EnginesEnabled, jsonReportsPayload.ReportName) + + jsonReportsPayload.ReportType = CliType + jsonReportsPayload.FileFormat = printer.FormatJSON + jsonReportsPayload.Data.ScanID = summary.ScanID + jsonReportsPayload.Data.ProjectID = summary.ProjectID + jsonReportsPayload.Data.BranchName = summary.BranchName + jsonReportsPayload.Data.Scanners = jsonOptionsEngines + jsonReportsPayload.Data.Sections = jsonOptionsSections + + jsonReportID, webErr, err := jsonWrapper.GenerateJSONReport(jsonReportsPayload) + if webErr != nil { + return errors.Errorf("Error generating JSON report - %s", webErr.Message) + } + if err != nil { + return errors.Errorf("Error generating JSON report - %s", err.Error()) + } + log.Println("Generating JSON report") + pollingResp.Status = startedStatus + for pollingResp.Status == startedStatus || pollingResp.Status == requestedStatus { + pollingResp, webErr, err = jsonWrapper.CheckJSONReportStatus(jsonReportID.ReportID) + if err != nil || webErr != nil { + return errors.Wrapf(err, "%v", webErr) + } + logger.PrintfIfVerbose("JSON report status: %s", pollingResp.Status) + time.Sleep(delayValueForReport * time.Millisecond) + } + if pollingResp.Status != completedStatus { + return errors.Errorf("JSON generating failed - Current status: %s", pollingResp.Status) + } + + minioEnabled, _ := wrappers.GetSpecificFeatureFlag(featureFlagsWrapper, wrappers.MinioEnabled) + infoPathType := "" + if minioEnabled.Status { + infoPathType = jsonReportID.ReportID + } else { + infoPathType = pollingResp.URL + } + err = jsonWrapper.DownloadJSONReport(infoPathType, summaryRpt, minioEnabled.Status) + if err != nil { + return errors.Wrapf(err, "%s", "Failed downloading JSON report") + } + return nil +} + +func parseJSONOptions(enabledEngines []string, reportName string) (jsonOptionsSections, jsonOptionsEngines []string) { + jsonOptionsSections = []string{ + "ScanSummary", + "ExecutiveSummary", + "ScanResults", + } + + var jsonOptionsEnginesMap = map[string]string{ + commonParams.ScaType: "SCA", + commonParams.SastType: "SAST", + commonParams.KicsType: "KICS", + commonParams.IacType: "KICS", + commonParams.ContainersType: "Containers", + commonParams.ScsType: "Microengines", + } + if jsonOptionsEngines == nil { + for _, engine := range enabledEngines { + if jsonOptionsEnginesMap[engine] != "" { + jsonOptionsEngines = append(jsonOptionsEngines, jsonOptionsEnginesMap[engine]) + } + } + } + + if reportName == reportNameImprovedScanReport { + jsonOptionsSections = translateReportSectionsForImproved(jsonOptionsSections) + } + + return jsonOptionsSections, jsonOptionsEngines +} + +func exportJSONSummaryResults(targetFile string, results *wrappers.ResultSummary) error { + var err error + var resultsJSON []byte + log.Println("Creating summary JSON Report: ", targetFile) + resultsJSON, err = json.Marshal(results) + if err != nil { + return errors.Wrapf(err, "%s: failed to serialize results response ", failedGettingAll) + } + f, err := os.Create(targetFile) + if err != nil { + return errors.Wrapf(err, "%s: failed to create target file ", failedGettingAll) + } + _, _ = fmt.Fprintln(f, string(resultsJSON)) + _ = f.Close() + return nil +} + +func exportPdfResults(pdfWrapper wrappers.ResultsPdfWrapper, summary *wrappers.ResultSummary, summaryRpt, formatPdfToEmail, + pdfOptions string, featureFlagsWrapper wrappers.FeatureFlagsWrapper) error { + pdfReportsPayload := &wrappers.PdfReportsPayload{} + pollingResp := &wrappers.PdfPollingResponse{} + pdfReportsPayload.ReportName = reportNameImprovedScanReport + pdfOptionsSections, pdfOptionsEngines, err := parsePDFOptions(pdfOptions, summary.EnginesEnabled, pdfReportsPayload.ReportName) + if err != nil { + return err + } + pdfReportsPayload.ReportType = CliType + pdfReportsPayload.FileFormat = printer.FormatPDF + pdfReportsPayload.Data.ScanID = summary.ScanID + pdfReportsPayload.Data.ProjectID = summary.ProjectID + pdfReportsPayload.Data.BranchName = summary.BranchName + pdfReportsPayload.Data.Scanners = pdfOptionsEngines + pdfReportsPayload.Data.Sections = pdfOptionsSections + + // will generate pdf report and send it to the email list + // instead of saving it to the file system + if len(formatPdfToEmail) > 0 { + emailList, validateErr := validateEmails(formatPdfToEmail) + if validateErr != nil { + return validateErr + } + pdfReportsPayload.ReportType = reportTypeEmail + pdfReportsPayload.Data.Email = emailList + } + pdfReportID, webErr, err := pdfWrapper.GeneratePdfReport(pdfReportsPayload) + if webErr != nil { + return errors.Errorf("Error generating PDF report - %s", webErr.Message) + } + if err != nil { + return errors.Errorf("Error generating PDF report - %s", err.Error()) + } + if pdfReportsPayload.ReportType == reportTypeEmail { + log.Println("Sending PDF report to: ", pdfReportsPayload.Data.Email) + return nil + } + log.Println("Generating PDF report") + pollingResp.Status = startedStatus + for pollingResp.Status == startedStatus || pollingResp.Status == requestedStatus { + pollingResp, webErr, err = pdfWrapper.CheckPdfReportStatus(pdfReportID.ReportID) + if err != nil || webErr != nil { + return errors.Wrapf(err, "%v", webErr) + } + logger.PrintfIfVerbose("PDF report status: %s", pollingResp.Status) + time.Sleep(delayValueForReport * time.Millisecond) + } + if pollingResp.Status != completedStatus { + return errors.Errorf("PDF generating failed - Current status: %s", pollingResp.Status) + } + + minioEnabled, _ := wrappers.GetSpecificFeatureFlag(featureFlagsWrapper, wrappers.MinioEnabled) + infoPathType := "" + if minioEnabled.Status { + infoPathType = pdfReportID.ReportID + } else { + infoPathType = pollingResp.URL + } + err = pdfWrapper.DownloadPdfReport(infoPathType, summaryRpt, minioEnabled.Status) + if err != nil { + return errors.Wrapf(err, "%s", "Failed downloading PDF report") + } + return nil +} + +func parsePDFOptions(pdfOptions string, enabledEngines []string, reportName string) (pdfOptionsSections, pdfOptionsEngines []string, err error) { + var pdfOptionsSectionsMap = map[string]string{ + "scansummary": "ScanSummary", + "executivesummary": "ExecutiveSummary", + "scanresults": "ScanResults", + } + + var pdfOptionsEnginesMap = map[string]string{ + commonParams.ScaType: "SCA", + commonParams.SastType: "SAST", + commonParams.KicsType: "KICS", + commonParams.IacType: "KICS", + } + + pdfOptions = strings.ToLower(strings.ReplaceAll(pdfOptions, " ", "")) + options := strings.Split(strings.ReplaceAll(pdfOptions, "\n", ""), ",") + for _, s := range options { + if pdfOptionsEnginesMap[s] != "" { + pdfOptionsEngines = append(pdfOptionsEngines, pdfOptionsEnginesMap[s]) + } else if pdfOptionsSectionsMap[s] != "" { + pdfOptionsSections = append(pdfOptionsSections, pdfOptionsSectionsMap[s]) + } else { + return nil, nil, errors.Errorf("report option \"%s\" unavailable", s) + } + } + if pdfOptionsEngines == nil { + for _, engine := range enabledEngines { + if pdfOptionsEnginesMap[engine] != "" { + pdfOptionsEngines = append(pdfOptionsEngines, pdfOptionsEnginesMap[engine]) + } + } + } + + if reportName == reportNameImprovedScanReport { + pdfOptionsSections = translateReportSectionsForImproved(pdfOptionsSections) + } + + return pdfOptionsSections, pdfOptionsEngines, nil +} + +func translateReportSectionsForImproved(sections []string) []string { + var resultSections = make([]string, 0) + + var pdfOptionsSectionsImprovedTranslation = map[string][]string{ + "ScanSummary": {"scan-information"}, + "ExecutiveSummary": {"results-overview"}, + "ScanResults": {"scan-results", "categories", "resolved-results", "vulnerability-details"}, + } + + for _, section := range sections { + if translatedSections := pdfOptionsSectionsImprovedTranslation[section]; translatedSections != nil { + resultSections = append(resultSections, translatedSections...) + } + } + + return resultSections +} + +func convertCxResultsToSarif(results *wrappers.ScanResultsCollection) *wrappers.SarifResultsCollection { + var sarif = new(wrappers.SarifResultsCollection) + sarif.Schema = "https://raw.githubusercontent.com/oasis-tcs/sarif-spec/master/Schemata/sarif-schema-2.1.0.json" + sarif.Version = "2.1.0" + sarif.Runs = []wrappers.SarifRun{} + sarif.Runs = append(sarif.Runs, createSarifRun(results)) + return sarif +} + +func convertCxResultToGlSastVulnerability(results *wrappers.ScanResultsCollection, glSast *wrappers.GlSastResultsCollection, summary *wrappers.ResultSummary) { + for _, result := range results.Results { + if strings.TrimSpace(result.Type) == commonParams.SastType { + glSast = parseGlSastVulnerability(result, glSast, summary) + } + } +} + +func convertCxResultToGlScaVulnerability(results *wrappers.ScanResultsCollection, glScaResult *wrappers.GlScaResultsCollection) { + for _, result := range results.Results { + if strings.TrimSpace(result.Type) == commonParams.ScaType { + glScaResult = parseGlscaVulnerability(result, glScaResult) + } + } +} + +func convertCxResultToGlScaFiles(results *wrappers.ScanResultsCollection, glScaResult *wrappers.GlScaResultsCollection) { + for _, result := range results.Results { + if strings.TrimSpace(result.Type) == commonParams.ScaType { + glScaResult = parseGlScaFiles(result, glScaResult) + } + } +} +func parseGlSastVulnerability(result *wrappers.ScanResult, glSast *wrappers.GlSastResultsCollection, summary *wrappers.ResultSummary) *wrappers.GlSastResultsCollection { + hostName := parseURI(summary.BaseURI) + + queryName := result.ScanResultData.QueryName + fileName := result.ScanResultData.Nodes[0].FileName + lineNumber := strconv.FormatUint(uint64(result.ScanResultData.Nodes[0].Line), 10) + startLine := result.ScanResultData.Nodes[0].Line + endLine := result.ScanResultData.Nodes[0].Line + result.ScanResultData.Nodes[0].Length + ID := fmt.Sprintf("%s:%s:%s", queryName, fileName, lineNumber) + category := fmt.Sprintf("%s-%s", wrappers.VendorName, result.Type) + message := fmt.Sprintf("%s@%s:%s", queryName, fileName, lineNumber) + QueryDescriptionLink := fmt.Sprintf("%s/results/%s/%s/sast/description/%s/%s", hostName, summary.ScanID, summary.ProjectID, result.VulnerabilityDetails.CweID, result.ScanResultData.QueryID) + + glSast.Vulnerabilities = append(glSast.Vulnerabilities, wrappers.GlVulnerabilities{ + ID: ID, + Category: category, + Name: queryName, + Message: message, + Description: result.Description + " \n" + QueryDescriptionLink, + CVE: ID, + Severity: cases.Title(language.English).String(result.Severity), + Confidence: cases.Title(language.English).String(result.Severity), + Solution: "", + + Scanner: wrappers.GlScanner{ + ID: category, + Name: category, + }, + Identifiers: []wrappers.Identifier{ + { + Type: "cxOneScan", + Name: "CxOne Scan", + URL: summary.BaseURI, + Value: result.ID, + }, + }, + Links: make([]string, 0), + Tracking: wrappers.Tracking{ + Type: "source", + Items: []wrappers.Item{ + { + Signatures: []wrappers.Signature{{Algorithm: result.Type + "-Algorithm ", Value: "NA"}}, + File: fileName, + EndLine: endLine, + StartLine: startLine, + }, + }, + }, + Flags: make([]wrappers.Flag, 0), + Location: wrappers.Location{ + File: fileName, + StartLine: startLine, + EndLine: endLine, + }, + }) + return glSast +} +func parseGlscaVulnerability(result *wrappers.ScanResult, glDependencyResult *wrappers.GlScaResultsCollection) *wrappers.GlScaResultsCollection { + if result.ScanResultData.ScaPackageCollection != nil { + glDependencyResult.Vulnerabilities = append(glDependencyResult.Vulnerabilities, wrappers.GlScaDepVulnerabilities{ + ID: result.ID, + Name: result.VulnerabilityDetails.CveName, + Description: result.Description, + Severity: cases.Title(language.English).String(result.Severity), + Solution: result.ScanResultData.RecommendedVersion, + Identifiers: collectScaPackageData(result), + Links: collectScaPackageLinks(result), + TrackingDep: wrappers.TrackingDep{ + Items: collectScaPackageItemsDep(result), + }, + Flags: make([]string, 0), + LocationDep: wrappers.GlScaDepVulnerabilityLocation{ + File: parseGlDependencyLocation(result), + Dependency: wrappers.ScaDependencyLocation{ + Package: wrappers.PackageName{Name: result.ScanResultData.PackageIdentifier}, + ScaDependencyLocationVersion: "", + Direct: result.ScanResultData.ScaPackageCollection.IsDirectDependency, + ScaDependencyPath: result.ScanResultData.Line, + }, + }, + }) + } + return glDependencyResult +} +func parseGlDependencyLocation(result *wrappers.ScanResult) string { + var location string + if result != nil && result.ScanResultData.ScaPackageCollection != nil && result.ScanResultData.ScaPackageCollection.Locations != nil { + location = *result.ScanResultData.ScaPackageCollection.Locations[0] + } else { + location = "" + } + return location +} +func parseGlScaFiles(result *wrappers.ScanResult, glScaResult *wrappers.GlScaResultsCollection) *wrappers.GlScaResultsCollection { + if result.ScanResultData.ScaPackageCollection != nil && result.ScanResultData.ScaPackageCollection.Locations != nil { + glScaResult.ScaDependencyFiles = append(glScaResult.ScaDependencyFiles, wrappers.ScaDependencyFile{ + Path: *result.ScanResultData.ScaPackageCollection.Locations[0], + PackageManager: result.ScanResultData.ScaPackageCollection.ID, + Dependencies: collectScaFileLocations(result), + }) + } + return glScaResult +} +func collectScaFileLocations(result *wrappers.ScanResult) []wrappers.ScaDependencyLocation { + allScaIdentifierLocations := []wrappers.ScaDependencyLocation{} + for _, packageInfo := range result.ScanResultData.PackageData { + allScaIdentifierLocations = append(allScaIdentifierLocations, wrappers.ScaDependencyLocation{ + Package: wrappers.PackageName{ + Name: packageInfo.Type, + }, + ScaDependencyLocationVersion: packageInfo.URL, + Direct: true, + ScaDependencyPath: result.ScanResultData.Line, + }) + } + return allScaIdentifierLocations +} +func collectScaPackageItemsDep(result *wrappers.ScanResult) []wrappers.ItemDep { + allScaPackageItemDep := []wrappers.ItemDep{} + allScaPackageItemDep = append(allScaPackageItemDep, wrappers.ItemDep{ + Signature: []wrappers.SignatureDep{{Algorithm: "SCA-Algorithm ", Value: "NA"}}, + File: result.VulnerabilityDetails.CveName, + EndLine: 0, + StartLine: 0, + }) + return allScaPackageItemDep +} +func collectScaPackageLinks(result *wrappers.ScanResult) []wrappers.LinkDep { + allScaPackageLinks := []wrappers.LinkDep{} + for _, packageInfo := range result.ScanResultData.PackageData { + allScaPackageLinks = append(allScaPackageLinks, wrappers.LinkDep{ + Name: packageInfo.Type, + URL: packageInfo.URL, + }) + } + return allScaPackageLinks +} +func collectScaPackageData(result *wrappers.ScanResult) []wrappers.IdentifierDep { + allIdentifierDep := []wrappers.IdentifierDep{} + for _, packageInfo := range result.ScanResultData.PackageData { + allIdentifierDep = append(allIdentifierDep, wrappers.IdentifierDep{ + Type: packageInfo.Type, + Value: packageInfo.URL, + Name: packageInfo.URL, + }) + } + return allIdentifierDep +} + +func convertCxResultsToSonar(results *wrappers.ScanResultsCollection) *wrappers.ScanResultsSonar { + var sonar = new(wrappers.ScanResultsSonar) + sonar.Issues, sonar.Rules = parseSonar(results) + return sonar +} + +func createSarifRun(results *wrappers.ScanResultsCollection) wrappers.SarifRun { + var sarifRun wrappers.SarifRun + sarifRun.Tool.Driver.Name = wrappers.SarifName + sarifRun.Tool.Driver.Version = wrappers.SarifVersion + sarifRun.Tool.Driver.InformationURI = wrappers.SarifInformationURI + sarifRun.Tool.Driver.Rules, sarifRun.Results = parseResults(results) + return sarifRun +} + +func parseResults(results *wrappers.ScanResultsCollection) ([]wrappers.SarifDriverRule, []wrappers.SarifScanResult) { + var sarifRules = make([]wrappers.SarifDriverRule, 0) + var sarifResults = make([]wrappers.SarifScanResult, 0) + if results != nil { + ruleIds := map[interface{}]bool{} + for _, result := range results.Results { + if rule := findRule(ruleIds, result); rule != nil { + sarifRules = append(sarifRules, *rule) + } + if sarifResult := findResult(result); sarifResult != nil { + sarifResults = append(sarifResults, sarifResult...) + } + } + } + return sarifRules, sarifResults +} + +func parseSonar(results *wrappers.ScanResultsCollection) ([]wrappers.SonarIssues, []wrappers.SonarRules) { + var sonarIssues []wrappers.SonarIssues + var sonarRules []wrappers.SonarRules + seenRuleIDs := make(map[string]bool) // Track already added rule IDs + + if results != nil { + for _, result := range results.Results { + var auxRules = initSonarRules(result) + var auxIssue = initSonarIssue(result) + + if !seenRuleIDs[auxRules.ID] { + sonarRules = append(sonarRules, auxRules) + seenRuleIDs[auxRules.ID] = true + } + + engineType := strings.TrimSpace(result.Type) + + if engineType == commonParams.SastType { + auxIssue.PrimaryLocation = parseSonarPrimaryLocation(result) + auxIssue.SecondaryLocations = parseSonarSecondaryLocations(result) + sonarIssues = append(sonarIssues, auxIssue) + } else if engineType == commonParams.KicsType { + auxIssue.PrimaryLocation = parseLocationKics(result) + sonarIssues = append(sonarIssues, auxIssue) + } else if engineType == commonParams.ScaType { + sonarIssuesByLocation := parseScaSonarLocations(result) + sonarIssues = append(sonarIssues, sonarIssuesByLocation...) + } else if wrappers.IsContainersEnabled && engineType == commonParams.ContainersType { + auxIssue.PrimaryLocation = parseContainersSonar(result) + sonarIssues = append(sonarIssues, auxIssue) + } else if strings.HasPrefix(engineType, commonParams.SscsType) { + sscsSonarIssue := parseSscsSonar(result, &auxIssue) + sonarIssues = append(sonarIssues, sscsSonarIssue) + } + } + } + return sonarIssues, sonarRules +} + +func parseContainersSonar(result *wrappers.ScanResult) wrappers.SonarLocation { + var auxLocation wrappers.SonarLocation + auxLocation.FilePath = result.ScanResultData.ImageFilePath + auxLocation.Message = html.UnescapeString(result.Description) + var textRange wrappers.SonarTextRange + textRange.StartColumn = 1 + textRange.EndColumn = 2 + textRange.StartLine = 1 + textRange.EndLine = 2 + auxLocation.TextRange = textRange + return auxLocation +} + +func parseSscsSonar(result *wrappers.ScanResult, sonarIssue *wrappers.SonarIssues) wrappers.SonarIssues { + sonarIssue.PrimaryLocation.FilePath = result.ScanResultData.Filename + + sonarIssue.PrimaryLocation.Message = html.UnescapeString(result.ScanResultData.Remediation) + var textRange wrappers.SonarTextRange + textRange.StartColumn = 1 + textRange.EndColumn = 2 + textRange.StartLine = result.ScanResultData.Line + sonarIssue.PrimaryLocation.TextRange = textRange + return *sonarIssue +} + +func initSonarIssue(result *wrappers.ScanResult) wrappers.SonarIssues { + var sonarIssue wrappers.SonarIssues + engineType := strings.TrimSpace(result.Type) + if engineType == commonParams.SastType { + sonarIssue.RuleID = result.ScanResultData.LanguageName + " - " + result.ScanResultData.QueryName + } else if engineType == commonParams.KicsType { + sonarIssue.RuleID = result.ScanResultData.QueryName + } else if engineType == commonParams.ScaType { + sonarIssue.RuleID = result.ID + } else if wrappers.IsContainersEnabled && engineType == commonParams.ContainersType { + sonarIssue.RuleID = result.ID + } else if strings.HasPrefix(engineType, commonParams.SscsType) { + sonarIssue.RuleID = result.ID + } + + sonarIssue.PrimaryLocation.Message = html.UnescapeString(result.Description) + sonarIssue.EffortMinutes = 0 + + return sonarIssue +} + +func initSonarRules(result *wrappers.ScanResult) wrappers.SonarRules { + var sonarRules wrappers.SonarRules + var sonarImpacts wrappers.SonarImpacts + + sonarImpacts.Severity = sonarSeverities[result.Severity] + sonarImpacts.SoftwareQuality = vulnerabilitySonar + + sonarRules.EngineID = result.Type + sonarRules.CleanCodeAttribute = cleanCodeAttribute + + engineType := strings.TrimSpace(result.Type) + if engineType == commonParams.SastType { + sonarRules.Name = result.ScanResultData.QueryName + sonarRules.Description = html.UnescapeString(result.Description) + sonarRules.ID = result.ScanResultData.LanguageName + " - " + result.ScanResultData.QueryName + } else if engineType == commonParams.KicsType { + sonarRules.Name = result.ScanResultData.QueryName + sonarRules.Description = html.UnescapeString(result.Description) + sonarRules.ID = result.ScanResultData.QueryName + } else if engineType == commonParams.ScaType { + sonarRules.Name = result.ScanResultData.PackageIdentifier + sonarRules.Description = html.UnescapeString(result.Description) + sonarRules.ID = result.ID + } else if wrappers.IsContainersEnabled && engineType == commonParams.ContainersType { + sonarRules.Name = result.ScanResultData.ImageTag + sonarRules.Description = html.UnescapeString(result.Description) + sonarRules.ID = result.ID + } else if strings.HasPrefix(engineType, commonParams.SscsType) { + sonarRules.Name = result.ScanResultData.RuleName + sonarRules.Description = html.UnescapeString(result.ScanResultData.RuleDescription) + sonarRules.ID = result.ID + } + + sonarRules.Impacts = []wrappers.SonarImpacts{sonarImpacts} + + return sonarRules +} + +func parseScaSonarLocations(result *wrappers.ScanResult) []wrappers.SonarIssues { + if result == nil || result.ScanResultData.ScaPackageCollection == nil || result.ScanResultData.ScaPackageCollection.Locations == nil { + return []wrappers.SonarIssues{} + } + + var issuesByLocation []wrappers.SonarIssues + + for _, location := range result.ScanResultData.ScaPackageCollection.Locations { + issueByLocation := initSonarIssue(result) + + var primaryLocation wrappers.SonarLocation + + primaryLocation.FilePath = *location + _, _, primaryLocation.Message = findRuleID(result) + + var textRange wrappers.SonarTextRange + textRange.StartColumn = 1 + textRange.EndColumn = 2 + textRange.StartLine = 1 + textRange.EndLine = 2 + + primaryLocation.TextRange = textRange + + issueByLocation.PrimaryLocation = primaryLocation + + issuesByLocation = append(issuesByLocation, issueByLocation) + } + + return issuesByLocation +} + +func parseLocationKics(results *wrappers.ScanResult) wrappers.SonarLocation { + var auxLocation wrappers.SonarLocation + auxLocation.FilePath = strings.TrimLeft(results.ScanResultData.Filename, "/") + auxLocation.Message = html.UnescapeString(results.ScanResultData.Value) + var auxTextRange wrappers.SonarTextRange + auxTextRange.StartLine = results.ScanResultData.Line + auxTextRange.StartColumn = 0 + auxTextRange.EndColumn = 1 + auxLocation.TextRange = auxTextRange + return auxLocation +} + +func parseSonarPrimaryLocation(results *wrappers.ScanResult) wrappers.SonarLocation { + var auxLocation wrappers.SonarLocation + // fill the details in the primary Location + if len(results.ScanResultData.Nodes) > 0 { + auxLocation.FilePath = strings.TrimLeft(results.ScanResultData.Nodes[0].FileName, "/") + auxLocation.Message = html.UnescapeString(strings.ReplaceAll(results.ScanResultData.QueryName, "_", " ")) + auxLocation.TextRange = parseSonarTextRange(results.ScanResultData.Nodes[0]) + } + return auxLocation +} + +func parseSonarSecondaryLocations(results *wrappers.ScanResult) []wrappers.SonarLocation { + var auxSecondaryLocations []wrappers.SonarLocation + // Traverse all the rest of the scan result nodes into secondary location of sonar + if len(results.ScanResultData.Nodes) >= 1 { + for _, node := range results.ScanResultData.Nodes[1:] { + var auxSecondaryLocation wrappers.SonarLocation + auxSecondaryLocation.FilePath = strings.TrimLeft(node.FileName, "/") + auxSecondaryLocation.Message = html.UnescapeString(strings.ReplaceAll(results.ScanResultData.QueryName, "_", " ")) + auxSecondaryLocation.TextRange = parseSonarTextRange(node) + auxSecondaryLocations = append(auxSecondaryLocations, auxSecondaryLocation) + } + } + return auxSecondaryLocations +} + +func parseSonarTextRange(results *wrappers.ScanResultNode) wrappers.SonarTextRange { + var auxTextRange wrappers.SonarTextRange + auxTextRange.StartLine = results.Line + startColumn := getSastStartColumn(results.Column) + + auxTextRange.StartColumn = startColumn + auxTextRange.EndColumn = startColumn + results.Length + + if auxTextRange.StartColumn == auxTextRange.EndColumn { + auxTextRange.EndColumn++ + } + + return auxTextRange +} + +func findRule(ruleIds map[interface{}]bool, result *wrappers.ScanResult) *wrappers.SarifDriverRule { + var sarifRule wrappers.SarifDriverRule + sarifRule.ID, sarifRule.Name, _ = findRuleID(result) + sarifRule.FullDescription = findFullDescription(result) + sarifRule.Help = findHelp(result) + sarifRule.HelpURI = findHelpURI(result) + sarifRule.Properties = findProperties(result) + + if !ruleIds[sarifRule.ID] { + ruleIds[sarifRule.ID] = true + return &sarifRule + } + + return nil +} + +func getSastStartColumn(column uint) uint { + if column == 0 { + return 0 + } + return column - 1 +} + +func findRuleID(result *wrappers.ScanResult) (ruleID, ruleName, shortMessage string) { + caser := cases.Title(language.English) + + if result.ScanResultData.QueryID == nil && result.ScanResultData.RuleID == nil { + return fmt.Sprintf("%s (%s)", result.ID, result.Type), + caser.String(strings.ToLower(strings.ReplaceAll(result.ID, "-", ""))), + html.UnescapeString(fmt.Sprintf("%s (%s)", result.ScanResultData.PackageIdentifier, result.ID)) + } + + if result.ScanResultData.RuleID != nil { + ruleName = strings.ReplaceAll(result.ScanResultData.RuleName, "_", " ") + return fmt.Sprintf("%s - %s (%s)", ruleName, *result.ScanResultData.RuleID, result.Type), + ruleName, + ruleName + } + + ruleName = strings.ReplaceAll(result.ScanResultData.QueryName, "_", " ") + return fmt.Sprintf("%v - %s (%s)", ruleName, result.ScanResultData.QueryID, result.Type), + ruleName, + ruleName +} + +func findFullDescription(result *wrappers.ScanResult) wrappers.SarifDescription { + var sarifDescription wrappers.SarifDescription + sarifDescription.Text = findDescriptionText(result) + return sarifDescription +} + +func findHelp(result *wrappers.ScanResult) wrappers.SarifHelp { + var sarifHelp wrappers.SarifHelp + sarifHelp.Text = findHelpText(result) + sarifHelp.Markdown = findHelpMarkdownText(result) + + return sarifHelp +} + +func findHelpURI(result *wrappers.ScanResult) string { + if strings.HasPrefix(result.Type, commonParams.SscsType) { + if result.ScanResultData.RemediationLink != "" { + return result.ScanResultData.RemediationLink + } + } + + return wrappers.SarifInformationURI +} + +func findDescriptionText(result *wrappers.ScanResult) string { + if result.Type == commonParams.KicsType { + return fmt.Sprintf( + "%s Value: %s Excepted value: %s", + result.Description, result.ScanResultData.Value, result.ScanResultData.ExpectedValue, + ) + } else if strings.HasPrefix(result.Type, commonParams.SscsType) { + return result.ScanResultData.RuleDescription + } + + return result.Description +} + +func findHelpText(result *wrappers.ScanResult) string { + if strings.HasPrefix(result.Type, commonParams.SscsType) { + return findHelpMarkdownText(result) + } + + return findDescriptionText(result) +} + +func findHelpMarkdownText(result *wrappers.ScanResult) string { + if result.Type == commonParams.KicsType { + return fmt.Sprintf( + "%s

Value: %s
Excepted value: %s", + result.Description, result.ScanResultData.Value, result.ScanResultData.ExpectedValue, + ) + } else if strings.HasPrefix(result.Type, commonParams.SscsType) { + return result.ScanResultData.Remediation + } + + return result.Description +} + +func findProperties(result *wrappers.ScanResult) wrappers.SarifProperties { + var sarifProperties wrappers.SarifProperties + sarifProperties.ID, sarifProperties.Name, _ = findRuleID(result) + sarifProperties.Description = findDescriptionText(result) + sarifProperties.SecuritySeverity = securities[result.Severity] + sarifProperties.Tags = []string{"security", "checkmarx", result.Type} + return sarifProperties +} + +func findSarifLevel(result *wrappers.ScanResult) string { + level := map[string]string{ + infoCx: infoLowSarif, + lowCx: infoLowSarif, + mediumCx: mediumSarif, + highCx: highSarif, + criticalCx: highSarif, + } + return level[result.Severity] +} + +func initSarifResult(result *wrappers.ScanResult) wrappers.SarifScanResult { + var scanResult wrappers.SarifScanResult + scanResult.RuleID, _, scanResult.Message.Text = findRuleID(result) + scanResult.Level = findSarifLevel(result) + scanResult.Locations = []wrappers.SarifLocation{} + + return scanResult +} + +func findResult(result *wrappers.ScanResult) []wrappers.SarifScanResult { + var scanResults []wrappers.SarifScanResult + + if len(result.ScanResultData.Nodes) > 0 { + scanResults = parseSarifResultSast(result, scanResults) + } else if result.Type == commonParams.KicsType { + scanResults = parseSarifResultKics(result, scanResults) + } else if result.Type == commonParams.ScaType { + scanResults = parseSarifResultsSca(result, scanResults) + } else if result.Type == commonParams.ContainersType && wrappers.IsContainersEnabled { + scanResults = parseSarifResultsContainers(result, scanResults) + } else if strings.HasPrefix(result.Type, commonParams.SscsType) { + scanResults = parseSarifResultsSscs(result, scanResults) + } + + if len(scanResults) > 0 { + return scanResults + } + return nil +} + +func parseSarifResultsContainers(result *wrappers.ScanResult, scanResults []wrappers.SarifScanResult) []wrappers.SarifScanResult { + var scanResult = initSarifResult(result) + var scanLocation wrappers.SarifLocation + + scanLocation.PhysicalLocation.ArtifactLocation.URI = result.ScanResultData.ImageFilePath + scanLocation.PhysicalLocation.Region = &wrappers.SarifRegion{} + scanLocation.PhysicalLocation.Region.StartLine = 1 + scanLocation.PhysicalLocation.Region.StartColumn = 1 + scanLocation.PhysicalLocation.Region.EndColumn = 2 + scanResult.Locations = append(scanResult.Locations, scanLocation) + + scanResults = append(scanResults, scanResult) + return scanResults +} + +func parseSarifResultsSca(result *wrappers.ScanResult, scanResults []wrappers.SarifScanResult) []wrappers.SarifScanResult { + if result == nil || result.ScanResultData.ScaPackageCollection == nil || result.ScanResultData.ScaPackageCollection.Locations == nil { + return scanResults + } + for _, location := range result.ScanResultData.ScaPackageCollection.Locations { + var scanResult = initSarifResult(result) + + var scanLocation wrappers.SarifLocation + scanLocation.PhysicalLocation.ArtifactLocation.URI = *location + scanLocation.PhysicalLocation.Region = &wrappers.SarifRegion{} + scanLocation.PhysicalLocation.Region.StartLine = 1 + scanLocation.PhysicalLocation.Region.StartColumn = 1 + scanLocation.PhysicalLocation.Region.EndColumn = 2 + scanResult.Locations = append(scanResult.Locations, scanLocation) + + scanResults = append(scanResults, scanResult) + } + return scanResults +} + +func parseSarifResultKics(result *wrappers.ScanResult, scanResults []wrappers.SarifScanResult) []wrappers.SarifScanResult { + var scanResult = initSarifResult(result) + var scanLocation wrappers.SarifLocation + + scanLocation.PhysicalLocation.ArtifactLocation.URI = strings.Replace( + result.ScanResultData.Filename, + "/", + "", + 1, + ) + scanLocation.PhysicalLocation.Region = &wrappers.SarifRegion{} + scanLocation.PhysicalLocation.Region.StartLine = result.ScanResultData.Line + scanLocation.PhysicalLocation.Region.StartColumn = 1 + scanLocation.PhysicalLocation.Region.EndColumn = 2 + scanResult.Locations = append(scanResult.Locations, scanLocation) + + scanResults = append(scanResults, scanResult) + return scanResults +} + +func parseSarifResultSast(result *wrappers.ScanResult, scanResults []wrappers.SarifScanResult) []wrappers.SarifScanResult { + if result == nil || result.ScanResultData.Nodes == nil { + return scanResults + } + var scanResult = initSarifResult(result) + + var allLocations []wrappers.SarifLocation + for _, node := range result.ScanResultData.Nodes { + var scanLocation wrappers.SarifLocation + if len(node.FileName) >= sarifNodeFileLength { + scanLocation.PhysicalLocation.ArtifactLocation.URI = node.FileName[1:] + if node.Line <= 0 { + continue + } + scanLocation.PhysicalLocation.Region = &wrappers.SarifRegion{} + scanLocation.PhysicalLocation.Region.StartLine = node.Line + column := node.Column + length := node.Length + scanLocation.PhysicalLocation.Region.StartColumn = column + scanLocation.PhysicalLocation.Region.EndColumn = column + length + + allLocations = append(allLocations, scanLocation) + } + } + + if len(allLocations) > 0 { + var threadFlowLocations []wrappers.SarifThreadFlowLocation + for _, loc := range allLocations { + threadFlowLocations = append(threadFlowLocations, wrappers.SarifThreadFlowLocation{Location: loc}) + } + scanResult.CodeFlows = []wrappers.SarifCodeFlow{ + { + ThreadFlows: []wrappers.SarifThreadFlow{ + { + Locations: threadFlowLocations, + }, + }, + }, + } + } + + scanResults = append(scanResults, scanResult) + return scanResults +} + +func parseSarifResultsSscs(result *wrappers.ScanResult, scanResults []wrappers.SarifScanResult) []wrappers.SarifScanResult { + var scanResult = initSarifResult(result) + scanResult.Message.Text = result.Description + + var scanLocation wrappers.SarifLocation + + trimOsSeparatorFromFileName(result) + if result.Type == commonParams.SCSScorecardType && result.ScanResultData.Filename == noFileForScorecardResultString { + scanLocation.PhysicalLocation.ArtifactLocation.URI = artifactLocationURIString + scanLocation.PhysicalLocation.ArtifactLocation.Description = &wrappers.SarifMessage{} + scanLocation.PhysicalLocation.ArtifactLocation.Description.Text = result.ScanResultData.Filename + } else { + scanLocation.PhysicalLocation.ArtifactLocation.URI = result.ScanResultData.Filename + } + + scanLocation.PhysicalLocation.Region = &wrappers.SarifRegion{} + scanLocation.PhysicalLocation.Region.StartLine = result.ScanResultData.Line + scanLocation.PhysicalLocation.Region.StartColumn = 1 + scanLocation.PhysicalLocation.Region.EndColumn = 2 + if result.ScanResultData.Snippet != "" { + scanLocation.PhysicalLocation.Region.Snippet = &wrappers.SarifSnippet{} + scanLocation.PhysicalLocation.Region.Snippet.Text = result.ScanResultData.Snippet + } + + scanResult.Locations = append(scanResult.Locations, scanLocation) + + var properties wrappers.SarifResultProperties + properties.Severity = result.Severity + properties.Validity = result.ScanResultData.Validity + properties.IsInSource = result.ScanResultData.IsInSource + properties.CommitURL = result.ScanResultData.CommitURL + scanResult.Properties = &properties + + scanResults = append(scanResults, scanResult) + return scanResults +} + +func convertNotAvailableNumberToZero(summary *wrappers.ResultSummary) { + if summary.KicsIssues == notAvailableNumber { + summary.KicsIssues = 0 + } else if summary.SastIssues == notAvailableNumber { + summary.SastIssues = 0 + } else if summary.ScaIssues == notAvailableNumber { + summary.ScaIssues = 0 + } else if wrappers.IsContainersEnabled && *summary.ContainersIssues == notAvailableNumber { + *summary.ContainersIssues = 0 + } +} + +func buildAuxiliaryScaMaps(resultsModel *wrappers.ScanResultsCollection, scaPackageModel *[]wrappers.ScaPackageCollection, + scaTypeModel *[]wrappers.ScaTypeCollection) (locationsByID map[string][]*string, typesByCVE map[string]wrappers.ScaTypeCollection) { + locationsByID = make(map[string][]*string) + typesByCVE = make(map[string]wrappers.ScaTypeCollection) + // Create map to be used to populate locations for each package path + for _, result := range resultsModel.Results { + if result.Type == commonParams.ScaType { + for _, packages := range *scaPackageModel { + currentPackage := packages + locationsByID[packages.ID] = currentPackage.Locations + } + for _, types := range *scaTypeModel { + identifier := fmt.Sprintf("%s:%s", types.ID, types.PackageID) + typesByCVE[identifier] = types + } + } + } + return locationsByID, typesByCVE +} + +func buildScaType(typesByCVE map[string]wrappers.ScaTypeCollection, result *wrappers.ScanResult) string { + identifier := buildVulnerabilityIdentifier(result) + types, ok := typesByCVE[identifier] + if ok && types.Type == "SupplyChain" { + return "Supply Chain" + } + return "Vulnerability" +} + +func buildScaState(typesByCVE map[string]wrappers.ScaTypeCollection, result *wrappers.ScanResult) string { + identifier := buildVulnerabilityIdentifier(result) + types, ok := typesByCVE[identifier] + if ok && types.IsIgnored { + return notExploitable + } + return result.State +} + +func buildVulnerabilityIdentifier(result *wrappers.ScanResult) string { + return fmt.Sprintf("%s:%s", result.ID, result.ScanResultData.PackageIdentifier) +} + +func addPackageInformation( + resultsModel *wrappers.ScanResultsCollection, + scaPackageModel *[]wrappers.ScaPackageCollection, + scaTypeModel *[]wrappers.ScaTypeCollection, +) *wrappers.ScanResultsCollection { + locationsByID, typesByCVE := buildAuxiliaryScaMaps(resultsModel, scaPackageModel, scaTypeModel) + scaPackageMap := buildScaPackageMap(*scaPackageModel) + + for _, result := range resultsModel.Results { + if result.Type == commonParams.ScaType { + processResult(result, locationsByID, typesByCVE, scaPackageMap) + } + } + + return resultsModel +} + +func processResult( + result *wrappers.ScanResult, + locationsByID map[string][]*string, + typesByCVE map[string]wrappers.ScaTypeCollection, + scaPackageMap map[string]wrappers.ScaPackageCollection, // Updated parameter +) { + const precision = 1 + + currentID := result.ScanResultData.PackageIdentifier + result.VulnerabilityDetails.CvssScore = util.RoundFloat(result.VulnerabilityDetails.CvssScore, precision) + result.ScaType = buildScaType(typesByCVE, result) + result.State = buildScaState(typesByCVE, result) + + updatePackages(result, scaPackageMap, locationsByID, currentID) +} + +func updatePackages( + result *wrappers.ScanResult, + scaPackageMap map[string]wrappers.ScaPackageCollection, + locationsByID map[string][]*string, + currentID string, +) { + packages, found := scaPackageMap[currentID] + if !found { + return + } + + updateDependencyPaths(packages.DependencyPathArray, locationsByID) + if !packages.SupportsQuickFix { + packages.SupportsQuickFix = hasQuickFix(packages.DependencyPathArray) + } + + if packages.IsDirectDependency { + packages.TypeOfDependency = directDependencyType + } else { + packages.TypeOfDependency = indirectDependencyType + } + + packages.FixLink = buildFixLink(result) + result.ScanResultData.ScaPackageCollection = &packages +} + +func hasQuickFix(dependencyPaths [][]wrappers.DependencyPath) bool { + for i := range dependencyPaths { + head := &dependencyPaths[i][0] + if head.SupportsQuickFix { + return true + } + } + return false +} + +func buildScaPackageMap(scaPackageModel []wrappers.ScaPackageCollection) map[string]wrappers.ScaPackageCollection { + scaPackageMap := make(map[string]wrappers.ScaPackageCollection) + for i := range scaPackageModel { + scaPackageMap[scaPackageModel[i].ID] = scaPackageModel[i] + } + return scaPackageMap +} + +func updateDependencyPaths(dependencyPaths [][]wrappers.DependencyPath, locationsByID map[string][]*string) { + for i := range dependencyPaths { + head := &dependencyPaths[i][0] + head.Locations = locationsByID[head.ID] + head.SupportsQuickFix = len(dependencyPaths[i]) == 1 + + for _, location := range locationsByID[head.ID] { + head.SupportsQuickFix = head.SupportsQuickFix && util.IsPackageFileSupported(*location) + } + } +} + +func buildFixLink(result *wrappers.ScanResult) string { + if result.ID != "" { + return fmt.Sprint(fixLinkPrefix, result.ID) + } + return "" +} + +func filterViolatedRules(policyModel wrappers.PolicyResponseModel) *wrappers.PolicyResponseModel { + i := 0 + for _, policy := range policyModel.Policies { + if len(policy.RulesViolated) > 0 { + policyModel.Policies[i] = policy + i++ + } + } + policyModel.Policies = policyModel.Policies[:i] + return &policyModel +} + +func trimOsSeparatorFromFileName(result *wrappers.ScanResult) { + if result.ScanResultData.Filename != "" { + result.ScanResultData.Filename = strings.TrimPrefix(result.ScanResultData.Filename, "/") + result.ScanResultData.Filename = strings.TrimPrefix(result.ScanResultData.Filename, "\\") + } +} + +type ScannerResponse struct { + ScanID string `json:"ScanID,omitempty"` + Name string `json:"Name,omitempty"` + Status string `json:"Status,omitempty"` + Details string `json:"Details,omitempty"` + ErrorCode string `json:"ErrorCode,omitempty"` +} + +func parseURI(summaryBaseURI string) (hostName string) { + parsedURL, err := url.Parse(summaryBaseURI) + if err != nil { + return "" + } + hostName = fmt.Sprintf("%s://%s", parsedURL.Scheme, parsedURL.Host) + + return hostName +} + +func printWarningIfIgnorePolicyOmiited() { + fmt.Printf("\n Warning: The --ignore-policy flag was not implemented because you don’t have the required permission.\n Only users with 'override-policy-management' permission can use this flag. \n\n") +} + +func getFilterResultsForAPISecScanner(risksOverviewWrapper wrappers.RisksOverviewWrapper, scanID string, resultsParams map[string]string) (aPISecSeveritySummary *wrappers.APISecFilteredResult, err error) { + var apiSecRiskEntriesResult wrappers.APISecRiskEntriesResult + var errorModel *wrappers.WebError + + apiSecRiskEntriesResult, errorModel, err = risksOverviewWrapper.GetFilterResultForAPISecByScanID(scanID, resultsParams) + if err != nil { + return nil, errors.Wrapf(err, "%s", failedListingResults) + } + if errorModel != nil { + return nil, errors.Errorf("%s: CODE: %d, %s", failedListingResults, errorModel.Code, errorModel.Message) + } + if len(apiSecRiskEntriesResult.Entries) > 0 { + entries := apiSecRiskEntriesResult.Entries + severityCount := make(map[string]int) + originCount := make(map[string]int) + totalRecords := 0 + for i := range entries { + entry := &entries[i] + if !isExploitable(entry.State) { + continue + } + sev := strings.ToLower(entry.Severity) + severityCount[sev]++ + orig := strings.ToLower(entry.Origin) + originCount[orig]++ + totalRecords++ + } + var riskDistribution []wrappers.RiskDistributionEntry + if originCount["code"] > 0 { + riskDistribution = append(riskDistribution, wrappers.RiskDistributionEntry{Origin: "code", Total: originCount["code"]}) + } + if originCount["documentation"] > 0 { + riskDistribution = append(riskDistribution, wrappers.RiskDistributionEntry{Origin: "documentation", Total: originCount["documentation"]}) + } + return &wrappers.APISecFilteredResult{ + SeverityCount: severityCount, + RiskDistribution: riskDistribution, + TotalRisksCount: totalRecords, + }, nil + } + return nil, nil +} diff --git a/internal/commands/scan.go b/internal/commands/scan.go index 777632c6a..1ea696e8f 100644 --- a/internal/commands/scan.go +++ b/internal/commands/scan.go @@ -791,8 +791,8 @@ func scanCreateSubCommand( commonParams.Branch, commonParams.BranchFlagUsage, ) createScanCmd.PersistentFlags().String(commonParams.SastFilterFlag, "", commonParams.SastFilterUsage) - createScanCmd.PersistentFlags().String(commonParams.IacsFilterFlag, "", commonParams.IacsFilterUsage) - createScanCmd.PersistentFlags().String(commonParams.KicsFilterFlag, "", commonParams.KicsFilterUsage) + createScanCmd.PersistentFlags().StringSlice(commonParams.IacsFilterFlag, []string{}, commonParams.IacsFilterUsage) + createScanCmd.PersistentFlags().StringSlice(commonParams.KicsFilterFlag, []string{}, commonParams.KicsFilterUsage) err = createScanCmd.PersistentFlags().MarkDeprecated(commonParams.KicsFilterFlag, "please use the replacement flag --iac-security-filter") if err != nil { diff --git a/internal/params/filters.go b/internal/params/filters.go index 7ed55271d..fae79903f 100644 --- a/internal/params/filters.go +++ b/internal/params/filters.go @@ -150,6 +150,47 @@ var BaseIncludeFilters = []string{ "*.html", "*.xhtml", "*.vm", + "*.ac", + "*.am", + "*.app", + "*.asax", + "*.cmake", + "*.dspf", + "*.env", + "*.evt", + "*.ftl", + "*.gsp", + "*.gtl", + "*.handlebars", + "*.ini", + "*.jade", + "*.jsf", + "*.latex", + "*.lock", + "*.master", + "*.mf", + "*.mustache", + "*.pc", + "*.ph", + "*.phk", + "*.pro", + "*.rpgle", + "*.rpg", + "*.rpg38", + "*.sqlrpg", + "*.sqlrpgle", + "*.tex", + "*.toml", + "*.tsql", + "*.txt", + "*.vue", + "*.xsaccess", + "*.xsapp", + "*.pug", + "*.lua", + "*.ec", + "*.csv", + "*.apxc", } var BaseExcludeFilters = []string{ diff --git a/internal/services/applications.go b/internal/services/applications.go index 19880f529..10292c32f 100644 --- a/internal/services/applications.go +++ b/internal/services/applications.go @@ -79,12 +79,20 @@ func findApplicationAndUpdate(applicationName string, applicationsWrapper wrappe return errors.Errorf("%s: %s", errorConstants.ApplicationNotFound, applicationName) } + // Check if project is already associated (prevents unnecessary API calls for both when flag enabled/disabled) + for _, id := range applicationResp.ProjectIds { + if id == projectID { + logger.PrintfIfVerbose("Project is already associated with the application. Skipping association") + return nil + } + } + isEnabled, err := checkDirectAssociationEnabled(featureFlagsWrapper, tenantWrapper) if err != nil { return errors.Wrap(err, "error while checking if direct association is enabled") } if isEnabled { - err = associateProjectToApplication(applicationResp.ID, projectID, applicationResp.ProjectIds, applicationsWrapper) + err = associateProjectToApplication(applicationResp.ID, projectID, applicationsWrapper) if err != nil { return err } @@ -139,13 +147,7 @@ func updateApplication(applicationModel *wrappers.ApplicationConfiguration, appl return handleApplicationUpdateResponse(errorModel, err) } -func associateProjectToApplication(applicationID, projectID string, associatedProjectIds []string, applicationsWrapper wrappers.ApplicationsWrapper) error { - for _, id := range associatedProjectIds { - if id == projectID { - logger.PrintfIfVerbose("Project is already associated with the application. Skipping association") - return nil - } - } +func associateProjectToApplication(applicationID, projectID string, applicationsWrapper wrappers.ApplicationsWrapper) error { associateProjectsModel := &wrappers.AssociateProjectModel{ ProjectIds: []string{projectID}, } diff --git a/internal/services/applications_test.go b/internal/services/applications_test.go index ca1398c3e..0af427a97 100644 --- a/internal/services/applications_test.go +++ b/internal/services/applications_test.go @@ -11,6 +11,11 @@ import ( "gotest.tools/assert" ) +const ( + mockApplicationName = "MOCK" + testProjectName = "test-project" +) + func Test_createApplicationIds(t *testing.T) { type args struct { applicationID []string @@ -59,7 +64,7 @@ func Test_ProjectAssociation_ToApplicationDirectly(t *testing.T) { for _, test := range tests { tt := test t.Run(tt.description, func(t *testing.T) { - err := associateProjectToApplication(tt.applicationName, tt.projectName, []string{}, applicationWrapper) + err := associateProjectToApplication(tt.applicationName, tt.projectName, applicationWrapper) assert.Assert(t, strings.Contains(err.Error(), tt.error), err.Error()) }) } @@ -91,9 +96,8 @@ func Test_ProjectAssociation_ToApplicationWithoutDirectAssociation(t *testing.T) func Test_AssociateProjectToApplication_ProjectAlreadyAssociated(t *testing.T) { projectID := "project-123" - associatedProjectIds := []string{"project-123", "project-456"} applicationName := "app-1" applicationWrapper := &mock.ApplicationsMockWrapper{} - err := associateProjectToApplication(applicationName, projectID, associatedProjectIds, applicationWrapper) + err := associateProjectToApplication(applicationName, projectID, applicationWrapper) assert.NilError(t, err) } diff --git a/internal/services/projects.go b/internal/services/projects.go index 4d65e1b68..875568746 100644 --- a/internal/services/projects.go +++ b/internal/services/projects.go @@ -219,7 +219,6 @@ func updateProject(project *wrappers.ProjectResponseModel, projModel.Name = projModelResp.Name projModel.Groups = projModelResp.Groups projModel.Tags = projModelResp.Tags - projModel.ApplicationIds = projModelResp.ApplicationIds if projectTags != "" { logger.PrintIfVerbose("Updating project tags") projModel.Tags = createTagMap(projectTags) diff --git a/internal/wrappers/mock/application-mock.go b/internal/wrappers/mock/application-mock.go index 9bbdd28ef..8a0271492 100644 --- a/internal/wrappers/mock/application-mock.go +++ b/internal/wrappers/mock/application-mock.go @@ -31,12 +31,14 @@ func (a ApplicationsMockWrapper) Get(params map[string]string) (*wrappers.Applic Name: "MOCK", Description: "This is a mock application", Criticality: 2, - ProjectIds: []string{"ProjectID1", "ProjectID2", "MOCK", "test_project", "ID-new-project-name", "ID-newProject"}, + ProjectIds: []string{"ProjectID1", "ProjectID2", "test_project", "ID-new-project-name"}, CreatedAt: time.Now(), } if params["name"] == ExistingApplication { mockApplication.Name = ExistingApplication mockApplication.ID = "ID-newProject" + // For ExistingApplication, include "ID-newProject" for polling tests + mockApplication.ProjectIds = []string{"ProjectID1", "ProjectID2", "test_project", "ID-new-project-name", "ID-newProject"} return &wrappers.ApplicationsResponseModel{ TotalCount: 1, Applications: []wrappers.Application{mockApplication}, diff --git a/internal/wrappers/results-sarif.go b/internal/wrappers/results-sarif.go index 93e4ff3b4..e73786532 100644 --- a/internal/wrappers/results-sarif.go +++ b/internal/wrappers/results-sarif.go @@ -59,9 +59,22 @@ type SarifScanResult struct { Message SarifMessage `json:"message"` PartialFingerprints *SarifResultFingerprint `json:"partialFingerprints,omitempty"` Locations []SarifLocation `json:"locations,omitempty"` + CodeFlows []SarifCodeFlow `json:"codeFlows,omitempty"` Properties *SarifResultProperties `json:"properties,omitempty"` } +type SarifCodeFlow struct { + ThreadFlows []SarifThreadFlow `json:"threadFlows"` +} + +type SarifThreadFlow struct { + Locations []SarifThreadFlowLocation `json:"locations"` +} + +type SarifThreadFlowLocation struct { + Location SarifLocation `json:"location"` +} + type SarifLocation struct { PhysicalLocation SarifPhysicalLocation `json:"physicalLocation"` } From 820681be4030febfaa20cb704f2e9625c0b44d39 Mon Sep 17 00:00:00 2001 From: atishj99 <141334503+cx-atish-jadhav@users.noreply.github.com> Date: Wed, 27 May 2026 12:08:36 +0530 Subject: [PATCH 16/27] Fix SCA vulnerabilities: update dependencies to patched versions - Upgrade distribution/v3 to v3.0.1-0.20260120145532-40594bd98e6d (security patch) - Upgrade go-jose/v3 to v3.0.5 (CWE-345: Insufficient Verification) - Upgrade anchore/stereoscope to v0.2.0 - Upgrade google.golang.org/grpc to v1.80.0 - Upgrade gonum to v0.17.0 - Upgrade containerd/v2 to v2.3.1 - Upgrade go-git/go-git/v5 to v5.18.1-0.20260420130857-e5bbc088b774 (CVE-2026-45022) - Upgrade go-git/go-billy/v5 to v5.8.1-0.20260506061021-07f2a0bf50e4 (CVE-2026-44973) - Upgrade Go version to 1.26.3 Co-Authored-By: Claude Haiku 4.5 --- go.mod | 68 +++++++++++++++++++++--------------------- go.sum | 94 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++-- 2 files changed, 127 insertions(+), 35 deletions(-) diff --git a/go.mod b/go.mod index 5a93ebf35..2ac014f7f 100644 --- a/go.mod +++ b/go.mod @@ -1,6 +1,6 @@ module github.com/checkmarx/ast-cli -go 1.25.9 +go 1.26.3 require ( github.com/Checkmarx/containers-resolver v1.0.34 @@ -30,8 +30,8 @@ require ( golang.org/x/crypto v0.50.0 golang.org/x/sync v0.20.0 golang.org/x/text v0.36.0 - google.golang.org/grpc v1.79.3 - google.golang.org/protobuf v1.36.11 + google.golang.org/grpc v1.80.0 + google.golang.org/protobuf v1.36.12-0.20260120151049-f2248ac996af gopkg.in/yaml.v3 v3.0.1 gotest.tools v2.2.0+incompatible ) @@ -46,7 +46,7 @@ require ( cloud.google.com/go/monitoring v1.24.3 // indirect cloud.google.com/go/storage v1.61.3 // indirect cyphar.com/go-pathrs v0.2.1 // indirect - github.com/GoogleCloudPlatform/opentelemetry-operations-go/detectors/gcp v1.30.0 // indirect + github.com/GoogleCloudPlatform/opentelemetry-operations-go/detectors/gcp v1.31.0 // indirect github.com/GoogleCloudPlatform/opentelemetry-operations-go/exporter/metric v0.55.0 // indirect github.com/GoogleCloudPlatform/opentelemetry-operations-go/internal/resourcemapping v0.55.0 // indirect github.com/OneOfOne/xxhash v1.2.8 // indirect @@ -82,11 +82,13 @@ require ( github.com/clipperhouse/displaywidth v0.10.0 // indirect github.com/clipperhouse/uax29/v2 v2.6.0 // indirect github.com/cncf/xds/go v0.0.0-20251210132809-ee656c7534f5 // indirect - github.com/containerd/containerd/v2 v2.2.3 // indirect - github.com/containerd/plugin v1.0.0 // indirect + github.com/containerd/containerd/v2 v2.3.1 // indirect + github.com/containerd/plugin v1.1.0 // indirect github.com/diskfs/go-diskfs v1.7.0 // indirect + github.com/distribution/distribution/v3 v3.0.1-0.20260120145532-40594bd98e6d // indirect github.com/envoyproxy/go-control-plane/envoy v1.36.0 // indirect github.com/envoyproxy/protoc-gen-validate v1.3.0 // indirect + github.com/go-jose/go-jose/v3 v3.0.5 // indirect github.com/go-jose/go-jose/v4 v4.1.4 // indirect github.com/goccy/go-yaml v1.19.2 // indirect github.com/gohugoio/hashstructure v0.6.0 // indirect @@ -116,14 +118,14 @@ require ( github.com/sorairolake/lzip-go v0.3.8 // indirect github.com/spiffe/go-spiffe/v2 v2.6.0 // indirect go.opentelemetry.io/contrib/detectors/gcp v1.39.0 // indirect - go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.63.0 // indirect + go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.68.0 // indirect go.opentelemetry.io/otel/sdk v1.43.0 // indirect go.opentelemetry.io/otel/sdk/metric v1.43.0 // indirect go4.org v0.0.0-20230225012048-214862532bf5 // indirect - gonum.org/v1/gonum v0.16.0 // indirect + gonum.org/v1/gonum v0.17.0 // indirect google.golang.org/api v0.271.0 // indirect - google.golang.org/genproto/googleapis/api v0.0.0-20260203192932-546029d2fa20 // indirect - sigs.k8s.io/structured-merge-diff/v6 v6.3.0 // indirect + google.golang.org/genproto/googleapis/api v0.0.0-20260401024825-9d38bb4040a9 // indirect + sigs.k8s.io/structured-merge-diff/v6 v6.3.2 // indirect ) require ( @@ -139,8 +141,8 @@ require ( github.com/Masterminds/semver/v3 v3.4.0 // indirect github.com/Masterminds/sprig/v3 v3.3.0 // indirect github.com/Masterminds/squirrel v1.5.4 // indirect - github.com/Microsoft/go-winio v0.6.2 // indirect - github.com/Microsoft/hcsshim v0.14.1 // indirect + github.com/Microsoft/go-winio v0.6.3-0.20251027160822-ad3df93bed29 // indirect + github.com/Microsoft/hcsshim v0.15.0-rc.1 // indirect github.com/ProtonMail/go-crypto v1.4.0 // indirect github.com/acobaugh/osrelease v0.1.0 // indirect github.com/adrg/xdg v0.5.3 // indirect @@ -154,7 +156,7 @@ require ( github.com/anchore/go-struct-converter v0.1.0 // indirect github.com/anchore/go-version v1.2.2-0.20200701162849-18adb9c92b9b // indirect github.com/anchore/packageurl-go v0.2.0 // indirect - github.com/anchore/stereoscope v0.1.23 // indirect + github.com/anchore/stereoscope v0.2.0 // indirect github.com/anchore/syft v1.43.0 // indirect github.com/andybalholm/brotli v1.2.0 // indirect github.com/apparentlymart/go-textseg/v15 v15.0.0 // indirect @@ -174,23 +176,23 @@ require ( github.com/charmbracelet/x/cellbuf v0.0.15 // indirect github.com/charmbracelet/x/term v0.2.2 // indirect github.com/cloudflare/circl v1.6.3 // indirect - github.com/containerd/cgroups/v3 v3.1.2 // indirect + github.com/containerd/cgroups/v3 v3.1.3 // indirect github.com/containerd/containerd v1.7.30 // indirect - github.com/containerd/containerd/api v1.10.0 // indirect - github.com/containerd/continuity v0.4.5 // indirect + github.com/containerd/containerd/api v1.11.1 // indirect + github.com/containerd/continuity v0.5.0 // indirect github.com/containerd/errdefs v1.0.0 // indirect github.com/containerd/errdefs/pkg v0.3.0 // indirect github.com/containerd/fifo v1.1.0 // indirect github.com/containerd/log v0.1.0 // indirect github.com/containerd/platforms v1.0.0-rc.4 // indirect github.com/containerd/stargz-snapshotter/estargz v0.18.2 // indirect - github.com/containerd/ttrpc v1.2.7 // indirect + github.com/containerd/ttrpc v1.2.8 // indirect github.com/containerd/typeurl/v2 v2.2.3 // indirect github.com/cyphar/filepath-securejoin v0.6.1 // indirect github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect github.com/deitch/magic v0.0.0-20240306090643-c67ab88f10cb // indirect github.com/distribution/reference v0.6.0 // indirect - github.com/docker/cli v29.4.0+incompatible // indirect + github.com/docker/cli v29.4.3+incompatible // indirect github.com/docker/docker-credential-helpers v0.9.5 // indirect github.com/docker/go-connections v0.6.0 // indirect github.com/docker/go-units v0.5.0 // indirect @@ -213,8 +215,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.8.0 // indirect - github.com/go-git/go-git/v5 v5.18.0 // indirect + github.com/go-git/go-billy/v5 v5.8.1-0.20260506061021-07f2a0bf50e4 // indirect + github.com/go-git/go-git/v5 v5.18.1-0.20260420130857-e5bbc088b774 // 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 @@ -294,7 +296,7 @@ require ( github.com/opencontainers/selinux v1.13.1 // indirect github.com/pborman/indent v1.2.1 // indirect github.com/pelletier/go-toml v1.9.5 // indirect - github.com/pelletier/go-toml/v2 v2.2.4 // indirect + github.com/pelletier/go-toml/v2 v2.3.1 // indirect github.com/peterbourgon/diskv v2.0.1+incompatible // indirect github.com/pierrec/lz4/v4 v4.1.22 // indirect github.com/pjbgf/sha1cd v0.3.2 // indirect @@ -345,14 +347,14 @@ require ( github.com/zricethezav/gitleaks/v8 v8.18.2 // indirect go.opencensus.io v0.24.0 // indirect go.opentelemetry.io/auto/sdk v1.2.1 // indirect - go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.61.0 // indirect + go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.68.0 // indirect go.opentelemetry.io/otel v1.43.0 // indirect go.opentelemetry.io/otel/metric v1.43.0 // indirect go.opentelemetry.io/otel/trace v1.43.0 // indirect - go.uber.org/mock v0.5.2 // indirect + go.uber.org/mock v0.6.0 // indirect go.yaml.in/yaml/v2 v2.4.3 // indirect go.yaml.in/yaml/v3 v3.0.4 // indirect - golang.org/x/exp v0.0.0-20251023183803-a4bb9ffd2546 // indirect + golang.org/x/exp v0.0.0-20260410095643-746e56fc9e2f // indirect golang.org/x/mod v0.35.0 // indirect golang.org/x/net v0.53.0 // indirect golang.org/x/oauth2 v0.36.0 // indirect @@ -362,23 +364,23 @@ require ( golang.org/x/tools v0.44.0 // indirect golang.org/x/xerrors v0.0.0-20240903120638-7835f813f4da // indirect google.golang.org/genproto v0.0.0-20260128011058-8636f8732409 // indirect - google.golang.org/genproto/googleapis/rpc v0.0.0-20260226221140-a57be14db171 // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20260406210006-6f92a3bedf2d // indirect gopkg.in/evanphx/json-patch.v4 v4.13.0 // indirect gopkg.in/inf.v0 v0.9.1 // indirect gopkg.in/warnings.v0 v0.1.2 // indirect gopkg.in/yaml.v2 v2.4.0 // indirect helm.sh/helm/v3 v3.20.2 // indirect - k8s.io/api v0.35.1 // indirect + k8s.io/api v0.36.0 // indirect k8s.io/apiextensions-apiserver v0.35.1 // indirect - k8s.io/apimachinery v0.35.1 // indirect + k8s.io/apimachinery v0.36.0 // indirect k8s.io/apiserver v0.35.1 // indirect k8s.io/cli-runtime v0.35.1 // indirect - k8s.io/client-go v0.35.1 // indirect - k8s.io/component-base v0.35.1 // indirect - k8s.io/klog/v2 v2.130.1 // indirect - k8s.io/kube-openapi v0.0.0-20250910181357-589584f1c912 // indirect + k8s.io/client-go v0.36.0 // indirect + k8s.io/component-base v0.36.0 // indirect + k8s.io/klog/v2 v2.140.0 // indirect + k8s.io/kube-openapi v0.0.0-20260319004828-5883c5ee87b9 // indirect k8s.io/kubectl v0.35.1 // indirect - k8s.io/utils v0.0.0-20251002143259-bc988d571ff4 // indirect + k8s.io/utils v0.0.0-20260319190234-28399d86e0b5 // indirect modernc.org/libc v1.70.0 // indirect modernc.org/mathutil v1.7.1 // indirect modernc.org/memory v1.11.0 // indirect @@ -391,6 +393,6 @@ require ( sigs.k8s.io/yaml v1.6.0 // indirect ) -replace github.com/containerd/containerd => github.com/containerd/containerd v1.7.31 +replace github.com/containerd/containerd => github.com/containerd/containerd v1.7.32 replace github.com/opencontainers/selinux => github.com/opencontainers/selinux v1.13.0 diff --git a/go.sum b/go.sum index 705cd99ef..d46acad4d 100644 --- a/go.sum +++ b/go.sum @@ -110,6 +110,8 @@ github.com/DataDog/zstd v1.5.6 h1:LbEglqepa/ipmmQJUDnSsfvA8e8IStVcGaFWDuxvGOY= github.com/DataDog/zstd v1.5.6/go.mod h1:g4AWEaM3yOg3HYfnJ3YIawPnVdXJh9QME85blwSAmyw= github.com/GoogleCloudPlatform/opentelemetry-operations-go/detectors/gcp v1.30.0 h1:sBEjpZlNHzK1voKq9695PJSX2o5NEXl7/OL3coiIY0c= github.com/GoogleCloudPlatform/opentelemetry-operations-go/detectors/gcp v1.30.0/go.mod h1:P4WPRUkOhJC13W//jWpyfJNDAIpvRbAUIYLX/4jtlE0= +github.com/GoogleCloudPlatform/opentelemetry-operations-go/detectors/gcp v1.31.0 h1:DHa2U07rk8syqvCge0QIGMCE1WxGj9njT44GH7zNJLQ= +github.com/GoogleCloudPlatform/opentelemetry-operations-go/detectors/gcp v1.31.0/go.mod h1:P4WPRUkOhJC13W//jWpyfJNDAIpvRbAUIYLX/4jtlE0= github.com/GoogleCloudPlatform/opentelemetry-operations-go/exporter/metric v0.55.0 h1:UnDZ/zFfG1JhH/DqxIZYU/1CUAlTUScoXD/LcM2Ykk8= github.com/GoogleCloudPlatform/opentelemetry-operations-go/exporter/metric v0.55.0/go.mod h1:IA1C1U7jO/ENqm/vhi7V9YYpBsp+IMyqNrEN94N7tVc= github.com/GoogleCloudPlatform/opentelemetry-operations-go/internal/cloudmock v0.55.0 h1:7t/qx5Ost0s0wbA/VDrByOooURhp+ikYwv20i9Y07TQ= @@ -129,8 +131,12 @@ github.com/Masterminds/squirrel v1.5.4/go.mod h1:NNaOrjSoIDfDA40n7sr2tPNZRfjzjA4 github.com/Microsoft/go-winio v0.5.2/go.mod h1:WpS1mjBmmwHBEWmogvA2mj8546UReBk4v8QkMxJ6pZY= github.com/Microsoft/go-winio v0.6.2 h1:F2VQgta7ecxGYO8k3ZZz3RS8fVIXVxONVUPlNERoyfY= github.com/Microsoft/go-winio v0.6.2/go.mod h1:yd8OoFMLzJbo9gZq8j5qaps8bJ9aShtEA8Ipt1oGCvU= +github.com/Microsoft/go-winio v0.6.3-0.20251027160822-ad3df93bed29 h1:0kQAzHq8vLs7Pptv+7TxjdETLf/nIqJpIB4oC6Ba4vY= +github.com/Microsoft/go-winio v0.6.3-0.20251027160822-ad3df93bed29/go.mod h1:ZWa7ssZJT30CCDGJ7fk/2SBTq9BIQrrVjrcss0UW2s0= github.com/Microsoft/hcsshim v0.14.1 h1:CMuB3fqQVfPdhyXhUqYdUmPUIOhJkmghCx3dJet8Cqs= github.com/Microsoft/hcsshim v0.14.1/go.mod h1:VnzvPLyWUhxiPVsJ31P6XadxCcTogTguBFDy/1GR/OM= +github.com/Microsoft/hcsshim v0.15.0-rc.1 h1:FbbwtQmiD+BVHynGkx5S65JkLyhkEiiTP8nrpmg2SZw= +github.com/Microsoft/hcsshim v0.15.0-rc.1/go.mod h1:HWvvUPIy9HF6LotILj1G4VyS065rcLQ6tqj6tMUdOfI= github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU= github.com/OneOfOne/xxhash v1.2.8 h1:31czK/TI9sNkxIKfaUfGlU47BAxQ0ztGgd9vPyqimf8= github.com/OneOfOne/xxhash v1.2.8/go.mod h1:eZbhyaAYD41SGSSsnmcpxVoRiQ/MPUTjUdIIOT9Um7Q= @@ -176,6 +182,8 @@ github.com/anchore/packageurl-go v0.2.0 h1:CkrM4RMUwrEGAiE1OVlxaZNzWj0TuHRey7o4T github.com/anchore/packageurl-go v0.2.0/go.mod h1:2JCgOQMIsqZ7TmliXG4PnUthPJAKE3mWQbsW2XHjAOE= github.com/anchore/stereoscope v0.1.23 h1:q9i3CtbicTuSlcCnA+5pfoT9WDCEoSqvXDfHMH1hyWo= github.com/anchore/stereoscope v0.1.23/go.mod h1:JLnun49fkLkuv3ebU0ROvFl/0JiRmNmUtCzc6y4ollo= +github.com/anchore/stereoscope v0.2.0 h1:8haOu2ugLymmxvyfrZR7OTBFiRFRBh5LlNUtRrSRoxI= +github.com/anchore/stereoscope v0.2.0/go.mod h1:PYx3fD4lvBVsYoQ/fBdauhZ5hmkRrJgw1B73svKx7/U= github.com/anchore/syft v1.43.0 h1:m6BwN48vgD0j2U4uk/wwqkUCxVKp2On30ZnKWQGCjKI= github.com/anchore/syft v1.43.0/go.mod h1:6jC8wnvN5Jble2qrWrS7q9jVoR1K2DVMKGBookHZai0= github.com/andreyvit/diff v0.0.0-20170406064948-c7f18ee00883/go.mod h1:rCTlJbsFo29Kk6CurOXKm700vrz8f0KW0JNfpkRJY/8= @@ -331,14 +339,26 @@ github.com/cncf/xds/go v0.0.0-20251210132809-ee656c7534f5 h1:6xNmx7iTtyBRev0+D/T github.com/cncf/xds/go v0.0.0-20251210132809-ee656c7534f5/go.mod h1:KdCmV+x/BuvyMxRnYBlmVaq4OLiKW6iRQfvC62cvdkI= github.com/containerd/cgroups/v3 v3.1.2 h1:OSosXMtkhI6Qove637tg1XgK4q+DhR0mX8Wi8EhrHa4= github.com/containerd/cgroups/v3 v3.1.2/go.mod h1:PKZ2AcWmSBsY/tJUVhtS/rluX0b1uq1GmPO1ElCmbOw= -github.com/containerd/containerd v1.7.31 h1:jn3IMuTV4Bb1Uwb0MFPW2ASJAD3W1lh6QqqZHIZwDh4= -github.com/containerd/containerd v1.7.31/go.mod h1:jdwD6s/BhV4XVJGrvtziNPVA+83n66TwptVaPKprq4E= +github.com/containerd/cgroups/v3 v3.1.3 h1:eUNflyMddm18+yrDmZPn3jI7C5hJ9ahABE5q6dyLYXQ= +github.com/containerd/cgroups/v3 v3.1.3/go.mod h1:PKZ2AcWmSBsY/tJUVhtS/rluX0b1uq1GmPO1ElCmbOw= +github.com/containerd/containerd v1.7.32 h1:S54xuVcPxeLaYgaRABtpJ2VyVUVsy0IGf7qHBs+sbY8= +github.com/containerd/containerd v1.7.32/go.mod h1:jdwD6s/BhV4XVJGrvtziNPVA+83n66TwptVaPKprq4E= github.com/containerd/containerd/api v1.10.0 h1:5n0oHYVBwN4VhoX9fFykCV9dF1/BvAXeg2F8W6UYq1o= github.com/containerd/containerd/api v1.10.0/go.mod h1:NBm1OAk8ZL+LG8R0ceObGxT5hbUYj7CzTmR3xh0DlMM= +github.com/containerd/containerd/api v1.11.0 h1:smv4e74S/wwIx0Sj7lhwO1t3M/oi+mSzk2VXqHq8aO0= +github.com/containerd/containerd/api v1.11.0/go.mod h1:CaQFRu+N1MtbgL6JDOJLUB1hCKESU1lD6MuTJhgtdlw= +github.com/containerd/containerd/api v1.11.1 h1:h8nfoDW9+fNsC/9TwiAHj8B1GzXKtR4eFtkhi/X5RLU= +github.com/containerd/containerd/api v1.11.1/go.mod h1:CaQFRu+N1MtbgL6JDOJLUB1hCKESU1lD6MuTJhgtdlw= github.com/containerd/containerd/v2 v2.2.3 h1:mOBRLaHGvmgy0bRo1Sg6OD8ugMKZIvCoWWMeMMygliA= github.com/containerd/containerd/v2 v2.2.3/go.mod h1:ns24cwt+p36mRnuKE3hLRxVBpuSP+a/Y25AMki1t/RY= +github.com/containerd/containerd/v2 v2.3.0 h1:qpB5dyToxPqea1OdedyAiAnnor5wxTM+Py9nWt5CnWY= +github.com/containerd/containerd/v2 v2.3.0/go.mod h1:+chyhxLNeqUVOcTJGgaSu/IbDGX6p3+d8AJjAaerAS8= +github.com/containerd/containerd/v2 v2.3.1 h1:4dVXBdlvotRBlaP2TmNbY/EGc06KJrMDDUqQdxX/HOk= +github.com/containerd/containerd/v2 v2.3.1/go.mod h1:xVoxGPWZBwwph8DF2IbDhriLKdHfjdpO0b3wFP9wQ1I= github.com/containerd/continuity v0.4.5 h1:ZRoN1sXq9u7V6QoHMcVWGhOwDFqZ4B9i5H6un1Wh0x4= github.com/containerd/continuity v0.4.5/go.mod h1:/lNJvtJKUQStBzpVQ1+rasXO1LAWtUQssk28EZvJ3nE= +github.com/containerd/continuity v0.5.0 h1:7a85HZpCSs+1Zps0Ee3DPSuAWY+0SJM1JNM51nlEVDg= +github.com/containerd/continuity v0.5.0/go.mod h1:/lNJvtJKUQStBzpVQ1+rasXO1LAWtUQssk28EZvJ3nE= github.com/containerd/errdefs v1.0.0 h1:tg5yIfIlQIrxYtu9ajqY42W3lpS19XqdxRQeEwYG8PI= github.com/containerd/errdefs v1.0.0/go.mod h1:+YBYIdtsnF4Iw6nWZhJcqGSg/dwvV7tyJ/kCkyJ2k+M= github.com/containerd/errdefs/pkg v0.3.0 h1:9IKJ06FvyNlexW690DXuQNx2KA2cUJXx151Xdx3ZPPE= @@ -351,10 +371,14 @@ github.com/containerd/platforms v1.0.0-rc.4 h1:M42JrUT4zfZTqtkUwkr0GzmUWbfyO5VO0 github.com/containerd/platforms v1.0.0-rc.4/go.mod h1:lKlMXyLybmBedS/JJm11uDofzI8L2v0J2ZbYvNsbq1A= github.com/containerd/plugin v1.0.0 h1:c8Kf1TNl6+e2TtMHZt+39yAPDbouRH9WAToRjex483Y= github.com/containerd/plugin v1.0.0/go.mod h1:hQfJe5nmWfImiqT1q8Si3jLv3ynMUIBB47bQ+KexvO8= +github.com/containerd/plugin v1.1.0 h1:O+7lczNJVMy8rz0YNx3xGB8tTf5qY4i5abF041Ew19U= +github.com/containerd/plugin v1.1.0/go.mod h1:qBTum+A8lJ6lO44A19Eo7y1OlcLj4OWFH1DA/vnHmcc= github.com/containerd/stargz-snapshotter/estargz v0.18.2 h1:yXkZFYIzz3eoLwlTUZKz2iQ4MrckBxJjkmD16ynUTrw= github.com/containerd/stargz-snapshotter/estargz v0.18.2/go.mod h1:XyVU5tcJ3PRpkA9XS2T5us6Eg35yM0214Y+wvrZTBrY= github.com/containerd/ttrpc v1.2.7 h1:qIrroQvuOL9HQ1X6KHe2ohc7p+HP/0VE6XPU7elJRqQ= github.com/containerd/ttrpc v1.2.7/go.mod h1:YCXHsb32f+Sq5/72xHubdiJRQY9inL4a4ZQrAbN1q9o= +github.com/containerd/ttrpc v1.2.8 h1:xbVu6D4qF2jihdh9rDVOKqUMiFBQk6YctTdo1zk087Y= +github.com/containerd/ttrpc v1.2.8/go.mod h1:wyZW2K79t4Hfcxl+GUvkZqRBzJlqFFvgEeeWXa42tyE= github.com/containerd/typeurl/v2 v2.2.3 h1:yNA/94zxWdvYACdYO8zofhrTVuQY73fFU1y++dYSw40= github.com/containerd/typeurl/v2 v2.2.3/go.mod h1:95ljDnPfD3bAbDJRugOiShd/DlAAsxGtUBhJxIn7SCk= github.com/coreos/go-semver v0.3.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk= @@ -362,6 +386,7 @@ github.com/coreos/go-systemd/v22 v22.3.2/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSV github.com/coreos/go-systemd/v22 v22.5.0/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc= github.com/coreos/go-systemd/v22 v22.6.0 h1:aGVa/v8B7hpb0TKl0MWoAavPDmHvobFe5R5zn0bCJWo= github.com/coreos/go-systemd/v22 v22.6.0/go.mod h1:iG+pp635Fo7ZmV/j14KUcmEyWF+0X7Lua8rrTWzYgWU= +github.com/coreos/go-systemd/v22 v22.7.0 h1:LAEzFkke61DFROc7zNLX/WA2i5J8gYqe0rSj9KI28KA= github.com/cpuguy83/go-md2man/v2 v2.0.1/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= github.com/cpuguy83/go-md2man/v2 v2.0.6/go.mod h1:oOW0eioCTA6cOiMLiUPZOpcVxMig6NIQQ7OS05n1F4g= github.com/creack/pty v1.1.24 h1:bJrF4RRfyJnbTJqzRLHzcGaZK1NeM5kTC9jGgovnR1s= @@ -381,6 +406,8 @@ github.com/diskfs/go-diskfs v1.7.0 h1:vonWmt5CMowXwUc79jWyGrf2DIMeoOjkLlMnQYGVOs github.com/diskfs/go-diskfs v1.7.0/go.mod h1:LhQyXqOugWFRahYUSw47NyZJPezFzB9UELwhpszLP/k= github.com/distribution/distribution/v3 v3.0.1-0.20250403190400-dbca4995c83c h1:tFjIrcN2x16eg3aob8g8LPNJClLxtQbu1wqeUMydXRc= github.com/distribution/distribution/v3 v3.0.1-0.20250403190400-dbca4995c83c/go.mod h1:tRNuFoZsUdyRVegq8xGNeds4KLjwLCRin/tTo6i1DhU= +github.com/distribution/distribution/v3 v3.0.1-0.20260120145532-40594bd98e6d h1:c2HDaWKU1MalLXwrAek+Yks7n80p/salSR5u6alHPBo= +github.com/distribution/distribution/v3 v3.0.1-0.20260120145532-40594bd98e6d/go.mod h1:WiiB9B3TqqAPe7hPjI1P9OMtEW7Ub/HHGndi11SqeDA= github.com/distribution/reference v0.6.0 h1:0IXCQ5g4/QMHHkarYzh5l+u8T3t73zM5QvfrDyIgxBk= github.com/distribution/reference v0.6.0/go.mod h1:BbU0aIcezP1/5jX/8MP0YiH4SdvB5Y4f/wlDRiLyi3E= github.com/djherbis/times v1.6.0 h1:w2ctJ92J8fBvWPxugmXIv7Nz7Q3iDMKNx9v5ocVH20c= @@ -389,6 +416,8 @@ github.com/dlclark/regexp2 v1.11.0 h1:G/nrcoOa7ZXlpoa/91N3X7mM3r8eIlMBBJZvsz/mxK github.com/dlclark/regexp2 v1.11.0/go.mod h1:DHkYz0B9wPfa6wondMfaivmHpzrQ3v9q8cnmRbL6yW8= github.com/docker/cli v29.4.0+incompatible h1:+IjXULMetlvWJiuSI0Nbor36lcJ5BTcVpUmB21KBoVM= github.com/docker/cli v29.4.0+incompatible/go.mod h1:JLrzqnKDaYBop7H2jaqPtU4hHvMKP+vjCwu2uszcLI8= +github.com/docker/cli v29.4.3+incompatible h1:u+UliYm2J/rYrIh2FqHQg32neRG8GjbvNuwQRTzGspU= +github.com/docker/cli v29.4.3+incompatible/go.mod h1:JLrzqnKDaYBop7H2jaqPtU4hHvMKP+vjCwu2uszcLI8= github.com/docker/docker-credential-helpers v0.9.5 h1:EFNN8DHvaiK8zVqFA2DT6BjXE0GzfLOZ38ggPTKePkY= github.com/docker/docker-credential-helpers v0.9.5/go.mod h1:v1S+hepowrQXITkEfw6o4+BMbGot02wiKpzWhGUZK6c= github.com/docker/go-connections v0.6.0 h1:LlMG9azAe1TqfR7sO+NJttz1gy6KO7VJBh+pMmjSD94= @@ -486,15 +515,21 @@ github.com/go-git/gcfg v1.5.1-0.20230307220236-3a3c6141e376 h1:+zs/tPmkDkHx3U66D github.com/go-git/gcfg v1.5.1-0.20230307220236-3a3c6141e376/go.mod h1:an3vInlBmSxCcxctByoQdvwPiA7DTK7jaaFDBTtu0ic= 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-billy/v5 v5.8.1-0.20260506061021-07f2a0bf50e4 h1:XK6pelr1UQyrCSXsrqrJxr0jkrHXg7QCzfPH3UQMYp8= +github.com/go-git/go-billy/v5 v5.8.1-0.20260506061021-07f2a0bf50e4/go.mod h1:jCnQMLj9eUgGU7+ludSTYoZL/GGmii14RxKFj7ROgHw= 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.18.0 h1:O831KI+0PR51hM2kep6T8k+w0/LIAD490gvqMCvL5hM= github.com/go-git/go-git/v5 v5.18.0/go.mod h1:pW/VmeqkanRFqR6AljLcs7EA7FbZaN5MQqO7oZADXpo= +github.com/go-git/go-git/v5 v5.18.1-0.20260420130857-e5bbc088b774 h1:FED4o0JOD1z8x/dMcmM6IKkqoIz22xz7sWE81FEdXNQ= +github.com/go-git/go-git/v5 v5.18.1-0.20260420130857-e5bbc088b774/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= github.com/go-gorp/gorp/v3 v3.1.0 h1:ItKF/Vbuj31dmV4jxA1qblpSwkl9g1typ24xoe70IGs= github.com/go-gorp/gorp/v3 v3.1.0/go.mod h1:dLEjIyyRNiXvNZ8PSmzpt1GsWAUK8kjVhEpjH8TixEw= +github.com/go-jose/go-jose/v3 v3.0.5 h1:BLLJWbC4nMZOfuPVxoZIxeYsn6Nl2r1fITaJ78UQlVQ= +github.com/go-jose/go-jose/v3 v3.0.5/go.mod h1:5b+7YgP7ZICgJDBdfjZaIt+H/9L9T/YQrVfLAMboGkQ= github.com/go-jose/go-jose/v4 v4.1.4 h1:moDMcTHmvE6Groj34emNPLs/qtYXRVcd6S7NHbHz3kA= github.com/go-jose/go-jose/v4 v4.1.4/go.mod h1:x4oUasVrzR7071A4TnHLGSPpNOm2a21K9Kf04k1rs08= github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= @@ -601,6 +636,7 @@ github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/ github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.7/go.mod h1:n+brtR0CgQNWTVd5ZUFpTBC8YFBDLK/h/bpaJ8/DtOE= +github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8= github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU= github.com/google/go-containerregistry v0.21.5 h1:KTJG9Pn/jC0VdZR6ctV3/jcN+q6/Iqlx0sTVz3ywZlM= @@ -673,6 +709,7 @@ github.com/grpc-ecosystem/grpc-gateway v1.16.0 h1:gmcG1KaJ57LophUzW0Hy8NmPhnMZb4 github.com/grpc-ecosystem/grpc-gateway v1.16.0/go.mod h1:BDjrQk3hbvj6Nolgz8mAMFbcEtjT1g+wF4CSlocrBnw= github.com/grpc-ecosystem/grpc-gateway/v2 v2.26.3 h1:5ZPtiqj0JL5oKWmcsq4VMaAW5ukBEgSGXEN89zeH1Jo= github.com/grpc-ecosystem/grpc-gateway/v2 v2.26.3/go.mod h1:ndYquD05frm2vACXE1nsccT4oJzjhw2arTS2cpUD1PI= +github.com/grpc-ecosystem/grpc-gateway/v2 v2.28.0 h1:HWRh5R2+9EifMyIHV7ZV+MIZqgz+PMpZ14Jynv3O2Zs= github.com/h2non/filetype v1.1.3 h1:FKkx9QbD7HR/zjK1Ia5XiBsq9zdLi5Kf3zGyFTAFkGg= github.com/h2non/filetype v1.1.3/go.mod h1:319b3zT68BvV+WRj7cwy856M2ehB3HqNOt6sy1HndBY= github.com/hashicorp/aws-sdk-go-base/v2 v2.0.0-beta.72 h1:vTCWu1wbdYo7PEZFem/rlr01+Un+wwVmI7wiegFdRLk= @@ -946,6 +983,8 @@ github.com/pelletier/go-toml v1.9.5 h1:4yBQzkHv+7BHq2PQUZF3Mx0IYxG7LsP222s7Agd3v github.com/pelletier/go-toml v1.9.5/go.mod h1:u1nR/EPcESfeI/szUZKdtJ0xRNbUoANCkoOuaOx1Y+c= github.com/pelletier/go-toml/v2 v2.2.4 h1:mye9XuhQ6gvn5h28+VilKrrPoQVanw5PMw/TB0t5Ec4= github.com/pelletier/go-toml/v2 v2.2.4/go.mod h1:2gIqNv+qfxSVS7cM2xJQKtLSTLUE9V8t9Stt+h56mCY= +github.com/pelletier/go-toml/v2 v2.3.1 h1:MYEvvGnQjeNkRF1qUuGolNtNExTDwct51yp7olPtrEc= +github.com/pelletier/go-toml/v2 v2.3.1/go.mod h1:2gIqNv+qfxSVS7cM2xJQKtLSTLUE9V8t9Stt+h56mCY= github.com/peterbourgon/diskv v2.0.1+incompatible h1:UBdAOUP5p4RWqPBg048CAvpKN+vxiaj6gdUUzhl4XmI= github.com/peterbourgon/diskv v2.0.1+incompatible/go.mod h1:uqqh8zWWbv1HBMNONnaR/tNboyR3/BZd58JJSHlUSCU= github.com/phayes/freeport v0.0.0-20220201140144-74d24b5ae9f5 h1:Ii+DKncOVM8Cu1Hc+ETb5K+23HdAMvESYE3ZJ5b5cMI= @@ -987,11 +1026,13 @@ github.com/prometheus/common v0.4.1/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y8 github.com/prometheus/common v0.9.1/go.mod h1:yhUN8i9wzaXS3w1O07YhxHEBxD+W35wd8bs7vj7HSQ4= github.com/prometheus/common v0.66.1 h1:h5E0h5/Y8niHc5DlaLlWLArTQI7tMrsfQjHV+d9ZoGs= github.com/prometheus/common v0.66.1/go.mod h1:gcaUsgf3KfRSwHY4dIMXLPV0K/Wg1oZ8+SbZk/HH/dA= +github.com/prometheus/common v0.67.5 h1:pIgK94WWlQt1WLwAC5j2ynLaBRDiinoAb86HZHTUGI4= github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA= github.com/prometheus/procfs v0.0.8/go.mod h1:7Qr8sr6344vo1JqZ6HhLceV9o3AJ1Ff+GxbHq6oeK9A= github.com/prometheus/procfs v0.16.1 h1:hZ15bTNuirocR6u0JZ6BAHHmwS1p8B4P6MRqxtzMyRg= github.com/prometheus/procfs v0.16.1/go.mod h1:teAbpZRB1iIAJYREa1LsoWUXykVXA1KlTmWl8x/U+Is= +github.com/prometheus/procfs v0.19.2 h1:zUMhqEW66Ex7OXIiDkll3tl9a1ZdilUOd/F6ZXw4Vws= github.com/redis/go-redis/extra/rediscmd/v9 v9.0.5 h1:EaDatTxkdHG+U3Bk4EUr+DZ7fOGwTfezUiUJMaIcaho= github.com/redis/go-redis/extra/rediscmd/v9 v9.0.5/go.mod h1:fyalQWdtzDBECAQFBJuQe5bzQ02jGd5Qcbgb97Flm7U= github.com/redis/go-redis/extra/redisotel/v9 v9.0.5 h1:EfpWLLCyXw8PSM2/XNJLjI3Pb27yVE+gIAfeqp8LUCc= @@ -1190,8 +1231,12 @@ go.opentelemetry.io/contrib/exporters/autoexport v0.57.0 h1:jmTVJ86dP60C01K3slFQ go.opentelemetry.io/contrib/exporters/autoexport v0.57.0/go.mod h1:EJBheUMttD/lABFyLXhce47Wr6DPWYReCzaZiXadH7g= go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.63.0 h1:YH4g8lQroajqUwWbq/tr2QX1JFmEXaDLgG+ew9bLMWo= go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.63.0/go.mod h1:fvPi2qXDqFs8M4B4fmJhE92TyQs9Ydjlg3RvfUp+NbQ= +go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.68.0 h1:0Qx7VGBacMm9ZENQ7TnNObTYI4ShC+lHI16seduaxZo= +go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.68.0/go.mod h1:Sje3i3MjSPKTSPvVWCaL8ugBzJwik3u4smCjUeuupqg= go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.61.0 h1:F7Jx+6hwnZ41NSFTO5q4LYDtJRXBf2PD0rNBkeB/lus= go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.61.0/go.mod h1:UHB22Z8QsdRDrnAtX4PntOl36ajSxcdUMt1sF7Y6E7Q= +go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.68.0 h1:CqXxU8VOmDefoh0+ztfGaymYbhdB/tT3zs79QaZTNGY= +go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.68.0/go.mod h1:BuhAPThV8PBHBvg8ZzZ/Ok3idOdhWIodywz2xEcRbJo= go.opentelemetry.io/otel v1.43.0 h1:mYIM03dnh5zfN7HautFE4ieIig9amkNANT+xcVxAj9I= go.opentelemetry.io/otel v1.43.0/go.mod h1:JuG+u74mvjvcm8vj8pI5XiHy1zDeoCS2LB1spIq7Ay0= go.opentelemetry.io/otel/exporters/otlp/otlplog/otlploggrpc v0.8.0 h1:WzNab7hOOLzdDF/EoWCt4glhrbMPVMOO5JYTmpz36Ls= @@ -1204,10 +1249,13 @@ go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetrichttp v1.32.0 h1:t/Q go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetrichttp v1.32.0/go.mod h1:Rl61tySSdcOJWoEgYZVtmnKdA0GeKrSqkHC1t+91CH8= go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.35.0 h1:1fTNlAIJZGWLP5FVu0fikVry1IsiUnXjf7QFvoNN3Xw= go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.35.0/go.mod h1:zjPK58DtkqQFn+YUMbx0M2XV3QgKU0gS9LeGohREyK4= +go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.43.0 h1:88Y4s2C8oTui1LGM6bTWkw0ICGcOLCAI5l6zsD1j20k= go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.35.0 h1:m639+BofXTvcY1q8CGs4ItwQarYtJPOWmVobfM1HpVI= go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.35.0/go.mod h1:LjReUci/F4BUyv+y4dwnq3h/26iNOeC3wAIqgvTIZVo= +go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.43.0 h1:RAE+JPfvEmvy+0LzyUA25/SGawPwIUbZ6u0Wug54sLc= go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.35.0 h1:xJ2qHD0C1BeYVTLLR9sX12+Qb95kfeD/byKj6Ky1pXg= go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.35.0/go.mod h1:u5BF1xyjstDowA1R5QAO9JHzqK+ublenEW/dyqTjBVk= +go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.43.0 h1:3iZJKlCZufyRzPzlQhUIWVmfltrXuGyfjREgGP3UUjc= go.opentelemetry.io/otel/exporters/prometheus v0.54.0 h1:rFwzp68QMgtzu9PgP3jm9XaMICI6TsofWWPcBDKwlsU= go.opentelemetry.io/otel/exporters/prometheus v0.54.0/go.mod h1:QyjcV9qDP6VeK5qPyKETvNjmaaEc7+gqjh4SS0ZYzDU= go.opentelemetry.io/otel/exporters/stdout/stdoutlog v0.8.0 h1:CHXNXwfKWfzS65yrlB2PVds1IBZcdsX8Vepy9of0iRU= @@ -1231,11 +1279,14 @@ go.opentelemetry.io/otel/trace v1.43.0/go.mod h1:/QJhyVBUUswCphDVxq+8mld+AvhXZLh go.opentelemetry.io/proto/otlp v0.7.0/go.mod h1:PqfVotwruBrMGOCsRd/89rSnXhoiJIqeYNgFYFoEGnI= go.opentelemetry.io/proto/otlp v1.7.1 h1:gTOMpGDb0WTBOP8JaO72iL3auEZhVmAQg4ipjOVAtj4= go.opentelemetry.io/proto/otlp v1.7.1/go.mod h1:b2rVh6rfI/s2pHWNlB7ILJcRALpcNDzKhACevjI+ZnE= +go.opentelemetry.io/proto/otlp v1.10.0 h1:IQRWgT5srOCYfiWnpqUYz9CVmbO8bFmKcwYxpuCSL2g= go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc= go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto= go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE= go.uber.org/mock v0.5.2 h1:LbtPTcP8A5k9WPXj54PPPbjcI4Y6lhyOZXn+VS7wNko= go.uber.org/mock v0.5.2/go.mod h1:wLlUxC2vVTPTaE3UD51E0BGOAElKrILxhVSDYQLld5o= +go.uber.org/mock v0.6.0 h1:hyF9dfmbgIX5EfOdasqLsWD6xqpNZlXblLB/Dbnwv3Y= +go.uber.org/mock v0.6.0/go.mod h1:KiVJ4BqZJaMj4svdfmHM0AUx4NJYO8ZNpPnZn1Z+BBU= go.uber.org/multierr v1.6.0/go.mod h1:cdWPpRnG4AhwMwsgIHip0KRBQjJy5kYEpYjJxpXp9iU= go.uber.org/zap v1.17.0/go.mod h1:MXVU+bhUf/A7Xi2HNOnopQOrmycQ5Ih87HtOu4q5SSo= go.yaml.in/yaml/v2 v2.4.3 h1:6gvOSjQoTB3vt1l+CU+tSyi/HOjfOjRLJ4YwYZGwRO0= @@ -1258,6 +1309,7 @@ golang.org/x/crypto v0.0.0-20210817164053-32db794688a5/go.mod h1:GvvjBRRGRdwPK5y golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/crypto v0.0.0-20220622213112-05595931fe9d/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= golang.org/x/crypto v0.6.0/go.mod h1:OFC/31mSvZgRz0V1QTNCzfAI1aIRzbiufJtkMIlEp58= +golang.org/x/crypto v0.19.0/go.mod h1:Iy9bg/ha4yyC70EfRS8jz+B6ybOBKMaSxLj6P6oBDfU= golang.org/x/crypto v0.50.0 h1:zO47/JPrL6vsNkINmLoo/PH1gcxpls50DNogFvB5ZGI= golang.org/x/crypto v0.50.0/go.mod h1:3muZ7vA7PBCE6xgPX7nkzzjiUq87kRItoJQM1Yo8S+Q= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= @@ -1272,6 +1324,8 @@ golang.org/x/exp v0.0.0-20200207192155-f17229e696bd/go.mod h1:J/WKrq2StrnmMY6+EH golang.org/x/exp v0.0.0-20200224162631-6cc2880d07d6/go.mod h1:3jZMyOhIsHpP37uCMkUooju7aAi5cS1Q23tOzKc+0MU= golang.org/x/exp v0.0.0-20251023183803-a4bb9ffd2546 h1:mgKeJMpvi0yx/sU5GsxQ7p6s2wtOnGAHZWCHUM4KGzY= golang.org/x/exp v0.0.0-20251023183803-a4bb9ffd2546/go.mod h1:j/pmGrbnkbPtQfxEe5D0VQhZC6qKbfKifgD0oM7sR70= +golang.org/x/exp v0.0.0-20260410095643-746e56fc9e2f h1:W3F4c+6OLc6H2lb//N1q4WpJkhzJCK5J6kUi1NTVXfM= +golang.org/x/exp v0.0.0-20260410095643-746e56fc9e2f/go.mod h1:J1xhfL/vlindoeF/aINzNzt2Bket5bjo9sdOYzOsU80= golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js= golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= @@ -1299,6 +1353,7 @@ golang.org/x/mod v0.4.1/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.5.0/go.mod h1:5OXOZSfqPIIbmVBIIKWRFfZjPR0E5r58TLhUjH0a2Ro= golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= +golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= golang.org/x/mod v0.35.0 h1:Ww1D637e6Pg+Zb2KrWfHQUnH2dQRLBQyAtpr/haaJeM= golang.org/x/mod v0.35.0/go.mod h1:+GwiRhIInF8wPm+4AoT6L0FA1QWAad3OMdTRx4tFYlU= golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= @@ -1346,6 +1401,7 @@ golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qx golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= golang.org/x/net v0.7.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= +golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg= golang.org/x/net v0.53.0 h1:d+qAbo5L0orcWAr0a9JweQpjXF19LMXJE8Ey7hwOdUA= golang.org/x/net v0.53.0/go.mod h1:JvMuJH7rrdiCfbeHoo3fCQU24Lf5JJwT9W3sJFulfgs= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= @@ -1379,6 +1435,7 @@ golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJ golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.20.0 h1:e0PTpb7pjO8GAtTs2dQ6jYa5BWYlMuX047Dco/pItO4= golang.org/x/sync v0.20.0/go.mod h1:9xrNwdLfx4jkKbNva9FpL6vEN7evnE43NNNJQ2LF3+0= golang.org/x/sys v0.0.0-20180823144017-11551d06cbcc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= @@ -1456,12 +1513,16 @@ golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.17.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/sys v0.43.0 h1:Rlag2XtaFTxp19wS8MXlJwTvoh8ArU6ezoyFsMyCTNI= golang.org/x/sys v0.43.0/go.mod h1:4GL1E5IUh+htKOUEOaiffhrAeqysfVGipDYzABqnCmw= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k= +golang.org/x/term v0.8.0/go.mod h1:xPskH00ivmX89bAKVGSKKtLOWNx2+17Eiy94tnKShWo= +golang.org/x/term v0.17.0/go.mod h1:lLRBjIVuehSbZlaOtGMbcMncT+aqLLLmKrsjNrUguwk= golang.org/x/term v0.42.0 h1:UiKe+zDFmJobeJ5ggPwOshJIVt6/Ft0rcfrXZDLWAWY= golang.org/x/term v0.42.0/go.mod h1:Dq/D+snpsbazcBG5+F9Q1n2rXV8Ma+71xEjTRufARgY= golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= @@ -1474,6 +1535,8 @@ golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= +golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= +golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= golang.org/x/text v0.36.0 h1:JfKh3XmcRPqZPKevfXVpI1wXPTqbkE5f7JA92a55Yxg= golang.org/x/text v0.36.0/go.mod h1:NIdBknypM8iqVmPiuco0Dh6P5Jcdk8lJL0CUebqK164= golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= @@ -1536,6 +1599,7 @@ golang.org/x/tools v0.1.3/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= golang.org/x/tools v0.1.4/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= golang.org/x/tools v0.1.5/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= +golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU= golang.org/x/tools v0.44.0 h1:UP4ajHPIcuMjT1GqzDWRlalUEoY+uzoZKnhOjbIPD2c= golang.org/x/tools v0.44.0/go.mod h1:KA0AfVErSdxRZIsOVipbv3rQhVXTnlU6UhKxHd1seDI= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= @@ -1546,6 +1610,8 @@ golang.org/x/xerrors v0.0.0-20240903120638-7835f813f4da h1:noIWHXmPHxILtqtCOPIhS golang.org/x/xerrors v0.0.0-20240903120638-7835f813f4da/go.mod h1:NDW/Ps6MPRej6fsCIbMTohpP40sJ/P/vI1MoTEGwX90= gonum.org/v1/gonum v0.16.0 h1:5+ul4Swaf3ESvrOnidPp4GZbzf0mxVQpDCYUQE7OJfk= gonum.org/v1/gonum v0.16.0/go.mod h1:fef3am4MQ93R2HHpKnLk4/Tbh/s0+wqD5nfa6Pnwy4E= +gonum.org/v1/gonum v0.17.0 h1:VbpOemQlsSMrYmn7T2OUvQ4dqxQXU+ouZFQsZOx50z4= +gonum.org/v1/gonum v0.17.0/go.mod h1:El3tOrEuMpv2UdMrbNlKEh9vd86bmQ6vqIcDwxEOc1E= google.golang.org/api v0.4.0/go.mod h1:8k5glujaEP+g9n7WNsDg8QP6cUVNI86fCNMcbazEtwE= google.golang.org/api v0.7.0/go.mod h1:WtwebWUNSVBH/HAw79HIFXZNqEvBhG+Ra+ax0hx3E3M= google.golang.org/api v0.8.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg= @@ -1654,8 +1720,12 @@ google.golang.org/genproto v0.0.0-20260128011058-8636f8732409 h1:VQZ/yAbAtjkHgH8 google.golang.org/genproto v0.0.0-20260128011058-8636f8732409/go.mod h1:rxKD3IEILWEu3P44seeNOAwZN4SaoKaQ/2eTg4mM6EM= google.golang.org/genproto/googleapis/api v0.0.0-20260203192932-546029d2fa20 h1:7ei4lp52gK1uSejlA8AZl5AJjeLUOHBQscRQZUgAcu0= google.golang.org/genproto/googleapis/api v0.0.0-20260203192932-546029d2fa20/go.mod h1:ZdbssH/1SOVnjnDlXzxDHK2MCidiqXtbYccJNzNYPEE= +google.golang.org/genproto/googleapis/api v0.0.0-20260401024825-9d38bb4040a9 h1:VPWxll4HlMw1Vs/qXtN7BvhZqsS9cdAittCNvVENElA= +google.golang.org/genproto/googleapis/api v0.0.0-20260401024825-9d38bb4040a9/go.mod h1:7QBABkRtR8z+TEnmXTqIqwJLlzrZKVfAUm7tY3yGv0M= google.golang.org/genproto/googleapis/rpc v0.0.0-20260226221140-a57be14db171 h1:ggcbiqK8WWh6l1dnltU4BgWGIGo+EVYxCaAPih/zQXQ= google.golang.org/genproto/googleapis/rpc v0.0.0-20260226221140-a57be14db171/go.mod h1:4Hqkh8ycfw05ld/3BWL7rJOSfebL2Q+DVDeRgYgxUU8= +google.golang.org/genproto/googleapis/rpc v0.0.0-20260406210006-6f92a3bedf2d h1:wT2n40TBqFY6wiwazVK9/iTWbsQrgk5ZfCSVFLO9LQA= +google.golang.org/genproto/googleapis/rpc v0.0.0-20260406210006-6f92a3bedf2d/go.mod h1:4Hqkh8ycfw05ld/3BWL7rJOSfebL2Q+DVDeRgYgxUU8= google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38= google.golang.org/grpc v1.21.1/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM= @@ -1685,6 +1755,8 @@ google.golang.org/grpc v1.40.1/go.mod h1:ogyxbiOoUXAkP+4+xa6PZSE9DZgIHtSpzjDTB9K google.golang.org/grpc v1.42.0/go.mod h1:k+4IHHFw41K8+bbowsex27ge2rCb65oeWqe4jJ590SU= google.golang.org/grpc v1.79.3 h1:sybAEdRIEtvcD68Gx7dmnwjZKlyfuc61Dyo9pGXXkKE= google.golang.org/grpc v1.79.3/go.mod h1:KmT0Kjez+0dde/v2j9vzwoAScgEPx/Bw1CYChhHLrHQ= +google.golang.org/grpc v1.80.0 h1:Xr6m2WmWZLETvUNvIUmeD5OAagMw3FiKmMlTdViWsHM= +google.golang.org/grpc v1.80.0/go.mod h1:ho/dLnxwi3EDJA4Zghp7k2Ec1+c2jqup0bFkw07bwF4= google.golang.org/grpc/cmd/protoc-gen-go-grpc v1.1.0/go.mod h1:6Kw0yEErY5E/yWrBtf03jp27GLLJujG4z/JK95pnjjw= google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= @@ -1701,6 +1773,8 @@ google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQ google.golang.org/protobuf v1.27.1/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= google.golang.org/protobuf v1.36.11 h1:fV6ZwhNocDyBLK0dj+fg8ektcVegBBuEolpbTQyBNVE= google.golang.org/protobuf v1.36.11/go.mod h1:HTf+CrKn2C3g5S8VImy6tdcUvCska2kB7j23XfzDpco= +google.golang.org/protobuf v1.36.12-0.20260120151049-f2248ac996af h1:+5/Sw3GsDNlEmu7TfklWKPdQ0Ykja5VEmq2i817+jbI= +google.golang.org/protobuf v1.36.12-0.20260120151049-f2248ac996af/go.mod h1:HTf+CrKn2C3g5S8VImy6tdcUvCska2kB7j23XfzDpco= gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= @@ -1742,26 +1816,40 @@ honnef.co/go/tools v0.0.1-2020.1.3/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9 honnef.co/go/tools v0.0.1-2020.1.4/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= k8s.io/api v0.35.1 h1:0PO/1FhlK/EQNVK5+txc4FuhQibV25VLSdLMmGpDE/Q= k8s.io/api v0.35.1/go.mod h1:28uR9xlXWml9eT0uaGo6y71xK86JBELShLy4wR1XtxM= +k8s.io/api v0.36.0 h1:SgqDhZzHdOtMk40xVSvCXkP9ME0H05hPM3p9AB1kL80= +k8s.io/api v0.36.0/go.mod h1:m1LVrGPNYax5NBHdO+QuAedXyuzTt4RryI/qnmNvs34= k8s.io/apiextensions-apiserver v0.35.1 h1:p5vvALkknlOcAqARwjS20kJffgzHqwyQRM8vHLwgU7w= k8s.io/apiextensions-apiserver v0.35.1/go.mod h1:2CN4fe1GZ3HMe4wBr25qXyJnJyZaquy4nNlNmb3R7AQ= k8s.io/apimachinery v0.35.1 h1:yxO6gV555P1YV0SANtnTjXYfiivaTPvCTKX6w6qdDsU= k8s.io/apimachinery v0.35.1/go.mod h1:jQCgFZFR1F4Ik7hvr2g84RTJSZegBc8yHgFWKn//hns= +k8s.io/apimachinery v0.36.0 h1:jZyPzhd5Z+3h9vJLt0z9XdzW9VzNzWAUw+P1xZ9PXtQ= +k8s.io/apimachinery v0.36.0/go.mod h1:FklypaRJt6n5wUIwWXIP6GJlIpUizTgfo1T/As+Tyxc= k8s.io/apiserver v0.35.1 h1:potxdhhTL4i6AYAa2QCwtlhtB1eCdWQFvJV6fXgJzxs= k8s.io/apiserver v0.35.1/go.mod h1:BiL6Dd3A2I/0lBnteXfWmCFobHM39vt5+hJQd7Lbpi4= k8s.io/cli-runtime v0.35.1 h1:uKcXFe8J7AMAM4Gm2JDK4mp198dBEq2nyeYtO+JfGJE= k8s.io/cli-runtime v0.35.1/go.mod h1:55/hiXIq1C8qIJ3WBrWxEwDLdHQYhBNRdZOz9f7yvTw= k8s.io/client-go v0.35.1 h1:+eSfZHwuo/I19PaSxqumjqZ9l5XiTEKbIaJ+j1wLcLM= k8s.io/client-go v0.35.1/go.mod h1:1p1KxDt3a0ruRfc/pG4qT/3oHmUj1AhSHEcxNSGg+OA= +k8s.io/client-go v0.36.0 h1:pOYi7C4RHChYjMiHpZSpSbIM6ZxVbRXBy7CuiIwqA3c= +k8s.io/client-go v0.36.0/go.mod h1:ZKKcpwF0aLYfkHFCjillCKaTK/yBkEDHTDXCFY6AS9Y= k8s.io/component-base v0.35.1 h1:XgvpRf4srp037QWfGBLFsYMUQJkE5yMa94UsJU7pmcE= k8s.io/component-base v0.35.1/go.mod h1:HI/6jXlwkiOL5zL9bqA3en1Ygv60F03oEpnuU1G56Bs= +k8s.io/component-base v0.36.0 h1:hFjEktssxiJhrK1zfybkH4kJOi8iZuF+mIDCqS5+jRo= +k8s.io/component-base v0.36.0/go.mod h1:JZvIfcNHk+uck+8LhJzhSBtydWXaZNQwX2OdL+Mnwsk= k8s.io/klog/v2 v2.130.1 h1:n9Xl7H1Xvksem4KFG4PYbdQCQxqc/tTUyrgXaOhHSzk= k8s.io/klog/v2 v2.130.1/go.mod h1:3Jpz1GvMt720eyJH1ckRHK1EDfpxISzJ7I9OYgaDtPE= +k8s.io/klog/v2 v2.140.0 h1:Tf+J3AH7xnUzZyVVXhTgGhEKnFqye14aadWv7bzXdzc= +k8s.io/klog/v2 v2.140.0/go.mod h1:o+/RWfJ6PwpnFn7OyAG3QnO47BFsymfEfrz6XyYSSp0= k8s.io/kube-openapi v0.0.0-20250910181357-589584f1c912 h1:Y3gxNAuB0OBLImH611+UDZcmKS3g6CthxToOb37KgwE= k8s.io/kube-openapi v0.0.0-20250910181357-589584f1c912/go.mod h1:kdmbQkyfwUagLfXIad1y2TdrjPFWp2Q89B3qkRwf/pQ= +k8s.io/kube-openapi v0.0.0-20260319004828-5883c5ee87b9 h1:Sztf7ESG9tAXRW/ACJZjrj5jhdOUqS2KFRQT+CTvu78= +k8s.io/kube-openapi v0.0.0-20260319004828-5883c5ee87b9/go.mod h1:uGBT7iTA6c6MvqUvSXIaYZo9ukscABYi2btjhvgKGZ0= k8s.io/kubectl v0.35.1 h1:zP3Er8C5i1dcAFUMh9Eva0kVvZHptXIn/+8NtRWMxwg= k8s.io/kubectl v0.35.1/go.mod h1:cQ2uAPs5IO/kx8R5s5J3Ihv3VCYwrx0obCXum0CvnXo= k8s.io/utils v0.0.0-20251002143259-bc988d571ff4 h1:SjGebBtkBqHFOli+05xYbK8YF1Dzkbzn+gDM4X9T4Ck= k8s.io/utils v0.0.0-20251002143259-bc988d571ff4/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0= +k8s.io/utils v0.0.0-20260319190234-28399d86e0b5 h1:kBawHLSnx/mYHmRnNUf9d4CpjREbeZuxoSGOX/J+aYM= +k8s.io/utils v0.0.0-20260319190234-28399d86e0b5/go.mod h1:xDxuJ0whA3d0I4mf/C4ppKHxXynQ+fxnkmQH0vTHnuk= modernc.org/cc/v4 v4.27.1 h1:9W30zRlYrefrDV2JE2O8VDtJ1yPGownxciz5rrbQZis= modernc.org/cc/v4 v4.27.1/go.mod h1:uVtb5OGqUKpoLWhqwNQo/8LwvoiEBLvZXIQ/SmO6mL0= modernc.org/ccgo/v4 v4.32.0 h1:hjG66bI/kqIPX1b2yT6fr/jt+QedtP2fqojG2VrFuVw= @@ -1807,5 +1895,7 @@ sigs.k8s.io/randfill v1.0.0 h1:JfjMILfT8A6RbawdsK2JXGBR5AQVfd+9TbzrlneTyrU= sigs.k8s.io/randfill v1.0.0/go.mod h1:XeLlZ/jmk4i1HRopwe7/aU3H5n1zNUcX6TM94b3QxOY= sigs.k8s.io/structured-merge-diff/v6 v6.3.0 h1:jTijUJbW353oVOd9oTlifJqOGEkUw2jB/fXCbTiQEco= sigs.k8s.io/structured-merge-diff/v6 v6.3.0/go.mod h1:M3W8sfWvn2HhQDIbGWj3S099YozAsymCo/wrT5ohRUE= +sigs.k8s.io/structured-merge-diff/v6 v6.3.2 h1:kwVWMx5yS1CrnFWA/2QHyRVJ8jM6dBA80uLmm0wJkk8= +sigs.k8s.io/structured-merge-diff/v6 v6.3.2/go.mod h1:M3W8sfWvn2HhQDIbGWj3S099YozAsymCo/wrT5ohRUE= sigs.k8s.io/yaml v1.6.0 h1:G8fkbMSAFqgEFgh4b1wmtzDnioxFCUgTZhlbj5P9QYs= sigs.k8s.io/yaml v1.6.0/go.mod h1:796bPqUfzR/0jLAl6XjHl3Ck7MiyVv8dbTdyT3/pMf4= From 28c1d8fc800b7cad0e7cf445c3b272eb01c2bbe4 Mon Sep 17 00:00:00 2001 From: atishj99 <141334503+cx-atish-jadhav@users.noreply.github.com> Date: Wed, 27 May 2026 12:41:37 +0530 Subject: [PATCH 17/27] Fix additional SCA vulnerabilities: containerd, golang.org/x/image, and opencontainers/runc - Upgrade github.com/containerd/containerd v1.7.30 to v1.7.32 (CVE-2026-46680) - Upgrade golang.org/x/image v0.25.0 to v0.36.1-0.20260211191414-e3d762b1d37e (CVE-2026-33813) - Upgrade github.com/opencontainers/runc v1.3.3 to v1.3.4 (CVE-2025-52881) - Upgrade github.com/cilium/ebpf v0.16.0 to v0.17.3 (transitive dependency) Co-Authored-By: Claude Haiku 4.5 --- go.mod | 20 +++++++++++++++++++- go.sum | 41 +++++++++++++++++++++++++++++++++++++++++ 2 files changed, 60 insertions(+), 1 deletion(-) diff --git a/go.mod b/go.mod index 2ac014f7f..afc5207b2 100644 --- a/go.mod +++ b/go.mod @@ -46,6 +46,8 @@ require ( cloud.google.com/go/monitoring v1.24.3 // indirect cloud.google.com/go/storage v1.61.3 // indirect cyphar.com/go-pathrs v0.2.1 // indirect + github.com/AdaLogics/go-fuzz-headers v0.0.0-20240806141605-e8a1dd7889d6 // indirect + github.com/AdamKorcz/go-118-fuzz-build v0.0.0-20240914100643-eb91380d8434 // indirect github.com/GoogleCloudPlatform/opentelemetry-operations-go/detectors/gcp v1.31.0 // indirect github.com/GoogleCloudPlatform/opentelemetry-operations-go/exporter/metric v0.55.0 // indirect github.com/GoogleCloudPlatform/opentelemetry-operations-go/internal/resourcemapping v0.55.0 // indirect @@ -79,18 +81,25 @@ require ( github.com/bodgit/sevenzip v1.6.1 // indirect github.com/bodgit/windows v1.0.1 // indirect github.com/cespare/xxhash/v2 v2.3.0 // indirect + github.com/checkpoint-restore/go-criu/v6 v6.3.0 // indirect + github.com/cilium/ebpf v0.17.3 // indirect github.com/clipperhouse/displaywidth v0.10.0 // indirect github.com/clipperhouse/uax29/v2 v2.6.0 // indirect github.com/cncf/xds/go v0.0.0-20251210132809-ee656c7534f5 // indirect + github.com/containerd/console v1.0.5 // indirect github.com/containerd/containerd/v2 v2.3.1 // indirect github.com/containerd/plugin v1.1.0 // indirect + github.com/coreos/go-systemd/v22 v22.7.0 // indirect + github.com/cpuguy83/go-md2man/v2 v2.0.7 // indirect github.com/diskfs/go-diskfs v1.7.0 // indirect github.com/distribution/distribution/v3 v3.0.1-0.20260120145532-40594bd98e6d // indirect + github.com/docker/go-events v0.0.0-20250114142523-c867878c5e32 // indirect github.com/envoyproxy/go-control-plane/envoy v1.36.0 // indirect github.com/envoyproxy/protoc-gen-validate v1.3.0 // indirect github.com/go-jose/go-jose/v3 v3.0.5 // indirect github.com/go-jose/go-jose/v4 v4.1.4 // indirect github.com/goccy/go-yaml v1.19.2 // indirect + github.com/godbus/dbus/v5 v5.1.0 // indirect github.com/gohugoio/hashstructure v0.6.0 // indirect github.com/google/s2a-go v0.1.9 // indirect github.com/googleapis/enterprise-certificate-proxy v0.3.14 // indirect @@ -107,21 +116,30 @@ require ( github.com/minio/minlz v1.0.1 // indirect github.com/moby/moby/api v1.54.1 // indirect github.com/moby/moby/client v0.4.0 // indirect + github.com/moby/sys/capability v0.4.0 // indirect + github.com/mrunalp/fileutils v0.5.1 // indirect github.com/nix-community/go-nix v0.0.0-20250101154619-4bdde671e0a1 // indirect github.com/nwaples/rardecode/v2 v2.2.0 // indirect github.com/olekukonko/cat v0.0.0-20250911104152-50322a0618f6 // indirect github.com/olekukonko/errors v1.2.0 // indirect github.com/olekukonko/ll v0.1.6 // indirect + github.com/opencontainers/cgroups v0.0.4 // indirect + github.com/opencontainers/runc v1.3.4 // indirect github.com/pkg/xattr v0.4.9 // indirect github.com/planetscale/vtprotobuf v0.6.1-0.20240319094008-0393e58bdf10 // indirect + github.com/seccomp/libseccomp-golang v0.10.0 // indirect github.com/smallnest/ringbuffer v0.0.0-20241116012123-461381446e3d // indirect github.com/sorairolake/lzip-go v0.3.8 // indirect github.com/spiffe/go-spiffe/v2 v2.6.0 // indirect + github.com/urfave/cli v1.22.16 // indirect + github.com/vishvananda/netlink v1.3.1 // indirect + github.com/vishvananda/netns v0.0.5 // indirect go.opentelemetry.io/contrib/detectors/gcp v1.39.0 // indirect go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.68.0 // indirect go.opentelemetry.io/otel/sdk v1.43.0 // indirect go.opentelemetry.io/otel/sdk/metric v1.43.0 // indirect go4.org v0.0.0-20230225012048-214862532bf5 // indirect + golang.org/x/image v0.36.1-0.20260211191414-e3d762b1d37e // indirect gonum.org/v1/gonum v0.17.0 // indirect google.golang.org/api v0.271.0 // indirect google.golang.org/genproto/googleapis/api v0.0.0-20260401024825-9d38bb4040a9 // indirect @@ -177,7 +195,7 @@ require ( github.com/charmbracelet/x/term v0.2.2 // indirect github.com/cloudflare/circl v1.6.3 // indirect github.com/containerd/cgroups/v3 v3.1.3 // indirect - github.com/containerd/containerd v1.7.30 // indirect + github.com/containerd/containerd v1.7.32 // indirect github.com/containerd/containerd/api v1.11.1 // indirect github.com/containerd/continuity v0.5.0 // indirect github.com/containerd/errdefs v1.0.0 // indirect diff --git a/go.sum b/go.sum index d46acad4d..a63a6355c 100644 --- a/go.sum +++ b/go.sum @@ -76,12 +76,15 @@ filippo.io/edwards25519 v1.1.0 h1:FNf4tywRC1HmFuKW5xopWpigGjJKiJSV0Cqo0cJWDaA= filippo.io/edwards25519 v1.1.0/go.mod h1:BxyFTGdWcka3PhytdK4V28tE5sGfRvvvRV7EaN4VDT4= github.com/AdaLogics/go-fuzz-headers v0.0.0-20240806141605-e8a1dd7889d6 h1:He8afgbRMd7mFxO99hRNu+6tazq8nFF9lIwo9JFroBk= github.com/AdaLogics/go-fuzz-headers v0.0.0-20240806141605-e8a1dd7889d6/go.mod h1:8o94RPi1/7XTJvwPpRSzSUedZrtlirdB3r9Z20bi2f8= +github.com/AdamKorcz/go-118-fuzz-build v0.0.0-20240914100643-eb91380d8434 h1:t9mXVk8SurivauUmW28nWggC/aOm5NBZ+U2ddBfbyP8= +github.com/AdamKorcz/go-118-fuzz-build v0.0.0-20240914100643-eb91380d8434/go.mod h1:n+tj8pffsLO7fLdcrnbfl444A2OwGv8a6ISsac75Wow= github.com/Azure/go-ansiterm v0.0.0-20250102033503-faa5f7b0171c h1:udKWzYgxTojEKWjV8V+WSxDXJ4NFATAsZjh8iIbsQIg= github.com/Azure/go-ansiterm v0.0.0-20250102033503-faa5f7b0171c/go.mod h1:xomTg63KZ2rFqZQzSB4Vz2SUXa1BpHTVz9L5PTmPC4E= github.com/BobuSumisu/aho-corasick v1.0.3 h1:uuf+JHwU9CHP2Vx+wAy6jcksJThhJS9ehR8a+4nPE9g= github.com/BobuSumisu/aho-corasick v1.0.3/go.mod h1:hm4jLcvZKI2vRF2WDU1N4p/jpWtpOzp3nLmi9AzX/XE= github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= github.com/BurntSushi/toml v0.4.1/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbicEuybxQ= +github.com/BurntSushi/toml v1.4.0/go.mod h1:ukJfTF/6rtPPRCnwkur4qwRxa8vTRFBF0uk2lLoLwho= github.com/BurntSushi/toml v1.6.0 h1:dRaEfpa2VI55EwlIW72hMRHdWouJeRF7TPYhI+AUQjk= github.com/BurntSushi/toml v1.6.0/go.mod h1:ukJfTF/6rtPPRCnwkur4qwRxa8vTRFBF0uk2lLoLwho= github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo= @@ -307,6 +310,8 @@ github.com/charmbracelet/x/term v0.2.2 h1:xVRT/S2ZcKdhhOuSP4t5cLi5o+JxklsoEObBSg github.com/charmbracelet/x/term v0.2.2/go.mod h1:kF8CY5RddLWrsgVwpw4kAa6TESp6EB5y3uxGLeCqzAI= github.com/checkmarx/2ms/v3 v3.21.0 h1:EcabeDypNMsSidISQbziZ062HjMZQ+Hm/uOJ5AOxK8o= github.com/checkmarx/2ms/v3 v3.21.0/go.mod h1:e8f4F94MZ+iCetR/G3aw7nXdPe6TgPI92Zzk/NG1l0o= +github.com/checkpoint-restore/go-criu/v6 v6.3.0 h1:mIdrSO2cPNWQY1truPg6uHLXyKHk3Z5Odx4wjKOASzA= +github.com/checkpoint-restore/go-criu/v6 v6.3.0/go.mod h1:rrRTN/uSwY2X+BPRl/gkulo9gsKOSAeVp9/K2tv7xZI= github.com/chromedp/cdproto v0.0.0-20230802225258-3cf4e6d46a89/go.mod h1:GKljq0VrfU4D5yc+2qA6OVr8pmO/MBbPEWqWQ/oqGEs= github.com/chromedp/chromedp v0.9.2/go.mod h1:LkSXJKONWTCHAfQasKFUZI+mxqS4tZqhmtGzzhLsnLs= github.com/chromedp/sysutil v1.0.0/go.mod h1:kgWmDdq8fTzXYcKIBqIYvRRTnYb9aNS9moAV0xufSww= @@ -316,6 +321,8 @@ github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5P github.com/chzyer/readline v1.5.1/go.mod h1:Eh+b79XXUwfKfcPLepksvw2tcLE/Ct21YObkaSkeBlk= github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU= github.com/chzyer/test v1.0.0/go.mod h1:2JlltgoNkt4TW/z9V/IzDdFaMTM2JPIi26O1pF38GC8= +github.com/cilium/ebpf v0.17.3 h1:FnP4r16PWYSE4ux6zN+//jMcW4nMVRvuTLVTvCjyyjg= +github.com/cilium/ebpf v0.17.3/go.mod h1:G5EDHij8yiLzaqn0WjyfJHvRa+3aDlReIaLVRMvOyJk= github.com/circonus-labs/circonus-gometrics v2.3.1+incompatible/go.mod h1:nmEj6Dob7S7YxXgwXpfOuvO54S+tGdZdw9fuRZt25Ag= github.com/circonus-labs/circonusllhist v0.1.3/go.mod h1:kMXHVDlOchFAehlya5ePtbp5jckzBHf4XRpQvBOLI+I= github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= @@ -341,6 +348,8 @@ github.com/containerd/cgroups/v3 v3.1.2 h1:OSosXMtkhI6Qove637tg1XgK4q+DhR0mX8Wi8 github.com/containerd/cgroups/v3 v3.1.2/go.mod h1:PKZ2AcWmSBsY/tJUVhtS/rluX0b1uq1GmPO1ElCmbOw= github.com/containerd/cgroups/v3 v3.1.3 h1:eUNflyMddm18+yrDmZPn3jI7C5hJ9ahABE5q6dyLYXQ= github.com/containerd/cgroups/v3 v3.1.3/go.mod h1:PKZ2AcWmSBsY/tJUVhtS/rluX0b1uq1GmPO1ElCmbOw= +github.com/containerd/console v1.0.5 h1:R0ymNeydRqH2DmakFNdmjR2k0t7UPuiOV/N/27/qqsc= +github.com/containerd/console v1.0.5/go.mod h1:YynlIjWYF8myEu6sdkwKIvGQq+cOckRm6So2avqoYAk= github.com/containerd/containerd v1.7.32 h1:S54xuVcPxeLaYgaRABtpJ2VyVUVsy0IGf7qHBs+sbY8= github.com/containerd/containerd v1.7.32/go.mod h1:jdwD6s/BhV4XVJGrvtziNPVA+83n66TwptVaPKprq4E= github.com/containerd/containerd/api v1.10.0 h1:5n0oHYVBwN4VhoX9fFykCV9dF1/BvAXeg2F8W6UYq1o= @@ -387,8 +396,13 @@ github.com/coreos/go-systemd/v22 v22.5.0/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSV github.com/coreos/go-systemd/v22 v22.6.0 h1:aGVa/v8B7hpb0TKl0MWoAavPDmHvobFe5R5zn0bCJWo= github.com/coreos/go-systemd/v22 v22.6.0/go.mod h1:iG+pp635Fo7ZmV/j14KUcmEyWF+0X7Lua8rrTWzYgWU= github.com/coreos/go-systemd/v22 v22.7.0 h1:LAEzFkke61DFROc7zNLX/WA2i5J8gYqe0rSj9KI28KA= +github.com/coreos/go-systemd/v22 v22.7.0/go.mod h1:xNUYtjHu2EDXbsxz1i41wouACIwT7Ybq9o0BQhMwD0w= github.com/cpuguy83/go-md2man/v2 v2.0.1/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= +github.com/cpuguy83/go-md2man/v2 v2.0.2/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= +github.com/cpuguy83/go-md2man/v2 v2.0.5/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= github.com/cpuguy83/go-md2man/v2 v2.0.6/go.mod h1:oOW0eioCTA6cOiMLiUPZOpcVxMig6NIQQ7OS05n1F4g= +github.com/cpuguy83/go-md2man/v2 v2.0.7 h1:zbFlGlXEAKlwXpmvle3d8Oe3YnkKIK4xSRTd3sHPnBo= +github.com/cpuguy83/go-md2man/v2 v2.0.7/go.mod h1:oOW0eioCTA6cOiMLiUPZOpcVxMig6NIQQ7OS05n1F4g= github.com/creack/pty v1.1.24 h1:bJrF4RRfyJnbTJqzRLHzcGaZK1NeM5kTC9jGgovnR1s= github.com/creack/pty v1.1.24/go.mod h1:08sCNb52WyoAwi2QDyzUCTgcvVFhUzewun7wtTfvcwE= github.com/cyphar/filepath-securejoin v0.6.1 h1:5CeZ1jPXEiYt3+Z6zqprSAgSWiggmpVyciv8syjIpVE= @@ -570,6 +584,8 @@ github.com/gobwas/ws v1.2.1/go.mod h1:hRKAFb8wOxFROYNsT1bqfWnhX+b5MFeJM9r2ZSwg/K github.com/goccy/go-yaml v1.19.2 h1:PmFC1S6h8ljIz6gMRBopkjP1TVT7xuwrButHID66PoM= github.com/goccy/go-yaml v1.19.2/go.mod h1:XBurs7gK8ATbW4ZPGKgcbrY1Br56PdM69F7LkFRi1kA= github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= +github.com/godbus/dbus/v5 v5.1.0 h1:4KLkAxT3aOY8Li4FRJe/KvhoNFFxo0m6fNuFUO8QJUk= +github.com/godbus/dbus/v5 v5.1.0/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= github.com/gofrs/flock v0.13.0 h1:95JolYOvGMqeH31+FC7D2+uULf6mG61mEZ/A8dRYMzw= github.com/gofrs/flock v0.13.0/go.mod h1:jxeyy9R1auM5S6JYDBhDt+E2TCo7DkratH4Pgi8P+Z0= github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= @@ -912,6 +928,8 @@ github.com/moby/moby/api v1.54.1 h1:TqVzuJkOLsgLDDwNLmYqACUuTehOHRGKiPhvH8V3Nn4= github.com/moby/moby/api v1.54.1/go.mod h1:+RQ6wluLwtYaTd1WnPLykIDPekkuyD/ROWQClE83pzs= github.com/moby/moby/client v0.4.0 h1:S+2XegzHQrrvTCvF6s5HFzcrywWQmuVnhOXe2kiWjIw= github.com/moby/moby/client v0.4.0/go.mod h1:QWPbvWchQbxBNdaLSpoKpCdf5E+WxFAgNHogCWDoa7g= +github.com/moby/sys/capability v0.4.0 h1:4D4mI6KlNtWMCM1Z/K0i7RV1FkX+DBDHKVJpCndZoHk= +github.com/moby/sys/capability v0.4.0/go.mod h1:4g9IK291rVkms3LKCDOoYlnV8xKwoDTpIrNEE35Wq0I= github.com/moby/sys/mountinfo v0.7.2 h1:1shs6aH5s4o5H2zQLn796ADW1wMrIwHsyJ2v9KouLrg= github.com/moby/sys/mountinfo v0.7.2/go.mod h1:1YOa8w8Ih7uW0wALDUgT1dTTSBrZ+HiBLGws92L2RU4= github.com/moby/sys/sequential v0.6.0 h1:qrx7XFUd/5DxtqcoH1h438hF5TmOvzC/lspjy7zgvCU= @@ -934,6 +952,8 @@ github.com/modern-go/reflect2 v1.0.3-0.20250322232337-35a7c28c31ee h1:W5t00kpgFd github.com/modern-go/reflect2 v1.0.3-0.20250322232337-35a7c28c31ee/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk= github.com/monochromegane/go-gitignore v0.0.0-20200626010858-205db1a8cc00 h1:n6/2gBQ3RWajuToeY6ZtZTIKv2v7ThUy5KKusIT0yc0= github.com/monochromegane/go-gitignore v0.0.0-20200626010858-205db1a8cc00/go.mod h1:Pm3mSP3c5uWn86xMLZ5Sa7JB9GsEZySvHYXCTK4E9q4= +github.com/mrunalp/fileutils v0.5.1 h1:F+S7ZlNKnrwHfSwdlgNSkKo67ReVf8o9fel6C3dkm/Q= +github.com/mrunalp/fileutils v0.5.1/go.mod h1:M1WthSahJixYnrXQl/DFQuteStB1weuxD2QJNHXfbSQ= github.com/mssola/user_agent v0.6.0 h1:uwPR4rtWlCHRFyyP9u2KOV0u8iQXmS7Z7feTrstQwk4= github.com/mssola/user_agent v0.6.0/go.mod h1:TTPno8LPY3wAIEKRpAtkdMT0f8SE24pLRGPahjCH4uw= github.com/muesli/ansi v0.0.0-20230316100256-276c6243b2f6 h1:ZK8zHtRHOkbHy6Mmr5D264iyp3TiX5OmNcI5cIARiQI= @@ -965,10 +985,14 @@ github.com/onsi/ginkgo/v2 v2.27.2 h1:LzwLj0b89qtIy6SSASkzlNvX6WktqurSHwkk2ipF/Ns github.com/onsi/ginkgo/v2 v2.27.2/go.mod h1:ArE1D/XhNXBXCBkKOLkbsb2c81dQHCRcF5zwn/ykDRo= github.com/onsi/gomega v1.38.2 h1:eZCjf2xjZAqe+LeWvKb5weQ+NcPwX84kqJ0cZNxok2A= github.com/onsi/gomega v1.38.2/go.mod h1:W2MJcYxRGV63b418Ai34Ud0hEdTVXq9NW9+Sx6uXf3k= +github.com/opencontainers/cgroups v0.0.4 h1:XVj8P/IHVms/j+7eh8ggdkTLAxjz84ZzuFyGoE28DR4= +github.com/opencontainers/cgroups v0.0.4/go.mod h1:s8lktyhlGUqM7OSRL5P7eAW6Wb+kWPNvt4qvVfzA5vs= github.com/opencontainers/go-digest v1.0.0 h1:apOUWs51W5PlhuyGyz9FCeeBIOUDA/6nW8Oi/yOhh5U= github.com/opencontainers/go-digest v1.0.0/go.mod h1:0JzlMkj0TRzQZfJkVvzbP0HBR3IKzErnv2BNG4W4MAM= github.com/opencontainers/image-spec v1.1.1 h1:y0fUlFfIZhPF1W537XOLg0/fcx6zcHCJwooC2xJA040= github.com/opencontainers/image-spec v1.1.1/go.mod h1:qpqAh3Dmcf36wStyyWU+kCeDgrGnAve2nCC8+7h8Q0M= +github.com/opencontainers/runc v1.3.4 h1:+lwmPUTzbgv0JFqu8zBU2WtHYbm+JPPS9hxB/PvWd30= +github.com/opencontainers/runc v1.3.4/go.mod h1:o1wyv76EDlTkcf0KTFgN8bMWLPvgF/HfX709lDv+rr4= github.com/opencontainers/runtime-spec v1.3.0 h1:YZupQUdctfhpZy3TM39nN9Ika5CBWT5diQ8ibYCRkxg= github.com/opencontainers/runtime-spec v1.3.0/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0= github.com/opencontainers/selinux v1.13.0 h1:Zza88GWezyT7RLql12URvoxsbLfjFx988+LGaWfbL84= @@ -1076,6 +1100,8 @@ github.com/scylladb/go-set v1.0.3-0.20200225121959-cc7b2070d91e/go.mod h1:DkpGd7 github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529/go.mod h1:DxrIzT+xaE7yg65j358z/aeFdxmN0P9QXhEzd20vsDc= github.com/sebdah/goldie/v2 v2.8.0 h1:dZb9wR8q5++oplmEiJT+U/5KyotVD+HNGCAc5gNr8rc= github.com/sebdah/goldie/v2 v2.8.0/go.mod h1:oZ9fp0+se1eapSRjfYbsV/0Hqhbuu3bJVvKI/NNtssI= +github.com/seccomp/libseccomp-golang v0.10.0 h1:aA4bp+/Zzi0BnWZ2F1wgNBs5gTpm+na2rWM6M9YjLpY= +github.com/seccomp/libseccomp-golang v0.10.0/go.mod h1:JA8cRccbGaA1s33RQf7Y1+q9gHmZX1yB/z9WDN1C6fg= github.com/sergi/go-diff v1.1.0/go.mod h1:STckp+ISIX8hZLjrqAeVduY0gWCT9IjLuqbuNXdaHfM= github.com/sergi/go-diff v1.2.0/go.mod h1:STckp+ISIX8hZLjrqAeVduY0gWCT9IjLuqbuNXdaHfM= github.com/sergi/go-diff v1.4.0 h1:n/SP9D5ad1fORl+llWyN+D6qoUETXNZARKjyY2/KVCw= @@ -1112,6 +1138,7 @@ github.com/spf13/cast v1.4.1/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkU github.com/spf13/cast v1.10.0 h1:h2x0u2shc1QuLHfxi+cTJvs30+ZAHOGRic8uyGTDWxY= github.com/spf13/cast v1.10.0/go.mod h1:jNfB8QC9IA6ZuY2ZjDp0KtFO2LZZlg4S/7bzP6qqeHo= github.com/spf13/cobra v1.3.0/go.mod h1:BrRVncBjOJa/eUcVVm9CE+oC6as8k+VYr4NY7WCi9V4= +github.com/spf13/cobra v1.5.0/go.mod h1:dWXEIy2H428czQCjInthrTRUg7yKbok+2Qi/yBIJoUM= github.com/spf13/cobra v1.10.2 h1:DMTTonx5m65Ic0GOoRY2c16WCbHxOOw6xxezuLaBpcU= github.com/spf13/cobra v1.10.2/go.mod h1:7C1pvHqHw5A4vrJfjNwvOdzYu0Gml16OCs2GRiTUUS4= github.com/spf13/jwalterweatherman v1.1.0/go.mod h1:aNWZUN0dPAAO/Ljvb5BEdw96iTZ0EXowPYD95IqWIGo= @@ -1139,6 +1166,8 @@ github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/ github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= +github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= +github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= github.com/stretchr/testify v1.11.1 h1:7s2iGBzp5EwR7/aIZr8ao5+dra3wiQyKjjFuvgVKu7U= github.com/stretchr/testify v1.11.1/go.mod h1:wZwfW3scLgRK+23gO65QZefKpKQRnfz6sD981Nm4B6U= github.com/subosito/gotenv v1.2.0/go.mod h1:N0PQaV/YGNqwC0u51sEeR/aUtSLEXKX9iv69rRypqCw= @@ -1166,12 +1195,18 @@ github.com/tv42/httpunix v0.0.0-20150427012821-b75d8614f926/go.mod h1:9ESjWnEqri github.com/ulikunitz/xz v0.5.8/go.mod h1:nbz6k7qbPmH4IRqmfOplQw/tblSgqTqBwxkY0oWt/14= github.com/ulikunitz/xz v0.5.15 h1:9DNdB5s+SgV3bQ2ApL10xRc35ck0DuIX/isZvIk+ubY= github.com/ulikunitz/xz v0.5.15/go.mod h1:nbz6k7qbPmH4IRqmfOplQw/tblSgqTqBwxkY0oWt/14= +github.com/urfave/cli v1.22.16 h1:MH0k6uJxdwdeWQTwhSO42Pwr4YLrNLwBtg1MRgTqPdQ= +github.com/urfave/cli v1.22.16/go.mod h1:EeJR6BKodywf4zciqrdw6hpCPk68JO9z5LazXZMn5Po= github.com/vbatts/go-mtree v0.7.0 h1:ytmOc3MTRidZiBi9VBCyZ2BHe4fZS47L5v7BVXDWW4E= github.com/vbatts/go-mtree v0.7.0/go.mod h1:EjdpFC+LZy1TXbRGNa1MKKgjQ+7ew3foMFJK8o4/TdY= github.com/vbatts/tar-split v0.12.2 h1:w/Y6tjxpeiFMR47yzZPlPj/FcPLpXbTUi/9H7d3CPa4= github.com/vbatts/tar-split v0.12.2/go.mod h1:eF6B6i6ftWQcDqEn3/iGFRFRo8cBIMSJVOpnNdfTMFA= github.com/vifraa/gopom v1.0.0 h1:L9XlKbyvid8PAIK8nr0lihMApJQg/12OBvMA28BcWh0= github.com/vifraa/gopom v1.0.0/go.mod h1:oPa1dcrGrtlO37WPDBm5SqHAT+wTgF8An1Q71Z6Vv4o= +github.com/vishvananda/netlink v1.3.1 h1:3AEMt62VKqz90r0tmNhog0r/PpWKmrEShJU0wJW6bV0= +github.com/vishvananda/netlink v1.3.1/go.mod h1:ARtKouGSTGchR8aMwmkzC0qiNPrrWO5JS/XMVl45+b4= +github.com/vishvananda/netns v0.0.5 h1:DfiHV+j8bA32MFM7bfEunvT8IAqQ/NzSJHtcmW5zdEY= +github.com/vishvananda/netns v0.0.5/go.mod h1:SpkAiCQRtJ6TvvxPnOSyH3BMl6unz3xZlaprSwhNNJM= github.com/wagoodman/go-partybus v0.0.0-20230516145632-8ccac152c651 h1:jIVmlAFIqV3d+DOxazTR9v+zgj8+VYuQBzPgBZvWBHA= github.com/wagoodman/go-partybus v0.0.0-20230516145632-8ccac152c651/go.mod h1:b26F2tHLqaoRQf8DywqzVaV1MQ9yvjb0OMcNl7Nxu20= github.com/wagoodman/go-progress v0.0.0-20260303201901-10176f79b2c0 h1:EHsPe0Q0ANoLOZff1dBLAyeWLTA4sbPTpGI+2zb0FnM= @@ -1328,6 +1363,8 @@ golang.org/x/exp v0.0.0-20260410095643-746e56fc9e2f h1:W3F4c+6OLc6H2lb//N1q4WpJk golang.org/x/exp v0.0.0-20260410095643-746e56fc9e2f/go.mod h1:J1xhfL/vlindoeF/aINzNzt2Bket5bjo9sdOYzOsU80= golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js= golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= +golang.org/x/image v0.36.1-0.20260211191414-e3d762b1d37e h1:gkwT7ZpRdJBB47MJ0h7xeUSHKkd8f3RcM47FgUIRgd4= +golang.org/x/image v0.36.1-0.20260211191414-e3d762b1d37e/go.mod h1:ZK2ak7W75f61R/Pwr7T25elpTMmDbUsuiOt4FcDsNI0= golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU= golang.org/x/lint v0.0.0-20190301231843-5614ed5bae6f/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= @@ -1511,9 +1548,12 @@ golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.2.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.10.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.17.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/sys v0.43.0 h1:Rlag2XtaFTxp19wS8MXlJwTvoh8ArU6ezoyFsMyCTNI= @@ -1771,6 +1811,7 @@ google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlba google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= google.golang.org/protobuf v1.27.1/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= +google.golang.org/protobuf v1.28.1/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= google.golang.org/protobuf v1.36.11 h1:fV6ZwhNocDyBLK0dj+fg8ektcVegBBuEolpbTQyBNVE= google.golang.org/protobuf v1.36.11/go.mod h1:HTf+CrKn2C3g5S8VImy6tdcUvCska2kB7j23XfzDpco= google.golang.org/protobuf v1.36.12-0.20260120151049-f2248ac996af h1:+5/Sw3GsDNlEmu7TfklWKPdQ0Ykja5VEmq2i817+jbI= From c1a7a8b771cb1593542ca881aabda57e8a6c246d Mon Sep 17 00:00:00 2001 From: atishj99 <141334503+cx-atish-jadhav@users.noreply.github.com> Date: Wed, 27 May 2026 16:54:08 +0530 Subject: [PATCH 18/27] Fix k8s.io/kubectl version mismatch after SCA dependency upgrades Upgrade k8s.io/kubectl from v0.35.1 to v0.36.0 to resolve missing package k8s.io/api/scheduling/v1alpha1 caused by k8s.io/api being upgraded to v0.36.0 during SCA vulnerability remediation. Co-Authored-By: Claude Haiku 4.5 --- go.mod | 10 +++++----- go.sum | 12 ++++++++++++ 2 files changed, 17 insertions(+), 5 deletions(-) diff --git a/go.mod b/go.mod index afc5207b2..8cd6ba556 100644 --- a/go.mod +++ b/go.mod @@ -252,7 +252,7 @@ require ( github.com/google/go-cmp v0.7.0 // indirect github.com/google/go-containerregistry v0.21.5 // indirect github.com/google/licensecheck v0.3.1 // indirect - github.com/google/pprof v0.0.0-20250820193118-f64d9cf942d6 // indirect + github.com/google/pprof v0.0.0-20260115054156-294ebfa9ad83 // indirect github.com/gorilla/websocket v1.5.4-0.20250319132907-e064f32e3674 // indirect github.com/gosuri/uitable v0.0.4 // indirect github.com/gregjones/httpcache v0.0.0-20190611155906-901d90724c79 // indirect @@ -392,12 +392,12 @@ require ( k8s.io/apiextensions-apiserver v0.35.1 // indirect k8s.io/apimachinery v0.36.0 // indirect k8s.io/apiserver v0.35.1 // indirect - k8s.io/cli-runtime v0.35.1 // indirect + k8s.io/cli-runtime v0.36.0 // indirect k8s.io/client-go v0.36.0 // indirect k8s.io/component-base v0.36.0 // indirect k8s.io/klog/v2 v2.140.0 // indirect k8s.io/kube-openapi v0.0.0-20260319004828-5883c5ee87b9 // indirect - k8s.io/kubectl v0.35.1 // indirect + k8s.io/kubectl v0.36.0 // indirect k8s.io/utils v0.0.0-20260319190234-28399d86e0b5 // indirect modernc.org/libc v1.70.0 // indirect modernc.org/mathutil v1.7.1 // indirect @@ -405,8 +405,8 @@ require ( modernc.org/sqlite v1.46.2 // indirect oras.land/oras-go/v2 v2.6.0 // indirect sigs.k8s.io/json v0.0.0-20250730193827-2d320260d730 // indirect - sigs.k8s.io/kustomize/api v0.20.1 // indirect - sigs.k8s.io/kustomize/kyaml v0.20.1 // indirect + sigs.k8s.io/kustomize/api v0.21.1 // indirect + sigs.k8s.io/kustomize/kyaml v0.21.1 // indirect sigs.k8s.io/randfill v1.0.0 // indirect sigs.k8s.io/yaml v1.6.0 // indirect ) diff --git a/go.sum b/go.sum index a63a6355c..5db673f17 100644 --- a/go.sum +++ b/go.sum @@ -685,6 +685,8 @@ github.com/google/pprof v0.0.0-20211214055906-6f57359322fd/go.mod h1:KgnwoLYCZ8I github.com/google/pprof v0.0.0-20240227163752-401108e1b7e7/go.mod h1:czg5+yv1E0ZGTi6S6vVK1mke0fV+FaUhNGcd6VRS9Ik= github.com/google/pprof v0.0.0-20250820193118-f64d9cf942d6 h1:EEHtgt9IwisQ2AZ4pIsMjahcegHh6rmhqxzIRQIyepY= github.com/google/pprof v0.0.0-20250820193118-f64d9cf942d6/go.mod h1:I6V7YzU0XDpsHqbsyrghnFZLO1gwK6NPTNvmetQIk9U= +github.com/google/pprof v0.0.0-20260115054156-294ebfa9ad83 h1:z2ogiKUYzX5Is6zr/vP9vJGqPwcdqsWjOt+V8J7+bTc= +github.com/google/pprof v0.0.0-20260115054156-294ebfa9ad83/go.mod h1:MxpfABSjhmINe3F1It9d+8exIHFvUqtLIRCdOGNXqiI= github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= github.com/google/s2a-go v0.1.9 h1:LGD7gtMgezd8a/Xak7mEWL0PjoTQFvpRudN895yqKW0= github.com/google/s2a-go v0.1.9/go.mod h1:YA0Ei2ZQL3acow2O62kdp9UlnvMmU7kA6Eutn0dXayM= @@ -983,8 +985,10 @@ github.com/olekukonko/tablewriter v1.1.4 h1:ORUMI3dXbMnRlRggJX3+q7OzQFDdvgbN9nVW github.com/olekukonko/tablewriter v1.1.4/go.mod h1:+kedxuyTtgoZLwif3P1Em4hARJs+mVnzKxmsCL/C5RY= github.com/onsi/ginkgo/v2 v2.27.2 h1:LzwLj0b89qtIy6SSASkzlNvX6WktqurSHwkk2ipF/Ns= github.com/onsi/ginkgo/v2 v2.27.2/go.mod h1:ArE1D/XhNXBXCBkKOLkbsb2c81dQHCRcF5zwn/ykDRo= +github.com/onsi/ginkgo/v2 v2.28.1 h1:S4hj+HbZp40fNKuLUQOYLDgZLwNUVn19N3Atb98NCyI= github.com/onsi/gomega v1.38.2 h1:eZCjf2xjZAqe+LeWvKb5weQ+NcPwX84kqJ0cZNxok2A= github.com/onsi/gomega v1.38.2/go.mod h1:W2MJcYxRGV63b418Ai34Ud0hEdTVXq9NW9+Sx6uXf3k= +github.com/onsi/gomega v1.39.1 h1:1IJLAad4zjPn2PsnhH70V4DKRFlrCzGBNrNaru+Vf28= github.com/opencontainers/cgroups v0.0.4 h1:XVj8P/IHVms/j+7eh8ggdkTLAxjz84ZzuFyGoE28DR4= github.com/opencontainers/cgroups v0.0.4/go.mod h1:s8lktyhlGUqM7OSRL5P7eAW6Wb+kWPNvt4qvVfzA5vs= github.com/opencontainers/go-digest v1.0.0 h1:apOUWs51W5PlhuyGyz9FCeeBIOUDA/6nW8Oi/yOhh5U= @@ -1869,6 +1873,8 @@ k8s.io/apiserver v0.35.1 h1:potxdhhTL4i6AYAa2QCwtlhtB1eCdWQFvJV6fXgJzxs= k8s.io/apiserver v0.35.1/go.mod h1:BiL6Dd3A2I/0lBnteXfWmCFobHM39vt5+hJQd7Lbpi4= k8s.io/cli-runtime v0.35.1 h1:uKcXFe8J7AMAM4Gm2JDK4mp198dBEq2nyeYtO+JfGJE= k8s.io/cli-runtime v0.35.1/go.mod h1:55/hiXIq1C8qIJ3WBrWxEwDLdHQYhBNRdZOz9f7yvTw= +k8s.io/cli-runtime v0.36.0 h1:HNxciQpQMMOKS0/GiUXcKDyA6J2FDILJj9NmP2BZrTg= +k8s.io/cli-runtime v0.36.0/go.mod h1:KObkknK9Ro5LYX+1RdiKc7C8CvGg4aX+V/Zv+E8WPHA= k8s.io/client-go v0.35.1 h1:+eSfZHwuo/I19PaSxqumjqZ9l5XiTEKbIaJ+j1wLcLM= k8s.io/client-go v0.35.1/go.mod h1:1p1KxDt3a0ruRfc/pG4qT/3oHmUj1AhSHEcxNSGg+OA= k8s.io/client-go v0.36.0 h1:pOYi7C4RHChYjMiHpZSpSbIM6ZxVbRXBy7CuiIwqA3c= @@ -1887,6 +1893,8 @@ k8s.io/kube-openapi v0.0.0-20260319004828-5883c5ee87b9 h1:Sztf7ESG9tAXRW/ACJZjrj k8s.io/kube-openapi v0.0.0-20260319004828-5883c5ee87b9/go.mod h1:uGBT7iTA6c6MvqUvSXIaYZo9ukscABYi2btjhvgKGZ0= k8s.io/kubectl v0.35.1 h1:zP3Er8C5i1dcAFUMh9Eva0kVvZHptXIn/+8NtRWMxwg= k8s.io/kubectl v0.35.1/go.mod h1:cQ2uAPs5IO/kx8R5s5J3Ihv3VCYwrx0obCXum0CvnXo= +k8s.io/kubectl v0.36.0 h1:hEGr8NvIm2Wjqs2Xy48Uzmvo6lpHdGKlLyMvau2gTms= +k8s.io/kubectl v0.36.0/go.mod h1:iDe8aV5BEi45W8k+5n71I2pJ/nwE0PHDu+/2cejzYoo= k8s.io/utils v0.0.0-20251002143259-bc988d571ff4 h1:SjGebBtkBqHFOli+05xYbK8YF1Dzkbzn+gDM4X9T4Ck= k8s.io/utils v0.0.0-20251002143259-bc988d571ff4/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0= k8s.io/utils v0.0.0-20260319190234-28399d86e0b5 h1:kBawHLSnx/mYHmRnNUf9d4CpjREbeZuxoSGOX/J+aYM= @@ -1930,8 +1938,12 @@ sigs.k8s.io/json v0.0.0-20250730193827-2d320260d730 h1:IpInykpT6ceI+QxKBbEflcR5E sigs.k8s.io/json v0.0.0-20250730193827-2d320260d730/go.mod h1:mdzfpAEoE6DHQEN0uh9ZbOCuHbLK5wOm7dK4ctXE9Tg= sigs.k8s.io/kustomize/api v0.20.1 h1:iWP1Ydh3/lmldBnH/S5RXgT98vWYMaTUL1ADcr+Sv7I= sigs.k8s.io/kustomize/api v0.20.1/go.mod h1:t6hUFxO+Ph0VxIk1sKp1WS0dOjbPCtLJ4p8aADLwqjM= +sigs.k8s.io/kustomize/api v0.21.1 h1:lzqbzvz2CSvsjIUZUBNFKtIMsEw7hVLJp0JeSIVmuJs= +sigs.k8s.io/kustomize/api v0.21.1/go.mod h1:f3wkKByTrgpgltLgySCntrYoq5d3q7aaxveSagwTlwI= sigs.k8s.io/kustomize/kyaml v0.20.1 h1:PCMnA2mrVbRP3NIB6v9kYCAc38uvFLVs8j/CD567A78= sigs.k8s.io/kustomize/kyaml v0.20.1/go.mod h1:0EmkQHRUsJxY8Ug9Niig1pUMSCGHxQ5RklbpV/Ri6po= +sigs.k8s.io/kustomize/kyaml v0.21.1 h1:IVlbmhC076nf6foyL6Taw4BkrLuEsXUXNpsE+ScX7fI= +sigs.k8s.io/kustomize/kyaml v0.21.1/go.mod h1:hmxADesM3yUN2vbA5z1/YTBnzLJ1dajdqpQonwBL1FQ= sigs.k8s.io/randfill v1.0.0 h1:JfjMILfT8A6RbawdsK2JXGBR5AQVfd+9TbzrlneTyrU= sigs.k8s.io/randfill v1.0.0/go.mod h1:XeLlZ/jmk4i1HRopwe7/aU3H5n1zNUcX6TM94b3QxOY= sigs.k8s.io/structured-merge-diff/v6 v6.3.0 h1:jTijUJbW353oVOd9oTlifJqOGEkUw2jB/fXCbTiQEco= From df1be10d8fb3299513db79f25ad38e616e13ac66 Mon Sep 17 00:00:00 2001 From: atishj99 <141334503+cx-atish-jadhav@users.noreply.github.com> Date: Thu, 28 May 2026 12:28:32 +0530 Subject: [PATCH 19/27] create CLAUDE.md file for ast-cli repo --- CLAUDE.md | 500 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 500 insertions(+) create mode 100644 CLAUDE.md diff --git a/CLAUDE.md b/CLAUDE.md new file mode 100644 index 000000000..54116995e --- /dev/null +++ b/CLAUDE.md @@ -0,0 +1,500 @@ +# CLAUDE.md + +This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository. + +## Project Overview + +Checkmarx One CLI (`cx`) — a standalone command-line interface for the Checkmarx One application security platform. It orchestrates SAST, SCA, KICS (IaC), API Security, Container Security, Software Supply Chain Security, and DAST scans, manages projects/applications, retrieves results in multiple formats (JSON, SARIF, PDF, SBOM), and decorates pull requests across GitHub, GitLab, Azure DevOps, and Bitbucket. Licensed under Apache 2.0. + +**The CLI is the backbone for all Checkmarx One plugins.** All plugins (IDE extensions, CI/CD integrations) wrap this CLI to initiate scans rather than calling APIs directly. This means changes here propagate to the entire plugin ecosystem — minimizing per-plugin updates but requiring careful backward compatibility. + +### Key Capabilities + +- **Project management:** Create, delete, list, show projects; manage tags +- **Scanning:** SAST, SCA, IaC Security, Container Security, API Security, Supply Chain Security +- **Results:** Retrieve, filter, export in JSON/SARIF/PDF/SBOM; CodeBashing training links; engine-specific exit codes +- **Utilities:** Shell auto-completion (bash/zsh/fish/PowerShell), environment variable display, contributor counting across SCMs (90-day window), PR decoration, SCA remediation (npm) +- **Integration:** CI/CD pipelines (Jenkins, Azure DevOps, GitHub Actions), IDEs, ServiceNow, Jira, Slack, Teams + + +### Plugin Ecosystem Context + +The CLI sits at the center of the Checkmarx One plugin architecture. Downstream consumers that wrap this CLI: +- **Language wrappers:** ast-cli-java-wrapper, ast-cli-javascript-wrapper +- **IDE plugins:** VS Code, JetBrains (IntelliJ), Eclipse, Visual Studio extensions +- **CI/CD plugins:** Jenkins, Azure DevOps, TeamCity, GitHub Action, Maven plugin + +All plugins invoke the `cx` binary rather than calling Checkmarx APIs directly. This centralizes API interaction logic but means CLI flag changes, exit code changes, or output format changes can break downstream consumers. + +### Layered Design: Commands → Services → Wrappers → HTTP Client + +1. **`cmd/main.go`** — Entry point. Instantiates all 30+ wrapper implementations via viper config keys and injects them into `commands.NewAstCLI()`. +2. **`internal/commands/`** — Cobra command definitions. Each command constructor accepts wrapper interfaces as parameters (e.g., `NewScanCommand(...wrappers...)`). Commands are registered in `root.go` via `rootCmd.AddCommand(...)`. +3. **`internal/services/`** — Business logic layer for multi-step operations (e.g., export, application management). +4. **`internal/wrappers/`** — HTTP abstractions for Checkmarx One APIs. Each service follows a triple-file pattern: + - Interface definition (e.g., `scans.go`) + - HTTP implementation (e.g., `scans-http.go`) + - Mock implementation in `mock/` subdirectory (e.g., `mock/scans-mock.go`) +5. **`internal/wrappers/client.go`** — Central HTTP client with OAuth2 auth, token caching, retry with exponential backoff, proxy support (Basic/NTLM/Kerberos/SSPI), TLS config, and request/response logging. +6. **`internal/wrappers/grpcs/`** — gRPC client for the ASCA (Abstract Syntax Code Analysis) engine running on localhost. + +### Adding a New API Integration + +- Define the wrapper interface in `internal/wrappers/` +- Create HTTP implementation in a `-http.go` file +- Create mock in `internal/wrappers/mock/` +- Add the wrapper parameter to `NewAstCLI()` in `internal/commands/root.go` and instantiate it in `cmd/main.go` +- Command constructors follow the pattern: `func NewXyzCommand(wrapper wrappers.XyzWrapper, ...) *cobra.Command` + +## Common User Flow + +1. **Configure:** `cx configure --apikey ` or set `CX_CLIENT_ID` + `CX_CLIENT_SECRET` env vars +2. **Create project:** `cx project create --name "MyProject"` +3. **Initiate scan:** `cx scan create --project-name "MyProject" --branch "main" --file-source "path/to/code" --scan-types "sast,sca,iac-security"` +4. **Retrieve results:** `cx results show --scan-id "" --report-format "json"` (supports json, sarif, pdf, sbom) +5. **Integrate findings:** PR decoration, IDE feedback, CI/CD pipeline exit codes + +Scans can target local directories (`--file-source`), Git repos (`--repo-url`), or container images (`--container-images`). Multiple engines can run simultaneously via `--scan-types`. + +## Repository Structure + +``` +cmd/ Entry point (main.go) — wrapper instantiation & DI +internal/ + commands/ Cobra command definitions (~20 top-level commands) + asca/ AI-powered code analysis subcommand + dast/ DAST environment management + util/ Shared utilities, printer, user count + .scripts/ CI test runner scripts (up.sh, integration_up.sh) + services/ Business logic (projects, applications, groups, export) + wrappers/ HTTP API abstractions (30+ wrapper interfaces) + mock/ Mock implementations for unit testing + grpcs/ gRPC clients (ASCA engine) + configuration/ Config file loading (~/.checkmarx/checkmarxcli.yaml) + bitbucketserver/ Bitbucket Server-specific wrapper + params/ CLI flags, env vars, viper keys, bindings + flags.go Flag name constants + envs.go Environment variable names (CX_* prefix) + keys.go Viper configuration keys + binds.go Flag-to-env-var bindings + constants/ + errors/ Domain-specific error constants + exit-codes/ Engine-specific exit codes for CI/CD + logger/ Logging with sensitive data sanitization +test/ + integration/ Integration tests (//go:build integration) + cleandata/ Post-test cleanup utilities +``` + +## Technology Stack + +- **Language:** Go 1.25.8 +- **CLI Framework:** Cobra v1.10.1 + Viper v1.20.1 +- **gRPC:** google.golang.org/grpc v1.79.3 + protobuf v1.36.10 +- **Auth:** golang-jwt/jwt/v5 v5.2.2, gokrb5/v8 (Kerberos), alexbrainman/sspi (Windows NTLM) +- **Container Analysis:** containers-resolver, containers-images-extractor, anchore/syft (SBOM) +- **Testing:** stretchr/testify v1.11.1, gotest.tools +- **Linting:** golangci-lint v2 with 20 enabled linters +- **Release:** GoReleaser, Cosign (image signing), gon (macOS notarization) +- **No database** — the CLI is stateless; all persistence is server-side + + +### Build + +```bash +# Build (runs fmt → vet → build) +make build + +# Individual steps +go fmt ./... +go vet ./... +go build -o bin/cx.exe ./cmd # Windows +go build -o bin/cx ./cmd # Linux/macOS + +# Initial CLI configuration +cx configure # Interactive prompt for base-uri, tenant, credentials +``` + +**Config file location:** `~/.checkmarx/checkmarxcli.yaml` (override with `--config-file-path` or `CX_CONFIG_FILE_PATH`). Uses file locking (`gofrs/flock`) for thread-safe writes. + +### Running Tests + +```bash +# Run all unit tests (excludes mock, wrappers, bitbucketserver, logger packages) +# Add -v for verbose output +go test $(go list ./... | grep -v "mock" | grep -v "wrappers" | grep -v "bitbucketserver" | grep -v "logger") -timeout 25m + +# Run tests for a specific package +go test ./internal/commands/ -v +go test ./internal/services/ -v + +# Run a specific test by name +go test ./internal/commands/ -run TestAuthValidate -v + +# Run tests matching a pattern +go test ./internal/commands/ -run TestScan -v # Runs all tests starting with "TestScan" + +# Run integration tests (requires env vars — see "Integration Test Configuration" below) +go test -tags integration -v -timeout 210m github.com/checkmarx/ast-cli/test/integration + +# Run a specific integration test +go test -tags integration -run TestScanCreate -v -timeout 210m github.com/checkmarx/ast-cli/test/integration +``` + +### Coverage + +```bash +# Generate coverage report (console summary) +go test $(go list ./... | grep -v "mock" | grep -v "wrappers" | grep -v "bitbucketserver" | grep -v "logger") -timeout 25m -coverprofile cover.out +go tool cover -func cover.out # Show per-function coverage +go tool cover -func cover.out | grep total # Show total coverage percentage + +# Generate detailed HTML coverage report +go tool cover -html=cover.out -o coverage.html + +# View coverage in browser +go tool cover -html=cover.out # Opens browser automatically + +# Integration test coverage (specific packages only) +go test -tags integration -v -timeout 210m \ + -coverpkg github.com/checkmarx/ast-cli/internal/commands,github.com/checkmarx/ast-cli/internal/services,github.com/checkmarx/ast-cli/internal/wrappers \ + -coverprofile cover-integration.out \ + github.com/checkmarx/ast-cli/test/integration +``` + +### Linting & Static Analysis + +```bash +# Run full linter suite (20 linters, see .golangci.yml) +golangci-lint run -c .golangci.yml +# or +make lint + +# Run Go vet only +go vet ./... + +# Run vulnerability scanner +govulncheck ./... +``` + +### Pre-Commit Checklist + +Always run before committing: + +```bash +go mod tidy +go vet ./... +go test -v $(go list ./... | grep -v "mock" | grep -v "wrappers" | grep -v "bitbucketserver" | grep -v "logger") -timeout 25m +golangci-lint run -c .golangci.yml +``` + +### Integration Test Configuration + +Integration tests require these environment variables (set via `.env` file or IDE run configuration): + +| Variable | Purpose | +|---|---| +| `CX_BASE_URI` | Checkmarx One API base URL | +| `CX_BASE_AUTH_URI` | Keycloak authentication URL | +| `CX_CLIENT_ID` | OAuth2 client ID | +| `CX_CLIENT_SECRET` | OAuth2 client secret | +| `CX_APIKEY` | API key (for API key auth tests) | +| `CX_TENANT` | Tenant name | +| `CX_AST_USERNAME` | Username (for basic auth tests) | +| `CX_AST_PASSWORD` | Password (for basic auth tests) | +| `CX_SCAN_SSH_KEY` | SSH key (for SSH scan tests) | +| `PERSONAL_ACCESS_TOKEN` | GitHub/GitLab token (for SCM tests) | +| `PR_GITHUB_TOKEN`, `PR_GITLAB_TOKEN`, `AZURE_TOKEN` | PR decoration tests | +| `PROXY_HOST`, `PROXY_PORT`, `PROXY_USERNAME`, `PROXY_PASSWORD` | Proxy tests | + +No `.env.example` file exists — refer to `.github/workflows/ci-tests.yml` (lines 55-93) for the full list of required secrets. + +## Coding Standards + +- **Flag naming:** kebab-case (e.g., `--scan-id`, `--client-secret`) +- **Environment variables:** `CX_` prefix in SCREAMING_SNAKE_CASE (e.g., `CX_BASE_URI`, `CX_CLIENT_ID`) +- **Max function length:** 200 lines / 100 statements (`funlen`) +- **Max cyclomatic complexity:** 15 (`gocyclo`) +- **Max line length:** 185 characters (`lll` — configured in `.golangci.yml` settings but not in the enabled linters list; not actively enforced) +- **Magic numbers:** Flagged by `mnd` linter (except in test files) +- **Duplicate code threshold:** 500 tokens (`dupl`) +- **Import restrictions:** `depguard` limits imports to stdlib + explicitly whitelisted packages in `.golangci.yml` +- **Formatters:** `gofmt` and `goimports` enforced + +## Project Rules + +- All wrapper dependencies must be injected through constructor parameters — never instantiate wrappers inside commands directly +- Every new wrapper needs all three files: interface, HTTP implementation, and mock +- When adding a wrapper, update both `NewAstCLI()` signature in `internal/commands/root.go` AND instantiation in `cmd/main.go` +- Viper config precedence (highest to lowest): CLI flags (`BindPFlag` in `root.go`) > env vars (`BindEnv` in `binds.go`) > config file > defaults +- Build with `CGO_ENABLED=0` for static linking (no C dependencies) +- Exit codes are engine-specific (SAST=2, SCA=3, KICS=4, API Security=5, multiple=1) — do not change these as CI/CD pipelines and downstream plugins depend on them +- The `depguard` linter will reject any import not on the allowlist — add new external packages to `.golangci.yml` before using them +- **Do not break CLI flag names, output formats, or exit codes without coordinating with the plugin ecosystem** — Java wrapper, JavaScript wrapper, and all IDE/CI plugins parse CLI output and depend on stable interfaces +- Dependabot PRs are auto-merged after CI passes — do not add manual approval gates to dependency update workflows + +## Testing Strategy + +### Coverage Thresholds + +- **Unit tests:** **77.7%** minimum (CI-enforced) +- **Integration tests:** **75%** minimum (CI-enforced) +- **CI pipeline order:** Unit tests → Integration tests → Lint (`golangci-lint`) → Vulnerability scan (`govulncheck`) → Docker image scan (Trivy) + +### Test File Creation Rules + +- Test files **must** end with `_test.go` and live in the same package as the code being tested +- **Unit tests in `internal/commands/`** must include `//go:build !integration` as the first line — this prevents them from running during integration test builds. Tests in other packages (`services/`, `wrappers/`) do not need this tag. +- **Integration tests must include** `//go:build integration` as the first line and live in `test/integration/` +- Each integration test file corresponds to a specific wrapper/service (e.g., `scan_test.go` for scanning) +- Test data files go in `test/integration/data/` (contains Dockerfiles, source files, ZIP archives, sample results) + +### Unit Test Patterns + +Unit tests use mock wrappers from `internal/wrappers/mock/`. The key setup function is `createASTTestCommand()` in `internal/commands/root_test.go`, which instantiates all mock wrappers and returns a fully-wired Cobra command: + +```go +//go:build !integration + +func TestMyFeature(t *testing.T) { + err := executeTestCommand(createASTTestCommand(), "scan", "create", "--project-name", "test") + assert.NilError(t, err) +} +``` + +**Helper functions** (defined in `internal/commands/root_test.go`): +- `createASTTestCommand()` — creates a CLI command with all mock wrappers injected +- `executeTestCommand(cmd, args...)` — executes command, resets viper after +- `execCmdNilAssertion(t, args...)` — execute and assert no error +- `execCmdNotNilAssertion(t, args...)` — execute and assert error returned +- `executeRedirectedTestCommand(args...)` — capture stdout to buffer + +**Assertion libraries:** `gotest.tools/assert` (primary: `assert.NilError()`, `assert.Assert()`, `assert.ErrorContains()`) and `stretchr/testify/assert` + +Both packages have a `TestMain(m *testing.M)` function for setup/teardown in `internal/commands/root_test.go` and `test/integration/root_test.go`. + +### Integration Test Patterns + +Integration tests use real HTTP wrappers (not mocks) and hit the **Checkmarx One integration environment configured via `CX_BASE_URI`**. The key setup function is `createASTIntegrationTestCommand(t)` in `test/integration/util_command.go`: + +```go +//go:build integration + +func TestScanCreate(t *testing.T) { + cmd := createASTIntegrationTestCommand(t) + err := execute(cmd, "scan", "create", "--project-name", projectName, "-b", "main", "-s", ".") + assert.NilError(t, err) +} +``` + +**Helper functions** (defined in `test/integration/util_command.go`): +- `createASTIntegrationTestCommand(t)` — creates CLI command with real HTTP wrappers +- `executeWithTimeout(cmd, timeout, args...)` — execute with context deadline and automatic retry/proxy flags +- `flag(f)` — adds `--` prefix to flag name + +**Test utilities** (defined in `test/integration/util.go`): +- `getProjectNameForTest()` / `GenerateRandomProjectNameForScan()` — unique project names +- `WriteProjectNameToFile(name)` — persist names for cleanup +- `formatTags(tags)` / `formatGroups(groups)` — format test data + +**Flaky test handling:** Integration test CI script (`internal/commands/.scripts/integration_up.sh`) includes automatic retry logic for flaky tests and uses `gocovmerge` to merge coverage profiles from retried runs. + + +## External Integrations + +| Integration | Protocol | Purpose | +|---|---|---| +| Checkmarx One API | REST/HTTPS | Scans, results, projects, applications, groups, policies, feature flags | +| ASCA Engine | gRPC (localhost) | AI-powered real-time code analysis | +| GitHub API | REST v3 | PR decoration, org/repo/commit fetching | +| GitLab API | REST v4 | PR decoration, project/commit fetching | +| Azure DevOps API | REST v5.0 | PR decoration, repo/project fetching | +| Bitbucket Cloud | REST | PR decoration, workspace/repo fetching | +| Bitbucket Server | REST v1.0 | PR decoration, project/repo fetching | +| SCA Realtime | HTTPS (`api-sca.checkmarx.net`) | Public endpoint for package vulnerability checks | +| Checkmarx Gen-AI | REST | AI chat for remediation guidance | +| Keycloak | OAuth2/OIDC | Token-based authentication | + +## Deployment + +- **Platforms:** Linux (amd64, arm, arm64), Windows (amd64), macOS (universal binary) +- **Formats:** tar.gz (Linux), ZIP (Windows), DMG (macOS), Docker image, Homebrew tap +- **Docker image:** Based on `checkmarx/bash:5.3` (Alpine), runs as `nonroot` user, SHA256-pinned base +- **Docker registries:** `checkmarx/ast-cli` and `cxsdlc/ast-cli` on Docker Hub +- **Signing:** Windows via AWS CloudHSM + osslsigncode, macOS via Apple Developer ID + gon notarization, Docker via Cosign +- **Release tool:** GoReleaser (`.goreleaser.yml` for production, `.goreleaser-dev.yml` for pre-releases) +- **Artifacts stored in:** GitHub Releases + AWS S3 (`CxOne/CLI/{tag}` and `CxOne/CLI/latest`) +- **Release workflow:** `.github/workflows/release.yml` — triggered via `workflow_dispatch` (manual) or `workflow_call` (from upstream). Runs on macOS 15 Intel. + +### Release Process + +1. Build binaries for all platforms (CGO_ENABLED=0, static linking) +2. Sign Windows binary (remote HSM signing), notarize macOS binary (gon) +3. Build and push Docker images (production only) +4. Sign Docker images with Cosign and verify signatures (production only) +5. Publish to GitHub Releases, S3, and Homebrew tap +6. **Notify** Microsoft Teams and JIRA with release info (production only) +7. **Dispatch auto-release** to downstream plugin repositories to update their CLI version + +### CI/CD Workflows (`.github/workflows/`) + +| Workflow | Purpose | +|---|---| +| `ci-tests.yml` | Unit tests, integration tests, lint, govulncheck, Trivy | +| `release.yml` | Full build, sign, publish, notify pipeline | +| `issue_automation.yml` | Auto-label and assign issues | +| `pr-add-reviewers.yml` | Auto-assign reviewers to PRs | +| `pr-label.yml` | Auto-label PRs | +| `pr-linter.yml` | Enforce PR guidelines | +| `checkmarx-one-scan.yml` | Security scan on PRs | +| `trivy-cache.yml` | Keep Trivy vulnerability definitions current | +| `ai-code-review.yml` | AI-powered code review on PRs | +| `dependabot-auto-merge.yml` | Auto-merge Dependabot PRs after CI passes | +| `nightly-parallel.yml` | Nightly parallel test runs | + +### JIRA Integration + +- JIRA tasks are automatically tagged with the release version upon deployment +- JIRA ticket numbers in PR titles (e.g., `AST-3432`) enable automation — see Contributing section for PR requirements + +## Performance Considerations + +- **HTTP timeout:** Default 5 seconds (configurable via `--timeout` / `CX_TIMEOUT`) +- **Connection pooling:** Persistent `KeepAlive` at 30 seconds via `http.Transport` +- **Token caching:** In-memory JWT cache with 10-second grace period before expiry; protected by `sync.Mutex` +- **Retry with exponential backoff:** Default 3 retries, 20s base delay. IAM retries: 4 attempts, 500ms base. Polling delay: 60s. +- **Rate limiting:** SCM-specific rate limit handling (GitHub, GitLab, Bitbucket, Azure) with 60s default wait and up to 3 retries +- **HTTP body logging cap:** Request/response bodies >1MB are not logged to prevent memory issues +- **Static binary:** `CGO_ENABLED=0` with `-s -w` flags strips symbols for smaller binaries + +## API / Endpoints / Interfaces + +All API paths are configured via environment variables with `CX_` prefix. Key endpoints: + +| Category | Env Var | Description | +|---|---|---| +| Core | `CX_BASE_URI` | Main Checkmarx One API URL | +| Auth | `CX_BASE_AUTH_URI` | Keycloak token endpoint | +| Scans | `CX_SCANS_PATH` | Scan CRUD operations | +| Results | `CX_RESULTS_PATH` | Scan result retrieval | +| Projects | `CX_PROJECTS_PATH` | Project management | +| Uploads | `CX_UPLOADS_PATH` | File upload (supports multipart via pre-signed URLs) | +| Feature Flags | `CX_FEATURE_FLAGS_PATH` | Feature gating per tenant | +| Export | `CX_EXPORT_PATH` | Bulk export operations | +| Reports | `CX_RESULTS_PDF_REPORT_PATH`, `CX_RESULTS_JSON_REPORT_PATH` | PDF/JSON report generation | + +Full list of env vars in `internal/params/envs.go`. Viper bindings in `internal/params/binds.go`. + +## Security & Access + +- **Authentication methods:** OAuth2 client credentials (`CX_CLIENT_ID` + `CX_CLIENT_SECRET`) or API key (`CX_APIKEY` — a JWT refresh token) +- **Token endpoint:** `{base_auth_uri}/auth/realms/{tenant}/protocol/openid-connect/token` +- **Token refresh:** Automatic on 401 responses; cached in-memory with mutex protection +- **TLS:** `--insecure` flag disables certificate verification (for testing only) +- **Sensitive data sanitization:** Logger automatically replaces values of `CX_APIKEY`, `CX_CLIENT_ID`, `CX_CLIENT_SECRET`, `--username`, `--password`, `ast-token`, `--ssh-key`, `CX_HTTP_PROXY`, `--token`, and `SCS_REPO_TOKEN` with `***` in all output +- **Config obfuscation:** Interactive `cx configure` shows only last 4 characters of sensitive values + +## Proxy Configuration + +The CLI supports four methods to configure proxy settings (in order of typical usage): + +### 1. Standard Environment Variables + +```bash +export HTTP_PROXY=http://username:password@proxy.example.com:8080 +export HTTPS_PROXY=http://username:password@proxy.example.com:8080 +export NO_PROXY=localhost,127.0.0.1,*.example.com +``` + +### 2. CX-Specific Environment Variables + +| Variable | Purpose | +|---|---| +| `CX_HTTP_PROXY` | Proxy server URL (overrides `HTTP_PROXY`) | +| `CX_PROXY_AUTH_TYPE` | Authentication type: `basic`, `ntlm`, `kerberos`, or `kerberos-native` | +| `CX_PROXY_NTLM_DOMAIN` | Windows domain for NTLM auth | +| `CX_PROXY_KERBEROS_SPN` | Kerberos SPN (e.g., `HTTP/proxy.example.com`) — required for Kerberos | +| `CX_PROXY_KERBEROS_KRB5_CONF` | Path to krb5.conf (default: `/etc/krb5.conf` or `C:\Windows\krb5.ini`) | +| `CX_PROXY_KERBEROS_CCACHE` | Path to Kerberos credential cache (optional) | +| `CX_IGNORE_PROXY` | Bypass proxy for current command | + +### 3. CLI Global Flags + +```bash +cx scan create --project-name "MyProject" \ + --proxy http://username:password@proxy.example.com:8080 \ + --proxy-auth-type ntlm \ + --proxy-ntlm-domain CORP +``` + +Flags: `--proxy`, `--proxy-auth-type` (basic/ntlm/kerberos/kerberos-native), `--proxy-ntlm-domain`, `--proxy-kerberos-spn`, `--ignore-proxy` + +Proxy URL format: `http://:` or `http://:@:` (must include `http://` prefix). + +### 4. CLI Config File + +Settings in `~/.checkmarx/checkmarxcli.yaml`: + +```yaml +cx_http_proxy: http://proxy.example.com:8080 +cx_proxy_auth_type: ntlm +cx_proxy_ntlm_domain: dm.cx +``` + +## Logging + +- **Debug mode:** `--debug` flag enables verbose output to stdout +- **File logging:** `--log-file ` writes to `/ast-cli.log` (file only) +- **File + console:** `--log-file-console ` writes to both file and stdout +- **HTTP tracing (debug mode):** Connection timing, DNS lookups, TLS handshake, full request/response dumps (sanitized, capped at 1MB, binary data excluded) +- **All log output** passes through `sanitizeLogs()` which replaces credential values with `***` + +## Debugging Steps + +### Runtime Debugging + +1. **Enable debug output:** Add `--debug` to any command (e.g., `cx scan create --debug ...`) +2. **Check auth:** `cx auth validate --debug` — shows token fetch, credential type, tenant resolution +3. **Inspect HTTP traffic:** Debug mode logs full request/response including headers, status codes, and timing +4. **Proxy issues:** Debug mode logs proxy type detection ("Creating HTTP Client with Proxy", "Using NTLM Proxy", "Using Kerberos Proxy") +5. **Token problems:** Look for "Fetching API access token", "Using cached API access token", "API access token not found in cache" in debug output +6. **Log to file for analysis:** `cx --log-file-console /tmp/logs` then inspect `/tmp/logs/ast-cli.log` +7. **Exit codes:** Non-zero exit identifies the failing engine (2=SAST, 3=SCA, 4=KICS, 5=API Security, 1=multiple) +8. **Config verification:** `cx utils env` shows current environment variable values +9. **Version check:** `cx version` to verify installed version and identify version-related issues +10. **Help:** `cx help` or `cx --help` for usage and available flags + +### Source Code Debugging + +1. Set environment variables via `.env` file or IDE run configuration (`CX_BASE_URI`, `CX_CLIENT_ID`, `CX_CLIENT_SECRET`, etc.) +2. Set the CLI command as program arguments in your IDE (e.g., `scan create --project-name "Test" -b main -s `) +3. Use **Delve** debugger to set breakpoints and step through code +4. Alternatively, add `fmt.Println` statements for quick variable inspection +5. Build and test: `go build -o bin/cx ./cmd` (Mac/Linux) or `go build -o bin/cx.exe ./cmd` (Windows) + +### Debugging Integration Tests + +1. Open `test/integration/` and select the test file for the functionality being debugged +2. Configure environment variables in your IDE run configuration +3. **Important:** Comment out `appendProxyArgs` call in `executeWithTimeout` function in `test/integration/util_command.go` before running locally — this avoids proxy-related failures in local debugging +4. Set breakpoints and run/debug the test; adjust test arguments to simulate scenarios +5. **Do NOT commit the `appendProxyArgs` change** — it is for local debugging only + +## Contributing + +- Branch naming: `feature/-name` or `hotfix/-name` +- PRs require associated issue marked "accepted" +- All changes need unit or integration tests meeting coverage thresholds +- Post-release, a dispatch triggers downstream plugin repositories to update their CLI version + +### PR Requirements — Team Members + +- Must have a valid JIRA ID in the PR title (e.g., `AST-3432`) — enables JIRA automation and traceability +- CI workflow must pass: **unit-tests**, **integration-tests**, **lint**, **cx-scan** +- Review by at least one team member +- Use the PR template (`.github/PULL_REQUEST_TEMPLATE.md`) — includes sections for changes, related issues, testing, and checklist + +### PR Requirements — Dependabot + +- CI workflow must pass: **unit-tests**, **integration-tests**, **lint**, **cx-scan** +- Auto-merged after CI passes (no manual review required) From 92a7fe6e31ad3531f6c9b455fdedca318c6aff18 Mon Sep 17 00:00:00 2001 From: atishj99 <141334503+cx-atish-jadhav@users.noreply.github.com> Date: Thu, 28 May 2026 14:33:57 +0530 Subject: [PATCH 20/27] Updated filters.go --- internal/params/filters.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/internal/params/filters.go b/internal/params/filters.go index fae79903f..7312918bc 100644 --- a/internal/params/filters.go +++ b/internal/params/filters.go @@ -182,7 +182,7 @@ var BaseIncludeFilters = []string{ "*.tex", "*.toml", "*.tsql", - "*.txt", + "CMakeLists*.txt", "*.vue", "*.xsaccess", "*.xsapp", From 18dc8d1055f482de50adfbe24e42a5c0b35fdc80 Mon Sep 17 00:00:00 2001 From: atishj99 <141334503+cx-atish-jadhav@users.noreply.github.com> Date: Thu, 28 May 2026 16:02:30 +0530 Subject: [PATCH 21/27] fix failing unit test case --- internal/commands/result.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/internal/commands/result.go b/internal/commands/result.go index 34320193c..22803b39e 100644 --- a/internal/commands/result.go +++ b/internal/commands/result.go @@ -2912,7 +2912,7 @@ func parseURI(summaryBaseURI string) (hostName string) { } func printWarningIfIgnorePolicyOmiited() { - fmt.Printf("\n Warning: The --ignore-policy flag was not implemented because you don’t have the required permission.\n Only users with 'override-policy-management' permission can use this flag. \n\n") + fmt.Printf("\n Warning: The --ignore-policy flag was not implemented because you don't have the required permission.\n Only users with 'override-policy-management' permission can use this flag. \n\n") } func getFilterResultsForAPISecScanner(risksOverviewWrapper wrappers.RisksOverviewWrapper, scanID string, resultsParams map[string]string) (aPISecSeveritySummary *wrappers.APISecFilteredResult, err error) { From 680841389ba28b67db9c624116a15c11a8495a5d Mon Sep 17 00:00:00 2001 From: atishj99 <141334503+cx-atish-jadhav@users.noreply.github.com> Date: Thu, 28 May 2026 19:41:17 +0530 Subject: [PATCH 22/27] trivy and integration check fixes --- Dockerfile | 2 +- go.mod | 17 +- go.sum | 33 +++ internal/commands/result.go | 299 ++++++++++++--------- internal/params/filters.go | 12 +- internal/services/applications_test.go | 5 - internal/wrappers/mock/application-mock.go | 12 +- internal/wrappers/results-sarif.go | 3 + test/integration/data/config.yaml | 1 - 9 files changed, 232 insertions(+), 152 deletions(-) diff --git a/Dockerfile b/Dockerfile index f30a838bf..cca0b0fdd 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,4 +1,4 @@ -FROM checkmarx/bash:5.3-r12-0e56cb6e000601@sha256:0e56cb6e000601d35ed11ddcc973ca268c431a176be53cdc31bc85f3208dc44a +FROM checkmarx/bash:5.3-r12-f48dd8a45af577@sha256:f48dd8a45af5771e98cb5d56d204ada0e0dc045093ca3272b4c3dbe3f85e6e4f USER nonroot COPY cx /app/bin/cx diff --git a/go.mod b/go.mod index 8cd6ba556..1e3576d3f 100644 --- a/go.mod +++ b/go.mod @@ -14,7 +14,7 @@ require ( github.com/bouk/monkey v1.0.0 github.com/checkmarx/2ms/v3 v3.21.0 github.com/gofrs/flock v0.13.0 - github.com/golang-jwt/jwt/v5 v5.2.2 + github.com/golang-jwt/jwt/v5 v5.3.0 github.com/gomarkdown/markdown v0.0.0-20260417124207-7d523f7318df github.com/google/uuid v1.6.0 github.com/gookit/color v1.6.0 @@ -92,8 +92,8 @@ require ( github.com/coreos/go-systemd/v22 v22.7.0 // indirect github.com/cpuguy83/go-md2man/v2 v2.0.7 // indirect github.com/diskfs/go-diskfs v1.7.0 // indirect - github.com/distribution/distribution/v3 v3.0.1-0.20260120145532-40594bd98e6d // indirect - github.com/docker/go-events v0.0.0-20250114142523-c867878c5e32 // indirect + github.com/distribution/distribution/v3 v3.1.1 // indirect + github.com/docker/go-events v0.0.0-20250808211157-605354379745 // indirect github.com/envoyproxy/go-control-plane/envoy v1.36.0 // indirect github.com/envoyproxy/protoc-gen-validate v1.3.0 // indirect github.com/go-jose/go-jose/v3 v3.0.5 // indirect @@ -111,6 +111,7 @@ require ( github.com/hashicorp/go-version v1.8.0 // indirect github.com/hashicorp/golang-lru/v2 v2.0.7 // indirect github.com/henvic/httpretty v0.1.4 // indirect + github.com/klauspost/cpuid/v2 v2.3.0 // indirect github.com/mholt/archives v0.1.5 // indirect github.com/mikelolasagasti/xz v1.0.1 // indirect github.com/minio/minlz v1.0.1 // indirect @@ -139,7 +140,7 @@ require ( go.opentelemetry.io/otel/sdk v1.43.0 // indirect go.opentelemetry.io/otel/sdk/metric v1.43.0 // indirect go4.org v0.0.0-20230225012048-214862532bf5 // indirect - golang.org/x/image v0.36.1-0.20260211191414-e3d762b1d37e // indirect + golang.org/x/image v0.38.0 // indirect gonum.org/v1/gonum v0.17.0 // indirect google.golang.org/api v0.271.0 // indirect google.golang.org/genproto/googleapis/api v0.0.0-20260401024825-9d38bb4040a9 // indirect @@ -233,8 +234,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.8.1-0.20260506061021-07f2a0bf50e4 // indirect - github.com/go-git/go-git/v5 v5.18.1-0.20260420130857-e5bbc088b774 // indirect + github.com/go-git/go-billy/v5 v5.9.0 // indirect + github.com/go-git/go-git/v5 v5.19.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 @@ -317,7 +318,7 @@ require ( github.com/pelletier/go-toml/v2 v2.3.1 // indirect github.com/peterbourgon/diskv v2.0.1+incompatible // indirect github.com/pierrec/lz4/v4 v4.1.22 // indirect - github.com/pjbgf/sha1cd v0.3.2 // indirect + github.com/pjbgf/sha1cd v0.6.0 // indirect github.com/pkg/profile v1.7.0 // indirect github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec // indirect @@ -336,7 +337,7 @@ require ( github.com/shopspring/decimal v1.4.0 // indirect github.com/sirupsen/logrus v1.9.4 // indirect github.com/skeema/knownhosts v1.3.1 // indirect - github.com/slack-go/slack v0.12.2 // indirect + github.com/slack-go/slack v0.23.1 // indirect github.com/sourcegraph/conc v0.3.1-0.20240121214520-5f936abd7ae8 // indirect github.com/spdx/gordf v0.0.0-20250128162952-000978ccd6fb // indirect github.com/spdx/tools-golang v0.5.7 // indirect diff --git a/go.sum b/go.sum index 5db673f17..65c70b7f2 100644 --- a/go.sum +++ b/go.sum @@ -281,6 +281,7 @@ github.com/bradleyjkemp/cupaloy/v2 v2.8.0 h1:any4BmKE+jGIaMpnU8YgH/I2LPiLBufr6oM github.com/bradleyjkemp/cupaloy/v2 v2.8.0/go.mod h1:bm7JXdkRd4BHJk9HpwqAI8BoAY1lps46Enkdqw6aRX0= github.com/bshuster-repo/logrus-logstash-hook v1.0.0 h1:e+C0SB5R1pu//O4MQ3f9cFuPGoOVeF2fE4Og9otCc70= github.com/bshuster-repo/logrus-logstash-hook v1.0.0/go.mod h1:zsTqEiSzDgAa/8GZR7E1qaXrhYNDKBYy5/dWPTIflbk= +github.com/bshuster-repo/logrus-logstash-hook v1.1.0 h1:o2FzZifLg+z/DN1OFmzTWzZZx/roaqt8IPZCIVco8r4= github.com/bwmarrin/discordgo v0.27.1 h1:ib9AIc/dom1E/fSIulrBwnez0CToJE113ZGt4HoliGY= github.com/bwmarrin/discordgo v0.27.1/go.mod h1:NJZpH+1AfhIcyQsPeuBKsUtYrRnjkyu0kIVMCHkZtRY= github.com/cenkalti/backoff/v4 v4.3.0 h1:MyRJ/UdXutAwSAT+s3wNd7MfTIcy71VQueUuFK343L8= @@ -422,6 +423,8 @@ github.com/distribution/distribution/v3 v3.0.1-0.20250403190400-dbca4995c83c h1: github.com/distribution/distribution/v3 v3.0.1-0.20250403190400-dbca4995c83c/go.mod h1:tRNuFoZsUdyRVegq8xGNeds4KLjwLCRin/tTo6i1DhU= github.com/distribution/distribution/v3 v3.0.1-0.20260120145532-40594bd98e6d h1:c2HDaWKU1MalLXwrAek+Yks7n80p/salSR5u6alHPBo= github.com/distribution/distribution/v3 v3.0.1-0.20260120145532-40594bd98e6d/go.mod h1:WiiB9B3TqqAPe7hPjI1P9OMtEW7Ub/HHGndi11SqeDA= +github.com/distribution/distribution/v3 v3.1.1 h1:KUbk7C8CfaLXy8kbf/hGq9cad/wCoLB6dbWH6DMbmX0= +github.com/distribution/distribution/v3 v3.1.1/go.mod h1:d7lXwZpph0bVcOj4Aqn0nMrWHIwRQGdiV5TLeI+/w6Y= github.com/distribution/reference v0.6.0 h1:0IXCQ5g4/QMHHkarYzh5l+u8T3t73zM5QvfrDyIgxBk= github.com/distribution/reference v0.6.0/go.mod h1:BbU0aIcezP1/5jX/8MP0YiH4SdvB5Y4f/wlDRiLyi3E= github.com/djherbis/times v1.6.0 h1:w2ctJ92J8fBvWPxugmXIv7Nz7Q3iDMKNx9v5ocVH20c= @@ -438,6 +441,8 @@ github.com/docker/go-connections v0.6.0 h1:LlMG9azAe1TqfR7sO+NJttz1gy6KO7VJBh+pM github.com/docker/go-connections v0.6.0/go.mod h1:AahvXYshr6JgfUJGdDCs2b5EZG/vmaMAntpSFH5BFKE= github.com/docker/go-events v0.0.0-20250114142523-c867878c5e32 h1:EHZfspsnLAz8Hzccd67D5abwLiqoqym2jz/jOS39mCk= github.com/docker/go-events v0.0.0-20250114142523-c867878c5e32/go.mod h1:Uw6UezgYA44ePAFQYUehOuCzmy5zmg/+nl2ZfMWGkpA= +github.com/docker/go-events v0.0.0-20250808211157-605354379745 h1:yOn6Ze6IbYI/KAw2lw/83ELYvZh6hvsygTVkD0dzMC4= +github.com/docker/go-events v0.0.0-20250808211157-605354379745/go.mod h1:Uw6UezgYA44ePAFQYUehOuCzmy5zmg/+nl2ZfMWGkpA= github.com/docker/go-metrics v0.0.1 h1:AgB/0SvBxihN0X8OR4SjsblXkbMvalQ8cjmtKQ2rQV8= github.com/docker/go-metrics v0.0.1/go.mod h1:cG1hvH2utMXtqgqqYE9plW6lDxS3/5ayHzueweSI3Vw= github.com/docker/go-units v0.5.0 h1:69rxXcBk27SvSaaxTtLh/8llcHD8vYHT7WSdRZ/jvr4= @@ -531,12 +536,16 @@ github.com/go-git/go-billy/v5 v5.8.0 h1:I8hjc3LbBlXTtVuFNJuwYuMiHvQJDq1AT6u4DwDz github.com/go-git/go-billy/v5 v5.8.0/go.mod h1:RpvI/rw4Vr5QA+Z60c6d6LXH0rYJo0uD5SqfmrrheCY= github.com/go-git/go-billy/v5 v5.8.1-0.20260506061021-07f2a0bf50e4 h1:XK6pelr1UQyrCSXsrqrJxr0jkrHXg7QCzfPH3UQMYp8= github.com/go-git/go-billy/v5 v5.8.1-0.20260506061021-07f2a0bf50e4/go.mod h1:jCnQMLj9eUgGU7+ludSTYoZL/GGmii14RxKFj7ROgHw= +github.com/go-git/go-billy/v5 v5.9.0 h1:jItGXszUDRtR/AlferWPTMN4j38BQ88XnXKbilmmBPA= +github.com/go-git/go-billy/v5 v5.9.0/go.mod h1:jCnQMLj9eUgGU7+ludSTYoZL/GGmii14RxKFj7ROgHw= 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.18.0 h1:O831KI+0PR51hM2kep6T8k+w0/LIAD490gvqMCvL5hM= github.com/go-git/go-git/v5 v5.18.0/go.mod h1:pW/VmeqkanRFqR6AljLcs7EA7FbZaN5MQqO7oZADXpo= github.com/go-git/go-git/v5 v5.18.1-0.20260420130857-e5bbc088b774 h1:FED4o0JOD1z8x/dMcmM6IKkqoIz22xz7sWE81FEdXNQ= github.com/go-git/go-git/v5 v5.18.1-0.20260420130857-e5bbc088b774/go.mod h1:pW/VmeqkanRFqR6AljLcs7EA7FbZaN5MQqO7oZADXpo= +github.com/go-git/go-git/v5 v5.19.1 h1:nX27AnaU43/K5bKktKwgBmR9lawoYVe1Ckg0rgzzN00= +github.com/go-git/go-git/v5 v5.19.1/go.mod h1:Pb1v0c7/g8aGQJwx9Us09W85yGoyvSwuhEGMH7zjDKQ= 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= @@ -595,6 +604,8 @@ github.com/gohugoio/hashstructure v0.6.0 h1:7wMB/2CfXoThFYhdWRGv3u3rUM761Cq29CxU github.com/gohugoio/hashstructure v0.6.0/go.mod h1:lapVLk9XidheHG1IQ4ZSbyYrXcaILU1ZEP/+vno5rBQ= github.com/golang-jwt/jwt/v5 v5.2.2 h1:Rl4B7itRWVtYIHFrSNd7vhTiz9UpLdi6gZhZ3wEeDy8= github.com/golang-jwt/jwt/v5 v5.2.2/go.mod h1:pqrtFR0X4osieyHYxtmOUWsAWrfe1Q5UVIyoH402zdk= +github.com/golang-jwt/jwt/v5 v5.3.0 h1:pv4AsKCKKZuqlgs5sUmn4x8UlGa0kEVt/puTpKx9vvo= +github.com/golang-jwt/jwt/v5 v5.3.0/go.mod h1:fxCRLWMO43lRc8nhHWY6LGqRcf+1gQWArsqaEUEa5bE= github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/groupcache v0.0.0-20191227052852-215e87163ea7/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= @@ -834,7 +845,10 @@ github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+o github.com/klauspost/compress v1.4.1/go.mod h1:RyIbtBH6LamlWaDj8nUwkbUhJ87Yi3uG0guNDohfE1A= github.com/klauspost/compress v1.18.5 h1:/h1gH5Ce+VWNLSWqPzOVn6XBO+vJbCNGvjoaGBFW2IE= github.com/klauspost/compress v1.18.5/go.mod h1:cwPg85FWrGar70rWktvGQj8/hthj3wpl0PGDogxkrSQ= +github.com/klauspost/cpuid v1.2.0 h1:NMpwD2G9JSFOE1/TJjGSo5zG7Yb2bTe7eq1jH+irmeE= github.com/klauspost/cpuid v1.2.0/go.mod h1:Pj4uuM528wm8OyEC2QMXAi2YiTZ96dNQPGgoMS4s3ek= +github.com/klauspost/cpuid/v2 v2.3.0 h1:S4CRMLnYUhGeDFDqkGriYKdfoFlDnMtqTiI/sFzhA9Y= +github.com/klauspost/cpuid/v2 v2.3.0/go.mod h1:hqwkgyIinND0mEev00jJYCxPNVRVXFQeu1XKlok6oO0= github.com/klauspost/pgzip v1.2.6 h1:8RXeL5crjEUFnR2/Sn6GJNWtSQ3Dk8pq4CL3jvdDyjU= github.com/klauspost/pgzip v1.2.6/go.mod h1:Ch1tH69qFZu15pkjo5kYi6mth2Zzwzt50oCQKQE9RUs= github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= @@ -1021,6 +1035,8 @@ github.com/pierrec/lz4/v4 v4.1.22 h1:cKFw6uJDK+/gfw5BcDL0JL5aBsAFdsIT18eRtLj7VIU github.com/pierrec/lz4/v4 v4.1.22/go.mod h1:gZWDp/Ze/IJXGXf23ltt2EXimqmTUXEy0GFuRQyBid4= github.com/pjbgf/sha1cd v0.3.2 h1:a9wb0bp1oC2TGwStyn0Umc/IGKQnEgF0vVaZ8QF8eo4= github.com/pjbgf/sha1cd v0.3.2/go.mod h1:zQWigSxVmsHEZow5qaLtPYxpcKMMQpa09ixqBxuCS6A= +github.com/pjbgf/sha1cd v0.6.0 h1:3WJ8Wz8gvDz29quX1OcEmkAlUg9diU4GxJHqs0/XiwU= +github.com/pjbgf/sha1cd v0.6.0/go.mod h1:lhpGlyHLpQZoxMv8HcgXvZEhcGs0PG/vsZnEJ7H0iCM= github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= @@ -1061,6 +1077,7 @@ github.com/prometheus/procfs v0.0.8/go.mod h1:7Qr8sr6344vo1JqZ6HhLceV9o3AJ1Ff+Gx github.com/prometheus/procfs v0.16.1 h1:hZ15bTNuirocR6u0JZ6BAHHmwS1p8B4P6MRqxtzMyRg= github.com/prometheus/procfs v0.16.1/go.mod h1:teAbpZRB1iIAJYREa1LsoWUXykVXA1KlTmWl8x/U+Is= github.com/prometheus/procfs v0.19.2 h1:zUMhqEW66Ex7OXIiDkll3tl9a1ZdilUOd/F6ZXw4Vws= +github.com/prometheus/procfs v0.20.1 h1:XwbrGOIplXW/AU3YhIhLODXMJYyC1isLFfYCsTEycfc= github.com/redis/go-redis/extra/rediscmd/v9 v9.0.5 h1:EaDatTxkdHG+U3Bk4EUr+DZ7fOGwTfezUiUJMaIcaho= github.com/redis/go-redis/extra/rediscmd/v9 v9.0.5/go.mod h1:fyalQWdtzDBECAQFBJuQe5bzQ02jGd5Qcbgb97Flm7U= github.com/redis/go-redis/extra/redisotel/v9 v9.0.5 h1:EfpWLLCyXw8PSM2/XNJLjI3Pb27yVE+gIAfeqp8LUCc= @@ -1123,6 +1140,8 @@ github.com/skeema/knownhosts v1.3.1 h1:X2osQ+RAjK76shCbvhHHHVl3ZlgDm8apHEHFqRjnB github.com/skeema/knownhosts v1.3.1/go.mod h1:r7KTdC8l4uxWRyK2TpQZ/1o5HaSzh06ePQNxPwTcfiY= github.com/slack-go/slack v0.12.2 h1:x3OppyMyGIbbiyFhsBmpf9pwkUzMhthJMRNmNlA4LaQ= github.com/slack-go/slack v0.12.2/go.mod h1:hlGi5oXA+Gt+yWTPP0plCdRKmjsDxecdHxYQdlMQKOw= +github.com/slack-go/slack v0.23.1 h1:ZS5B96wxxYQRwvJ3/vJFtqtUZi3tXhsZCyT44Nv7M80= +github.com/slack-go/slack v0.23.1/go.mod h1:H0yR/YBuRJ39RkE+JpV/d/oEsbanzTRowR82bCN0cEs= github.com/smallnest/ringbuffer v0.0.0-20241116012123-461381446e3d h1:3VwvTjiRPA7cqtgOWddEL+JrcijMlXUmj99c/6YyZoY= github.com/smallnest/ringbuffer v0.0.0-20241116012123-461381446e3d/go.mod h1:tAG61zBM1DYRaGIPloumExGvScf08oHuo0kFoOqdbT0= github.com/sorairolake/lzip-go v0.3.8 h1:j5Q2313INdTA80ureWYRhX+1K78mUXfMoPZCw/ivWik= @@ -1264,10 +1283,12 @@ go.opentelemetry.io/auto/sdk v1.2.1 h1:jXsnJ4Lmnqd11kwkBV2LgLoFMZKizbCi5fNZ/ipaZ go.opentelemetry.io/auto/sdk v1.2.1/go.mod h1:KRTj+aOaElaLi+wW1kO/DZRXwkF4C5xPbEe3ZiIhN7Y= go.opentelemetry.io/contrib/bridges/prometheus v0.57.0 h1:UW0+QyeyBVhn+COBec3nGhfnFe5lwB0ic1JBVjzhk0w= go.opentelemetry.io/contrib/bridges/prometheus v0.57.0/go.mod h1:ppciCHRLsyCio54qbzQv0E4Jyth/fLWDTJYfvWpcSVk= +go.opentelemetry.io/contrib/bridges/prometheus v0.67.0 h1:dkBzNEAIKADEaFnuESzcXvpd09vxvDZsOjx11gjUqLk= go.opentelemetry.io/contrib/detectors/gcp v1.39.0 h1:kWRNZMsfBHZ+uHjiH4y7Etn2FK26LAGkNFw7RHv1DhE= go.opentelemetry.io/contrib/detectors/gcp v1.39.0/go.mod h1:t/OGqzHBa5v6RHZwrDBJ2OirWc+4q/w2fTbLZwAKjTk= go.opentelemetry.io/contrib/exporters/autoexport v0.57.0 h1:jmTVJ86dP60C01K3slFQa2NQ/Aoi7zA+wy7vMOKD9H4= go.opentelemetry.io/contrib/exporters/autoexport v0.57.0/go.mod h1:EJBheUMttD/lABFyLXhce47Wr6DPWYReCzaZiXadH7g= +go.opentelemetry.io/contrib/exporters/autoexport v0.67.0 h1:4fnRcNpc6YFtG3zsFw9achKn3XgmxPxuMuqIL5rE8e8= go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.63.0 h1:YH4g8lQroajqUwWbq/tr2QX1JFmEXaDLgG+ew9bLMWo= go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.63.0/go.mod h1:fvPi2qXDqFs8M4B4fmJhE92TyQs9Ydjlg3RvfUp+NbQ= go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.68.0 h1:0Qx7VGBacMm9ZENQ7TnNObTYI4ShC+lHI16seduaxZo= @@ -1280,12 +1301,16 @@ go.opentelemetry.io/otel v1.43.0 h1:mYIM03dnh5zfN7HautFE4ieIig9amkNANT+xcVxAj9I= go.opentelemetry.io/otel v1.43.0/go.mod h1:JuG+u74mvjvcm8vj8pI5XiHy1zDeoCS2LB1spIq7Ay0= go.opentelemetry.io/otel/exporters/otlp/otlplog/otlploggrpc v0.8.0 h1:WzNab7hOOLzdDF/EoWCt4glhrbMPVMOO5JYTmpz36Ls= go.opentelemetry.io/otel/exporters/otlp/otlplog/otlploggrpc v0.8.0/go.mod h1:hKvJwTzJdp90Vh7p6q/9PAOd55dI6WA6sWj62a/JvSs= +go.opentelemetry.io/otel/exporters/otlp/otlplog/otlploggrpc v0.18.0 h1:deI9UQMoGFgrg5iLPgzueqFPHevDl+28YKfSpPTI6rY= go.opentelemetry.io/otel/exporters/otlp/otlplog/otlploghttp v0.8.0 h1:S+LdBGiQXtJdowoJoQPEtI52syEP/JYBUpjO49EQhV8= go.opentelemetry.io/otel/exporters/otlp/otlplog/otlploghttp v0.8.0/go.mod h1:5KXybFvPGds3QinJWQT7pmXf+TN5YIa7CNYObWRkj50= +go.opentelemetry.io/otel/exporters/otlp/otlplog/otlploghttp v0.19.0 h1:HIBTQ3VO5aupLKjC90JgMqpezVXwFuq6Ryjn0/izoag= go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc v1.32.0 h1:j7ZSD+5yn+lo3sGV69nW04rRR0jhYnBwjuX3r0HvnK0= go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc v1.32.0/go.mod h1:WXbYJTUaZXAbYd8lbgGuvih0yuCfOFC5RJoYnoLcGz8= +go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc v1.42.0 h1:MdKucPl/HbzckWWEisiNqMPhRrAOQX8r4jTuGr636gk= go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetrichttp v1.32.0 h1:t/Qur3vKSkUCcDVaSumWF2PKHt85pc7fRvFuoVT8qFU= go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetrichttp v1.32.0/go.mod h1:Rl61tySSdcOJWoEgYZVtmnKdA0GeKrSqkHC1t+91CH8= +go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetrichttp v1.43.0 h1:w1K+pCJoPpQifuVpsKamUdn9U0zM3xUziVOqsGksUrY= go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.35.0 h1:1fTNlAIJZGWLP5FVu0fikVry1IsiUnXjf7QFvoNN3Xw= go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.35.0/go.mod h1:zjPK58DtkqQFn+YUMbx0M2XV3QgKU0gS9LeGohREyK4= go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.43.0 h1:88Y4s2C8oTui1LGM6bTWkw0ICGcOLCAI5l6zsD1j20k= @@ -1297,20 +1322,26 @@ go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.35.0/go.mod h go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.43.0 h1:3iZJKlCZufyRzPzlQhUIWVmfltrXuGyfjREgGP3UUjc= go.opentelemetry.io/otel/exporters/prometheus v0.54.0 h1:rFwzp68QMgtzu9PgP3jm9XaMICI6TsofWWPcBDKwlsU= go.opentelemetry.io/otel/exporters/prometheus v0.54.0/go.mod h1:QyjcV9qDP6VeK5qPyKETvNjmaaEc7+gqjh4SS0ZYzDU= +go.opentelemetry.io/otel/exporters/prometheus v0.64.0 h1:g0LRDXMX/G1SEZtK8zl8Chm4K6GBwRkjPKE36LxiTYs= go.opentelemetry.io/otel/exporters/stdout/stdoutlog v0.8.0 h1:CHXNXwfKWfzS65yrlB2PVds1IBZcdsX8Vepy9of0iRU= go.opentelemetry.io/otel/exporters/stdout/stdoutlog v0.8.0/go.mod h1:zKU4zUgKiaRxrdovSS2amdM5gOc59slmo/zJwGX+YBg= +go.opentelemetry.io/otel/exporters/stdout/stdoutlog v0.18.0 h1:KJVjPD3rcPb98rIs3HznyJlrfx9ge5oJvxxlGR+P/7s= go.opentelemetry.io/otel/exporters/stdout/stdoutmetric v1.40.0 h1:ZrPRak/kS4xI3AVXy8F7pipuDXmDsrO8Lg+yQjBLjw0= go.opentelemetry.io/otel/exporters/stdout/stdoutmetric v1.40.0/go.mod h1:3y6kQCWztq6hyW8Z9YxQDDm0Je9AJoFar2G0yDcmhRk= +go.opentelemetry.io/otel/exporters/stdout/stdoutmetric v1.42.0 h1:lSZHgNHfbmQTPfuTmWVkEu8J8qXaQwuV30pjCcAUvP8= go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.32.0 h1:cC2yDI3IQd0Udsux7Qmq8ToKAx1XCilTQECZ0KDZyTw= go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.32.0/go.mod h1:2PD5Ex6z8CFzDbTdOlwyNIUywRr1DN0ospafJM1wJ+s= +go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.42.0 h1:s/1iRkCKDfhlh1JF26knRneorus8aOwVIDhvYx9WoDw= go.opentelemetry.io/otel/log v0.8.0 h1:egZ8vV5atrUWUbnSsHn6vB8R21G2wrKqNiDt3iWertk= go.opentelemetry.io/otel/log v0.8.0/go.mod h1:M9qvDdUTRCopJcGRKg57+JSQ9LgLBrwwfC32epk5NX8= +go.opentelemetry.io/otel/log v0.19.0 h1:KUZs/GOsw79TBBMfDWsXS+KZ4g2Ckzksd1ymzsIEbo4= go.opentelemetry.io/otel/metric v1.43.0 h1:d7638QeInOnuwOONPp4JAOGfbCEpYb+K6DVWvdxGzgM= go.opentelemetry.io/otel/metric v1.43.0/go.mod h1:RDnPtIxvqlgO8GRW18W6Z/4P462ldprJtfxHxyKd2PY= go.opentelemetry.io/otel/sdk v1.43.0 h1:pi5mE86i5rTeLXqoF/hhiBtUNcrAGHLKQdhg4h4V9Dg= go.opentelemetry.io/otel/sdk v1.43.0/go.mod h1:P+IkVU3iWukmiit/Yf9AWvpyRDlUeBaRg6Y+C58QHzg= go.opentelemetry.io/otel/sdk/log v0.8.0 h1:zg7GUYXqxk1jnGF/dTdLPrK06xJdrXgqgFLnI4Crxvs= go.opentelemetry.io/otel/sdk/log v0.8.0/go.mod h1:50iXr0UVwQrYS45KbruFrEt4LvAdCaWWgIrsN3ZQggo= +go.opentelemetry.io/otel/sdk/log v0.19.0 h1:scYVLqT22D2gqXItnWiocLUKGH9yvkkeql5dBDiXyko= go.opentelemetry.io/otel/sdk/metric v1.43.0 h1:S88dyqXjJkuBNLeMcVPRFXpRw2fuwdvfCGLEo89fDkw= go.opentelemetry.io/otel/sdk/metric v1.43.0/go.mod h1:C/RJtwSEJ5hzTiUz5pXF1kILHStzb9zFlIEe85bhj6A= go.opentelemetry.io/otel/trace v1.43.0 h1:BkNrHpup+4k4w+ZZ86CZoHHEkohws8AY+WTX09nk+3A= @@ -1369,6 +1400,8 @@ golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMx golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= golang.org/x/image v0.36.1-0.20260211191414-e3d762b1d37e h1:gkwT7ZpRdJBB47MJ0h7xeUSHKkd8f3RcM47FgUIRgd4= golang.org/x/image v0.36.1-0.20260211191414-e3d762b1d37e/go.mod h1:ZK2ak7W75f61R/Pwr7T25elpTMmDbUsuiOt4FcDsNI0= +golang.org/x/image v0.38.0 h1:5l+q+Y9JDC7mBOMjo4/aPhMDcxEptsX+Tt3GgRQRPuE= +golang.org/x/image v0.38.0/go.mod h1:/3f6vaXC+6CEanU4KJxbcUZyEePbyKbaLoDOe4ehFYY= golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU= golang.org/x/lint v0.0.0-20190301231843-5614ed5bae6f/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= diff --git a/internal/commands/result.go b/internal/commands/result.go index 22803b39e..1c6a78f50 100644 --- a/internal/commands/result.go +++ b/internal/commands/result.go @@ -33,36 +33,37 @@ import ( ) const ( - failedCreatingSummary = "Failed creating summary" - failedGettingScan = "Failed getting scan" - failedListingResults = "Failed listing results" - failedListingCodeBashing = "Failed codebashing link" - mediumLabel = "medium" - criticalLabel = "critical" - highLabel = "high" - lowLabel = "low" - infoLabel = "info" - sonarTypeLabel = "_sonar" - glSastTypeLabel = ".gl-sast-report" - glScaTypeLabel = ".gl-sca-report" - directoryPermission = 0700 - infoSonar = "INFO" - lowSonar = "LOW" - mediumSonar = "MEDIUM" - highSonar = "HIGH" - criticalSonar = "BLOCKER" - infoLowSarif = "note" - mediumSarif = "warning" - highSarif = "error" - vulnerabilitySonar = "SECURITY" - cleanCodeAttribute = "FORMATTED" - infoCx = "INFO" - lowCx = "LOW" - mediumCx = "MEDIUM" - highCx = "HIGH" - criticalCx = "CRITICAL" - tableResultsFormat = " | %-10s %6v %5d %6d %5d %4d %-9s |\n" - stringTableResultsFormat = " | %-10s %5s %6s %6s %5s %4s %5s |\n" + failedCreatingSummary = "Failed creating summary" + failedGettingScan = "Failed getting scan" + failedListingResults = "Failed listing results" + failedListingCodeBashing = "Failed codebashing link" + mediumLabel = "medium" + criticalLabel = "critical" + highLabel = "high" + lowLabel = "low" + infoLabel = "info" + sonarTypeLabel = "_sonar" + glSastTypeLabel = ".gl-sast-report" + glScaTypeLabel = ".gl-sca-report" + directoryPermission = 0700 + infoSonar = "INFO" + lowSonar = "LOW" + mediumSonar = "MEDIUM" + highSonar = "HIGH" + criticalSonar = "BLOCKER" + infoLowSarif = "note" + mediumSarif = "warning" + highSarif = "error" + vulnerabilitySonar = "SECURITY" + cleanCodeAttribute = "FORMATTED" + infoCx = "INFO" + lowCx = "LOW" + mediumCx = "MEDIUM" + highCx = "HIGH" + criticalCx = "CRITICAL" + tableResultsFormat = " | %-10s %6v %5d %6d %5d %4d %-9s |\n" + stringTableResultsFormat = " | %-10s %5s %6s %6s %5s %4s %5s |\n" + // TableTitleFormat is the printf format string for the scan results summary table title row. TableTitleFormat = " | %-11s %4s %4s %6s %4s %4s %6s |\n" twoNewLines = "\n\n" tableLine = " --------------------------------------------------------------------- " @@ -109,11 +110,28 @@ const ( redundantLabel = "redundant" delayValueForReport = 10 fixLinkPrefix = "https://devhub.checkmarx.com/cve-details/" - ScaDevAndTestExclusionParam = "DEV_AND_TEST" - ScaExcludeResultTypesParam = "exclude-result-types" - noFileForScorecardResultString = "Issue Found in your GitHub repository" - CliType = "cli" - artifactLocationURIString = "This alert has no associated file" + // ScaDevAndTestExclusionParam is the SCA exclude-result-types value used to filter out dev and test dependencies. + ScaDevAndTestExclusionParam = "DEV_AND_TEST" + // ScaExcludeResultTypesParam is the SCA query parameter name used to exclude specific result types. + ScaExcludeResultTypesParam = "exclude-result-types" + noFileForScorecardResultString = "Issue Found in your GitHub repository" + // CliType identifies the report type used when generating reports through the CLI. + CliType = "cli" + artifactLocationURIString = "This alert has no associated file" + commandDocAnnotation = "command:doc" + showSubCommand = "show" + sectionScanSummary = "ScanSummary" + sectionExecutiveSummary = "ExecutiveSummary" + sectionScanResults = "ScanResults" + scaEngineLabel = "SCA" + sastEngineLabel = "SAST" + kicsEngineLabel = "KICS" + notAvailableValue = "NA" + originCode = "code" + originDocumentation = "documentation" + statusCompleted = "Completed" + statusPartial = "Partial" + statusFailed = "Failed" ) var ( @@ -176,6 +194,7 @@ var ( } ) +// NewResultsCommand returns the `results` Cobra command tree with all subcommands attached. func NewResultsCommand( resultsWrapper wrappers.ResultsWrapper, scanWrapper wrappers.ScansWrapper, @@ -195,7 +214,7 @@ func NewResultsCommand( Use: "results", Short: "Retrieve results", Annotations: map[string]string{ - "command:doc": heredoc.Doc( + commandDocAnnotation: heredoc.Doc( ` https://checkmarx.com/resource/documents/en/34965-68640-results.html `, @@ -268,7 +287,7 @@ func resultShowSubCommand( jwtWrapper wrappers.JWTWrapper, ) *cobra.Command { resultShowCmd := &cobra.Command{ - Use: "show", + Use: showSubCommand, Short: "Show results of a scan", Long: "The show command enables the ability to show results about a requested scan in Checkmarx One", Example: heredoc.Doc( @@ -396,6 +415,7 @@ func getRiskManagementResults(riskManagement wrappers.RiskManagementWrapper, pro return ASPMResult, nil } +// GetScannerResults returns per-scanner status entries for the given scan, optionally filtered by scan types. func GetScannerResults(scanWrapper wrappers.ScansWrapper, scanID, scanTypesFlagValue string) ([]ScannerResponse, error) { scanResponseModel, errorModel, err := scanWrapper.GetByID(scanID) if err != nil { @@ -609,27 +629,7 @@ func convertScanToResultsSummary(scanInfo *wrappers.ScanResponseModel, resultsWr enginesStatusCode[commonParams.ScsType] = 0 if len(scanInfo.StatusDetails) > 0 { - for _, statusDetailItem := range scanInfo.StatusDetails { - if statusDetailItem.Status == wrappers.ScanFailed || statusDetailItem.Status == wrappers.ScanCanceled { - if statusDetailItem.Name == commonParams.SastType { - sastIssues = notAvailableNumber - } else if statusDetailItem.Name == commonParams.ScaType { - scaIssues = notAvailableNumber - } else if statusDetailItem.Name == commonParams.KicsType { - kicsIssues = notAvailableNumber - } else if statusDetailItem.Name == commonParams.ScsType { - *scsIssues = notAvailableNumber - } else if statusDetailItem.Name == commonParams.ContainersType && wrappers.IsContainersEnabled { - *containersIssues = notAvailableNumber - } - } - switch statusDetailItem.Status { - case wrappers.ScanFailed: - handleScanStatus(statusDetailItem, enginesStatusCode, scanFailedNumber) - case wrappers.ScanCanceled: - handleScanStatus(statusDetailItem, enginesStatusCode, scanCanceledNumber) - } - } + applyScanStatusDetails(scanInfo.StatusDetails, &sastIssues, &scaIssues, &kicsIssues, scsIssues, containersIssues, enginesStatusCode) } summary := &wrappers.ResultSummary{ ScanID: scanInfo.ID, @@ -680,6 +680,42 @@ func convertScanToResultsSummary(scanInfo *wrappers.ScanResponseModel, resultsWr return summary, nil } +func applyScanStatusDetails( + statusDetails []wrappers.StatusInfo, + sastIssues, scaIssues, kicsIssues *int, + scsIssues, containersIssues *int, + enginesStatusCode map[string]int, +) { + for _, statusDetailItem := range statusDetails { + if statusDetailItem.Status == wrappers.ScanFailed || statusDetailItem.Status == wrappers.ScanCanceled { + markEngineNotAvailable(statusDetailItem.Name, sastIssues, scaIssues, kicsIssues, scsIssues, containersIssues) + } + switch statusDetailItem.Status { + case wrappers.ScanFailed: + handleScanStatus(statusDetailItem, enginesStatusCode, scanFailedNumber) + case wrappers.ScanCanceled: + handleScanStatus(statusDetailItem, enginesStatusCode, scanCanceledNumber) + } + } +} + +func markEngineNotAvailable(name string, sastIssues, scaIssues, kicsIssues, scsIssues, containersIssues *int) { + switch name { + case commonParams.SastType: + *sastIssues = notAvailableNumber + case commonParams.ScaType: + *scaIssues = notAvailableNumber + case commonParams.KicsType: + *kicsIssues = notAvailableNumber + case commonParams.ScsType: + *scsIssues = notAvailableNumber + case commonParams.ContainersType: + if wrappers.IsContainersEnabled { + *containersIssues = notAvailableNumber + } + } +} + func handleScanStatus(statusDetailItem wrappers.StatusInfo, targetTypes map[string]int, statusCode int) { if _, ok := targetTypes[statusDetailItem.Name]; ok { targetTypes[statusDetailItem.Name] = statusCode @@ -853,7 +889,7 @@ func writeMarkdownSummary(targetFile string, data *wrappers.ResultSummary) error if err != nil { return err } - defer file.Close() + defer func() { _ = file.Close() }() err = tmpl.Execute(file, &data) if err != nil { @@ -863,7 +899,7 @@ func writeMarkdownSummary(targetFile string, data *wrappers.ResultSummary) error } // nolint: whitespace -func writeConsoleSummary(summary *wrappers.ResultSummary, featureFlagsWrapper wrappers.FeatureFlagsWrapper, ignorePolicyFlagOmit bool) error { +func writeConsoleSummary(summary *wrappers.ResultSummary, ignorePolicyFlagOmit bool) error { if !isScanPending(summary.Status) { fmt.Printf(" Scan Summary: \n") fmt.Printf(" Created At: %s\n", summary.CreatedAt) @@ -885,7 +921,7 @@ func writeConsoleSummary(summary *wrappers.ResultSummary, featureFlagsWrapper wr } if summary.HasSCS() { - printSCSSummary(summary.SCSOverview.MicroEngineOverviews, featureFlagsWrapper) + printSCSSummary(summary.SCSOverview.MicroEngineOverviews) } fmt.Printf(" Checkmarx One - Scan Summary & Details: %s\n", summary.BaseURI) @@ -951,17 +987,17 @@ func printTableRow(title string, counts *wrappers.EngineResultSummary, statusNum } } -func printSCSSummary(microEngineOverviews []*wrappers.MicroEngineOverview, featureFlagsWrapper wrappers.FeatureFlagsWrapper) { +func printSCSSummary(microEngineOverviews []*wrappers.MicroEngineOverview) { fmt.Printf(" Supply Chain Security Results\n") fmt.Printf(" -------------------------------------------------------------------------- \n") fmt.Println(" | Critical High Medium Low Info Status |") for _, microEngineOverview := range microEngineOverviews { - printSCSTableRow(microEngineOverview, featureFlagsWrapper) + printSCSTableRow(microEngineOverview) } fmt.Printf(" -------------------------------------------------------------------------- \n\n") } -func printSCSTableRow(microEngineOverview *wrappers.MicroEngineOverview, featureFlagsWrapper wrappers.FeatureFlagsWrapper) { +func printSCSTableRow(microEngineOverview *wrappers.MicroEngineOverview) { formatString := " | %-20s %4v %4v %6v %4v %4v %-9s |\n" notAvailableFormatString := " | %-20s %4v %4s %6s %4s %4s %5s |\n" @@ -1104,14 +1140,14 @@ func runGetCodeBashingCommand( codeBashingWrapper wrappers.CodeBashingWrapper, ) func(cmd *cobra.Command, args []string) error { return func(cmd *cobra.Command, args []string) error { - language, _ := cmd.Flags().GetString(commonParams.LanguageFlag) + lang, _ := cmd.Flags().GetString(commonParams.LanguageFlag) cwe, _ := cmd.Flags().GetString(commonParams.CweIDFlag) vulType, _ := cmd.Flags().GetString(commonParams.VulnerabilityTypeFlag) params, err := codeBashingWrapper.BuildCodeBashingParams( []wrappers.CodeBashingParamsCollection{ { CweID: "CWE-" + cwe, - Language: language, + Language: lang, CxQueryName: strings.ReplaceAll(vulType, " ", "_"), }, }, @@ -1179,6 +1215,7 @@ func filterScsResultsByAgent(results *wrappers.ScanResultsCollection, agent stri return results } +// CreateScanReport produces the requested report formats for a scan and writes them to the target path. func CreateScanReport( resultsWrapper wrappers.ResultsWrapper, risksOverviewWrapper wrappers.RisksOverviewWrapper, @@ -1377,63 +1414,75 @@ func getScanOverviewForSCSScanner( } func isScanPending(scanStatus string) bool { - return !(strings.EqualFold(scanStatus, "Completed") || strings.EqualFold( - scanStatus, - "Partial", - ) || strings.EqualFold(scanStatus, "Failed")) + return !strings.EqualFold(scanStatus, statusCompleted) && + !strings.EqualFold(scanStatus, statusPartial) && + !strings.EqualFold(scanStatus, statusFailed) } -func isValidScanStatus(status, format string) bool { - if isScanPending(status) { - log.Printf("Result format file %s not create because scan status is %s", format, status) - return false - } - return true -} - -func createReport(format, - formatPdfToEmail, - formatPdfOptions, - formatSbomOptions, - targetFile, - targetPath string, +func createRawReport( + format, targetFile, targetPath string, results *wrappers.ScanResultsCollection, summary *wrappers.ResultSummary, - exportWrapper wrappers.ExportWrapper, - resultsPdfReportsWrapper wrappers.ResultsPdfWrapper, resultsJSONReportsWrapper wrappers.ResultsJSONWrapper, featureFlagsWrapper wrappers.FeatureFlagsWrapper, - ignorePolicyFlagOmit bool) error { +) (handled bool, err error) { if printer.IsFormat(format, printer.FormatIndentedJSON) { - return nil + return true, nil } if printer.IsFormat(format, printer.FormatSarif) && isValidScanStatus(summary.Status, printer.FormatSarif) { sarifRpt := createTargetName(targetFile, targetPath, printer.FormatSarif) - return exportSarifResults(sarifRpt, results) + return true, exportSarifResults(sarifRpt, results) } if printer.IsFormat(format, printer.FormatSonar) && isValidScanStatus(summary.Status, printer.FormatSonar) { sonarRpt := createTargetName(fmt.Sprintf("%s%s", targetFile, sonarTypeLabel), targetPath, printer.FormatJSON) - return exportSonarResults(sonarRpt, results) + return true, exportSonarResults(sonarRpt, results) } if printer.IsFormat(format, printer.FormatJSON) && isValidScanStatus(summary.Status, printer.FormatJSON) { jsonRpt := createTargetName(targetFile, targetPath, printer.FormatJSON) - return exportJSONResults(jsonRpt, results) + return true, exportJSONResults(jsonRpt, results) } if printer.IsFormat(format, printer.FormatJSONv2) && isValidScanStatus(summary.Status, printer.FormatJSONv2) { summaryRpt := createTargetName(targetFile, targetPath, printer.FormatJSON) - return exportJSONReportResults(resultsJSONReportsWrapper, summary, summaryRpt, featureFlagsWrapper) + return true, exportJSONReportResults(resultsJSONReportsWrapper, summary, summaryRpt, featureFlagsWrapper) } if printer.IsFormat(format, printer.FormatGLSast) { jsonRpt := createTargetName(fmt.Sprintf("%s%s", targetFile, glSastTypeLabel), targetPath, printer.FormatJSON) - return exportGlSastResults(jsonRpt, results, summary) + return true, exportGlSastResults(jsonRpt, results, summary) } if printer.IsFormat(format, printer.FormatGLSca) { jsonRpt := createTargetName(fmt.Sprintf("%s%s", targetFile, glScaTypeLabel), targetPath, printer.FormatJSON) - return exportGlScaResults(jsonRpt, results, summary) + return true, exportGlScaResults(jsonRpt, results, summary) + } + return false, nil +} + +func isValidScanStatus(status, format string) bool { + if isScanPending(status) { + log.Printf("Result format file %s not create because scan status is %s", format, status) + return false + } + return true +} + +func createReport(format, + formatPdfToEmail, + formatPdfOptions, + formatSbomOptions, + targetFile, + targetPath string, + results *wrappers.ScanResultsCollection, + summary *wrappers.ResultSummary, + exportWrapper wrappers.ExportWrapper, + resultsPdfReportsWrapper wrappers.ResultsPdfWrapper, + resultsJSONReportsWrapper wrappers.ResultsJSONWrapper, + featureFlagsWrapper wrappers.FeatureFlagsWrapper, + ignorePolicyFlagOmit bool) error { + if handled, err := createRawReport(format, targetFile, targetPath, results, summary, resultsJSONReportsWrapper, featureFlagsWrapper); handled { + return err } if printer.IsFormat(format, printer.FormatSummaryConsole) { - return writeConsoleSummary(summary, featureFlagsWrapper, ignorePolicyFlagOmit) + return writeConsoleSummary(summary, ignorePolicyFlagOmit) } if printer.IsFormat(format, printer.FormatSummary) { summaryRpt := createTargetName(targetFile, targetPath, printer.FormatHTML) @@ -1491,6 +1540,7 @@ func createDirectory(targetPath string) error { return nil } +// ReadResults fetches all scan results for the given scan and enriches them with SCA and SCS data as applicable. func ReadResults( resultsWrapper wrappers.ResultsWrapper, exportWrapper wrappers.ExportWrapper, @@ -1663,7 +1713,7 @@ func exportGlSastResults(targetFile string, results *wrappers.ScanResultsCollect if err != nil { return errors.Wrapf(err, "%s: failed to create target file ", failedListingResults) } - defer f.Close() + defer func() { _ = f.Close() }() _, _ = fmt.Fprintln(f, string(resultsJSON)) return nil } @@ -1688,8 +1738,8 @@ func exportGlScaResults(targetFile string, results *wrappers.ScanResultsCollecti if err != nil { return errors.Wrapf(err, "%s: failed to create target file ", failedListingResults) } + defer func() { _ = f.Close() }() _, _ = fmt.Fprintln(f, string(resultsJSON)) - defer f.Close() return nil } @@ -1845,16 +1895,16 @@ func exportJSONReportResults(jsonWrapper wrappers.ResultsJSONWrapper, summary *w func parseJSONOptions(enabledEngines []string, reportName string) (jsonOptionsSections, jsonOptionsEngines []string) { jsonOptionsSections = []string{ - "ScanSummary", - "ExecutiveSummary", - "ScanResults", + sectionScanSummary, + sectionExecutiveSummary, + sectionScanResults, } var jsonOptionsEnginesMap = map[string]string{ - commonParams.ScaType: "SCA", - commonParams.SastType: "SAST", - commonParams.KicsType: "KICS", - commonParams.IacType: "KICS", + commonParams.ScaType: scaEngineLabel, + commonParams.SastType: sastEngineLabel, + commonParams.KicsType: kicsEngineLabel, + commonParams.IacType: kicsEngineLabel, commonParams.ContainersType: "Containers", commonParams.ScsType: "Microengines", } @@ -1909,7 +1959,7 @@ func exportPdfResults(pdfWrapper wrappers.ResultsPdfWrapper, summary *wrappers.R // will generate pdf report and send it to the email list // instead of saving it to the file system - if len(formatPdfToEmail) > 0 { + if formatPdfToEmail != "" { emailList, validateErr := validateEmails(formatPdfToEmail) if validateErr != nil { return validateErr @@ -1958,16 +2008,16 @@ func exportPdfResults(pdfWrapper wrappers.ResultsPdfWrapper, summary *wrappers.R func parsePDFOptions(pdfOptions string, enabledEngines []string, reportName string) (pdfOptionsSections, pdfOptionsEngines []string, err error) { var pdfOptionsSectionsMap = map[string]string{ - "scansummary": "ScanSummary", - "executivesummary": "ExecutiveSummary", - "scanresults": "ScanResults", + "scansummary": sectionScanSummary, + "executivesummary": sectionExecutiveSummary, + "scanresults": sectionScanResults, } var pdfOptionsEnginesMap = map[string]string{ - commonParams.ScaType: "SCA", - commonParams.SastType: "SAST", - commonParams.KicsType: "KICS", - commonParams.IacType: "KICS", + commonParams.ScaType: scaEngineLabel, + commonParams.SastType: sastEngineLabel, + commonParams.KicsType: kicsEngineLabel, + commonParams.IacType: kicsEngineLabel, } pdfOptions = strings.ToLower(strings.ReplaceAll(pdfOptions, " ", "")) @@ -2000,9 +2050,9 @@ func translateReportSectionsForImproved(sections []string) []string { var resultSections = make([]string, 0) var pdfOptionsSectionsImprovedTranslation = map[string][]string{ - "ScanSummary": {"scan-information"}, - "ExecutiveSummary": {"results-overview"}, - "ScanResults": {"scan-results", "categories", "resolved-results", "vulnerability-details"}, + sectionScanSummary: {"scan-information"}, + sectionExecutiveSummary: {"results-overview"}, + sectionScanResults: {"scan-results", "categories", "resolved-results", "vulnerability-details"}, } for _, section := range sections { @@ -2087,7 +2137,7 @@ func parseGlSastVulnerability(result *wrappers.ScanResult, glSast *wrappers.GlSa Type: "source", Items: []wrappers.Item{ { - Signatures: []wrappers.Signature{{Algorithm: result.Type + "-Algorithm ", Value: "NA"}}, + Signatures: []wrappers.Signature{{Algorithm: result.Type + "-Algorithm ", Value: notAvailableValue}}, File: fileName, EndLine: endLine, StartLine: startLine, @@ -2166,7 +2216,7 @@ func collectScaFileLocations(result *wrappers.ScanResult) []wrappers.ScaDependen func collectScaPackageItemsDep(result *wrappers.ScanResult) []wrappers.ItemDep { allScaPackageItemDep := []wrappers.ItemDep{} allScaPackageItemDep = append(allScaPackageItemDep, wrappers.ItemDep{ - Signature: []wrappers.SignatureDep{{Algorithm: "SCA-Algorithm ", Value: "NA"}}, + Signature: []wrappers.SignatureDep{{Algorithm: "SCA-Algorithm ", Value: notAvailableValue}}, File: result.VulnerabilityDetails.CveName, EndLine: 0, StartLine: 0, @@ -2743,9 +2793,9 @@ func buildAuxiliaryScaMaps(resultsModel *wrappers.ScanResultsCollection, scaPack // Create map to be used to populate locations for each package path for _, result := range resultsModel.Results { if result.Type == commonParams.ScaType { - for _, packages := range *scaPackageModel { - currentPackage := packages - locationsByID[packages.ID] = currentPackage.Locations + for i := range *scaPackageModel { + pkg := &(*scaPackageModel)[i] + locationsByID[pkg.ID] = pkg.Locations } for _, types := range *scaTypeModel { identifier := fmt.Sprintf("%s:%s", types.ID, types.PackageID) @@ -2893,6 +2943,7 @@ func trimOsSeparatorFromFileName(result *wrappers.ScanResult) { } } +// ScannerResponse is the per-scanner status info returned by the results exit-code subcommand. type ScannerResponse struct { ScanID string `json:"ScanID,omitempty"` Name string `json:"Name,omitempty"` @@ -2943,11 +2994,11 @@ func getFilterResultsForAPISecScanner(risksOverviewWrapper wrappers.RisksOvervie totalRecords++ } var riskDistribution []wrappers.RiskDistributionEntry - if originCount["code"] > 0 { - riskDistribution = append(riskDistribution, wrappers.RiskDistributionEntry{Origin: "code", Total: originCount["code"]}) + if originCount[originCode] > 0 { + riskDistribution = append(riskDistribution, wrappers.RiskDistributionEntry{Origin: originCode, Total: originCount[originCode]}) } - if originCount["documentation"] > 0 { - riskDistribution = append(riskDistribution, wrappers.RiskDistributionEntry{Origin: "documentation", Total: originCount["documentation"]}) + if originCount[originDocumentation] > 0 { + riskDistribution = append(riskDistribution, wrappers.RiskDistributionEntry{Origin: originDocumentation, Total: originCount[originDocumentation]}) } return &wrappers.APISecFilteredResult{ SeverityCount: severityCount, diff --git a/internal/params/filters.go b/internal/params/filters.go index 7312918bc..56db130a8 100644 --- a/internal/params/filters.go +++ b/internal/params/filters.go @@ -123,9 +123,7 @@ var BaseIncludeFilters = []string{ "yarn.lock", "pyproject.toml", "poetry.lock", - "requirements.txt", - "requirement.txt", - "requirement*.txt", + "*requirement*.txt", "composer.lock", "*Dockerfile*", "*dock*", @@ -152,12 +150,10 @@ var BaseIncludeFilters = []string{ "*.vm", "*.ac", "*.am", - "*.app", "*.asax", "*.cmake", "*.dspf", "*.env", - "*.evt", "*.ftl", "*.gsp", "*.gtl", @@ -165,8 +161,6 @@ var BaseIncludeFilters = []string{ "*.ini", "*.jade", "*.jsf", - "*.latex", - "*.lock", "*.master", "*.mf", "*.mustache", @@ -179,17 +173,15 @@ var BaseIncludeFilters = []string{ "*.rpg38", "*.sqlrpg", "*.sqlrpgle", - "*.tex", "*.toml", "*.tsql", - "CMakeLists*.txt", + "*CMakeLists*.txt", "*.vue", "*.xsaccess", "*.xsapp", "*.pug", "*.lua", "*.ec", - "*.csv", "*.apxc", } diff --git a/internal/services/applications_test.go b/internal/services/applications_test.go index 0af427a97..c1be66a70 100644 --- a/internal/services/applications_test.go +++ b/internal/services/applications_test.go @@ -11,11 +11,6 @@ import ( "gotest.tools/assert" ) -const ( - mockApplicationName = "MOCK" - testProjectName = "test-project" -) - func Test_createApplicationIds(t *testing.T) { type args struct { applicationID []string diff --git a/internal/wrappers/mock/application-mock.go b/internal/wrappers/mock/application-mock.go index 8a0271492..8d1546455 100644 --- a/internal/wrappers/mock/application-mock.go +++ b/internal/wrappers/mock/application-mock.go @@ -9,7 +9,13 @@ import ( "github.com/pkg/errors" ) -const code = 355 +const ( + code = 355 + idNewProjectNameStr = "ID-new-project-name" + projectID1Str = "ProjectID1" + projectID2Str = "ProjectID2" + testProjectStr = "test_project" +) type ApplicationsMockWrapper struct{} @@ -31,14 +37,14 @@ func (a ApplicationsMockWrapper) Get(params map[string]string) (*wrappers.Applic Name: "MOCK", Description: "This is a mock application", Criticality: 2, - ProjectIds: []string{"ProjectID1", "ProjectID2", "test_project", "ID-new-project-name"}, + ProjectIds: []string{projectID1Str, projectID2Str, testProjectStr, idNewProjectNameStr}, CreatedAt: time.Now(), } if params["name"] == ExistingApplication { mockApplication.Name = ExistingApplication mockApplication.ID = "ID-newProject" // For ExistingApplication, include "ID-newProject" for polling tests - mockApplication.ProjectIds = []string{"ProjectID1", "ProjectID2", "test_project", "ID-new-project-name", "ID-newProject"} + mockApplication.ProjectIds = []string{projectID1Str, projectID2Str, testProjectStr, idNewProjectNameStr, "ID-newProject"} return &wrappers.ApplicationsResponseModel{ TotalCount: 1, Applications: []wrappers.Application{mockApplication}, diff --git a/internal/wrappers/results-sarif.go b/internal/wrappers/results-sarif.go index e73786532..60c6ec63a 100644 --- a/internal/wrappers/results-sarif.go +++ b/internal/wrappers/results-sarif.go @@ -63,14 +63,17 @@ type SarifScanResult struct { Properties *SarifResultProperties `json:"properties,omitempty"` } +// SarifCodeFlow represents a SARIF codeFlows entry. type SarifCodeFlow struct { ThreadFlows []SarifThreadFlow `json:"threadFlows"` } +// SarifThreadFlow represents a SARIF threadFlow entry. type SarifThreadFlow struct { Locations []SarifThreadFlowLocation `json:"locations"` } +// SarifThreadFlowLocation represents a single location within a SARIF threadFlow. type SarifThreadFlowLocation struct { Location SarifLocation `json:"location"` } diff --git a/test/integration/data/config.yaml b/test/integration/data/config.yaml index 6d6b4c836..b01de3ac2 100644 --- a/test/integration/data/config.yaml +++ b/test/integration/data/config.yaml @@ -18,7 +18,6 @@ cx_byor_path: api/byor cx_client_id: example_client_id cx_client_secret: example_client_secret cx_codebashing_path: api/codebashing/lessons -cx_config_file_path: data/config.yaml cx_create_oath2_client_path: auth/realms/organization/pip/clients cx_custom_states_path: api/custom-states cx_descriptions_path: api/queries/descriptions From 780b52e7adad38b45d78bef5dbedae9b1f662557 Mon Sep 17 00:00:00 2001 From: atishj99 <141334503+cx-atish-jadhav@users.noreply.github.com> Date: Thu, 28 May 2026 20:48:05 +0530 Subject: [PATCH 23/27] CVE-2026-33813: fixing cxone scan vulnerability --- go.mod | 24 +- go.sum | 234 +- internal/commands/result.go | 6020 +++++++++++++++--------------- internal/commands/result_test.go | 6 +- 4 files changed, 3044 insertions(+), 3240 deletions(-) diff --git a/go.mod b/go.mod index 1e3576d3f..593b653b0 100644 --- a/go.mod +++ b/go.mod @@ -45,9 +45,6 @@ require ( cloud.google.com/go/iam v1.5.3 // indirect cloud.google.com/go/monitoring v1.24.3 // indirect cloud.google.com/go/storage v1.61.3 // indirect - cyphar.com/go-pathrs v0.2.1 // indirect - github.com/AdaLogics/go-fuzz-headers v0.0.0-20240806141605-e8a1dd7889d6 // indirect - github.com/AdamKorcz/go-118-fuzz-build v0.0.0-20240914100643-eb91380d8434 // indirect github.com/GoogleCloudPlatform/opentelemetry-operations-go/detectors/gcp v1.31.0 // indirect github.com/GoogleCloudPlatform/opentelemetry-operations-go/exporter/metric v0.55.0 // indirect github.com/GoogleCloudPlatform/opentelemetry-operations-go/internal/resourcemapping v0.55.0 // indirect @@ -81,25 +78,17 @@ require ( github.com/bodgit/sevenzip v1.6.1 // indirect github.com/bodgit/windows v1.0.1 // indirect github.com/cespare/xxhash/v2 v2.3.0 // indirect - github.com/checkpoint-restore/go-criu/v6 v6.3.0 // indirect - github.com/cilium/ebpf v0.17.3 // indirect github.com/clipperhouse/displaywidth v0.10.0 // indirect github.com/clipperhouse/uax29/v2 v2.6.0 // indirect github.com/cncf/xds/go v0.0.0-20251210132809-ee656c7534f5 // indirect - github.com/containerd/console v1.0.5 // indirect github.com/containerd/containerd/v2 v2.3.1 // indirect github.com/containerd/plugin v1.1.0 // indirect - github.com/coreos/go-systemd/v22 v22.7.0 // indirect - github.com/cpuguy83/go-md2man/v2 v2.0.7 // indirect github.com/diskfs/go-diskfs v1.7.0 // indirect github.com/distribution/distribution/v3 v3.1.1 // indirect - github.com/docker/go-events v0.0.0-20250808211157-605354379745 // indirect github.com/envoyproxy/go-control-plane/envoy v1.36.0 // indirect github.com/envoyproxy/protoc-gen-validate v1.3.0 // indirect - github.com/go-jose/go-jose/v3 v3.0.5 // indirect github.com/go-jose/go-jose/v4 v4.1.4 // indirect github.com/goccy/go-yaml v1.19.2 // indirect - github.com/godbus/dbus/v5 v5.1.0 // indirect github.com/gohugoio/hashstructure v0.6.0 // indirect github.com/google/s2a-go v0.1.9 // indirect github.com/googleapis/enterprise-certificate-proxy v0.3.14 // indirect @@ -117,30 +106,23 @@ require ( github.com/minio/minlz v1.0.1 // indirect github.com/moby/moby/api v1.54.1 // indirect github.com/moby/moby/client v0.4.0 // indirect - github.com/moby/sys/capability v0.4.0 // indirect - github.com/mrunalp/fileutils v0.5.1 // indirect github.com/nix-community/go-nix v0.0.0-20250101154619-4bdde671e0a1 // indirect github.com/nwaples/rardecode/v2 v2.2.0 // indirect github.com/olekukonko/cat v0.0.0-20250911104152-50322a0618f6 // indirect github.com/olekukonko/errors v1.2.0 // indirect github.com/olekukonko/ll v0.1.6 // indirect - github.com/opencontainers/cgroups v0.0.4 // indirect - github.com/opencontainers/runc v1.3.4 // indirect github.com/pkg/xattr v0.4.9 // indirect github.com/planetscale/vtprotobuf v0.6.1-0.20240319094008-0393e58bdf10 // indirect - github.com/seccomp/libseccomp-golang v0.10.0 // indirect + github.com/prometheus/procfs v0.20.1 // indirect github.com/smallnest/ringbuffer v0.0.0-20241116012123-461381446e3d // indirect github.com/sorairolake/lzip-go v0.3.8 // indirect github.com/spiffe/go-spiffe/v2 v2.6.0 // indirect - github.com/urfave/cli v1.22.16 // indirect - github.com/vishvananda/netlink v1.3.1 // indirect - github.com/vishvananda/netns v0.0.5 // indirect go.opentelemetry.io/contrib/detectors/gcp v1.39.0 // indirect go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.68.0 // indirect + go.opentelemetry.io/otel/exporters/stdout/stdoutmetric v1.42.0 // indirect go.opentelemetry.io/otel/sdk v1.43.0 // indirect go.opentelemetry.io/otel/sdk/metric v1.43.0 // indirect go4.org v0.0.0-20230225012048-214862532bf5 // indirect - golang.org/x/image v0.38.0 // indirect gonum.org/v1/gonum v0.17.0 // indirect google.golang.org/api v0.271.0 // indirect google.golang.org/genproto/googleapis/api v0.0.0-20260401024825-9d38bb4040a9 // indirect @@ -256,7 +238,6 @@ require ( github.com/google/pprof v0.0.0-20260115054156-294ebfa9ad83 // indirect github.com/gorilla/websocket v1.5.4-0.20250319132907-e064f32e3674 // indirect github.com/gosuri/uitable v0.0.4 // indirect - github.com/gregjones/httpcache v0.0.0-20190611155906-901d90724c79 // indirect github.com/h2non/filetype v1.1.3 // indirect github.com/hashicorp/errwrap v1.1.0 // indirect github.com/hashicorp/go-multierror v1.1.1 // indirect @@ -312,7 +293,6 @@ require ( github.com/opencontainers/go-digest v1.0.0 // indirect github.com/opencontainers/image-spec v1.1.1 // indirect github.com/opencontainers/runtime-spec v1.3.0 // indirect - github.com/opencontainers/selinux v1.13.1 // indirect github.com/pborman/indent v1.2.1 // indirect github.com/pelletier/go-toml v1.9.5 // indirect github.com/pelletier/go-toml/v2 v2.3.1 // indirect diff --git a/go.sum b/go.sum index 65c70b7f2..0a4e739f9 100644 --- a/go.sum +++ b/go.sum @@ -67,8 +67,6 @@ cloud.google.com/go/storage v1.61.3 h1:VS//ZfBuPGDvakfD9xyPW1RGF1Vy3BWUoVZXgW1KM cloud.google.com/go/storage v1.61.3/go.mod h1:JtqK8BBB7TWv0HVGHubtUdzYYrakOQIsMLffZ2Z/HWk= cloud.google.com/go/trace v1.11.7 h1:kDNDX8JkaAG3R2nq1lIdkb7FCSi1rCmsEtKVsty7p+U= cloud.google.com/go/trace v1.11.7/go.mod h1:TNn9d5V3fQVf6s4SCveVMIBS2LJUqo73GACmq/Tky0s= -cyphar.com/go-pathrs v0.2.1 h1:9nx1vOgwVvX1mNBWDu93+vaceedpbsDqo+XuBGL40b8= -cyphar.com/go-pathrs v0.2.1/go.mod h1:y8f1EMG7r+hCuFf/rXsKqMJrJAUoADZGNh5/vZPKcGc= dario.cat/mergo v1.0.2 h1:85+piFYR1tMbRrLcDwR18y4UKJ3aH1Tbzi24VRW1TK8= dario.cat/mergo v1.0.2/go.mod h1:E/hbnu0NxMFBjpMIE34DRGLWqDy0g5FuKDhCb31ngxA= dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU= @@ -76,15 +74,12 @@ filippo.io/edwards25519 v1.1.0 h1:FNf4tywRC1HmFuKW5xopWpigGjJKiJSV0Cqo0cJWDaA= filippo.io/edwards25519 v1.1.0/go.mod h1:BxyFTGdWcka3PhytdK4V28tE5sGfRvvvRV7EaN4VDT4= github.com/AdaLogics/go-fuzz-headers v0.0.0-20240806141605-e8a1dd7889d6 h1:He8afgbRMd7mFxO99hRNu+6tazq8nFF9lIwo9JFroBk= github.com/AdaLogics/go-fuzz-headers v0.0.0-20240806141605-e8a1dd7889d6/go.mod h1:8o94RPi1/7XTJvwPpRSzSUedZrtlirdB3r9Z20bi2f8= -github.com/AdamKorcz/go-118-fuzz-build v0.0.0-20240914100643-eb91380d8434 h1:t9mXVk8SurivauUmW28nWggC/aOm5NBZ+U2ddBfbyP8= -github.com/AdamKorcz/go-118-fuzz-build v0.0.0-20240914100643-eb91380d8434/go.mod h1:n+tj8pffsLO7fLdcrnbfl444A2OwGv8a6ISsac75Wow= github.com/Azure/go-ansiterm v0.0.0-20250102033503-faa5f7b0171c h1:udKWzYgxTojEKWjV8V+WSxDXJ4NFATAsZjh8iIbsQIg= github.com/Azure/go-ansiterm v0.0.0-20250102033503-faa5f7b0171c/go.mod h1:xomTg63KZ2rFqZQzSB4Vz2SUXa1BpHTVz9L5PTmPC4E= github.com/BobuSumisu/aho-corasick v1.0.3 h1:uuf+JHwU9CHP2Vx+wAy6jcksJThhJS9ehR8a+4nPE9g= github.com/BobuSumisu/aho-corasick v1.0.3/go.mod h1:hm4jLcvZKI2vRF2WDU1N4p/jpWtpOzp3nLmi9AzX/XE= github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= github.com/BurntSushi/toml v0.4.1/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbicEuybxQ= -github.com/BurntSushi/toml v1.4.0/go.mod h1:ukJfTF/6rtPPRCnwkur4qwRxa8vTRFBF0uk2lLoLwho= github.com/BurntSushi/toml v1.6.0 h1:dRaEfpa2VI55EwlIW72hMRHdWouJeRF7TPYhI+AUQjk= github.com/BurntSushi/toml v1.6.0/go.mod h1:ukJfTF/6rtPPRCnwkur4qwRxa8vTRFBF0uk2lLoLwho= github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo= @@ -111,8 +106,6 @@ github.com/DATA-DOG/go-sqlmock v1.5.2/go.mod h1:88MAG/4G7SMwSE3CeA0ZKzrT5CiOU3OJ github.com/DataDog/datadog-go v3.2.0+incompatible/go.mod h1:LButxg5PwREeZtORoXG3tL4fMGNddJ+vMq1mwgfaqoQ= github.com/DataDog/zstd v1.5.6 h1:LbEglqepa/ipmmQJUDnSsfvA8e8IStVcGaFWDuxvGOY= github.com/DataDog/zstd v1.5.6/go.mod h1:g4AWEaM3yOg3HYfnJ3YIawPnVdXJh9QME85blwSAmyw= -github.com/GoogleCloudPlatform/opentelemetry-operations-go/detectors/gcp v1.30.0 h1:sBEjpZlNHzK1voKq9695PJSX2o5NEXl7/OL3coiIY0c= -github.com/GoogleCloudPlatform/opentelemetry-operations-go/detectors/gcp v1.30.0/go.mod h1:P4WPRUkOhJC13W//jWpyfJNDAIpvRbAUIYLX/4jtlE0= github.com/GoogleCloudPlatform/opentelemetry-operations-go/detectors/gcp v1.31.0 h1:DHa2U07rk8syqvCge0QIGMCE1WxGj9njT44GH7zNJLQ= github.com/GoogleCloudPlatform/opentelemetry-operations-go/detectors/gcp v1.31.0/go.mod h1:P4WPRUkOhJC13W//jWpyfJNDAIpvRbAUIYLX/4jtlE0= github.com/GoogleCloudPlatform/opentelemetry-operations-go/exporter/metric v0.55.0 h1:UnDZ/zFfG1JhH/DqxIZYU/1CUAlTUScoXD/LcM2Ykk8= @@ -132,12 +125,8 @@ github.com/Masterminds/sprig/v3 v3.3.0/go.mod h1:Zy1iXRYNqNLUolqCpL4uhk6SHUMAOSC github.com/Masterminds/squirrel v1.5.4 h1:uUcX/aBc8O7Fg9kaISIUsHXdKuqehiXAMQTYX8afzqM= github.com/Masterminds/squirrel v1.5.4/go.mod h1:NNaOrjSoIDfDA40n7sr2tPNZRfjzjA400rg+riTZj10= github.com/Microsoft/go-winio v0.5.2/go.mod h1:WpS1mjBmmwHBEWmogvA2mj8546UReBk4v8QkMxJ6pZY= -github.com/Microsoft/go-winio v0.6.2 h1:F2VQgta7ecxGYO8k3ZZz3RS8fVIXVxONVUPlNERoyfY= -github.com/Microsoft/go-winio v0.6.2/go.mod h1:yd8OoFMLzJbo9gZq8j5qaps8bJ9aShtEA8Ipt1oGCvU= github.com/Microsoft/go-winio v0.6.3-0.20251027160822-ad3df93bed29 h1:0kQAzHq8vLs7Pptv+7TxjdETLf/nIqJpIB4oC6Ba4vY= github.com/Microsoft/go-winio v0.6.3-0.20251027160822-ad3df93bed29/go.mod h1:ZWa7ssZJT30CCDGJ7fk/2SBTq9BIQrrVjrcss0UW2s0= -github.com/Microsoft/hcsshim v0.14.1 h1:CMuB3fqQVfPdhyXhUqYdUmPUIOhJkmghCx3dJet8Cqs= -github.com/Microsoft/hcsshim v0.14.1/go.mod h1:VnzvPLyWUhxiPVsJ31P6XadxCcTogTguBFDy/1GR/OM= github.com/Microsoft/hcsshim v0.15.0-rc.1 h1:FbbwtQmiD+BVHynGkx5S65JkLyhkEiiTP8nrpmg2SZw= github.com/Microsoft/hcsshim v0.15.0-rc.1/go.mod h1:HWvvUPIy9HF6LotILj1G4VyS065rcLQ6tqj6tMUdOfI= github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU= @@ -183,8 +172,6 @@ github.com/anchore/go-version v1.2.2-0.20200701162849-18adb9c92b9b h1:e1bmaoJfZV github.com/anchore/go-version v1.2.2-0.20200701162849-18adb9c92b9b/go.mod h1:Bkc+JYWjMCF8OyZ340IMSIi2Ebf3uwByOk6ho4wne1E= github.com/anchore/packageurl-go v0.2.0 h1:CkrM4RMUwrEGAiE1OVlxaZNzWj0TuHRey7o4T/EAErk= github.com/anchore/packageurl-go v0.2.0/go.mod h1:2JCgOQMIsqZ7TmliXG4PnUthPJAKE3mWQbsW2XHjAOE= -github.com/anchore/stereoscope v0.1.23 h1:q9i3CtbicTuSlcCnA+5pfoT9WDCEoSqvXDfHMH1hyWo= -github.com/anchore/stereoscope v0.1.23/go.mod h1:JLnun49fkLkuv3ebU0ROvFl/0JiRmNmUtCzc6y4ollo= github.com/anchore/stereoscope v0.2.0 h1:8haOu2ugLymmxvyfrZR7OTBFiRFRBh5LlNUtRrSRoxI= github.com/anchore/stereoscope v0.2.0/go.mod h1:PYx3fD4lvBVsYoQ/fBdauhZ5hmkRrJgw1B73svKx7/U= github.com/anchore/syft v1.43.0 h1:m6BwN48vgD0j2U4uk/wwqkUCxVKp2On30ZnKWQGCjKI= @@ -279,13 +266,12 @@ github.com/bouk/monkey v1.0.0 h1:k6z8fLlPhETfn5l9rlWVE7Q6B23DoaqosTdArvNQRdc= github.com/bouk/monkey v1.0.0/go.mod h1:PG/63f4XEUlVyW1ttIeOJmJhhe1+t9EC/je3eTjvFhE= github.com/bradleyjkemp/cupaloy/v2 v2.8.0 h1:any4BmKE+jGIaMpnU8YgH/I2LPiLBufr6oMMlVBbn9M= github.com/bradleyjkemp/cupaloy/v2 v2.8.0/go.mod h1:bm7JXdkRd4BHJk9HpwqAI8BoAY1lps46Enkdqw6aRX0= -github.com/bshuster-repo/logrus-logstash-hook v1.0.0 h1:e+C0SB5R1pu//O4MQ3f9cFuPGoOVeF2fE4Og9otCc70= -github.com/bshuster-repo/logrus-logstash-hook v1.0.0/go.mod h1:zsTqEiSzDgAa/8GZR7E1qaXrhYNDKBYy5/dWPTIflbk= github.com/bshuster-repo/logrus-logstash-hook v1.1.0 h1:o2FzZifLg+z/DN1OFmzTWzZZx/roaqt8IPZCIVco8r4= +github.com/bshuster-repo/logrus-logstash-hook v1.1.0/go.mod h1:Q2aXOe7rNuPgbBtPCOzYyWDvKX7+FpxE5sRdvcPoui0= github.com/bwmarrin/discordgo v0.27.1 h1:ib9AIc/dom1E/fSIulrBwnez0CToJE113ZGt4HoliGY= github.com/bwmarrin/discordgo v0.27.1/go.mod h1:NJZpH+1AfhIcyQsPeuBKsUtYrRnjkyu0kIVMCHkZtRY= -github.com/cenkalti/backoff/v4 v4.3.0 h1:MyRJ/UdXutAwSAT+s3wNd7MfTIcy71VQueUuFK343L8= -github.com/cenkalti/backoff/v4 v4.3.0/go.mod h1:Y3VNntkOUPxTVeUxJ/G5vcM//AlwfmyYozVcomhLiZE= +github.com/cenkalti/backoff/v5 v5.0.3 h1:ZN+IMa753KfX5hd8vVaMixjnqRZ3y8CuJKRKj1xcsSM= +github.com/cenkalti/backoff/v5 v5.0.3/go.mod h1:rkhZdG3JZukswDf7f0cwqPNk4K0sa+F97BxZthm/crw= github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= github.com/census-instrumentation/opencensus-proto v0.3.0/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc= @@ -311,8 +297,6 @@ github.com/charmbracelet/x/term v0.2.2 h1:xVRT/S2ZcKdhhOuSP4t5cLi5o+JxklsoEObBSg github.com/charmbracelet/x/term v0.2.2/go.mod h1:kF8CY5RddLWrsgVwpw4kAa6TESp6EB5y3uxGLeCqzAI= github.com/checkmarx/2ms/v3 v3.21.0 h1:EcabeDypNMsSidISQbziZ062HjMZQ+Hm/uOJ5AOxK8o= github.com/checkmarx/2ms/v3 v3.21.0/go.mod h1:e8f4F94MZ+iCetR/G3aw7nXdPe6TgPI92Zzk/NG1l0o= -github.com/checkpoint-restore/go-criu/v6 v6.3.0 h1:mIdrSO2cPNWQY1truPg6uHLXyKHk3Z5Odx4wjKOASzA= -github.com/checkpoint-restore/go-criu/v6 v6.3.0/go.mod h1:rrRTN/uSwY2X+BPRl/gkulo9gsKOSAeVp9/K2tv7xZI= github.com/chromedp/cdproto v0.0.0-20230802225258-3cf4e6d46a89/go.mod h1:GKljq0VrfU4D5yc+2qA6OVr8pmO/MBbPEWqWQ/oqGEs= github.com/chromedp/chromedp v0.9.2/go.mod h1:LkSXJKONWTCHAfQasKFUZI+mxqS4tZqhmtGzzhLsnLs= github.com/chromedp/sysutil v1.0.0/go.mod h1:kgWmDdq8fTzXYcKIBqIYvRRTnYb9aNS9moAV0xufSww= @@ -322,8 +306,6 @@ github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5P github.com/chzyer/readline v1.5.1/go.mod h1:Eh+b79XXUwfKfcPLepksvw2tcLE/Ct21YObkaSkeBlk= github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU= github.com/chzyer/test v1.0.0/go.mod h1:2JlltgoNkt4TW/z9V/IzDdFaMTM2JPIi26O1pF38GC8= -github.com/cilium/ebpf v0.17.3 h1:FnP4r16PWYSE4ux6zN+//jMcW4nMVRvuTLVTvCjyyjg= -github.com/cilium/ebpf v0.17.3/go.mod h1:G5EDHij8yiLzaqn0WjyfJHvRa+3aDlReIaLVRMvOyJk= github.com/circonus-labs/circonus-gometrics v2.3.1+incompatible/go.mod h1:nmEj6Dob7S7YxXgwXpfOuvO54S+tGdZdw9fuRZt25Ag= github.com/circonus-labs/circonusllhist v0.1.3/go.mod h1:kMXHVDlOchFAehlya5ePtbp5jckzBHf4XRpQvBOLI+I= github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= @@ -345,28 +327,14 @@ github.com/cncf/xds/go v0.0.0-20211011173535-cb28da3451f1/go.mod h1:eXthEFrGJvWH github.com/cncf/xds/go v0.0.0-20211130200136-a8f946100490/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= github.com/cncf/xds/go v0.0.0-20251210132809-ee656c7534f5 h1:6xNmx7iTtyBRev0+D/Tv1FZd4SCg8axKApyNyRsAt/w= github.com/cncf/xds/go v0.0.0-20251210132809-ee656c7534f5/go.mod h1:KdCmV+x/BuvyMxRnYBlmVaq4OLiKW6iRQfvC62cvdkI= -github.com/containerd/cgroups/v3 v3.1.2 h1:OSosXMtkhI6Qove637tg1XgK4q+DhR0mX8Wi8EhrHa4= -github.com/containerd/cgroups/v3 v3.1.2/go.mod h1:PKZ2AcWmSBsY/tJUVhtS/rluX0b1uq1GmPO1ElCmbOw= github.com/containerd/cgroups/v3 v3.1.3 h1:eUNflyMddm18+yrDmZPn3jI7C5hJ9ahABE5q6dyLYXQ= github.com/containerd/cgroups/v3 v3.1.3/go.mod h1:PKZ2AcWmSBsY/tJUVhtS/rluX0b1uq1GmPO1ElCmbOw= -github.com/containerd/console v1.0.5 h1:R0ymNeydRqH2DmakFNdmjR2k0t7UPuiOV/N/27/qqsc= -github.com/containerd/console v1.0.5/go.mod h1:YynlIjWYF8myEu6sdkwKIvGQq+cOckRm6So2avqoYAk= github.com/containerd/containerd v1.7.32 h1:S54xuVcPxeLaYgaRABtpJ2VyVUVsy0IGf7qHBs+sbY8= github.com/containerd/containerd v1.7.32/go.mod h1:jdwD6s/BhV4XVJGrvtziNPVA+83n66TwptVaPKprq4E= -github.com/containerd/containerd/api v1.10.0 h1:5n0oHYVBwN4VhoX9fFykCV9dF1/BvAXeg2F8W6UYq1o= -github.com/containerd/containerd/api v1.10.0/go.mod h1:NBm1OAk8ZL+LG8R0ceObGxT5hbUYj7CzTmR3xh0DlMM= -github.com/containerd/containerd/api v1.11.0 h1:smv4e74S/wwIx0Sj7lhwO1t3M/oi+mSzk2VXqHq8aO0= -github.com/containerd/containerd/api v1.11.0/go.mod h1:CaQFRu+N1MtbgL6JDOJLUB1hCKESU1lD6MuTJhgtdlw= github.com/containerd/containerd/api v1.11.1 h1:h8nfoDW9+fNsC/9TwiAHj8B1GzXKtR4eFtkhi/X5RLU= github.com/containerd/containerd/api v1.11.1/go.mod h1:CaQFRu+N1MtbgL6JDOJLUB1hCKESU1lD6MuTJhgtdlw= -github.com/containerd/containerd/v2 v2.2.3 h1:mOBRLaHGvmgy0bRo1Sg6OD8ugMKZIvCoWWMeMMygliA= -github.com/containerd/containerd/v2 v2.2.3/go.mod h1:ns24cwt+p36mRnuKE3hLRxVBpuSP+a/Y25AMki1t/RY= -github.com/containerd/containerd/v2 v2.3.0 h1:qpB5dyToxPqea1OdedyAiAnnor5wxTM+Py9nWt5CnWY= -github.com/containerd/containerd/v2 v2.3.0/go.mod h1:+chyhxLNeqUVOcTJGgaSu/IbDGX6p3+d8AJjAaerAS8= github.com/containerd/containerd/v2 v2.3.1 h1:4dVXBdlvotRBlaP2TmNbY/EGc06KJrMDDUqQdxX/HOk= github.com/containerd/containerd/v2 v2.3.1/go.mod h1:xVoxGPWZBwwph8DF2IbDhriLKdHfjdpO0b3wFP9wQ1I= -github.com/containerd/continuity v0.4.5 h1:ZRoN1sXq9u7V6QoHMcVWGhOwDFqZ4B9i5H6un1Wh0x4= -github.com/containerd/continuity v0.4.5/go.mod h1:/lNJvtJKUQStBzpVQ1+rasXO1LAWtUQssk28EZvJ3nE= github.com/containerd/continuity v0.5.0 h1:7a85HZpCSs+1Zps0Ee3DPSuAWY+0SJM1JNM51nlEVDg= github.com/containerd/continuity v0.5.0/go.mod h1:/lNJvtJKUQStBzpVQ1+rasXO1LAWtUQssk28EZvJ3nE= github.com/containerd/errdefs v1.0.0 h1:tg5yIfIlQIrxYtu9ajqY42W3lpS19XqdxRQeEwYG8PI= @@ -379,14 +347,10 @@ github.com/containerd/log v0.1.0 h1:TCJt7ioM2cr/tfR8GPbGf9/VRAX8D2B4PjzCpfX540I= github.com/containerd/log v0.1.0/go.mod h1:VRRf09a7mHDIRezVKTRCrOq78v577GXq3bSa3EhrzVo= github.com/containerd/platforms v1.0.0-rc.4 h1:M42JrUT4zfZTqtkUwkr0GzmUWbfyO5VO0Q5b3op97T4= github.com/containerd/platforms v1.0.0-rc.4/go.mod h1:lKlMXyLybmBedS/JJm11uDofzI8L2v0J2ZbYvNsbq1A= -github.com/containerd/plugin v1.0.0 h1:c8Kf1TNl6+e2TtMHZt+39yAPDbouRH9WAToRjex483Y= -github.com/containerd/plugin v1.0.0/go.mod h1:hQfJe5nmWfImiqT1q8Si3jLv3ynMUIBB47bQ+KexvO8= github.com/containerd/plugin v1.1.0 h1:O+7lczNJVMy8rz0YNx3xGB8tTf5qY4i5abF041Ew19U= github.com/containerd/plugin v1.1.0/go.mod h1:qBTum+A8lJ6lO44A19Eo7y1OlcLj4OWFH1DA/vnHmcc= github.com/containerd/stargz-snapshotter/estargz v0.18.2 h1:yXkZFYIzz3eoLwlTUZKz2iQ4MrckBxJjkmD16ynUTrw= github.com/containerd/stargz-snapshotter/estargz v0.18.2/go.mod h1:XyVU5tcJ3PRpkA9XS2T5us6Eg35yM0214Y+wvrZTBrY= -github.com/containerd/ttrpc v1.2.7 h1:qIrroQvuOL9HQ1X6KHe2ohc7p+HP/0VE6XPU7elJRqQ= -github.com/containerd/ttrpc v1.2.7/go.mod h1:YCXHsb32f+Sq5/72xHubdiJRQY9inL4a4ZQrAbN1q9o= github.com/containerd/ttrpc v1.2.8 h1:xbVu6D4qF2jihdh9rDVOKqUMiFBQk6YctTdo1zk087Y= github.com/containerd/ttrpc v1.2.8/go.mod h1:wyZW2K79t4Hfcxl+GUvkZqRBzJlqFFvgEeeWXa42tyE= github.com/containerd/typeurl/v2 v2.2.3 h1:yNA/94zxWdvYACdYO8zofhrTVuQY73fFU1y++dYSw40= @@ -394,16 +358,10 @@ github.com/containerd/typeurl/v2 v2.2.3/go.mod h1:95ljDnPfD3bAbDJRugOiShd/DlAAsx github.com/coreos/go-semver v0.3.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk= github.com/coreos/go-systemd/v22 v22.3.2/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc= github.com/coreos/go-systemd/v22 v22.5.0/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc= -github.com/coreos/go-systemd/v22 v22.6.0 h1:aGVa/v8B7hpb0TKl0MWoAavPDmHvobFe5R5zn0bCJWo= -github.com/coreos/go-systemd/v22 v22.6.0/go.mod h1:iG+pp635Fo7ZmV/j14KUcmEyWF+0X7Lua8rrTWzYgWU= github.com/coreos/go-systemd/v22 v22.7.0 h1:LAEzFkke61DFROc7zNLX/WA2i5J8gYqe0rSj9KI28KA= github.com/coreos/go-systemd/v22 v22.7.0/go.mod h1:xNUYtjHu2EDXbsxz1i41wouACIwT7Ybq9o0BQhMwD0w= github.com/cpuguy83/go-md2man/v2 v2.0.1/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= -github.com/cpuguy83/go-md2man/v2 v2.0.2/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= -github.com/cpuguy83/go-md2man/v2 v2.0.5/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= github.com/cpuguy83/go-md2man/v2 v2.0.6/go.mod h1:oOW0eioCTA6cOiMLiUPZOpcVxMig6NIQQ7OS05n1F4g= -github.com/cpuguy83/go-md2man/v2 v2.0.7 h1:zbFlGlXEAKlwXpmvle3d8Oe3YnkKIK4xSRTd3sHPnBo= -github.com/cpuguy83/go-md2man/v2 v2.0.7/go.mod h1:oOW0eioCTA6cOiMLiUPZOpcVxMig6NIQQ7OS05n1F4g= github.com/creack/pty v1.1.24 h1:bJrF4RRfyJnbTJqzRLHzcGaZK1NeM5kTC9jGgovnR1s= github.com/creack/pty v1.1.24/go.mod h1:08sCNb52WyoAwi2QDyzUCTgcvVFhUzewun7wtTfvcwE= github.com/cyphar/filepath-securejoin v0.6.1 h1:5CeZ1jPXEiYt3+Z6zqprSAgSWiggmpVyciv8syjIpVE= @@ -419,10 +377,6 @@ github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f h1:lO4WD4F/r github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f/go.mod h1:cuUVRXasLTGF7a8hSLbxyZXjz+1KgoB3wDUb6vlszIc= github.com/diskfs/go-diskfs v1.7.0 h1:vonWmt5CMowXwUc79jWyGrf2DIMeoOjkLlMnQYGVOs8= github.com/diskfs/go-diskfs v1.7.0/go.mod h1:LhQyXqOugWFRahYUSw47NyZJPezFzB9UELwhpszLP/k= -github.com/distribution/distribution/v3 v3.0.1-0.20250403190400-dbca4995c83c h1:tFjIrcN2x16eg3aob8g8LPNJClLxtQbu1wqeUMydXRc= -github.com/distribution/distribution/v3 v3.0.1-0.20250403190400-dbca4995c83c/go.mod h1:tRNuFoZsUdyRVegq8xGNeds4KLjwLCRin/tTo6i1DhU= -github.com/distribution/distribution/v3 v3.0.1-0.20260120145532-40594bd98e6d h1:c2HDaWKU1MalLXwrAek+Yks7n80p/salSR5u6alHPBo= -github.com/distribution/distribution/v3 v3.0.1-0.20260120145532-40594bd98e6d/go.mod h1:WiiB9B3TqqAPe7hPjI1P9OMtEW7Ub/HHGndi11SqeDA= github.com/distribution/distribution/v3 v3.1.1 h1:KUbk7C8CfaLXy8kbf/hGq9cad/wCoLB6dbWH6DMbmX0= github.com/distribution/distribution/v3 v3.1.1/go.mod h1:d7lXwZpph0bVcOj4Aqn0nMrWHIwRQGdiV5TLeI+/w6Y= github.com/distribution/reference v0.6.0 h1:0IXCQ5g4/QMHHkarYzh5l+u8T3t73zM5QvfrDyIgxBk= @@ -431,16 +385,12 @@ github.com/djherbis/times v1.6.0 h1:w2ctJ92J8fBvWPxugmXIv7Nz7Q3iDMKNx9v5ocVH20c= github.com/djherbis/times v1.6.0/go.mod h1:gOHeRAz2h+VJNZ5Gmc/o7iD9k4wW7NMVqieYCY99oc0= github.com/dlclark/regexp2 v1.11.0 h1:G/nrcoOa7ZXlpoa/91N3X7mM3r8eIlMBBJZvsz/mxKI= github.com/dlclark/regexp2 v1.11.0/go.mod h1:DHkYz0B9wPfa6wondMfaivmHpzrQ3v9q8cnmRbL6yW8= -github.com/docker/cli v29.4.0+incompatible h1:+IjXULMetlvWJiuSI0Nbor36lcJ5BTcVpUmB21KBoVM= -github.com/docker/cli v29.4.0+incompatible/go.mod h1:JLrzqnKDaYBop7H2jaqPtU4hHvMKP+vjCwu2uszcLI8= github.com/docker/cli v29.4.3+incompatible h1:u+UliYm2J/rYrIh2FqHQg32neRG8GjbvNuwQRTzGspU= github.com/docker/cli v29.4.3+incompatible/go.mod h1:JLrzqnKDaYBop7H2jaqPtU4hHvMKP+vjCwu2uszcLI8= github.com/docker/docker-credential-helpers v0.9.5 h1:EFNN8DHvaiK8zVqFA2DT6BjXE0GzfLOZ38ggPTKePkY= github.com/docker/docker-credential-helpers v0.9.5/go.mod h1:v1S+hepowrQXITkEfw6o4+BMbGot02wiKpzWhGUZK6c= github.com/docker/go-connections v0.6.0 h1:LlMG9azAe1TqfR7sO+NJttz1gy6KO7VJBh+pMmjSD94= github.com/docker/go-connections v0.6.0/go.mod h1:AahvXYshr6JgfUJGdDCs2b5EZG/vmaMAntpSFH5BFKE= -github.com/docker/go-events v0.0.0-20250114142523-c867878c5e32 h1:EHZfspsnLAz8Hzccd67D5abwLiqoqym2jz/jOS39mCk= -github.com/docker/go-events v0.0.0-20250114142523-c867878c5e32/go.mod h1:Uw6UezgYA44ePAFQYUehOuCzmy5zmg/+nl2ZfMWGkpA= github.com/docker/go-events v0.0.0-20250808211157-605354379745 h1:yOn6Ze6IbYI/KAw2lw/83ELYvZh6hvsygTVkD0dzMC4= github.com/docker/go-events v0.0.0-20250808211157-605354379745/go.mod h1:Uw6UezgYA44ePAFQYUehOuCzmy5zmg/+nl2ZfMWGkpA= github.com/docker/go-metrics v0.0.1 h1:AgB/0SvBxihN0X8OR4SjsblXkbMvalQ8cjmtKQ2rQV8= @@ -483,6 +433,8 @@ github.com/envoyproxy/protoc-gen-validate v1.3.0 h1:TvGH1wof4H33rezVKWSpqKz5NXWg github.com/envoyproxy/protoc-gen-validate v1.3.0/go.mod h1:HvYl7zwPa5mffgyeTUHA9zHIH36nmrm7oCbo4YKoSWA= github.com/erikgeiser/coninput v0.0.0-20211004153227-1c3628e74d0f h1:Y/CXytFA4m6baUTXGLOoWe4PQhGxaX0KpnayAqC48p4= github.com/erikgeiser/coninput v0.0.0-20211004153227-1c3628e74d0f/go.mod h1:vw97MGsxSvLiUE2X8qFplwetxpGLQrlU1Q9AUEIzCaM= +github.com/erofs/go-erofs v0.3.0 h1:o/W5ABAA3sHYl97WL93dacKEfeDpJhdFf3c2snAti7I= +github.com/erofs/go-erofs v0.3.0/go.mod h1:XkSeN9MHszGd4+3gcEjadJLYHCQpWzJ7/8yznzMuzJs= github.com/evanphx/json-patch v5.9.11+incompatible h1:ixHHqfcGvxhWkniF1tWxBHA0yb4Z+d1UQi45df52xW8= github.com/evanphx/json-patch v5.9.11+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk= github.com/exponent-io/jsonpath v0.0.0-20210407135951-1de76d718b3f h1:Wl78ApPPB2Wvf/TIe2xdyJxTlb6obmF18d8QdkxNDu4= @@ -532,18 +484,10 @@ 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.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-billy/v5 v5.8.1-0.20260506061021-07f2a0bf50e4 h1:XK6pelr1UQyrCSXsrqrJxr0jkrHXg7QCzfPH3UQMYp8= -github.com/go-git/go-billy/v5 v5.8.1-0.20260506061021-07f2a0bf50e4/go.mod h1:jCnQMLj9eUgGU7+ludSTYoZL/GGmii14RxKFj7ROgHw= github.com/go-git/go-billy/v5 v5.9.0 h1:jItGXszUDRtR/AlferWPTMN4j38BQ88XnXKbilmmBPA= github.com/go-git/go-billy/v5 v5.9.0/go.mod h1:jCnQMLj9eUgGU7+ludSTYoZL/GGmii14RxKFj7ROgHw= 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.18.0 h1:O831KI+0PR51hM2kep6T8k+w0/LIAD490gvqMCvL5hM= -github.com/go-git/go-git/v5 v5.18.0/go.mod h1:pW/VmeqkanRFqR6AljLcs7EA7FbZaN5MQqO7oZADXpo= -github.com/go-git/go-git/v5 v5.18.1-0.20260420130857-e5bbc088b774 h1:FED4o0JOD1z8x/dMcmM6IKkqoIz22xz7sWE81FEdXNQ= -github.com/go-git/go-git/v5 v5.18.1-0.20260420130857-e5bbc088b774/go.mod h1:pW/VmeqkanRFqR6AljLcs7EA7FbZaN5MQqO7oZADXpo= github.com/go-git/go-git/v5 v5.19.1 h1:nX27AnaU43/K5bKktKwgBmR9lawoYVe1Ckg0rgzzN00= github.com/go-git/go-git/v5 v5.19.1/go.mod h1:Pb1v0c7/g8aGQJwx9Us09W85yGoyvSwuhEGMH7zjDKQ= github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU= @@ -551,8 +495,6 @@ github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2 github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= github.com/go-gorp/gorp/v3 v3.1.0 h1:ItKF/Vbuj31dmV4jxA1qblpSwkl9g1typ24xoe70IGs= github.com/go-gorp/gorp/v3 v3.1.0/go.mod h1:dLEjIyyRNiXvNZ8PSmzpt1GsWAUK8kjVhEpjH8TixEw= -github.com/go-jose/go-jose/v3 v3.0.5 h1:BLLJWbC4nMZOfuPVxoZIxeYsn6Nl2r1fITaJ78UQlVQ= -github.com/go-jose/go-jose/v3 v3.0.5/go.mod h1:5b+7YgP7ZICgJDBdfjZaIt+H/9L9T/YQrVfLAMboGkQ= github.com/go-jose/go-jose/v4 v4.1.4 h1:moDMcTHmvE6Groj34emNPLs/qtYXRVcd6S7NHbHz3kA= github.com/go-jose/go-jose/v4 v4.1.4/go.mod h1:x4oUasVrzR7071A4TnHLGSPpNOm2a21K9Kf04k1rs08= github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= @@ -580,7 +522,6 @@ github.com/go-sql-driver/mysql v1.8.1/go.mod h1:wEBSXgmK//2ZFJyE+qWnIsVGmvmEKlqw github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= github.com/go-task/slim-sprig/v3 v3.0.0 h1:sUs3vkvUymDpBKi3qH1YSqBQk9+9D/8M2mN1vB6EwHI= github.com/go-task/slim-sprig/v3 v3.0.0/go.mod h1:W848ghGpv3Qj3dhTPRyJypKRiqCdHZiAzKg9hl15HA8= -github.com/go-test/deep v1.0.4/go.mod h1:wGDj63lr65AM2AQyKZd/NYHGb0R+1RLqB8NKt3aSFNA= github.com/go-test/deep v1.1.1 h1:0r/53hagsehfO4bzD2Pgr/+RgHqhmf+k1Bpse2cTu1U= github.com/go-test/deep v1.1.1/go.mod h1:5C2ZWiW0ErCdrYzpqxLbTX7MG14M9iiw8DgHncVwcsE= github.com/go-viper/mapstructure/v2 v2.5.0 h1:vM5IJoUAy3d7zRSVtIwQgBj7BiWtMPfmPEgAXnvj1Ro= @@ -593,8 +534,6 @@ github.com/gobwas/ws v1.2.1/go.mod h1:hRKAFb8wOxFROYNsT1bqfWnhX+b5MFeJM9r2ZSwg/K github.com/goccy/go-yaml v1.19.2 h1:PmFC1S6h8ljIz6gMRBopkjP1TVT7xuwrButHID66PoM= github.com/goccy/go-yaml v1.19.2/go.mod h1:XBurs7gK8ATbW4ZPGKgcbrY1Br56PdM69F7LkFRi1kA= github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= -github.com/godbus/dbus/v5 v5.1.0 h1:4KLkAxT3aOY8Li4FRJe/KvhoNFFxo0m6fNuFUO8QJUk= -github.com/godbus/dbus/v5 v5.1.0/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= github.com/gofrs/flock v0.13.0 h1:95JolYOvGMqeH31+FC7D2+uULf6mG61mEZ/A8dRYMzw= github.com/gofrs/flock v0.13.0/go.mod h1:jxeyy9R1auM5S6JYDBhDt+E2TCo7DkratH4Pgi8P+Z0= github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= @@ -602,8 +541,6 @@ github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q= github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q= github.com/gohugoio/hashstructure v0.6.0 h1:7wMB/2CfXoThFYhdWRGv3u3rUM761Cq29CxUW+NltUg= github.com/gohugoio/hashstructure v0.6.0/go.mod h1:lapVLk9XidheHG1IQ4ZSbyYrXcaILU1ZEP/+vno5rBQ= -github.com/golang-jwt/jwt/v5 v5.2.2 h1:Rl4B7itRWVtYIHFrSNd7vhTiz9UpLdi6gZhZ3wEeDy8= -github.com/golang-jwt/jwt/v5 v5.2.2/go.mod h1:pqrtFR0X4osieyHYxtmOUWsAWrfe1Q5UVIyoH402zdk= github.com/golang-jwt/jwt/v5 v5.3.0 h1:pv4AsKCKKZuqlgs5sUmn4x8UlGa0kEVt/puTpKx9vvo= github.com/golang-jwt/jwt/v5 v5.3.0/go.mod h1:fxCRLWMO43lRc8nhHWY6LGqRcf+1gQWArsqaEUEa5bE= github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= @@ -662,8 +599,6 @@ github.com/google/go-cmp v0.5.3/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/ github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.7/go.mod h1:n+brtR0CgQNWTVd5ZUFpTBC8YFBDLK/h/bpaJ8/DtOE= -github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8= github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU= github.com/google/go-containerregistry v0.21.5 h1:KTJG9Pn/jC0VdZR6ctV3/jcN+q6/Iqlx0sTVz3ywZlM= @@ -694,8 +629,6 @@ github.com/google/pprof v0.0.0-20210609004039-a478d1d731e9/go.mod h1:kpwsk12EmLe github.com/google/pprof v0.0.0-20210720184732-4bb14d4b1be1/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= github.com/google/pprof v0.0.0-20211214055906-6f57359322fd/go.mod h1:KgnwoLYCZ8IQu3XUZ8Nc/bM9CCZFOyjUNOSygVozoDg= github.com/google/pprof v0.0.0-20240227163752-401108e1b7e7/go.mod h1:czg5+yv1E0ZGTi6S6vVK1mke0fV+FaUhNGcd6VRS9Ik= -github.com/google/pprof v0.0.0-20250820193118-f64d9cf942d6 h1:EEHtgt9IwisQ2AZ4pIsMjahcegHh6rmhqxzIRQIyepY= -github.com/google/pprof v0.0.0-20250820193118-f64d9cf942d6/go.mod h1:I6V7YzU0XDpsHqbsyrghnFZLO1gwK6NPTNvmetQIk9U= github.com/google/pprof v0.0.0-20260115054156-294ebfa9ad83 h1:z2ogiKUYzX5Is6zr/vP9vJGqPwcdqsWjOt+V8J7+bTc= github.com/google/pprof v0.0.0-20260115054156-294ebfa9ad83/go.mod h1:MxpfABSjhmINe3F1It9d+8exIHFvUqtLIRCdOGNXqiI= github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= @@ -732,13 +665,10 @@ github.com/gosuri/uitable v0.0.4 h1:IG2xLKRvErL3uhY6e1BylFzG+aJiwQviDDTfOKeKTpY= github.com/gosuri/uitable v0.0.4/go.mod h1:tKR86bXuXPZazfOTG1FIzvjIdXzd0mo4Vtn16vt0PJo= github.com/gpustack/gguf-parser-go v0.24.0 h1:tdJceXYp9e5RhE9RwVYIuUpir72Jz2D68NEtDXkKCKc= github.com/gpustack/gguf-parser-go v0.24.0/go.mod h1:y4TwTtDqFWTK+xvprOjRUh+dowgU2TKCX37vRKvGiZ0= -github.com/gregjones/httpcache v0.0.0-20190611155906-901d90724c79 h1:+ngKgrYPPJrOjhax5N+uePQ0Fh1Z7PheYoUI/0nzkPA= -github.com/gregjones/httpcache v0.0.0-20190611155906-901d90724c79/go.mod h1:FecbI9+v66THATjSRHfNgh1IVFe/9kFxbXtjV0ctIMA= github.com/grpc-ecosystem/grpc-gateway v1.16.0 h1:gmcG1KaJ57LophUzW0Hy8NmPhnMZb4M0+kPpLofRdBo= github.com/grpc-ecosystem/grpc-gateway v1.16.0/go.mod h1:BDjrQk3hbvj6Nolgz8mAMFbcEtjT1g+wF4CSlocrBnw= -github.com/grpc-ecosystem/grpc-gateway/v2 v2.26.3 h1:5ZPtiqj0JL5oKWmcsq4VMaAW5ukBEgSGXEN89zeH1Jo= -github.com/grpc-ecosystem/grpc-gateway/v2 v2.26.3/go.mod h1:ndYquD05frm2vACXE1nsccT4oJzjhw2arTS2cpUD1PI= github.com/grpc-ecosystem/grpc-gateway/v2 v2.28.0 h1:HWRh5R2+9EifMyIHV7ZV+MIZqgz+PMpZ14Jynv3O2Zs= +github.com/grpc-ecosystem/grpc-gateway/v2 v2.28.0/go.mod h1:JfhWUomR1baixubs02l85lZYYOm7LV6om4ceouMv45c= github.com/h2non/filetype v1.1.3 h1:FKkx9QbD7HR/zjK1Ia5XiBsq9zdLi5Kf3zGyFTAFkGg= github.com/h2non/filetype v1.1.3/go.mod h1:319b3zT68BvV+WRj7cwy856M2ehB3HqNOt6sy1HndBY= github.com/hashicorp/aws-sdk-go-base/v2 v2.0.0-beta.72 h1:vTCWu1wbdYo7PEZFem/rlr01+Un+wwVmI7wiegFdRLk= @@ -845,7 +775,6 @@ github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+o github.com/klauspost/compress v1.4.1/go.mod h1:RyIbtBH6LamlWaDj8nUwkbUhJ87Yi3uG0guNDohfE1A= github.com/klauspost/compress v1.18.5 h1:/h1gH5Ce+VWNLSWqPzOVn6XBO+vJbCNGvjoaGBFW2IE= github.com/klauspost/compress v1.18.5/go.mod h1:cwPg85FWrGar70rWktvGQj8/hthj3wpl0PGDogxkrSQ= -github.com/klauspost/cpuid v1.2.0 h1:NMpwD2G9JSFOE1/TJjGSo5zG7Yb2bTe7eq1jH+irmeE= github.com/klauspost/cpuid v1.2.0/go.mod h1:Pj4uuM528wm8OyEC2QMXAi2YiTZ96dNQPGgoMS4s3ek= github.com/klauspost/cpuid/v2 v2.3.0 h1:S4CRMLnYUhGeDFDqkGriYKdfoFlDnMtqTiI/sFzhA9Y= github.com/klauspost/cpuid/v2 v2.3.0/go.mod h1:hqwkgyIinND0mEev00jJYCxPNVRVXFQeu1XKlok6oO0= @@ -944,8 +873,6 @@ github.com/moby/moby/api v1.54.1 h1:TqVzuJkOLsgLDDwNLmYqACUuTehOHRGKiPhvH8V3Nn4= github.com/moby/moby/api v1.54.1/go.mod h1:+RQ6wluLwtYaTd1WnPLykIDPekkuyD/ROWQClE83pzs= github.com/moby/moby/client v0.4.0 h1:S+2XegzHQrrvTCvF6s5HFzcrywWQmuVnhOXe2kiWjIw= github.com/moby/moby/client v0.4.0/go.mod h1:QWPbvWchQbxBNdaLSpoKpCdf5E+WxFAgNHogCWDoa7g= -github.com/moby/sys/capability v0.4.0 h1:4D4mI6KlNtWMCM1Z/K0i7RV1FkX+DBDHKVJpCndZoHk= -github.com/moby/sys/capability v0.4.0/go.mod h1:4g9IK291rVkms3LKCDOoYlnV8xKwoDTpIrNEE35Wq0I= github.com/moby/sys/mountinfo v0.7.2 h1:1shs6aH5s4o5H2zQLn796ADW1wMrIwHsyJ2v9KouLrg= github.com/moby/sys/mountinfo v0.7.2/go.mod h1:1YOa8w8Ih7uW0wALDUgT1dTTSBrZ+HiBLGws92L2RU4= github.com/moby/sys/sequential v0.6.0 h1:qrx7XFUd/5DxtqcoH1h438hF5TmOvzC/lspjy7zgvCU= @@ -968,8 +895,6 @@ github.com/modern-go/reflect2 v1.0.3-0.20250322232337-35a7c28c31ee h1:W5t00kpgFd github.com/modern-go/reflect2 v1.0.3-0.20250322232337-35a7c28c31ee/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk= github.com/monochromegane/go-gitignore v0.0.0-20200626010858-205db1a8cc00 h1:n6/2gBQ3RWajuToeY6ZtZTIKv2v7ThUy5KKusIT0yc0= github.com/monochromegane/go-gitignore v0.0.0-20200626010858-205db1a8cc00/go.mod h1:Pm3mSP3c5uWn86xMLZ5Sa7JB9GsEZySvHYXCTK4E9q4= -github.com/mrunalp/fileutils v0.5.1 h1:F+S7ZlNKnrwHfSwdlgNSkKo67ReVf8o9fel6C3dkm/Q= -github.com/mrunalp/fileutils v0.5.1/go.mod h1:M1WthSahJixYnrXQl/DFQuteStB1weuxD2QJNHXfbSQ= github.com/mssola/user_agent v0.6.0 h1:uwPR4rtWlCHRFyyP9u2KOV0u8iQXmS7Z7feTrstQwk4= github.com/mssola/user_agent v0.6.0/go.mod h1:TTPno8LPY3wAIEKRpAtkdMT0f8SE24pLRGPahjCH4uw= github.com/muesli/ansi v0.0.0-20230316100256-276c6243b2f6 h1:ZK8zHtRHOkbHy6Mmr5D264iyp3TiX5OmNcI5cIARiQI= @@ -997,24 +922,16 @@ github.com/olekukonko/ll v0.1.6 h1:lGVTHO+Qc4Qm+fce/2h2m5y9LvqaW+DCN7xW9hsU3uA= github.com/olekukonko/ll v0.1.6/go.mod h1:NVUmjBb/aCtUpjKk75BhWrOlARz3dqsM+OtszpY4o88= github.com/olekukonko/tablewriter v1.1.4 h1:ORUMI3dXbMnRlRggJX3+q7OzQFDdvgbN9nVWj1drm6I= github.com/olekukonko/tablewriter v1.1.4/go.mod h1:+kedxuyTtgoZLwif3P1Em4hARJs+mVnzKxmsCL/C5RY= -github.com/onsi/ginkgo/v2 v2.27.2 h1:LzwLj0b89qtIy6SSASkzlNvX6WktqurSHwkk2ipF/Ns= -github.com/onsi/ginkgo/v2 v2.27.2/go.mod h1:ArE1D/XhNXBXCBkKOLkbsb2c81dQHCRcF5zwn/ykDRo= github.com/onsi/ginkgo/v2 v2.28.1 h1:S4hj+HbZp40fNKuLUQOYLDgZLwNUVn19N3Atb98NCyI= -github.com/onsi/gomega v1.38.2 h1:eZCjf2xjZAqe+LeWvKb5weQ+NcPwX84kqJ0cZNxok2A= -github.com/onsi/gomega v1.38.2/go.mod h1:W2MJcYxRGV63b418Ai34Ud0hEdTVXq9NW9+Sx6uXf3k= +github.com/onsi/ginkgo/v2 v2.28.1/go.mod h1:CLtbVInNckU3/+gC8LzkGUb9oF+e8W8TdUsxPwvdOgE= github.com/onsi/gomega v1.39.1 h1:1IJLAad4zjPn2PsnhH70V4DKRFlrCzGBNrNaru+Vf28= -github.com/opencontainers/cgroups v0.0.4 h1:XVj8P/IHVms/j+7eh8ggdkTLAxjz84ZzuFyGoE28DR4= -github.com/opencontainers/cgroups v0.0.4/go.mod h1:s8lktyhlGUqM7OSRL5P7eAW6Wb+kWPNvt4qvVfzA5vs= +github.com/onsi/gomega v1.39.1/go.mod h1:hL6yVALoTOxeWudERyfppUcZXjMwIMLnuSfruD2lcfg= github.com/opencontainers/go-digest v1.0.0 h1:apOUWs51W5PlhuyGyz9FCeeBIOUDA/6nW8Oi/yOhh5U= github.com/opencontainers/go-digest v1.0.0/go.mod h1:0JzlMkj0TRzQZfJkVvzbP0HBR3IKzErnv2BNG4W4MAM= github.com/opencontainers/image-spec v1.1.1 h1:y0fUlFfIZhPF1W537XOLg0/fcx6zcHCJwooC2xJA040= github.com/opencontainers/image-spec v1.1.1/go.mod h1:qpqAh3Dmcf36wStyyWU+kCeDgrGnAve2nCC8+7h8Q0M= -github.com/opencontainers/runc v1.3.4 h1:+lwmPUTzbgv0JFqu8zBU2WtHYbm+JPPS9hxB/PvWd30= -github.com/opencontainers/runc v1.3.4/go.mod h1:o1wyv76EDlTkcf0KTFgN8bMWLPvgF/HfX709lDv+rr4= github.com/opencontainers/runtime-spec v1.3.0 h1:YZupQUdctfhpZy3TM39nN9Ika5CBWT5diQ8ibYCRkxg= github.com/opencontainers/runtime-spec v1.3.0/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0= -github.com/opencontainers/selinux v1.13.0 h1:Zza88GWezyT7RLql12URvoxsbLfjFx988+LGaWfbL84= -github.com/opencontainers/selinux v1.13.0/go.mod h1:XxWTed+A/s5NNq4GmYScVy+9jzXhGBVEOAyucdRUY8s= github.com/orisano/pixelmatch v0.0.0-20220722002657-fb0b55479cde/go.mod h1:nZgzbfBr3hhjoZnS66nKrHmduYNpc34ny7RK4z5/HM0= github.com/pascaldekloe/goe v0.0.0-20180627143212-57f6aae5913c/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc= github.com/pascaldekloe/goe v0.1.0/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc= @@ -1023,8 +940,6 @@ github.com/pborman/indent v1.2.1/go.mod h1:FitS+t35kIYtB5xWTZAPhnmrxcciEEOdbyrrp github.com/pelletier/go-toml v1.9.4/go.mod h1:u1nR/EPcESfeI/szUZKdtJ0xRNbUoANCkoOuaOx1Y+c= github.com/pelletier/go-toml v1.9.5 h1:4yBQzkHv+7BHq2PQUZF3Mx0IYxG7LsP222s7Agd3ve8= github.com/pelletier/go-toml v1.9.5/go.mod h1:u1nR/EPcESfeI/szUZKdtJ0xRNbUoANCkoOuaOx1Y+c= -github.com/pelletier/go-toml/v2 v2.2.4 h1:mye9XuhQ6gvn5h28+VilKrrPoQVanw5PMw/TB0t5Ec4= -github.com/pelletier/go-toml/v2 v2.2.4/go.mod h1:2gIqNv+qfxSVS7cM2xJQKtLSTLUE9V8t9Stt+h56mCY= github.com/pelletier/go-toml/v2 v2.3.1 h1:MYEvvGnQjeNkRF1qUuGolNtNExTDwct51yp7olPtrEc= github.com/pelletier/go-toml/v2 v2.3.1/go.mod h1:2gIqNv+qfxSVS7cM2xJQKtLSTLUE9V8t9Stt+h56mCY= github.com/peterbourgon/diskv v2.0.1+incompatible h1:UBdAOUP5p4RWqPBg048CAvpKN+vxiaj6gdUUzhl4XmI= @@ -1033,8 +948,6 @@ github.com/phayes/freeport v0.0.0-20220201140144-74d24b5ae9f5 h1:Ii+DKncOVM8Cu1H github.com/phayes/freeport v0.0.0-20220201140144-74d24b5ae9f5/go.mod h1:iIss55rKnNBTvrwdmkUpLnDpZoAHvWaiq5+iMmen4AE= github.com/pierrec/lz4/v4 v4.1.22 h1:cKFw6uJDK+/gfw5BcDL0JL5aBsAFdsIT18eRtLj7VIU= github.com/pierrec/lz4/v4 v4.1.22/go.mod h1:gZWDp/Ze/IJXGXf23ltt2EXimqmTUXEy0GFuRQyBid4= -github.com/pjbgf/sha1cd v0.3.2 h1:a9wb0bp1oC2TGwStyn0Umc/IGKQnEgF0vVaZ8QF8eo4= -github.com/pjbgf/sha1cd v0.3.2/go.mod h1:zQWigSxVmsHEZow5qaLtPYxpcKMMQpa09ixqBxuCS6A= github.com/pjbgf/sha1cd v0.6.0 h1:3WJ8Wz8gvDz29quX1OcEmkAlUg9diU4GxJHqs0/XiwU= github.com/pjbgf/sha1cd v0.6.0/go.mod h1:lhpGlyHLpQZoxMv8HcgXvZEhcGs0PG/vsZnEJ7H0iCM= github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= @@ -1068,16 +981,15 @@ github.com/prometheus/client_model v0.6.2 h1:oBsgwpGs7iVziMvrGhE53c/GrLUsZdHnqNw github.com/prometheus/client_model v0.6.2/go.mod h1:y3m2F6Gdpfy6Ut/GBsUqTWZqCUvMVzSfMLjcu6wAwpE= github.com/prometheus/common v0.4.1/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= github.com/prometheus/common v0.9.1/go.mod h1:yhUN8i9wzaXS3w1O07YhxHEBxD+W35wd8bs7vj7HSQ4= -github.com/prometheus/common v0.66.1 h1:h5E0h5/Y8niHc5DlaLlWLArTQI7tMrsfQjHV+d9ZoGs= -github.com/prometheus/common v0.66.1/go.mod h1:gcaUsgf3KfRSwHY4dIMXLPV0K/Wg1oZ8+SbZk/HH/dA= github.com/prometheus/common v0.67.5 h1:pIgK94WWlQt1WLwAC5j2ynLaBRDiinoAb86HZHTUGI4= +github.com/prometheus/common v0.67.5/go.mod h1:SjE/0MzDEEAyrdr5Gqc6G+sXI67maCxzaT3A2+HqjUw= +github.com/prometheus/otlptranslator v1.0.0 h1:s0LJW/iN9dkIH+EnhiD3BlkkP5QVIUVEoIwkU+A6qos= +github.com/prometheus/otlptranslator v1.0.0/go.mod h1:vRYWnXvI6aWGpsdY/mOT/cbeVRBlPWtBNDb7kGR3uKM= github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA= github.com/prometheus/procfs v0.0.8/go.mod h1:7Qr8sr6344vo1JqZ6HhLceV9o3AJ1Ff+GxbHq6oeK9A= -github.com/prometheus/procfs v0.16.1 h1:hZ15bTNuirocR6u0JZ6BAHHmwS1p8B4P6MRqxtzMyRg= -github.com/prometheus/procfs v0.16.1/go.mod h1:teAbpZRB1iIAJYREa1LsoWUXykVXA1KlTmWl8x/U+Is= -github.com/prometheus/procfs v0.19.2 h1:zUMhqEW66Ex7OXIiDkll3tl9a1ZdilUOd/F6ZXw4Vws= github.com/prometheus/procfs v0.20.1 h1:XwbrGOIplXW/AU3YhIhLODXMJYyC1isLFfYCsTEycfc= +github.com/prometheus/procfs v0.20.1/go.mod h1:o9EMBZGRyvDrSPH1RqdxhojkuXstoe4UlK79eF5TGGo= github.com/redis/go-redis/extra/rediscmd/v9 v9.0.5 h1:EaDatTxkdHG+U3Bk4EUr+DZ7fOGwTfezUiUJMaIcaho= github.com/redis/go-redis/extra/rediscmd/v9 v9.0.5/go.mod h1:fyalQWdtzDBECAQFBJuQe5bzQ02jGd5Qcbgb97Flm7U= github.com/redis/go-redis/extra/redisotel/v9 v9.0.5 h1:EfpWLLCyXw8PSM2/XNJLjI3Pb27yVE+gIAfeqp8LUCc= @@ -1121,8 +1033,6 @@ github.com/scylladb/go-set v1.0.3-0.20200225121959-cc7b2070d91e/go.mod h1:DkpGd7 github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529/go.mod h1:DxrIzT+xaE7yg65j358z/aeFdxmN0P9QXhEzd20vsDc= github.com/sebdah/goldie/v2 v2.8.0 h1:dZb9wR8q5++oplmEiJT+U/5KyotVD+HNGCAc5gNr8rc= github.com/sebdah/goldie/v2 v2.8.0/go.mod h1:oZ9fp0+se1eapSRjfYbsV/0Hqhbuu3bJVvKI/NNtssI= -github.com/seccomp/libseccomp-golang v0.10.0 h1:aA4bp+/Zzi0BnWZ2F1wgNBs5gTpm+na2rWM6M9YjLpY= -github.com/seccomp/libseccomp-golang v0.10.0/go.mod h1:JA8cRccbGaA1s33RQf7Y1+q9gHmZX1yB/z9WDN1C6fg= github.com/sergi/go-diff v1.1.0/go.mod h1:STckp+ISIX8hZLjrqAeVduY0gWCT9IjLuqbuNXdaHfM= github.com/sergi/go-diff v1.2.0/go.mod h1:STckp+ISIX8hZLjrqAeVduY0gWCT9IjLuqbuNXdaHfM= github.com/sergi/go-diff v1.4.0 h1:n/SP9D5ad1fORl+llWyN+D6qoUETXNZARKjyY2/KVCw= @@ -1138,8 +1048,6 @@ github.com/sirupsen/logrus v1.9.4 h1:TsZE7l11zFCLZnZ+teH4Umoq5BhEIfIzfRDZ1Uzql2w github.com/sirupsen/logrus v1.9.4/go.mod h1:ftWc9WdOfJ0a92nsE2jF5u5ZwH8Bv2zdeOC42RjbV2g= github.com/skeema/knownhosts v1.3.1 h1:X2osQ+RAjK76shCbvhHHHVl3ZlgDm8apHEHFqRjnBY8= github.com/skeema/knownhosts v1.3.1/go.mod h1:r7KTdC8l4uxWRyK2TpQZ/1o5HaSzh06ePQNxPwTcfiY= -github.com/slack-go/slack v0.12.2 h1:x3OppyMyGIbbiyFhsBmpf9pwkUzMhthJMRNmNlA4LaQ= -github.com/slack-go/slack v0.12.2/go.mod h1:hlGi5oXA+Gt+yWTPP0plCdRKmjsDxecdHxYQdlMQKOw= github.com/slack-go/slack v0.23.1 h1:ZS5B96wxxYQRwvJ3/vJFtqtUZi3tXhsZCyT44Nv7M80= github.com/slack-go/slack v0.23.1/go.mod h1:H0yR/YBuRJ39RkE+JpV/d/oEsbanzTRowR82bCN0cEs= github.com/smallnest/ringbuffer v0.0.0-20241116012123-461381446e3d h1:3VwvTjiRPA7cqtgOWddEL+JrcijMlXUmj99c/6YyZoY= @@ -1161,7 +1069,6 @@ github.com/spf13/cast v1.4.1/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkU github.com/spf13/cast v1.10.0 h1:h2x0u2shc1QuLHfxi+cTJvs30+ZAHOGRic8uyGTDWxY= github.com/spf13/cast v1.10.0/go.mod h1:jNfB8QC9IA6ZuY2ZjDp0KtFO2LZZlg4S/7bzP6qqeHo= github.com/spf13/cobra v1.3.0/go.mod h1:BrRVncBjOJa/eUcVVm9CE+oC6as8k+VYr4NY7WCi9V4= -github.com/spf13/cobra v1.5.0/go.mod h1:dWXEIy2H428czQCjInthrTRUg7yKbok+2Qi/yBIJoUM= github.com/spf13/cobra v1.10.2 h1:DMTTonx5m65Ic0GOoRY2c16WCbHxOOw6xxezuLaBpcU= github.com/spf13/cobra v1.10.2/go.mod h1:7C1pvHqHw5A4vrJfjNwvOdzYu0Gml16OCs2GRiTUUS4= github.com/spf13/jwalterweatherman v1.1.0/go.mod h1:aNWZUN0dPAAO/Ljvb5BEdw96iTZ0EXowPYD95IqWIGo= @@ -1189,8 +1096,6 @@ github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/ github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= -github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= -github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= github.com/stretchr/testify v1.11.1 h1:7s2iGBzp5EwR7/aIZr8ao5+dra3wiQyKjjFuvgVKu7U= github.com/stretchr/testify v1.11.1/go.mod h1:wZwfW3scLgRK+23gO65QZefKpKQRnfz6sD981Nm4B6U= github.com/subosito/gotenv v1.2.0/go.mod h1:N0PQaV/YGNqwC0u51sEeR/aUtSLEXKX9iv69rRypqCw= @@ -1218,18 +1123,12 @@ github.com/tv42/httpunix v0.0.0-20150427012821-b75d8614f926/go.mod h1:9ESjWnEqri github.com/ulikunitz/xz v0.5.8/go.mod h1:nbz6k7qbPmH4IRqmfOplQw/tblSgqTqBwxkY0oWt/14= github.com/ulikunitz/xz v0.5.15 h1:9DNdB5s+SgV3bQ2ApL10xRc35ck0DuIX/isZvIk+ubY= github.com/ulikunitz/xz v0.5.15/go.mod h1:nbz6k7qbPmH4IRqmfOplQw/tblSgqTqBwxkY0oWt/14= -github.com/urfave/cli v1.22.16 h1:MH0k6uJxdwdeWQTwhSO42Pwr4YLrNLwBtg1MRgTqPdQ= -github.com/urfave/cli v1.22.16/go.mod h1:EeJR6BKodywf4zciqrdw6hpCPk68JO9z5LazXZMn5Po= github.com/vbatts/go-mtree v0.7.0 h1:ytmOc3MTRidZiBi9VBCyZ2BHe4fZS47L5v7BVXDWW4E= github.com/vbatts/go-mtree v0.7.0/go.mod h1:EjdpFC+LZy1TXbRGNa1MKKgjQ+7ew3foMFJK8o4/TdY= github.com/vbatts/tar-split v0.12.2 h1:w/Y6tjxpeiFMR47yzZPlPj/FcPLpXbTUi/9H7d3CPa4= github.com/vbatts/tar-split v0.12.2/go.mod h1:eF6B6i6ftWQcDqEn3/iGFRFRo8cBIMSJVOpnNdfTMFA= github.com/vifraa/gopom v1.0.0 h1:L9XlKbyvid8PAIK8nr0lihMApJQg/12OBvMA28BcWh0= github.com/vifraa/gopom v1.0.0/go.mod h1:oPa1dcrGrtlO37WPDBm5SqHAT+wTgF8An1Q71Z6Vv4o= -github.com/vishvananda/netlink v1.3.1 h1:3AEMt62VKqz90r0tmNhog0r/PpWKmrEShJU0wJW6bV0= -github.com/vishvananda/netlink v1.3.1/go.mod h1:ARtKouGSTGchR8aMwmkzC0qiNPrrWO5JS/XMVl45+b4= -github.com/vishvananda/netns v0.0.5 h1:DfiHV+j8bA32MFM7bfEunvT8IAqQ/NzSJHtcmW5zdEY= -github.com/vishvananda/netns v0.0.5/go.mod h1:SpkAiCQRtJ6TvvxPnOSyH3BMl6unz3xZlaprSwhNNJM= github.com/wagoodman/go-partybus v0.0.0-20230516145632-8ccac152c651 h1:jIVmlAFIqV3d+DOxazTR9v+zgj8+VYuQBzPgBZvWBHA= github.com/wagoodman/go-partybus v0.0.0-20230516145632-8ccac152c651/go.mod h1:b26F2tHLqaoRQf8DywqzVaV1MQ9yvjb0OMcNl7Nxu20= github.com/wagoodman/go-progress v0.0.0-20260303201901-10176f79b2c0 h1:EHsPe0Q0ANoLOZff1dBLAyeWLTA4sbPTpGI+2zb0FnM= @@ -1281,80 +1180,58 @@ go.opencensus.io v0.24.0 h1:y73uSU6J157QMP2kn2r30vwW1A2W2WFwSCGnAVxeaD0= go.opencensus.io v0.24.0/go.mod h1:vNK8G9p7aAivkbmorf4v+7Hgx+Zs0yY+0fOtgBfjQKo= go.opentelemetry.io/auto/sdk v1.2.1 h1:jXsnJ4Lmnqd11kwkBV2LgLoFMZKizbCi5fNZ/ipaZ64= go.opentelemetry.io/auto/sdk v1.2.1/go.mod h1:KRTj+aOaElaLi+wW1kO/DZRXwkF4C5xPbEe3ZiIhN7Y= -go.opentelemetry.io/contrib/bridges/prometheus v0.57.0 h1:UW0+QyeyBVhn+COBec3nGhfnFe5lwB0ic1JBVjzhk0w= -go.opentelemetry.io/contrib/bridges/prometheus v0.57.0/go.mod h1:ppciCHRLsyCio54qbzQv0E4Jyth/fLWDTJYfvWpcSVk= go.opentelemetry.io/contrib/bridges/prometheus v0.67.0 h1:dkBzNEAIKADEaFnuESzcXvpd09vxvDZsOjx11gjUqLk= +go.opentelemetry.io/contrib/bridges/prometheus v0.67.0/go.mod h1:Z5RIwRkZgauOIfnG5IpidvLpERjhTninpP1dTG2jTl4= go.opentelemetry.io/contrib/detectors/gcp v1.39.0 h1:kWRNZMsfBHZ+uHjiH4y7Etn2FK26LAGkNFw7RHv1DhE= go.opentelemetry.io/contrib/detectors/gcp v1.39.0/go.mod h1:t/OGqzHBa5v6RHZwrDBJ2OirWc+4q/w2fTbLZwAKjTk= -go.opentelemetry.io/contrib/exporters/autoexport v0.57.0 h1:jmTVJ86dP60C01K3slFQa2NQ/Aoi7zA+wy7vMOKD9H4= -go.opentelemetry.io/contrib/exporters/autoexport v0.57.0/go.mod h1:EJBheUMttD/lABFyLXhce47Wr6DPWYReCzaZiXadH7g= go.opentelemetry.io/contrib/exporters/autoexport v0.67.0 h1:4fnRcNpc6YFtG3zsFw9achKn3XgmxPxuMuqIL5rE8e8= -go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.63.0 h1:YH4g8lQroajqUwWbq/tr2QX1JFmEXaDLgG+ew9bLMWo= -go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.63.0/go.mod h1:fvPi2qXDqFs8M4B4fmJhE92TyQs9Ydjlg3RvfUp+NbQ= +go.opentelemetry.io/contrib/exporters/autoexport v0.67.0/go.mod h1:qTvIHMFKoxW7HXg02gm6/Wofhq5p3Ib/A/NNt1EoBSQ= go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.68.0 h1:0Qx7VGBacMm9ZENQ7TnNObTYI4ShC+lHI16seduaxZo= go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.68.0/go.mod h1:Sje3i3MjSPKTSPvVWCaL8ugBzJwik3u4smCjUeuupqg= -go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.61.0 h1:F7Jx+6hwnZ41NSFTO5q4LYDtJRXBf2PD0rNBkeB/lus= -go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.61.0/go.mod h1:UHB22Z8QsdRDrnAtX4PntOl36ajSxcdUMt1sF7Y6E7Q= go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.68.0 h1:CqXxU8VOmDefoh0+ztfGaymYbhdB/tT3zs79QaZTNGY= go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.68.0/go.mod h1:BuhAPThV8PBHBvg8ZzZ/Ok3idOdhWIodywz2xEcRbJo= go.opentelemetry.io/otel v1.43.0 h1:mYIM03dnh5zfN7HautFE4ieIig9amkNANT+xcVxAj9I= go.opentelemetry.io/otel v1.43.0/go.mod h1:JuG+u74mvjvcm8vj8pI5XiHy1zDeoCS2LB1spIq7Ay0= -go.opentelemetry.io/otel/exporters/otlp/otlplog/otlploggrpc v0.8.0 h1:WzNab7hOOLzdDF/EoWCt4glhrbMPVMOO5JYTmpz36Ls= -go.opentelemetry.io/otel/exporters/otlp/otlplog/otlploggrpc v0.8.0/go.mod h1:hKvJwTzJdp90Vh7p6q/9PAOd55dI6WA6sWj62a/JvSs= go.opentelemetry.io/otel/exporters/otlp/otlplog/otlploggrpc v0.18.0 h1:deI9UQMoGFgrg5iLPgzueqFPHevDl+28YKfSpPTI6rY= -go.opentelemetry.io/otel/exporters/otlp/otlplog/otlploghttp v0.8.0 h1:S+LdBGiQXtJdowoJoQPEtI52syEP/JYBUpjO49EQhV8= -go.opentelemetry.io/otel/exporters/otlp/otlplog/otlploghttp v0.8.0/go.mod h1:5KXybFvPGds3QinJWQT7pmXf+TN5YIa7CNYObWRkj50= +go.opentelemetry.io/otel/exporters/otlp/otlplog/otlploggrpc v0.18.0/go.mod h1:PFx9NgpNUKXdf7J4Q3agRxMs3Y07QhTCVipKmLsMKnU= go.opentelemetry.io/otel/exporters/otlp/otlplog/otlploghttp v0.19.0 h1:HIBTQ3VO5aupLKjC90JgMqpezVXwFuq6Ryjn0/izoag= -go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc v1.32.0 h1:j7ZSD+5yn+lo3sGV69nW04rRR0jhYnBwjuX3r0HvnK0= -go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc v1.32.0/go.mod h1:WXbYJTUaZXAbYd8lbgGuvih0yuCfOFC5RJoYnoLcGz8= +go.opentelemetry.io/otel/exporters/otlp/otlplog/otlploghttp v0.19.0/go.mod h1:ji9vId85hMxqfvICA0Jt8JqEdrXaAkcpkI9HPXya0ro= go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc v1.42.0 h1:MdKucPl/HbzckWWEisiNqMPhRrAOQX8r4jTuGr636gk= -go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetrichttp v1.32.0 h1:t/Qur3vKSkUCcDVaSumWF2PKHt85pc7fRvFuoVT8qFU= -go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetrichttp v1.32.0/go.mod h1:Rl61tySSdcOJWoEgYZVtmnKdA0GeKrSqkHC1t+91CH8= +go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc v1.42.0/go.mod h1:RolT8tWtfHcjajEH5wFIZ4Dgh5jpPdFXYV9pTAk/qjc= go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetrichttp v1.43.0 h1:w1K+pCJoPpQifuVpsKamUdn9U0zM3xUziVOqsGksUrY= -go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.35.0 h1:1fTNlAIJZGWLP5FVu0fikVry1IsiUnXjf7QFvoNN3Xw= -go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.35.0/go.mod h1:zjPK58DtkqQFn+YUMbx0M2XV3QgKU0gS9LeGohREyK4= +go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetrichttp v1.43.0/go.mod h1:HBy4BjzgVE8139ieRI75oXm3EcDN+6GhD88JT1Kjvxg= go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.43.0 h1:88Y4s2C8oTui1LGM6bTWkw0ICGcOLCAI5l6zsD1j20k= -go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.35.0 h1:m639+BofXTvcY1q8CGs4ItwQarYtJPOWmVobfM1HpVI= -go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.35.0/go.mod h1:LjReUci/F4BUyv+y4dwnq3h/26iNOeC3wAIqgvTIZVo= +go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.43.0/go.mod h1:Vl1/iaggsuRlrHf/hfPJPvVag77kKyvrLeD10kpMl+A= go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.43.0 h1:RAE+JPfvEmvy+0LzyUA25/SGawPwIUbZ6u0Wug54sLc= -go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.35.0 h1:xJ2qHD0C1BeYVTLLR9sX12+Qb95kfeD/byKj6Ky1pXg= -go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.35.0/go.mod h1:u5BF1xyjstDowA1R5QAO9JHzqK+ublenEW/dyqTjBVk= +go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.43.0/go.mod h1:AGmbycVGEsRx9mXMZ75CsOyhSP6MFIcj/6dnG+vhVjk= go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.43.0 h1:3iZJKlCZufyRzPzlQhUIWVmfltrXuGyfjREgGP3UUjc= -go.opentelemetry.io/otel/exporters/prometheus v0.54.0 h1:rFwzp68QMgtzu9PgP3jm9XaMICI6TsofWWPcBDKwlsU= -go.opentelemetry.io/otel/exporters/prometheus v0.54.0/go.mod h1:QyjcV9qDP6VeK5qPyKETvNjmaaEc7+gqjh4SS0ZYzDU= +go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.43.0/go.mod h1:/G+nUPfhq2e+qiXMGxMwumDrP5jtzU+mWN7/sjT2rak= go.opentelemetry.io/otel/exporters/prometheus v0.64.0 h1:g0LRDXMX/G1SEZtK8zl8Chm4K6GBwRkjPKE36LxiTYs= -go.opentelemetry.io/otel/exporters/stdout/stdoutlog v0.8.0 h1:CHXNXwfKWfzS65yrlB2PVds1IBZcdsX8Vepy9of0iRU= -go.opentelemetry.io/otel/exporters/stdout/stdoutlog v0.8.0/go.mod h1:zKU4zUgKiaRxrdovSS2amdM5gOc59slmo/zJwGX+YBg= +go.opentelemetry.io/otel/exporters/prometheus v0.64.0/go.mod h1:UrgcjnarfdlBDP3GjDIJWe6HTprwSazNjwsI+Ru6hro= go.opentelemetry.io/otel/exporters/stdout/stdoutlog v0.18.0 h1:KJVjPD3rcPb98rIs3HznyJlrfx9ge5oJvxxlGR+P/7s= -go.opentelemetry.io/otel/exporters/stdout/stdoutmetric v1.40.0 h1:ZrPRak/kS4xI3AVXy8F7pipuDXmDsrO8Lg+yQjBLjw0= -go.opentelemetry.io/otel/exporters/stdout/stdoutmetric v1.40.0/go.mod h1:3y6kQCWztq6hyW8Z9YxQDDm0Je9AJoFar2G0yDcmhRk= +go.opentelemetry.io/otel/exporters/stdout/stdoutlog v0.18.0/go.mod h1:K3kRa2ckmHWQaTWQdPRHc7qGXASuVuoEQXzrvlA98Ws= go.opentelemetry.io/otel/exporters/stdout/stdoutmetric v1.42.0 h1:lSZHgNHfbmQTPfuTmWVkEu8J8qXaQwuV30pjCcAUvP8= -go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.32.0 h1:cC2yDI3IQd0Udsux7Qmq8ToKAx1XCilTQECZ0KDZyTw= -go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.32.0/go.mod h1:2PD5Ex6z8CFzDbTdOlwyNIUywRr1DN0ospafJM1wJ+s= +go.opentelemetry.io/otel/exporters/stdout/stdoutmetric v1.42.0/go.mod h1:so9ounLcuoRDu033MW/E0AD4hhUjVqswrMF5FoZlBcw= go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.42.0 h1:s/1iRkCKDfhlh1JF26knRneorus8aOwVIDhvYx9WoDw= -go.opentelemetry.io/otel/log v0.8.0 h1:egZ8vV5atrUWUbnSsHn6vB8R21G2wrKqNiDt3iWertk= -go.opentelemetry.io/otel/log v0.8.0/go.mod h1:M9qvDdUTRCopJcGRKg57+JSQ9LgLBrwwfC32epk5NX8= +go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.42.0/go.mod h1:UI3wi0FXg1Pofb8ZBiBLhtMzgoTm1TYkMvn71fAqDzs= go.opentelemetry.io/otel/log v0.19.0 h1:KUZs/GOsw79TBBMfDWsXS+KZ4g2Ckzksd1ymzsIEbo4= +go.opentelemetry.io/otel/log v0.19.0/go.mod h1:5DQYeGmxVIr4n0/BcJvF4upsraHjg6vudJJpnkL6Ipk= go.opentelemetry.io/otel/metric v1.43.0 h1:d7638QeInOnuwOONPp4JAOGfbCEpYb+K6DVWvdxGzgM= go.opentelemetry.io/otel/metric v1.43.0/go.mod h1:RDnPtIxvqlgO8GRW18W6Z/4P462ldprJtfxHxyKd2PY= go.opentelemetry.io/otel/sdk v1.43.0 h1:pi5mE86i5rTeLXqoF/hhiBtUNcrAGHLKQdhg4h4V9Dg= go.opentelemetry.io/otel/sdk v1.43.0/go.mod h1:P+IkVU3iWukmiit/Yf9AWvpyRDlUeBaRg6Y+C58QHzg= -go.opentelemetry.io/otel/sdk/log v0.8.0 h1:zg7GUYXqxk1jnGF/dTdLPrK06xJdrXgqgFLnI4Crxvs= -go.opentelemetry.io/otel/sdk/log v0.8.0/go.mod h1:50iXr0UVwQrYS45KbruFrEt4LvAdCaWWgIrsN3ZQggo= go.opentelemetry.io/otel/sdk/log v0.19.0 h1:scYVLqT22D2gqXItnWiocLUKGH9yvkkeql5dBDiXyko= +go.opentelemetry.io/otel/sdk/log v0.19.0/go.mod h1:vFBowwXGLlW9AvpuF7bMgnNI95LiW10szrOdvzBHlAg= go.opentelemetry.io/otel/sdk/metric v1.43.0 h1:S88dyqXjJkuBNLeMcVPRFXpRw2fuwdvfCGLEo89fDkw= go.opentelemetry.io/otel/sdk/metric v1.43.0/go.mod h1:C/RJtwSEJ5hzTiUz5pXF1kILHStzb9zFlIEe85bhj6A= go.opentelemetry.io/otel/trace v1.43.0 h1:BkNrHpup+4k4w+ZZ86CZoHHEkohws8AY+WTX09nk+3A= go.opentelemetry.io/otel/trace v1.43.0/go.mod h1:/QJhyVBUUswCphDVxq+8mld+AvhXZLhe+8WVFxiFff0= go.opentelemetry.io/proto/otlp v0.7.0/go.mod h1:PqfVotwruBrMGOCsRd/89rSnXhoiJIqeYNgFYFoEGnI= -go.opentelemetry.io/proto/otlp v1.7.1 h1:gTOMpGDb0WTBOP8JaO72iL3auEZhVmAQg4ipjOVAtj4= -go.opentelemetry.io/proto/otlp v1.7.1/go.mod h1:b2rVh6rfI/s2pHWNlB7ILJcRALpcNDzKhACevjI+ZnE= go.opentelemetry.io/proto/otlp v1.10.0 h1:IQRWgT5srOCYfiWnpqUYz9CVmbO8bFmKcwYxpuCSL2g= +go.opentelemetry.io/proto/otlp v1.10.0/go.mod h1:/CV4QoCR/S9yaPj8utp3lvQPoqMtxXdzn7ozvvozVqk= go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc= go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto= go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE= -go.uber.org/mock v0.5.2 h1:LbtPTcP8A5k9WPXj54PPPbjcI4Y6lhyOZXn+VS7wNko= -go.uber.org/mock v0.5.2/go.mod h1:wLlUxC2vVTPTaE3UD51E0BGOAElKrILxhVSDYQLld5o= go.uber.org/mock v0.6.0 h1:hyF9dfmbgIX5EfOdasqLsWD6xqpNZlXblLB/Dbnwv3Y= go.uber.org/mock v0.6.0/go.mod h1:KiVJ4BqZJaMj4svdfmHM0AUx4NJYO8ZNpPnZn1Z+BBU= go.uber.org/multierr v1.6.0/go.mod h1:cdWPpRnG4AhwMwsgIHip0KRBQjJy5kYEpYjJxpXp9iU= @@ -1379,7 +1256,6 @@ golang.org/x/crypto v0.0.0-20210817164053-32db794688a5/go.mod h1:GvvjBRRGRdwPK5y golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/crypto v0.0.0-20220622213112-05595931fe9d/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= golang.org/x/crypto v0.6.0/go.mod h1:OFC/31mSvZgRz0V1QTNCzfAI1aIRzbiufJtkMIlEp58= -golang.org/x/crypto v0.19.0/go.mod h1:Iy9bg/ha4yyC70EfRS8jz+B6ybOBKMaSxLj6P6oBDfU= golang.org/x/crypto v0.50.0 h1:zO47/JPrL6vsNkINmLoo/PH1gcxpls50DNogFvB5ZGI= golang.org/x/crypto v0.50.0/go.mod h1:3muZ7vA7PBCE6xgPX7nkzzjiUq87kRItoJQM1Yo8S+Q= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= @@ -1392,16 +1268,10 @@ golang.org/x/exp v0.0.0-20191227195350-da58074b4299/go.mod h1:2RIsYlXP63K8oxa1u0 golang.org/x/exp v0.0.0-20200119233911-0405dc783f0a/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= golang.org/x/exp v0.0.0-20200207192155-f17229e696bd/go.mod h1:J/WKrq2StrnmMY6+EHIKF9dgMWnmCNThgcyBT1FY9mM= golang.org/x/exp v0.0.0-20200224162631-6cc2880d07d6/go.mod h1:3jZMyOhIsHpP37uCMkUooju7aAi5cS1Q23tOzKc+0MU= -golang.org/x/exp v0.0.0-20251023183803-a4bb9ffd2546 h1:mgKeJMpvi0yx/sU5GsxQ7p6s2wtOnGAHZWCHUM4KGzY= -golang.org/x/exp v0.0.0-20251023183803-a4bb9ffd2546/go.mod h1:j/pmGrbnkbPtQfxEe5D0VQhZC6qKbfKifgD0oM7sR70= golang.org/x/exp v0.0.0-20260410095643-746e56fc9e2f h1:W3F4c+6OLc6H2lb//N1q4WpJkhzJCK5J6kUi1NTVXfM= golang.org/x/exp v0.0.0-20260410095643-746e56fc9e2f/go.mod h1:J1xhfL/vlindoeF/aINzNzt2Bket5bjo9sdOYzOsU80= golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js= golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= -golang.org/x/image v0.36.1-0.20260211191414-e3d762b1d37e h1:gkwT7ZpRdJBB47MJ0h7xeUSHKkd8f3RcM47FgUIRgd4= -golang.org/x/image v0.36.1-0.20260211191414-e3d762b1d37e/go.mod h1:ZK2ak7W75f61R/Pwr7T25elpTMmDbUsuiOt4FcDsNI0= -golang.org/x/image v0.38.0 h1:5l+q+Y9JDC7mBOMjo4/aPhMDcxEptsX+Tt3GgRQRPuE= -golang.org/x/image v0.38.0/go.mod h1:/3f6vaXC+6CEanU4KJxbcUZyEePbyKbaLoDOe4ehFYY= golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU= golang.org/x/lint v0.0.0-20190301231843-5614ed5bae6f/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= @@ -1427,7 +1297,6 @@ golang.org/x/mod v0.4.1/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.5.0/go.mod h1:5OXOZSfqPIIbmVBIIKWRFfZjPR0E5r58TLhUjH0a2Ro= golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= -golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= golang.org/x/mod v0.35.0 h1:Ww1D637e6Pg+Zb2KrWfHQUnH2dQRLBQyAtpr/haaJeM= golang.org/x/mod v0.35.0/go.mod h1:+GwiRhIInF8wPm+4AoT6L0FA1QWAad3OMdTRx4tFYlU= golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= @@ -1475,7 +1344,6 @@ golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qx golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= golang.org/x/net v0.7.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= -golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg= golang.org/x/net v0.53.0 h1:d+qAbo5L0orcWAr0a9JweQpjXF19LMXJE8Ey7hwOdUA= golang.org/x/net v0.53.0/go.mod h1:JvMuJH7rrdiCfbeHoo3fCQU24Lf5JJwT9W3sJFulfgs= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= @@ -1509,7 +1377,6 @@ golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJ golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.20.0 h1:e0PTpb7pjO8GAtTs2dQ6jYa5BWYlMuX047Dco/pItO4= golang.org/x/sync v0.20.0/go.mod h1:9xrNwdLfx4jkKbNva9FpL6vEN7evnE43NNNJQ2LF3+0= golang.org/x/sys v0.0.0-20180823144017-11551d06cbcc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= @@ -1585,21 +1452,14 @@ golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.2.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.10.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.17.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/sys v0.43.0 h1:Rlag2XtaFTxp19wS8MXlJwTvoh8ArU6ezoyFsMyCTNI= golang.org/x/sys v0.43.0/go.mod h1:4GL1E5IUh+htKOUEOaiffhrAeqysfVGipDYzABqnCmw= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k= -golang.org/x/term v0.8.0/go.mod h1:xPskH00ivmX89bAKVGSKKtLOWNx2+17Eiy94tnKShWo= -golang.org/x/term v0.17.0/go.mod h1:lLRBjIVuehSbZlaOtGMbcMncT+aqLLLmKrsjNrUguwk= golang.org/x/term v0.42.0 h1:UiKe+zDFmJobeJ5ggPwOshJIVt6/Ft0rcfrXZDLWAWY= golang.org/x/term v0.42.0/go.mod h1:Dq/D+snpsbazcBG5+F9Q1n2rXV8Ma+71xEjTRufARgY= golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= @@ -1612,8 +1472,6 @@ golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= -golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= -golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= golang.org/x/text v0.36.0 h1:JfKh3XmcRPqZPKevfXVpI1wXPTqbkE5f7JA92a55Yxg= golang.org/x/text v0.36.0/go.mod h1:NIdBknypM8iqVmPiuco0Dh6P5Jcdk8lJL0CUebqK164= golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= @@ -1676,7 +1534,6 @@ golang.org/x/tools v0.1.3/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= golang.org/x/tools v0.1.4/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= golang.org/x/tools v0.1.5/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= -golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU= golang.org/x/tools v0.44.0 h1:UP4ajHPIcuMjT1GqzDWRlalUEoY+uzoZKnhOjbIPD2c= golang.org/x/tools v0.44.0/go.mod h1:KA0AfVErSdxRZIsOVipbv3rQhVXTnlU6UhKxHd1seDI= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= @@ -1685,8 +1542,6 @@ golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8T golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20240903120638-7835f813f4da h1:noIWHXmPHxILtqtCOPIhSt0ABwskkZKjD3bXGnZGpNY= golang.org/x/xerrors v0.0.0-20240903120638-7835f813f4da/go.mod h1:NDW/Ps6MPRej6fsCIbMTohpP40sJ/P/vI1MoTEGwX90= -gonum.org/v1/gonum v0.16.0 h1:5+ul4Swaf3ESvrOnidPp4GZbzf0mxVQpDCYUQE7OJfk= -gonum.org/v1/gonum v0.16.0/go.mod h1:fef3am4MQ93R2HHpKnLk4/Tbh/s0+wqD5nfa6Pnwy4E= gonum.org/v1/gonum v0.17.0 h1:VbpOemQlsSMrYmn7T2OUvQ4dqxQXU+ouZFQsZOx50z4= gonum.org/v1/gonum v0.17.0/go.mod h1:El3tOrEuMpv2UdMrbNlKEh9vd86bmQ6vqIcDwxEOc1E= google.golang.org/api v0.4.0/go.mod h1:8k5glujaEP+g9n7WNsDg8QP6cUVNI86fCNMcbazEtwE= @@ -1795,12 +1650,8 @@ google.golang.org/genproto v0.0.0-20211206160659-862468c7d6e0/go.mod h1:5CzLGKJ6 google.golang.org/genproto v0.0.0-20211208223120-3a66f561d7aa/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= google.golang.org/genproto v0.0.0-20260128011058-8636f8732409 h1:VQZ/yAbAtjkHgH80teYd2em3xtIkkHd7ZhqfH2N9CsM= google.golang.org/genproto v0.0.0-20260128011058-8636f8732409/go.mod h1:rxKD3IEILWEu3P44seeNOAwZN4SaoKaQ/2eTg4mM6EM= -google.golang.org/genproto/googleapis/api v0.0.0-20260203192932-546029d2fa20 h1:7ei4lp52gK1uSejlA8AZl5AJjeLUOHBQscRQZUgAcu0= -google.golang.org/genproto/googleapis/api v0.0.0-20260203192932-546029d2fa20/go.mod h1:ZdbssH/1SOVnjnDlXzxDHK2MCidiqXtbYccJNzNYPEE= google.golang.org/genproto/googleapis/api v0.0.0-20260401024825-9d38bb4040a9 h1:VPWxll4HlMw1Vs/qXtN7BvhZqsS9cdAittCNvVENElA= google.golang.org/genproto/googleapis/api v0.0.0-20260401024825-9d38bb4040a9/go.mod h1:7QBABkRtR8z+TEnmXTqIqwJLlzrZKVfAUm7tY3yGv0M= -google.golang.org/genproto/googleapis/rpc v0.0.0-20260226221140-a57be14db171 h1:ggcbiqK8WWh6l1dnltU4BgWGIGo+EVYxCaAPih/zQXQ= -google.golang.org/genproto/googleapis/rpc v0.0.0-20260226221140-a57be14db171/go.mod h1:4Hqkh8ycfw05ld/3BWL7rJOSfebL2Q+DVDeRgYgxUU8= google.golang.org/genproto/googleapis/rpc v0.0.0-20260406210006-6f92a3bedf2d h1:wT2n40TBqFY6wiwazVK9/iTWbsQrgk5ZfCSVFLO9LQA= google.golang.org/genproto/googleapis/rpc v0.0.0-20260406210006-6f92a3bedf2d/go.mod h1:4Hqkh8ycfw05ld/3BWL7rJOSfebL2Q+DVDeRgYgxUU8= google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= @@ -1830,8 +1681,6 @@ google.golang.org/grpc v1.39.1/go.mod h1:PImNr+rS9TWYb2O4/emRugxiyHZ5JyHW5F+RPnD google.golang.org/grpc v1.40.0/go.mod h1:ogyxbiOoUXAkP+4+xa6PZSE9DZgIHtSpzjDTB9KAK34= google.golang.org/grpc v1.40.1/go.mod h1:ogyxbiOoUXAkP+4+xa6PZSE9DZgIHtSpzjDTB9KAK34= google.golang.org/grpc v1.42.0/go.mod h1:k+4IHHFw41K8+bbowsex27ge2rCb65oeWqe4jJ590SU= -google.golang.org/grpc v1.79.3 h1:sybAEdRIEtvcD68Gx7dmnwjZKlyfuc61Dyo9pGXXkKE= -google.golang.org/grpc v1.79.3/go.mod h1:KmT0Kjez+0dde/v2j9vzwoAScgEPx/Bw1CYChhHLrHQ= google.golang.org/grpc v1.80.0 h1:Xr6m2WmWZLETvUNvIUmeD5OAagMw3FiKmMlTdViWsHM= google.golang.org/grpc v1.80.0/go.mod h1:ho/dLnxwi3EDJA4Zghp7k2Ec1+c2jqup0bFkw07bwF4= google.golang.org/grpc/cmd/protoc-gen-go-grpc v1.1.0/go.mod h1:6Kw0yEErY5E/yWrBtf03jp27GLLJujG4z/JK95pnjjw= @@ -1848,9 +1697,6 @@ google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlba google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= google.golang.org/protobuf v1.27.1/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= -google.golang.org/protobuf v1.28.1/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= -google.golang.org/protobuf v1.36.11 h1:fV6ZwhNocDyBLK0dj+fg8ektcVegBBuEolpbTQyBNVE= -google.golang.org/protobuf v1.36.11/go.mod h1:HTf+CrKn2C3g5S8VImy6tdcUvCska2kB7j23XfzDpco= google.golang.org/protobuf v1.36.12-0.20260120151049-f2248ac996af h1:+5/Sw3GsDNlEmu7TfklWKPdQ0Ykja5VEmq2i817+jbI= google.golang.org/protobuf v1.36.12-0.20260120151049-f2248ac996af/go.mod h1:HTf+CrKn2C3g5S8VImy6tdcUvCska2kB7j23XfzDpco= gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw= @@ -1892,44 +1738,26 @@ honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWh honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg= honnef.co/go/tools v0.0.1-2020.1.3/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= honnef.co/go/tools v0.0.1-2020.1.4/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= -k8s.io/api v0.35.1 h1:0PO/1FhlK/EQNVK5+txc4FuhQibV25VLSdLMmGpDE/Q= -k8s.io/api v0.35.1/go.mod h1:28uR9xlXWml9eT0uaGo6y71xK86JBELShLy4wR1XtxM= k8s.io/api v0.36.0 h1:SgqDhZzHdOtMk40xVSvCXkP9ME0H05hPM3p9AB1kL80= k8s.io/api v0.36.0/go.mod h1:m1LVrGPNYax5NBHdO+QuAedXyuzTt4RryI/qnmNvs34= k8s.io/apiextensions-apiserver v0.35.1 h1:p5vvALkknlOcAqARwjS20kJffgzHqwyQRM8vHLwgU7w= k8s.io/apiextensions-apiserver v0.35.1/go.mod h1:2CN4fe1GZ3HMe4wBr25qXyJnJyZaquy4nNlNmb3R7AQ= -k8s.io/apimachinery v0.35.1 h1:yxO6gV555P1YV0SANtnTjXYfiivaTPvCTKX6w6qdDsU= -k8s.io/apimachinery v0.35.1/go.mod h1:jQCgFZFR1F4Ik7hvr2g84RTJSZegBc8yHgFWKn//hns= k8s.io/apimachinery v0.36.0 h1:jZyPzhd5Z+3h9vJLt0z9XdzW9VzNzWAUw+P1xZ9PXtQ= k8s.io/apimachinery v0.36.0/go.mod h1:FklypaRJt6n5wUIwWXIP6GJlIpUizTgfo1T/As+Tyxc= k8s.io/apiserver v0.35.1 h1:potxdhhTL4i6AYAa2QCwtlhtB1eCdWQFvJV6fXgJzxs= k8s.io/apiserver v0.35.1/go.mod h1:BiL6Dd3A2I/0lBnteXfWmCFobHM39vt5+hJQd7Lbpi4= -k8s.io/cli-runtime v0.35.1 h1:uKcXFe8J7AMAM4Gm2JDK4mp198dBEq2nyeYtO+JfGJE= -k8s.io/cli-runtime v0.35.1/go.mod h1:55/hiXIq1C8qIJ3WBrWxEwDLdHQYhBNRdZOz9f7yvTw= k8s.io/cli-runtime v0.36.0 h1:HNxciQpQMMOKS0/GiUXcKDyA6J2FDILJj9NmP2BZrTg= k8s.io/cli-runtime v0.36.0/go.mod h1:KObkknK9Ro5LYX+1RdiKc7C8CvGg4aX+V/Zv+E8WPHA= -k8s.io/client-go v0.35.1 h1:+eSfZHwuo/I19PaSxqumjqZ9l5XiTEKbIaJ+j1wLcLM= -k8s.io/client-go v0.35.1/go.mod h1:1p1KxDt3a0ruRfc/pG4qT/3oHmUj1AhSHEcxNSGg+OA= k8s.io/client-go v0.36.0 h1:pOYi7C4RHChYjMiHpZSpSbIM6ZxVbRXBy7CuiIwqA3c= k8s.io/client-go v0.36.0/go.mod h1:ZKKcpwF0aLYfkHFCjillCKaTK/yBkEDHTDXCFY6AS9Y= -k8s.io/component-base v0.35.1 h1:XgvpRf4srp037QWfGBLFsYMUQJkE5yMa94UsJU7pmcE= -k8s.io/component-base v0.35.1/go.mod h1:HI/6jXlwkiOL5zL9bqA3en1Ygv60F03oEpnuU1G56Bs= k8s.io/component-base v0.36.0 h1:hFjEktssxiJhrK1zfybkH4kJOi8iZuF+mIDCqS5+jRo= k8s.io/component-base v0.36.0/go.mod h1:JZvIfcNHk+uck+8LhJzhSBtydWXaZNQwX2OdL+Mnwsk= -k8s.io/klog/v2 v2.130.1 h1:n9Xl7H1Xvksem4KFG4PYbdQCQxqc/tTUyrgXaOhHSzk= -k8s.io/klog/v2 v2.130.1/go.mod h1:3Jpz1GvMt720eyJH1ckRHK1EDfpxISzJ7I9OYgaDtPE= k8s.io/klog/v2 v2.140.0 h1:Tf+J3AH7xnUzZyVVXhTgGhEKnFqye14aadWv7bzXdzc= k8s.io/klog/v2 v2.140.0/go.mod h1:o+/RWfJ6PwpnFn7OyAG3QnO47BFsymfEfrz6XyYSSp0= -k8s.io/kube-openapi v0.0.0-20250910181357-589584f1c912 h1:Y3gxNAuB0OBLImH611+UDZcmKS3g6CthxToOb37KgwE= -k8s.io/kube-openapi v0.0.0-20250910181357-589584f1c912/go.mod h1:kdmbQkyfwUagLfXIad1y2TdrjPFWp2Q89B3qkRwf/pQ= k8s.io/kube-openapi v0.0.0-20260319004828-5883c5ee87b9 h1:Sztf7ESG9tAXRW/ACJZjrj5jhdOUqS2KFRQT+CTvu78= k8s.io/kube-openapi v0.0.0-20260319004828-5883c5ee87b9/go.mod h1:uGBT7iTA6c6MvqUvSXIaYZo9ukscABYi2btjhvgKGZ0= -k8s.io/kubectl v0.35.1 h1:zP3Er8C5i1dcAFUMh9Eva0kVvZHptXIn/+8NtRWMxwg= -k8s.io/kubectl v0.35.1/go.mod h1:cQ2uAPs5IO/kx8R5s5J3Ihv3VCYwrx0obCXum0CvnXo= k8s.io/kubectl v0.36.0 h1:hEGr8NvIm2Wjqs2Xy48Uzmvo6lpHdGKlLyMvau2gTms= k8s.io/kubectl v0.36.0/go.mod h1:iDe8aV5BEi45W8k+5n71I2pJ/nwE0PHDu+/2cejzYoo= -k8s.io/utils v0.0.0-20251002143259-bc988d571ff4 h1:SjGebBtkBqHFOli+05xYbK8YF1Dzkbzn+gDM4X9T4Ck= -k8s.io/utils v0.0.0-20251002143259-bc988d571ff4/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0= k8s.io/utils v0.0.0-20260319190234-28399d86e0b5 h1:kBawHLSnx/mYHmRnNUf9d4CpjREbeZuxoSGOX/J+aYM= k8s.io/utils v0.0.0-20260319190234-28399d86e0b5/go.mod h1:xDxuJ0whA3d0I4mf/C4ppKHxXynQ+fxnkmQH0vTHnuk= modernc.org/cc/v4 v4.27.1 h1:9W30zRlYrefrDV2JE2O8VDtJ1yPGownxciz5rrbQZis= @@ -1969,18 +1797,12 @@ rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0= rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA= sigs.k8s.io/json v0.0.0-20250730193827-2d320260d730 h1:IpInykpT6ceI+QxKBbEflcR5EXP7sU1kvOlxwZh5txg= sigs.k8s.io/json v0.0.0-20250730193827-2d320260d730/go.mod h1:mdzfpAEoE6DHQEN0uh9ZbOCuHbLK5wOm7dK4ctXE9Tg= -sigs.k8s.io/kustomize/api v0.20.1 h1:iWP1Ydh3/lmldBnH/S5RXgT98vWYMaTUL1ADcr+Sv7I= -sigs.k8s.io/kustomize/api v0.20.1/go.mod h1:t6hUFxO+Ph0VxIk1sKp1WS0dOjbPCtLJ4p8aADLwqjM= sigs.k8s.io/kustomize/api v0.21.1 h1:lzqbzvz2CSvsjIUZUBNFKtIMsEw7hVLJp0JeSIVmuJs= sigs.k8s.io/kustomize/api v0.21.1/go.mod h1:f3wkKByTrgpgltLgySCntrYoq5d3q7aaxveSagwTlwI= -sigs.k8s.io/kustomize/kyaml v0.20.1 h1:PCMnA2mrVbRP3NIB6v9kYCAc38uvFLVs8j/CD567A78= -sigs.k8s.io/kustomize/kyaml v0.20.1/go.mod h1:0EmkQHRUsJxY8Ug9Niig1pUMSCGHxQ5RklbpV/Ri6po= sigs.k8s.io/kustomize/kyaml v0.21.1 h1:IVlbmhC076nf6foyL6Taw4BkrLuEsXUXNpsE+ScX7fI= sigs.k8s.io/kustomize/kyaml v0.21.1/go.mod h1:hmxADesM3yUN2vbA5z1/YTBnzLJ1dajdqpQonwBL1FQ= sigs.k8s.io/randfill v1.0.0 h1:JfjMILfT8A6RbawdsK2JXGBR5AQVfd+9TbzrlneTyrU= sigs.k8s.io/randfill v1.0.0/go.mod h1:XeLlZ/jmk4i1HRopwe7/aU3H5n1zNUcX6TM94b3QxOY= -sigs.k8s.io/structured-merge-diff/v6 v6.3.0 h1:jTijUJbW353oVOd9oTlifJqOGEkUw2jB/fXCbTiQEco= -sigs.k8s.io/structured-merge-diff/v6 v6.3.0/go.mod h1:M3W8sfWvn2HhQDIbGWj3S099YozAsymCo/wrT5ohRUE= sigs.k8s.io/structured-merge-diff/v6 v6.3.2 h1:kwVWMx5yS1CrnFWA/2QHyRVJ8jM6dBA80uLmm0wJkk8= sigs.k8s.io/structured-merge-diff/v6 v6.3.2/go.mod h1:M3W8sfWvn2HhQDIbGWj3S099YozAsymCo/wrT5ohRUE= sigs.k8s.io/yaml v1.6.0 h1:G8fkbMSAFqgEFgh4b1wmtzDnioxFCUgTZhlbj5P9QYs= diff --git a/internal/commands/result.go b/internal/commands/result.go index 1c6a78f50..51a155a60 100644 --- a/internal/commands/result.go +++ b/internal/commands/result.go @@ -1,3010 +1,3010 @@ -package commands - -import ( - "encoding/json" - "fmt" - "html" - "log" - "net/url" - "os" - "path/filepath" - "regexp" - "slices" - "strconv" - "strings" - "text/template" - "time" - - "github.com/MakeNowJust/heredoc" - "github.com/checkmarx/ast-cli/internal/commands/util" - "github.com/checkmarx/ast-cli/internal/commands/util/printer" - errorConstants "github.com/checkmarx/ast-cli/internal/constants/errors" - "github.com/checkmarx/ast-cli/internal/logger" - "github.com/checkmarx/ast-cli/internal/services" - "github.com/checkmarx/ast-cli/internal/wrappers" - "github.com/checkmarx/ast-cli/internal/wrappers/utils" - "golang.org/x/text/cases" - "golang.org/x/text/language" - - commonParams "github.com/checkmarx/ast-cli/internal/params" - - "github.com/pkg/errors" - "github.com/spf13/cobra" -) - -const ( - failedCreatingSummary = "Failed creating summary" - failedGettingScan = "Failed getting scan" - failedListingResults = "Failed listing results" - failedListingCodeBashing = "Failed codebashing link" - mediumLabel = "medium" - criticalLabel = "critical" - highLabel = "high" - lowLabel = "low" - infoLabel = "info" - sonarTypeLabel = "_sonar" - glSastTypeLabel = ".gl-sast-report" - glScaTypeLabel = ".gl-sca-report" - directoryPermission = 0700 - infoSonar = "INFO" - lowSonar = "LOW" - mediumSonar = "MEDIUM" - highSonar = "HIGH" - criticalSonar = "BLOCKER" - infoLowSarif = "note" - mediumSarif = "warning" - highSarif = "error" - vulnerabilitySonar = "SECURITY" - cleanCodeAttribute = "FORMATTED" - infoCx = "INFO" - lowCx = "LOW" - mediumCx = "MEDIUM" - highCx = "HIGH" - criticalCx = "CRITICAL" - tableResultsFormat = " | %-10s %6v %5d %6d %5d %4d %-9s |\n" - stringTableResultsFormat = " | %-10s %5s %6s %6s %5s %4s %5s |\n" - // TableTitleFormat is the printf format string for the scan results summary table title row. - TableTitleFormat = " | %-11s %4s %4s %6s %4s %4s %6s |\n" - twoNewLines = "\n\n" - tableLine = " --------------------------------------------------------------------- " - codeBashingKey = "cb-url" - failedGettingBfl = "Failed getting BFL" - notAvailableString = "-" - disabledString = "N/A" - scanFailedString = "Failed " - scanCanceledString = "Canceled" - scanSuccessString = "Completed" - scanPartialString = "Partial" - scsScanUnavailableString = "" - notAvailableNumber = -1 - scanFailedNumber = -2 - scanCanceledNumber = -3 - scanPartialNumber = -4 - defaultPaddingSize = -13 - scanPendingMessage = "Scan triggered in asynchronous mode or still running. Click more details to get the full status." - directDependencyType = "Direct Dependency" - indirectDependencyType = "Transitive Dependency" - startedStatus = "started" - requestedStatus = "requested" - completedStatus = "completed" - pdfToEmailFlagDescription = "Send the PDF report to the specified email address." + - " Use \",\" as the delimiter for multiple emails" - pdfOptionsFlagDescription = "Sections to generate PDF report. Available options: Iac-Security,Sast,Sca," + - defaultPdfOptionsDataSections - sbomReportFlagDescription = "Sections to generate SBOM report. Available options: CycloneDxJson,CycloneDxXml,SpdxJson" - reportNameScanReport = "scan-report" - reportNameImprovedScanReport = "improved-scan-report" - reportTypeEmail = "email" - defaultPdfOptionsDataSections = "ScanSummary,ExecutiveSummary,ScanResults" - exploitablePathFlagDescription = "Enable or disable exploitable path in scan. Available options: true,false" - scaLastScanTimeFlagDescription = "SCA last scan time. Available options: integer above 1" - projectPrivatePackageFlagDescription = "Enable or disable project private package. Available options: true,false" - scaPrivatePackageVersionFlagDescription = "SCA project private package version. Example: 0.1.1" - scaHideDevAndTestDepFlagDescription = "Filter SCA results to exclude dev and test dependencies" - policeManagementNoneStatus = "none" - apiDocumentationFlagDescription = "Swagger folder/file filter for API-Security scan. Example: ./swagger.json" - summaryCreatedAtLayout = "2006-01-02, 15:04:05" - glTimeFormat = "2006-01-02T15:04:05" - sarifNodeFileLength = 2 - fixLabel = "fix" - redundantLabel = "redundant" - delayValueForReport = 10 - fixLinkPrefix = "https://devhub.checkmarx.com/cve-details/" - // ScaDevAndTestExclusionParam is the SCA exclude-result-types value used to filter out dev and test dependencies. - ScaDevAndTestExclusionParam = "DEV_AND_TEST" - // ScaExcludeResultTypesParam is the SCA query parameter name used to exclude specific result types. - ScaExcludeResultTypesParam = "exclude-result-types" - noFileForScorecardResultString = "Issue Found in your GitHub repository" - // CliType identifies the report type used when generating reports through the CLI. - CliType = "cli" - artifactLocationURIString = "This alert has no associated file" - commandDocAnnotation = "command:doc" - showSubCommand = "show" - sectionScanSummary = "ScanSummary" - sectionExecutiveSummary = "ExecutiveSummary" - sectionScanResults = "ScanResults" - scaEngineLabel = "SCA" - sastEngineLabel = "SAST" - kicsEngineLabel = "KICS" - notAvailableValue = "NA" - originCode = "code" - originDocumentation = "documentation" - statusCompleted = "Completed" - statusPartial = "Partial" - statusFailed = "Failed" -) - -var ( - summaryFormats = []string{ - printer.FormatSummaryConsole, - printer.FormatSummary, - printer.FormatSummaryJSON, - printer.FormatPDF, - printer.FormatSummaryMarkdown, - printer.FormatSbom, - printer.FormatGLSast, - printer.FormatGLSca, - printer.FormatSonar, - } - - filterResultsListFlagUsage = fmt.Sprintf( - "Filter the list of results. Use ';' as the delimiter for arrays. Available filters are: %s", - strings.Join( - []string{ - commonParams.ScanIDQueryParam, - commonParams.LimitQueryParam, - commonParams.OffsetQueryParam, - commonParams.SortQueryParam, - commonParams.IncludeNodesQueryParam, - commonParams.NodeIDsQueryParam, - commonParams.QueryQueryParam, - commonParams.GroupQueryParam, - commonParams.StatusQueryParam, - commonParams.SeverityQueryParam, - commonParams.StateQueryParam, - }, ",", - ), - ) - - // Follows: over 9.0 is critical, 7.0 to 8.9 is high, 4.0 to 6.9 is medium and 3.9 or less is low. - securities = map[string]string{ - infoCx: "1.0", - lowCx: "2.0", - mediumCx: "4.0", - highCx: "7.0", - criticalCx: "9.0", - } - - // Match cx severity with sonar severity - sonarSeverities = map[string]string{ - infoCx: infoSonar, - lowCx: lowSonar, - mediumCx: mediumSonar, - highCx: highSonar, - criticalCx: criticalSonar, - } - - containerEngineUnsupportedAgents = []string{ - commonParams.JetbrainsAgent, commonParams.VSCodeAgent, commonParams.VisualStudioAgent, commonParams.EclipseAgent, - } - - sscsEngineToOverviewEngineMap = map[string]string{ - commonParams.SCSScorecardType: commonParams.SCSScorecardOverviewType, - commonParams.SCSSecretDetectionType: commonParams.SCSSecretDetectionOverviewType, - } -) - -// NewResultsCommand returns the `results` Cobra command tree with all subcommands attached. -func NewResultsCommand( - resultsWrapper wrappers.ResultsWrapper, - scanWrapper wrappers.ScansWrapper, - exportWrapper wrappers.ExportWrapper, - resultsPdfReportsWrapper wrappers.ResultsPdfWrapper, - resultsJSONReportsWrapper wrappers.ResultsJSONWrapper, - codeBashingWrapper wrappers.CodeBashingWrapper, - bflWrapper wrappers.BflWrapper, - risksOverviewWrapper wrappers.RisksOverviewWrapper, - riskManagementWrapper wrappers.RiskManagementWrapper, - scsScanOverviewWrapper wrappers.ScanOverviewWrapper, - policyWrapper wrappers.PolicyWrapper, - featureFlagsWrapper wrappers.FeatureFlagsWrapper, - jwtWrapper wrappers.JWTWrapper, -) *cobra.Command { - resultCmd := &cobra.Command{ - Use: "results", - Short: "Retrieve results", - Annotations: map[string]string{ - commandDocAnnotation: heredoc.Doc( - ` - https://checkmarx.com/resource/documents/en/34965-68640-results.html - `, - ), - }, - } - showResultCmd := resultShowSubCommand(resultsWrapper, scanWrapper, exportWrapper, resultsPdfReportsWrapper, resultsJSONReportsWrapper, - risksOverviewWrapper, scsScanOverviewWrapper, policyWrapper, featureFlagsWrapper, jwtWrapper) - codeBashingCmd := resultCodeBashing(codeBashingWrapper) - bflResultCmd := resultBflSubCommand(bflWrapper) - exitCodeSubcommand := exitCodeSubCommand(scanWrapper) - riskManagementSubCommand := riskManagementSubCommand(riskManagementWrapper, featureFlagsWrapper) - resultCmd.AddCommand( - showResultCmd, bflResultCmd, codeBashingCmd, exitCodeSubcommand, riskManagementSubCommand, - ) - return resultCmd -} - -func exitCodeSubCommand(scanWrapper wrappers.ScansWrapper) *cobra.Command { - exitCodeCmd := &cobra.Command{ - Use: "exit-code", - Short: "Get exit code and details of a scan", - Long: "The exit-code command enables you to get the exit code and failure details of a requested scan in Checkmarx One", - Example: heredoc.Doc( - ` - $ cx results exit-code --scan-id --scan-types - `, - ), - RunE: runGetExitCodeCommand(scanWrapper), - } - - exitCodeCmd.PersistentFlags().String(commonParams.ScanIDFlag, "", "Scan ID") - exitCodeCmd.PersistentFlags().String(commonParams.ScanTypes, "", "Scan types") - - return exitCodeCmd -} -func riskManagementSubCommand(riskManagement wrappers.RiskManagementWrapper, featureFlagsWrapper wrappers.FeatureFlagsWrapper, -) *cobra.Command { - riskManagementCmd := &cobra.Command{ - Use: "risk-management", - Short: "Show risk-management results of a project", - Long: "The risk-management command displays risk management results for a specific project in Checkmarx One", - Example: heredoc.Doc( - ` - $ cx results risk-management --project-id --scan-id --limit (1-50, default: 50) - `, - ), - RunE: runRiskManagementCommand(riskManagement, featureFlagsWrapper), - } - - riskManagementCmd.PersistentFlags().String(commonParams.ProjectIDFlag, "", "Project ID") - riskManagementCmd.PersistentFlags().String(commonParams.ScanIDFlag, "", "Scan ID") - riskManagementCmd.PersistentFlags().Int(commonParams.LimitFlag, -1, "Limit") - - addFormatFlag(riskManagementCmd, printer.FormatJSON, printer.FormatTable, printer.FormatList) - - return riskManagementCmd -} - -func resultShowSubCommand( - resultsWrapper wrappers.ResultsWrapper, - scanWrapper wrappers.ScansWrapper, - exportWrapper wrappers.ExportWrapper, - resultsPdfReportsWrapper wrappers.ResultsPdfWrapper, - resultsJSONReportsWrapper wrappers.ResultsJSONWrapper, - risksOverviewWrapper wrappers.RisksOverviewWrapper, - scsScanOverviewWrapper wrappers.ScanOverviewWrapper, - policyWrapper wrappers.PolicyWrapper, - featureFlagsWrapper wrappers.FeatureFlagsWrapper, - jwtWrapper wrappers.JWTWrapper, -) *cobra.Command { - resultShowCmd := &cobra.Command{ - Use: showSubCommand, - Short: "Show results of a scan", - Long: "The show command enables the ability to show results about a requested scan in Checkmarx One", - Example: heredoc.Doc( - ` - $ cx results show --scan-id - `, - ), - RunE: runGetResultCommand(resultsWrapper, scanWrapper, exportWrapper, resultsPdfReportsWrapper, resultsJSONReportsWrapper, risksOverviewWrapper, scsScanOverviewWrapper, policyWrapper, featureFlagsWrapper, jwtWrapper), - } - addScanIDFlag(resultShowCmd, "ID to report on") - addResultFormatFlag( - resultShowCmd, - printer.FormatJSON, - printer.FormatJSONv2, - printer.FormatSummary, - printer.FormatSummaryConsole, - printer.FormatSarif, - printer.FormatSummaryJSON, - printer.FormatSbom, - printer.FormatPDF, - printer.FormatSummaryMarkdown, - printer.FormatGLSast, - printer.FormatGLSca, - printer.FormatSonar, - ) - resultShowCmd.PersistentFlags().String(commonParams.ReportFormatPdfToEmailFlag, "", pdfToEmailFlagDescription) - resultShowCmd.PersistentFlags().String(commonParams.ReportSbomFormatFlag, services.DefaultSbomOption, sbomReportFlagDescription) - resultShowCmd.PersistentFlags().String(commonParams.ReportFormatPdfOptionsFlag, defaultPdfOptionsDataSections, pdfOptionsFlagDescription) - resultShowCmd.PersistentFlags().String(commonParams.TargetFlag, "cx_result", "Output file") - resultShowCmd.PersistentFlags().String(commonParams.TargetPathFlag, ".", "Output Path") - resultShowCmd.PersistentFlags().StringSlice(commonParams.FilterFlag, []string{}, filterResultsListFlagUsage) - - resultShowCmd.PersistentFlags().IntP( - commonParams.WaitDelayFlag, - "", - commonParams.WaitDelayDefault, - "Polling wait time in seconds", - ) - resultShowCmd.PersistentFlags().Int( - commonParams.PolicyTimeoutFlag, - commonParams.ResultPolicyDefaultTimeout, - "Cancel the policy evaluation and fail after the timeout in minutes", - ) - resultShowCmd.PersistentFlags().Bool(commonParams.IgnorePolicyFlag, false, "Skip policy evaluation. Requires override-policy-management permission.") - resultShowCmd.PersistentFlags().Bool(commonParams.SastRedundancyFlag, false, - "Populate SAST results 'data.redundancy' with values '"+fixLabel+"' (to fix) or '"+redundantLabel+"' (no need to fix)") - resultShowCmd.PersistentFlags().Bool(commonParams.ScaHideDevAndTestDepFlag, false, scaHideDevAndTestDepFlagDescription) - - return resultShowCmd -} - -func resultBflSubCommand(bflWrapper wrappers.BflWrapper) *cobra.Command { - resultBflCmd := &cobra.Command{ - Use: "bfl", - Short: "Show best fix location for a query id within the scan result", - Long: "The bfl command enables the ability to show best fix location for a querid within the scan result", - Example: heredoc.Doc( - ` - $ cx results bfl --scan-id --query-id - `, - ), - RunE: runGetBestFixLocationCommand(bflWrapper), - } - addScanIDFlag(resultBflCmd, "ID to report on") - addQueryIDFlag(resultBflCmd, "Query Id from the result") - addFormatFlag(resultBflCmd, printer.FormatList, printer.FormatJSON) - - markFlagAsRequired(resultBflCmd, commonParams.ScanIDFlag) - markFlagAsRequired(resultBflCmd, commonParams.QueryIDFlag) - - return resultBflCmd -} - -func runGetExitCodeCommand(scanWrapper wrappers.ScansWrapper) func(cmd *cobra.Command, args []string) error { - return func(cmd *cobra.Command, args []string) error { - scanID, _ := cmd.Flags().GetString(commonParams.ScanIDFlag) - if scanID == "" { - return errors.New(errorConstants.ScanIDRequired) - } - scanTypesFlagValue, _ := cmd.Flags().GetString(commonParams.ScanTypes) - results, err := GetScannerResults(scanWrapper, scanID, scanTypesFlagValue) - if err != nil { - return err - } - - if len(results) == 0 { - return nil - } - - return printer.Print(cmd.OutOrStdout(), results, printer.FormatIndentedJSON) - } -} - -func runRiskManagementCommand(riskManagement wrappers.RiskManagementWrapper, featureFlagsWrapper wrappers.FeatureFlagsWrapper, -) func(cmd *cobra.Command, args []string) error { - return func(cmd *cobra.Command, args []string) error { - projectID, _ := cmd.Flags().GetString(commonParams.ProjectIDFlag) - scanID, _ := cmd.Flags().GetString(commonParams.ScanIDFlag) - - limit, _ := cmd.Flags().GetInt(commonParams.LimitFlag) - - flagResponse, _ := wrappers.GetSpecificFeatureFlag(featureFlagsWrapper, wrappers.RiskManagementEnabled) - ASPMEnabled := flagResponse.Status - if !ASPMEnabled { - return errors.Errorf("%s", "Risk management results are currently unavailable for your tenant.") - } - results, err := getRiskManagementResults(riskManagement, projectID, scanID) - if err != nil { - return err - } - results.Results = utils.LimitSlice(results.Results, limit) - err = printByFormat(cmd, results) - return err - } -} - -func getRiskManagementResults(riskManagement wrappers.RiskManagementWrapper, projectID, scanID string) (*wrappers.ASPMResult, error) { - ASPMResult, errorModel, err := riskManagement.GetTopVulnerabilitiesByProjectID(projectID, scanID) - if err != nil { - return nil, errors.Wrapf(err, "%s", failedListingResults) - } - if errorModel != nil { - return nil, errors.Errorf("%s: CODE: %d, %s", failedListingResults, errorModel.Code, errorModel.Message) - } - return ASPMResult, nil -} - -// GetScannerResults returns per-scanner status entries for the given scan, optionally filtered by scan types. -func GetScannerResults(scanWrapper wrappers.ScansWrapper, scanID, scanTypesFlagValue string) ([]ScannerResponse, error) { - scanResponseModel, errorModel, err := scanWrapper.GetByID(scanID) - if err != nil { - return nil, errors.Wrapf(err, "%s", failedGetting) - } - if errorModel != nil { - return nil, errors.Errorf("%s: CODE: %d, %s", failedGettingScan, errorModel.Code, errorModel.Message) - } - results := getScannerResponse(scanTypesFlagValue, scanResponseModel) - return results, nil -} - -func getScannerResponse(scanTypesFlagValue string, scanResponseModel *wrappers.ScanResponseModel) []ScannerResponse { - var results []ScannerResponse - - if scanResponseModel.Status == wrappers.ScanCanceled || - scanResponseModel.Status == wrappers.ScanRunning || - scanResponseModel.Status == wrappers.ScanQueued || - scanResponseModel.Status == wrappers.ScanPartial || - scanResponseModel.Status == wrappers.ScanCompleted { - result := ScannerResponse{ - ScanID: scanResponseModel.ID, - Status: string(scanResponseModel.Status), - } - results = append(results, result) - return results - } - - if scanTypesFlagValue == "" { - results = createAllFailedScannersResponse(scanResponseModel) - } else { - scanTypes := sanitizeScannerNames(scanTypesFlagValue) - results = createRequestedScannersResponse(scanTypes, scanResponseModel) - } - - return results -} - -func createRequestedScannersResponse(scanTypes map[string]string, scanResponseModel *wrappers.ScanResponseModel) []ScannerResponse { - var results []ScannerResponse - for i := range scanResponseModel.StatusDetails { - if _, ok := scanTypes[scanResponseModel.StatusDetails[i].Name]; ok { - results = append(results, createScannerResponse(&scanResponseModel.StatusDetails[i])) - } - } - return results -} - -func createAllFailedScannersResponse(scanResponseModel *wrappers.ScanResponseModel) []ScannerResponse { - var results []ScannerResponse - for i := range scanResponseModel.StatusDetails { - if scanResponseModel.StatusDetails[i].Status == wrappers.ScanFailed { - results = append(results, createScannerResponse(&scanResponseModel.StatusDetails[i])) - } - } - return results -} - -func sanitizeScannerNames(scanTypes string) map[string]string { - scanTypeSlice := strings.Split(scanTypes, ",") - scanTypeMap := make(map[string]string) - for i := range scanTypeSlice { - lowered := strings.ToLower(scanTypeSlice[i]) - scanTypeMap[lowered] = lowered - } - - return scanTypeMap -} - -func createScannerResponse(statusDetails *wrappers.StatusInfo) ScannerResponse { - return ScannerResponse{ - Name: statusDetails.Name, - Status: statusDetails.Status, - Details: statusDetails.Details, - ErrorCode: stringifyErrorCode(statusDetails.ErrorCode), - } -} - -func stringifyErrorCode(errorCode int) string { - if errorCode == 0 { - return "" - } - return strconv.Itoa(errorCode) -} - -func runGetBestFixLocationCommand(bflWrapper wrappers.BflWrapper) func(cmd *cobra.Command, args []string) error { - return func(cmd *cobra.Command, args []string) error { - var bflResponseModel *wrappers.BFLResponseModel - var errorModel *wrappers.WebError - var err error - - scanID, _ := cmd.Flags().GetString(commonParams.ScanIDFlag) - queryID, _ := cmd.Flags().GetString(commonParams.QueryIDFlag) - - scanIds := strings.Split(scanID, ",") - if len(scanIds) > 1 { - return errors.Errorf("%s", "Multiple scan-ids are not allowed.") - } - queryIds := strings.Split(queryID, ",") - if len(queryIds) > 1 { - return errors.Errorf("%s", "Multiple query-ids are not allowed.") - } - - params := make(map[string]string) - params[commonParams.ScanIDQueryParam] = scanID - params[commonParams.QueryIDQueryParam] = queryID - - bflResponseModel, errorModel, err = bflWrapper.GetBflByScanIDAndQueryID(params) - - if err != nil { - return errors.Wrapf(err, "%s", failedGettingBfl) - } - - // Checking the response - if errorModel != nil { - return errors.Errorf("%s: CODE: %d, %s", failedGettingBfl, errorModel.Code, errorModel.Message) - } else if bflResponseModel != nil { - err = printByFormat(cmd, toBflView(*bflResponseModel)) - if err != nil { - return err - } - } - - return nil - } -} - -func toBflView(bflResponseModel wrappers.BFLResponseModel) []wrappers.ScanResultNode { - if (bflResponseModel.TotalCount) > 0 { - views := make([]wrappers.ScanResultNode, bflResponseModel.TotalCount) - - for i := 0; i < bflResponseModel.TotalCount; i++ { - views[i] = wrappers.ScanResultNode{ - Name: bflResponseModel.Trees[i].BFL.Name, - FileName: bflResponseModel.Trees[i].BFL.FileName, - FullName: bflResponseModel.Trees[i].BFL.FullName, - Column: bflResponseModel.Trees[i].BFL.Column, - Length: bflResponseModel.Trees[i].BFL.Length, - Line: bflResponseModel.Trees[i].BFL.Line, - MethodLine: bflResponseModel.Trees[i].BFL.MethodLine, - Method: bflResponseModel.Trees[i].BFL.Method, - DomType: bflResponseModel.Trees[i].BFL.DomType, - } - } - return views - } - views := make([]wrappers.ScanResultNode, 0) - return views -} - -func resultCodeBashing(codeBashingWrapper wrappers.CodeBashingWrapper) *cobra.Command { - // Create a codeBashing wrapper - resultCmd := &cobra.Command{ - Use: "codebashing", - Short: "Get codebashing lesson link", - Long: "The codebashing command enables the ability to retrieve the link about a specific vulnerability", - Example: heredoc.Doc( - ` - $ cx results codebashing --language --vulnerability-type --cwe-id --format - `, - ), - RunE: runGetCodeBashingCommand(codeBashingWrapper), - } - resultCmd.PersistentFlags().String(commonParams.LanguageFlag, "", "Language of the vulnerability") - err := resultCmd.MarkPersistentFlagRequired(commonParams.LanguageFlag) - if err != nil { - log.Fatal(err) - } - resultCmd.PersistentFlags().String(commonParams.VulnerabilityTypeFlag, "", "Vulnerability type") - err = resultCmd.MarkPersistentFlagRequired(commonParams.VulnerabilityTypeFlag) - if err != nil { - log.Fatal(err) - } - resultCmd.PersistentFlags().String(commonParams.CweIDFlag, "", "CWE ID for the vulnerability") - err = resultCmd.MarkPersistentFlagRequired(commonParams.CweIDFlag) - if err != nil { - log.Fatal(err) - } - addFormatFlag(resultCmd, printer.FormatJSON, printer.FormatTable, printer.FormatList) - return resultCmd -} - -func convertScanToResultsSummary(scanInfo *wrappers.ScanResponseModel, resultsWrapper wrappers.ResultsWrapper) (*wrappers.ResultSummary, error) { - if scanInfo == nil { - return nil, errors.New(failedCreatingSummary) - } - - scanInfo.ReplaceMicroEnginesWithSCS() - - sastIssues := 0 - scaIssues := 0 - kicsIssues := 0 - var containersIssues *int - var scsIssues *int - enginesStatusCode := map[string]int{ - commonParams.SastType: 0, - commonParams.ScaType: 0, - commonParams.KicsType: 0, - commonParams.APISecType: 0, - commonParams.ScsType: 0, - commonParams.ContainersType: 0, - } - if wrappers.IsContainersEnabled { - containersIssues = new(int) - *containersIssues = 0 - enginesStatusCode[commonParams.ContainersType] = 0 - } - - scsIssues = new(int) - *scsIssues = 0 - enginesStatusCode[commonParams.ScsType] = 0 - - if len(scanInfo.StatusDetails) > 0 { - applyScanStatusDetails(scanInfo.StatusDetails, &sastIssues, &scaIssues, &kicsIssues, scsIssues, containersIssues, enginesStatusCode) - } - summary := &wrappers.ResultSummary{ - ScanID: scanInfo.ID, - Status: string(scanInfo.Status), - CreatedAt: scanInfo.CreatedAt.Format("2006-01-02, 15:04:05"), - ProjectID: scanInfo.ProjectID, - RiskStyle: "", - RiskMsg: "", - CriticalIssues: 0, - HighIssues: 0, - MediumIssues: 0, - LowIssues: 0, - InfoIssues: 0, - SastIssues: sastIssues, - KicsIssues: kicsIssues, - ScaIssues: scaIssues, - ScsIssues: scsIssues, - ContainersIssues: containersIssues, - Tags: scanInfo.Tags, - ProjectName: scanInfo.ProjectName, - BranchName: scanInfo.Branch, - EnginesEnabled: scanInfo.Engines, - EnginesResult: map[string]*wrappers.EngineResultSummary{ - commonParams.SastType: {StatusCode: enginesStatusCode[commonParams.SastType]}, - commonParams.ScaType: {StatusCode: enginesStatusCode[commonParams.ScaType]}, - commonParams.KicsType: {StatusCode: enginesStatusCode[commonParams.KicsType]}, - commonParams.APISecType: {StatusCode: enginesStatusCode[commonParams.APISecType]}, - commonParams.ContainersType: {StatusCode: enginesStatusCode[commonParams.ContainersType]}, - }, - } - if wrappers.IsContainersEnabled { - summary.EnginesResult[commonParams.ContainersType] = &wrappers.EngineResultSummary{StatusCode: enginesStatusCode[commonParams.ContainersType]} - } - - summary.EnginesResult[commonParams.ScsType] = &wrappers.EngineResultSummary{StatusCode: enginesStatusCode[commonParams.ScsType]} - - baseURI, err := resultsWrapper.GetResultsURL(summary.ProjectID) - if err != nil { - return nil, err - } - - summary.BaseURI = baseURI - summary.BaseURI = generateScanSummaryURL(summary) - if isScanPending(summary.Status) { - summary.ScanInfoMessage = scanPendingMessage - } - - return summary, nil -} - -func applyScanStatusDetails( - statusDetails []wrappers.StatusInfo, - sastIssues, scaIssues, kicsIssues *int, - scsIssues, containersIssues *int, - enginesStatusCode map[string]int, -) { - for _, statusDetailItem := range statusDetails { - if statusDetailItem.Status == wrappers.ScanFailed || statusDetailItem.Status == wrappers.ScanCanceled { - markEngineNotAvailable(statusDetailItem.Name, sastIssues, scaIssues, kicsIssues, scsIssues, containersIssues) - } - switch statusDetailItem.Status { - case wrappers.ScanFailed: - handleScanStatus(statusDetailItem, enginesStatusCode, scanFailedNumber) - case wrappers.ScanCanceled: - handleScanStatus(statusDetailItem, enginesStatusCode, scanCanceledNumber) - } - } -} - -func markEngineNotAvailable(name string, sastIssues, scaIssues, kicsIssues, scsIssues, containersIssues *int) { - switch name { - case commonParams.SastType: - *sastIssues = notAvailableNumber - case commonParams.ScaType: - *scaIssues = notAvailableNumber - case commonParams.KicsType: - *kicsIssues = notAvailableNumber - case commonParams.ScsType: - *scsIssues = notAvailableNumber - case commonParams.ContainersType: - if wrappers.IsContainersEnabled { - *containersIssues = notAvailableNumber - } - } -} - -func handleScanStatus(statusDetailItem wrappers.StatusInfo, targetTypes map[string]int, statusCode int) { - if _, ok := targetTypes[statusDetailItem.Name]; ok { - targetTypes[statusDetailItem.Name] = statusCode - } -} - -func summaryReport( - summary *wrappers.ResultSummary, - policies *wrappers.PolicyResponseModel, - risksOverviewWrapper wrappers.RisksOverviewWrapper, - scsScanOverviewWrapper wrappers.ScanOverviewWrapper, - featureFlagsWrapper wrappers.FeatureFlagsWrapper, - results *wrappers.ScanResultsCollection, - resultsParams map[string]string, -) (*wrappers.ResultSummary, error) { - if summary.HasAPISecurity() { - apiSecFilterRisks, err := getFilterResultsForAPISecScanner(risksOverviewWrapper, summary.ScanID, resultsParams) - if err != nil { - return nil, err - } - if apiSecFilterRisks != nil { - summary.APISecurity = *apiSecFilterRisks - } - apiSecRisks, err := getResultsForAPISecScanner(risksOverviewWrapper, summary.ScanID) - if err != nil { - return nil, err - } - if apiSecRisks != nil { - summary.APISecurity.APICount = apiSecRisks.APICount - } - } - if summary.HasSCS() { - // Getting the base SCS overview. Results counts are overwritten in enhanceWithScanSummary->countResult - SCSOverview, err := getScanOverviewForSCSScanner(scsScanOverviewWrapper, summary.ScanID) - if err != nil { - return nil, err - } - summary.SCSOverview = SCSOverview - } - - if policies != nil { - summary.Policies = filterViolatedRules(*policies) - } - - enhanceWithScanSummary(summary, results, featureFlagsWrapper) - - setNotAvailableNumberIfZero(summary, &summary.SastIssues, commonParams.SastType) - setNotAvailableNumberIfZero(summary, &summary.ScaIssues, commonParams.ScaType) - setNotAvailableNumberIfZero(summary, &summary.KicsIssues, commonParams.KicsType) - setNotAvailableNumberIfZero(summary, summary.ScsIssues, commonParams.ScsType) - - if wrappers.IsContainersEnabled { - setNotAvailableNumberIfZero(summary, summary.ContainersIssues, commonParams.ContainersType) - } - - setRiskMsgAndStyle(summary) - setNotAvailableEnginesStatusCode(summary) - - return summary, nil -} - -func setNotAvailableEnginesStatusCode(summary *wrappers.ResultSummary) { - for engineName, engineResult := range summary.EnginesResult { - setNotAvailableNumberIfZero(summary, &engineResult.StatusCode, engineName) - } -} - -func setRiskMsgAndStyle(summary *wrappers.ResultSummary) { - if summary.CriticalIssues > 0 { - summary.RiskStyle = criticalLabel - summary.RiskMsg = "Critical Risk" - } else if summary.HighIssues > 0 { - summary.RiskStyle = highLabel - summary.RiskMsg = "High Risk" - } else if summary.MediumIssues > 0 { - summary.RiskStyle = mediumLabel - summary.RiskMsg = "Medium Risk" - } else if summary.LowIssues > 0 { - summary.RiskStyle = lowLabel - summary.RiskMsg = "Low Risk" - } else if summary.TotalIssues == 0 { - summary.RiskMsg = "No Risk" - } -} - -func setNotAvailableNumberIfZero(summary *wrappers.ResultSummary, counter *int, engineType string) { - if *counter == 0 && !contains(summary.EnginesEnabled, engineType) { - *counter = notAvailableNumber - } -} - -func enhanceWithScanSummary(summary *wrappers.ResultSummary, results *wrappers.ScanResultsCollection, featureFlagsWrapper wrappers.FeatureFlagsWrapper) { - for _, result := range results.Results { - countResult(summary, result) - } - // Set critical count for a specific engine if critical is disabled - flagResponse, _ := wrappers.GetSpecificFeatureFlag(featureFlagsWrapper, wrappers.CVSSV3Enabled) - criticalEnabled := flagResponse.Status - if summary.HasAPISecurity() { - summary.EnginesResult[commonParams.APISecType].Low = summary.APISecurity.SeverityCount["low"] - summary.EnginesResult[commonParams.APISecType].Medium = summary.APISecurity.SeverityCount["medium"] - summary.EnginesResult[commonParams.APISecType].High = summary.APISecurity.SeverityCount["high"] - if !criticalEnabled { - summary.EnginesResult[commonParams.APISecType].Critical = notAvailableNumber - } else { - summary.EnginesResult[commonParams.APISecType].Critical = summary.APISecurity.SeverityCount["critical"] - } - } - - summary.TotalIssues = summary.SastIssues + summary.ScaIssues + summary.KicsIssues + summary.GetAPISecurityDocumentationTotal() - - if summary.HasSCS() { - // Special case for SCS where status is partial if any microengines failed - if summary.SCSOverview.Status == scanPartialString { - summary.EnginesResult[commonParams.ScsType].StatusCode = scanPartialNumber - } - if !criticalEnabled { - summary.EnginesResult[commonParams.ScsType].Critical = notAvailableNumber - removeCriticalFromSCSOverview(summary) - } - if *summary.ScsIssues >= 0 { - summary.TotalIssues += *summary.ScsIssues - } - } - if wrappers.IsContainersEnabled { - if *summary.ContainersIssues >= 0 { - summary.TotalIssues += *summary.ContainersIssues - } - } - if !criticalEnabled { - summary.EnginesResult[commonParams.SastType].Critical = notAvailableNumber - summary.EnginesResult[commonParams.KicsType].Critical = notAvailableNumber - summary.EnginesResult[commonParams.ScaType].Critical = notAvailableNumber - summary.EnginesResult[commonParams.ContainersType].Critical = notAvailableNumber - } -} - -func removeCriticalFromSCSOverview(summary *wrappers.ResultSummary) { - criticalCount := summary.SCSOverview.RiskSummary[criticalLabel] - summary.SCSOverview.TotalRisksCount -= criticalCount - summary.SCSOverview.RiskSummary[criticalLabel] = notAvailableNumber - for _, microEngineOverview := range summary.SCSOverview.MicroEngineOverviews { - if microEngineOverview.RiskSummary != nil && microEngineOverview.RiskSummary[criticalLabel] != nil { - engineCriticalCount := microEngineOverview.RiskSummary[criticalLabel] - microEngineOverview.TotalRisks -= engineCriticalCount.(int) - microEngineOverview.RiskSummary[criticalLabel] = disabledString - } - } -} - -func writeHTMLSummary(targetFile string, summary *wrappers.ResultSummary) error { - log.Println("Creating Summary Report: ", targetFile) - summaryTemp, err := template.New("summaryTemplate").Parse(wrappers.SummaryTemplate(isScanPending(summary.Status))) - if err == nil { - f, err := os.Create(targetFile) - if err == nil { - _ = summaryTemp.ExecuteTemplate(f, "SummaryTemplate", summary) - _ = f.Close() - } - return err - } - return nil -} -func writeMarkdownSummary(targetFile string, data *wrappers.ResultSummary) error { - log.Println("Creating Markdown Summary Report: ", targetFile) - tmpl, err := template.New(printer.FormatSummaryMarkdown).Parse(wrappers.SummaryMarkdownTemplate(isScanPending(data.Status))) - if err != nil { - return err - } - file, err := os.Create(targetFile) - if err != nil { - return err - } - defer func() { _ = file.Close() }() - - err = tmpl.Execute(file, &data) - if err != nil { - return err - } - return nil -} - -// nolint: whitespace -func writeConsoleSummary(summary *wrappers.ResultSummary, ignorePolicyFlagOmit bool) error { - if !isScanPending(summary.Status) { - fmt.Printf(" Scan Summary: \n") - fmt.Printf(" Created At: %s\n", summary.CreatedAt) - fmt.Printf(" Project Name: %s \n", summary.ProjectName) - fmt.Printf(" Scan ID: %s \n\n", summary.ScanID) - fmt.Printf(" Results Summary: \n") - fmt.Printf( - " Risk Level: %s \n", - summary.RiskMsg, - ) - if summary.Policies != nil && !strings.EqualFold(summary.Policies.Status, policeManagementNoneStatus) { - printPoliciesSummary(summary, ignorePolicyFlagOmit) - } - - printResultsSummaryTable(summary) - - if summary.HasAPISecurity() { - printAPIsSecuritySummary(summary) - } - - if summary.HasSCS() { - printSCSSummary(summary.SCSOverview.MicroEngineOverviews) - } - - 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") - fmt.Printf("For more information: %s\n", summary.BaseURI) - } - return nil -} - -func printPoliciesSummary(summary *wrappers.ResultSummary, ignorePolicyFlagOmit bool) { - hasViolations := false - for _, policy := range summary.Policies.Policies { - if len(policy.RulesViolated) > 0 { - hasViolations = true - break - } - } - if hasViolations { - fmt.Printf(tableLine + "\n") - if ignorePolicyFlagOmit { - printWarningIfIgnorePolicyOmiited() - } - if summary.Policies.BreakBuild { - fmt.Printf(" Policy Management Violation - Break Build Enabled: \n") - } else { - fmt.Printf(" Policy Management Violation: \n") - } - for _, police := range summary.Policies.Policies { - if len(police.RulesViolated) > 0 { - fmt.Printf(" Policy: %s | Break Build: %t | Violated Rules: ", police.Name, police.BreakBuild) - for _, violatedRule := range police.RulesViolated { - fmt.Printf("%s;", violatedRule) - } - } - fmt.Printf("\n") - } - fmt.Printf("\n") - } -} - -func printAPIsSecuritySummary(summary *wrappers.ResultSummary) { - fmt.Printf(" API Security - Total Detected APIs: %d \n", summary.APISecurity.APICount) - fmt.Printf(" APIS WITH RISK: %*d \n", defaultPaddingSize, summary.APISecurity.TotalRisksCount) - if summary.HasAPISecurityDocumentation() { - fmt.Printf(" APIS DOCUMENTATION: %*d \n", defaultPaddingSize, summary.GetAPISecurityDocumentationTotal()) - } - fmt.Printf(tableLine + twoNewLines) -} - -func printTableRow(title string, counts *wrappers.EngineResultSummary, statusNumber int) { - switch statusNumber { - case notAvailableNumber: - fmt.Printf(stringTableResultsFormat, title, notAvailableString, notAvailableString, notAvailableString, notAvailableString, notAvailableString, notAvailableString) - case scanFailedNumber: - fmt.Printf(tableResultsFormat, title, getCountValue(counts.Critical), counts.High, counts.Medium, counts.Low, counts.Info, scanFailedString) - case scanCanceledNumber: - fmt.Printf(tableResultsFormat, title, getCountValue(counts.Critical), counts.High, counts.Medium, counts.Low, counts.Info, scanCanceledString) - case scanPartialNumber: - fmt.Printf(tableResultsFormat, title, getCountValue(counts.Critical), counts.High, counts.Medium, counts.Low, counts.Info, scanPartialString) - default: - fmt.Printf(tableResultsFormat, title, getCountValue(counts.Critical), counts.High, counts.Medium, counts.Low, counts.Info, scanSuccessString) - } -} - -func printSCSSummary(microEngineOverviews []*wrappers.MicroEngineOverview) { - fmt.Printf(" Supply Chain Security Results\n") - fmt.Printf(" -------------------------------------------------------------------------- \n") - fmt.Println(" | Critical High Medium Low Info Status |") - for _, microEngineOverview := range microEngineOverviews { - printSCSTableRow(microEngineOverview) - } - fmt.Printf(" -------------------------------------------------------------------------- \n\n") -} - -func printSCSTableRow(microEngineOverview *wrappers.MicroEngineOverview) { - formatString := " | %-20s %4v %4v %6v %4v %4v %-9s |\n" - notAvailableFormatString := " | %-20s %4v %4s %6s %4s %4s %5s |\n" - - riskSummary := microEngineOverview.RiskSummary - microEngineName := microEngineOverview.FullName - - switch microEngineOverview.Status { - case scsScanUnavailableString: - fmt.Printf(notAvailableFormatString, microEngineName, notAvailableString, notAvailableString, notAvailableString, notAvailableString, notAvailableString, notAvailableString) - default: - fmt.Printf(formatString, microEngineName, riskSummary[criticalLabel], riskSummary[highLabel], riskSummary[mediumLabel], riskSummary[lowLabel], - riskSummary[infoLabel], microEngineOverview.Status) - } -} - -func getCountValue(count int) interface{} { - if count < 0 { - return disabledString - } - return count -} - -func printResultsSummaryTable(summary *wrappers.ResultSummary) { - totalCriticalIssues := summary.EnginesResult.GetCriticalIssues() - totalHighIssues := summary.EnginesResult.GetHighIssues() - totalMediumIssues := summary.EnginesResult.GetMediumIssues() - totalLowIssues := summary.EnginesResult.GetLowIssues() - totalInfoIssues := summary.EnginesResult.GetInfoIssues() - fmt.Printf(tableLine + twoNewLines) - fmt.Printf(" Total Results: %d (Total Results includes only API documentation vulnerabilities\n and does not include API code vulnerabilities.)\n", summary.TotalIssues) - fmt.Println(tableLine) - fmt.Printf(TableTitleFormat, " ", "Critical", "High", "Medium", "Low", "Info", "Status") - - printTableRow("APIs", summary.EnginesResult[commonParams.APISecType], summary.EnginesResult[commonParams.APISecType].StatusCode) - printTableRow("IAC", summary.EnginesResult[commonParams.KicsType], summary.EnginesResult[commonParams.KicsType].StatusCode) - printTableRow("SAST", summary.EnginesResult[commonParams.SastType], summary.EnginesResult[commonParams.SastType].StatusCode) - printTableRow("SCA", summary.EnginesResult[commonParams.ScaType], summary.EnginesResult[commonParams.ScaType].StatusCode) - printTableRow("SCS", summary.EnginesResult[commonParams.ScsType], summary.EnginesResult[commonParams.ScsType].StatusCode) - - if wrappers.IsContainersEnabled { - printTableRow("CONTAINERS", summary.EnginesResult[commonParams.ContainersType], summary.EnginesResult[commonParams.ContainersType].StatusCode) - } - - fmt.Println(tableLine) - fmt.Printf(tableResultsFormat, - "TOTAL", getCountValue(totalCriticalIssues), totalHighIssues, totalMediumIssues, totalLowIssues, totalInfoIssues, summary.Status) - fmt.Printf(tableLine + twoNewLines) -} - -func generateScanSummaryURL(summary *wrappers.ResultSummary) string { - summaryURL := fmt.Sprintf( - strings.Replace(summary.BaseURI, "overview", "scans?id=%s&branch=%s", 1), - summary.ScanID, url.QueryEscape(summary.BranchName), - ) - return summaryURL -} - -func runGetResultCommand( - resultsWrapper wrappers.ResultsWrapper, - scanWrapper wrappers.ScansWrapper, - exportWrapper wrappers.ExportWrapper, - resultsPdfReportsWrapper wrappers.ResultsPdfWrapper, - resultsJSONReportsWrapper wrappers.ResultsJSONWrapper, - risksOverviewWrapper wrappers.RisksOverviewWrapper, - scsScanOverviewWrapper wrappers.ScanOverviewWrapper, - policyWrapper wrappers.PolicyWrapper, - featureFlagsWrapper wrappers.FeatureFlagsWrapper, - jwtWrapper wrappers.JWTWrapper, -) func(cmd *cobra.Command, args []string) error { - return func(cmd *cobra.Command, args []string) error { - targetFile, _ := cmd.Flags().GetString(commonParams.TargetFlag) - targetPath, _ := cmd.Flags().GetString(commonParams.TargetPathFlag) - format, _ := cmd.Flags().GetString(commonParams.TargetFormatFlag) - formatPdfToEmail, _ := cmd.Flags().GetString(commonParams.ReportFormatPdfToEmailFlag) - formatPdfOptions, _ := cmd.Flags().GetString(commonParams.ReportFormatPdfOptionsFlag) - formatSbomOptions, _ := cmd.Flags().GetString(commonParams.ReportSbomFormatFlag) - sastRedundancy, _ := cmd.Flags().GetBool(commonParams.SastRedundancyFlag) - agent, _ := cmd.Flags().GetString(commonParams.AgentFlag) - scaHideDevAndTestDep, _ := cmd.Flags().GetBool(commonParams.ScaHideDevAndTestDepFlag) - ignorePolicy, _ := cmd.Flags().GetBool(commonParams.IgnorePolicyFlag) - // Check if the user has permission to override policy management if --ignore-policy is set - ignorePolicyFlagOmit := false - if ignorePolicy { - overridePolicyManagementPer, err := jwtWrapper.CheckPermissionByAccessToken(OverridePolicyManagement) - if err != nil { - return err - } - if !overridePolicyManagementPer { - ignorePolicyFlagOmit = true - ignorePolicy = false - } - } - waitDelay, _ := cmd.Flags().GetInt(commonParams.WaitDelayFlag) - policyTimeout, _ := cmd.Flags().GetInt(commonParams.PolicyTimeoutFlag) - - scanID, _ := cmd.Flags().GetString(commonParams.ScanIDFlag) - if scanID == "" { - return errors.Errorf("%s: Please provide a scan ID", failedListingResults) - } - - resultsParams, err := getFilters(cmd) - if err != nil { - return errors.Wrapf(err, "%s", failedListingResults) - } - - if scaHideDevAndTestDep { - resultsParams[ScaExcludeResultTypesParam] = ScaDevAndTestExclusionParam - } - - scan, errorModel, scanErr := scanWrapper.GetByID(scanID) - if scanErr != nil { - return errors.Wrapf(scanErr, "%s", failedGetting) - } - if errorModel != nil { - return errors.Errorf("%s: CODE: %d, %s", failedGettingScan, errorModel.Code, errorModel.Message) - } - - var policyResponseModel *wrappers.PolicyResponseModel - if !isScanPending(string(scan.Status)) { - policyResponseModel, err = services.HandlePolicyEvaluation(cmd, policyWrapper, scan, ignorePolicy, agent, waitDelay, policyTimeout) - if err != nil { - return err - } - } else { - logger.PrintIfVerbose("Policy violations aren't returned in the pipeline for scans run in async mode.") - } - - if sastRedundancy { - resultsParams[commonParams.SastRedundancyFlag] = "" - } - - _, err = CreateScanReport(resultsWrapper, risksOverviewWrapper, scsScanOverviewWrapper, exportWrapper, - policyResponseModel, resultsPdfReportsWrapper, resultsJSONReportsWrapper, scan, format, formatPdfToEmail, formatPdfOptions, - formatSbomOptions, targetFile, targetPath, agent, resultsParams, featureFlagsWrapper, ignorePolicyFlagOmit) - return err - } -} - -func runGetCodeBashingCommand( - codeBashingWrapper wrappers.CodeBashingWrapper, -) func(cmd *cobra.Command, args []string) error { - return func(cmd *cobra.Command, args []string) error { - lang, _ := cmd.Flags().GetString(commonParams.LanguageFlag) - cwe, _ := cmd.Flags().GetString(commonParams.CweIDFlag) - vulType, _ := cmd.Flags().GetString(commonParams.VulnerabilityTypeFlag) - params, err := codeBashingWrapper.BuildCodeBashingParams( - []wrappers.CodeBashingParamsCollection{ - { - CweID: "CWE-" + cwe, - Language: lang, - CxQueryName: strings.ReplaceAll(vulType, " ", "_"), - }, - }, - ) - if err != nil { - return err - } - // Fetch the cached token or a new one to obtain the codebashing URL incoded in the jwt token - codeBashingURL, err := codeBashingWrapper.GetCodeBashingURL(codeBashingKey) - if err != nil { - return err - } - // Make the request to the api to obtain the codebashing link and send the codebashing url to enrich the path - CodeBashingModel, webError, err := codeBashingWrapper.GetCodeBashingLinks(params, codeBashingURL) - if err != nil { - return err - } - if webError != nil { - return errors.New(webError.Message) - } - err = printByFormat(cmd, *CodeBashingModel) - if err != nil { - return errors.Wrapf(err, "%s", failedListingCodeBashing) - } - return nil - } -} - -func setIsContainersEnabled(agent string) { - wrappers.IsContainersEnabled = !containsIgnoreCase(containerEngineUnsupportedAgents, agent) -} - -func filterResultsByType(results *wrappers.ScanResultsCollection, excludedTypes map[string]struct{}) *wrappers.ScanResultsCollection { - var filteredResults []*wrappers.ScanResult - - for _, result := range results.Results { - if _, shouldExclude := excludedTypes[result.Type]; shouldExclude { - results.TotalCount-- - } else { - filteredResults = append(filteredResults, result) - } - } - results.Results = filteredResults - return results -} - -func filterScsResultsByAgent(results *wrappers.ScanResultsCollection, agent string) *wrappers.ScanResultsCollection { - unsupportedTypesByAgent := map[string][]string{ - commonParams.VSCodeAgent: {commonParams.SCSScorecardType}, - commonParams.JetbrainsAgent: {commonParams.SCSScorecardType}, - commonParams.EclipseAgent: {commonParams.SCSScorecardType, commonParams.SCSSecretDetectionType}, - commonParams.VisualStudioAgent: {commonParams.SCSScorecardType}, - } - - excludedTypes := make(map[string]struct{}) - - if typesToExclude, exists := unsupportedTypesByAgent[agent]; exists { - for _, excludeType := range typesToExclude { - excludedTypes[excludeType] = struct{}{} - } - } - - results = filterResultsByType(results, excludedTypes) - - return results -} - -// CreateScanReport produces the requested report formats for a scan and writes them to the target path. -func CreateScanReport( - resultsWrapper wrappers.ResultsWrapper, - risksOverviewWrapper wrappers.RisksOverviewWrapper, - scsScanOverviewWrapper wrappers.ScanOverviewWrapper, - exportWrapper wrappers.ExportWrapper, - policyResponseModel *wrappers.PolicyResponseModel, - resultsPdfReportsWrapper wrappers.ResultsPdfWrapper, - resultsJSONReportsWrapper wrappers.ResultsJSONWrapper, - scan *wrappers.ScanResponseModel, - reportTypes, - formatPdfToEmail, - formatPdfOptions, - formatSbomOptions, - targetFile, - targetPath string, - agent string, - resultsParams map[string]string, - featureFlagsWrapper wrappers.FeatureFlagsWrapper, - ignorePolicyFlagOmit bool, -) (*wrappers.ScanResultsCollection, error) { - reportList := strings.Split(reportTypes, ",") - results := &wrappers.ScanResultsCollection{} - setIsContainersEnabled(agent) - summary, err := convertScanToResultsSummary(scan, resultsWrapper) - if err != nil { - return nil, err - } - scanPending := isScanPending(summary.Status) - - err = createDirectory(targetPath) - if err != nil { - return nil, err - } - if !scanPending { - results, err = ReadResults(resultsWrapper, exportWrapper, scan, resultsParams, agent, featureFlagsWrapper) - if err != nil { - return nil, err - } - } - isSummaryNeeded := verifyFormatsByReportList(reportList, summaryFormats...) - if isSummaryNeeded && !scanPending { - summary, err = summaryReport(summary, policyResponseModel, risksOverviewWrapper, scsScanOverviewWrapper, featureFlagsWrapper, results, resultsParams) - if err != nil { - return nil, err - } - } - for _, reportType := range reportList { - err = createReport(reportType, formatPdfToEmail, formatPdfOptions, formatSbomOptions, targetFile, - targetPath, results, summary, exportWrapper, resultsPdfReportsWrapper, resultsJSONReportsWrapper, featureFlagsWrapper, ignorePolicyFlagOmit) - if err != nil { - return nil, err - } - } - return results, nil -} - -func countResult(summary *wrappers.ResultSummary, result *wrappers.ScanResult) { - engineType := strings.TrimSpace(result.Type) - severity := strings.ToLower(result.Severity) - if contains(summary.EnginesEnabled, engineType) && isExploitable(result.State) { - if engineType == commonParams.SastType { - summary.SastIssues++ - summary.TotalIssues++ - } else if engineType == commonParams.ScaType { - summary.ScaIssues++ - summary.TotalIssues++ - } else if engineType == commonParams.KicsType { - summary.KicsIssues++ - summary.TotalIssues++ - } else if engineType == commonParams.ContainersType { - if wrappers.IsContainersEnabled { - *summary.ContainersIssues++ - summary.TotalIssues++ - } else { - return - } - } else if strings.HasPrefix(engineType, commonParams.SscsType) { - addResultToSCSOverview(summary, result) - engineType = commonParams.ScsType - *summary.ScsIssues++ - summary.TotalIssues++ - } else { - return - } - - switch severity { - case criticalLabel: - summary.CriticalIssues++ - case highLabel: - summary.HighIssues++ - case mediumLabel: - summary.MediumIssues++ - case lowLabel: - summary.LowIssues++ - case infoLabel: - summary.InfoIssues++ - } - - summary.UpdateEngineResultSummary(engineType, severity) - } -} - -func addResultToSCSOverview(summary *wrappers.ResultSummary, result *wrappers.ScanResult) { - if engineOverviewName, engineExists := sscsEngineToOverviewEngineMap[result.Type]; engineExists { - for _, microEngineOverview := range summary.SCSOverview.MicroEngineOverviews { - if microEngineOverview.Name == engineOverviewName { - if microEngineOverview.RiskSummary != nil { - severity := strings.ToLower(result.Severity) - if severityCount, exists := microEngineOverview.RiskSummary[severity]; exists { - summary.SCSOverview.RiskSummary[severity]++ - microEngineOverview.TotalRisks++ - summary.SCSOverview.TotalRisksCount++ - microEngineOverview.RiskSummary[severity] = severityCount.(int) + 1 - } - } - } - } - } -} - -func verifyFormatsByReportList(reportFormats []string, formats ...string) bool { - for _, reportFormat := range reportFormats { - for _, format := range formats { - if printer.IsFormat(reportFormat, format) { - return true - } - } - } - return false -} - -func validateEmails(emailString string) ([]string, error) { - re := regexp.MustCompile(`^[a-zA-Z0-9_.+-]+@[a-zA-Z0-9-]+\.[a-zA-Z0-9-.]+$`) - emails := strings.Split(emailString, ",") - var validEmails []string - for _, emailStr := range emails { - email := strings.TrimSpace(emailStr) - if re.MatchString(email) { - validEmails = append(validEmails, email) - } else { - return nil, errors.Errorf("report not sent, invalid email address: %s", email) - } - } - return validEmails, nil -} - -func getResultsForAPISecScanner( - risksOverviewWrapper wrappers.RisksOverviewWrapper, - scanID string, -) (results *wrappers.APISecResult, err error) { - var apiSecResultsModel *wrappers.APISecResult - var errorModel *wrappers.WebError - - apiSecResultsModel, errorModel, err = risksOverviewWrapper.GetAllAPISecRisksByScanID(scanID) - if err != nil { - return nil, errors.Wrapf(err, "%s", failedListingResults) - } - if errorModel != nil { - return nil, errors.Errorf("%s: CODE: %d, %s", failedListingResults, errorModel.Code, errorModel.Message) - } else if apiSecResultsModel != nil { - return apiSecResultsModel, nil - } - return nil, nil -} - -func getScanOverviewForSCSScanner( - scsScanOverviewWrapper wrappers.ScanOverviewWrapper, - scanID string, -) (results *wrappers.SCSOverview, err error) { - var scsOverview *wrappers.SCSOverview - var errorModel *wrappers.WebError - - scsOverview, errorModel, err = scsScanOverviewWrapper.GetSCSOverviewByScanID(scanID) - if err != nil { - return nil, errors.Wrapf(err, "SCS: %s", failedListingResults) - } - if errorModel != nil { - return nil, errors.Errorf("SCS: %s: CODE: %d, %s", failedListingResults, errorModel.Code, errorModel.Message) - } else if scsOverview != nil { - // Setting all counts to 0. Results are recounted in enhanceWithScanSummary->countResult - scsOverview.TotalRisksCount = 0 - for key := range scsOverview.RiskSummary { - scsOverview.RiskSummary[key] = 0 - } - for _, microEngineOverview := range scsOverview.MicroEngineOverviews { - microEngineOverview.TotalRisks = 0 - if microEngineOverview.RiskSummary != nil { - for severity := range microEngineOverview.RiskSummary { - microEngineOverview.RiskSummary[severity] = 0 - } - } - } - return scsOverview, nil - } - return nil, nil -} - -func isScanPending(scanStatus string) bool { - return !strings.EqualFold(scanStatus, statusCompleted) && - !strings.EqualFold(scanStatus, statusPartial) && - !strings.EqualFold(scanStatus, statusFailed) -} - -func createRawReport( - format, targetFile, targetPath string, - results *wrappers.ScanResultsCollection, - summary *wrappers.ResultSummary, - resultsJSONReportsWrapper wrappers.ResultsJSONWrapper, - featureFlagsWrapper wrappers.FeatureFlagsWrapper, -) (handled bool, err error) { - if printer.IsFormat(format, printer.FormatIndentedJSON) { - return true, nil - } - if printer.IsFormat(format, printer.FormatSarif) && isValidScanStatus(summary.Status, printer.FormatSarif) { - sarifRpt := createTargetName(targetFile, targetPath, printer.FormatSarif) - return true, exportSarifResults(sarifRpt, results) - } - if printer.IsFormat(format, printer.FormatSonar) && isValidScanStatus(summary.Status, printer.FormatSonar) { - sonarRpt := createTargetName(fmt.Sprintf("%s%s", targetFile, sonarTypeLabel), targetPath, printer.FormatJSON) - return true, exportSonarResults(sonarRpt, results) - } - if printer.IsFormat(format, printer.FormatJSON) && isValidScanStatus(summary.Status, printer.FormatJSON) { - jsonRpt := createTargetName(targetFile, targetPath, printer.FormatJSON) - return true, exportJSONResults(jsonRpt, results) - } - if printer.IsFormat(format, printer.FormatJSONv2) && isValidScanStatus(summary.Status, printer.FormatJSONv2) { - summaryRpt := createTargetName(targetFile, targetPath, printer.FormatJSON) - return true, exportJSONReportResults(resultsJSONReportsWrapper, summary, summaryRpt, featureFlagsWrapper) - } - if printer.IsFormat(format, printer.FormatGLSast) { - jsonRpt := createTargetName(fmt.Sprintf("%s%s", targetFile, glSastTypeLabel), targetPath, printer.FormatJSON) - return true, exportGlSastResults(jsonRpt, results, summary) - } - if printer.IsFormat(format, printer.FormatGLSca) { - jsonRpt := createTargetName(fmt.Sprintf("%s%s", targetFile, glScaTypeLabel), targetPath, printer.FormatJSON) - return true, exportGlScaResults(jsonRpt, results, summary) - } - return false, nil -} - -func isValidScanStatus(status, format string) bool { - if isScanPending(status) { - log.Printf("Result format file %s not create because scan status is %s", format, status) - return false - } - return true -} - -func createReport(format, - formatPdfToEmail, - formatPdfOptions, - formatSbomOptions, - targetFile, - targetPath string, - results *wrappers.ScanResultsCollection, - summary *wrappers.ResultSummary, - exportWrapper wrappers.ExportWrapper, - resultsPdfReportsWrapper wrappers.ResultsPdfWrapper, - resultsJSONReportsWrapper wrappers.ResultsJSONWrapper, - featureFlagsWrapper wrappers.FeatureFlagsWrapper, - ignorePolicyFlagOmit bool) error { - if handled, err := createRawReport(format, targetFile, targetPath, results, summary, resultsJSONReportsWrapper, featureFlagsWrapper); handled { - return err - } - - if printer.IsFormat(format, printer.FormatSummaryConsole) { - return writeConsoleSummary(summary, ignorePolicyFlagOmit) - } - if printer.IsFormat(format, printer.FormatSummary) { - summaryRpt := createTargetName(targetFile, targetPath, printer.FormatHTML) - convertNotAvailableNumberToZero(summary) - return writeHTMLSummary(summaryRpt, summary) - } - if printer.IsFormat(format, printer.FormatSummaryJSON) { - summaryRpt := createTargetName(targetFile, targetPath, printer.FormatJSON) - convertNotAvailableNumberToZero(summary) - return exportJSONSummaryResults(summaryRpt, summary) - } - if printer.IsFormat(format, printer.FormatPDF) && isValidScanStatus(summary.Status, printer.FormatPDF) { - summaryRpt := createTargetName(targetFile, targetPath, printer.FormatPDF) - return exportPdfResults(resultsPdfReportsWrapper, summary, summaryRpt, formatPdfToEmail, formatPdfOptions, featureFlagsWrapper) - } - if printer.IsFormat(format, printer.FormatSummaryMarkdown) { - summaryRpt := createTargetName(targetFile, targetPath, "md") - convertNotAvailableNumberToZero(summary) - return writeMarkdownSummary(summaryRpt, summary) - } - if printer.IsFormat(format, printer.FormatSbom) && isValidScanStatus(summary.Status, printer.FormatSbom) { - targetType := printer.FormatJSON - if strings.Contains(strings.ToLower(formatSbomOptions), printer.FormatXML) { - targetType = printer.FormatXML - } - summaryRpt := createTargetName(fmt.Sprintf("%s_%s", targetFile, printer.FormatSbom), targetPath, targetType) - convertNotAvailableNumberToZero(summary) - - if !contains(summary.EnginesEnabled, commonParams.ScaType) { - return fmt.Errorf("unable to generate %s report - SCA engine must be enabled on scan summary", printer.FormatSbom) - } - - if summary.ScaIssues == notAvailableNumber { - return fmt.Errorf("unable to generate %s report - SCA engine did not complete successfully", printer.FormatSbom) - } - - return services.ExportSbomResults(exportWrapper, summaryRpt, summary, formatSbomOptions) - } - return fmt.Errorf("bad report format %s", format) -} - -func createTargetName(targetFile, targetPath, targetType string) string { - return filepath.Join(targetPath, targetFile+"."+targetType) -} - -func createDirectory(targetPath string) error { - if _, err := os.Stat(targetPath); os.IsNotExist(err) { - log.Printf("\nOutput path not found: %s\n", targetPath) - log.Printf("Creating directory: %s\n", targetPath) - err = os.Mkdir(targetPath, directoryPermission) - if err != nil { - return err - } - } - return nil -} - -// ReadResults fetches all scan results for the given scan and enriches them with SCA and SCS data as applicable. -func ReadResults( - resultsWrapper wrappers.ResultsWrapper, - exportWrapper wrappers.ExportWrapper, - scan *wrappers.ScanResponseModel, - resultsParams map[string]string, - agent string, featureflagsWrappers wrappers.FeatureFlagsWrapper) (results *wrappers.ScanResultsCollection, err error) { - var resultsModel *wrappers.ScanResultsCollection - var errorModel *wrappers.WebError - - resultsParams[commonParams.ScanIDQueryParam] = scan.ID - _, sastRedundancy := resultsParams[commonParams.SastRedundancyFlag] - - scaHideDevAndTestDep := resultsParams[ScaExcludeResultTypesParam] == ScaDevAndTestExclusionParam - - resultsModel, errorModel, err = resultsWrapper.GetAllResultsByScanID(resultsParams) - - if err != nil { - return nil, errors.Wrapf(err, "%s", failedListingResults) - } - if errorModel != nil { - return nil, errors.Errorf("%s: CODE: %d, %s", failedListingResults, errorModel.Code, errorModel.Message) - } - - if resultsModel != nil { - if slices.Contains(scan.Engines, commonParams.SastType) && sastRedundancy { - // Compute SAST results redundancy - resultsModel = ComputeRedundantSastResults(resultsModel) - } - resultsModel, err = enrichScaResults(exportWrapper, scan, resultsModel, scaHideDevAndTestDep, featureflagsWrappers) - if err != nil { - return nil, err - } - - if slices.Contains(scan.Engines, commonParams.ScsType) { - resultsModel = filterScsResultsByAgent(resultsModel, agent) - } - - resultsModel.ScanID = scan.ID - return resultsModel, nil - } - return nil, nil -} - -func enrichScaResults( - exportWrapper wrappers.ExportWrapper, - scan *wrappers.ScanResponseModel, - resultsModel *wrappers.ScanResultsCollection, - scaHideDevAndTestDep bool, featureflagWrapper wrappers.FeatureFlagsWrapper) (*wrappers.ScanResultsCollection, error) { - if slices.Contains(scan.Engines, commonParams.ScaType) { - scaExportDetails, err := services.GetExportPackage(exportWrapper, scan.ID, scaHideDevAndTestDep, featureflagWrapper) - if err != nil { - return nil, errors.Wrapf(err, "%s", failedListingResults) - } - scaPackageModel := parseScaExportPackage(scaExportDetails.Packages) - scaTypeModel := parseExportScaVulnerability(scaExportDetails.ScaTypes) - if scaPackageModel != nil { - resultsModel = addPackageInformation(resultsModel, scaPackageModel, scaTypeModel) - } - } - if slices.Contains(scan.Engines, commonParams.ContainersType) && !wrappers.IsContainersEnabled { - resultsModel = removeResultsByType(resultsModel, commonParams.ContainersType) - } - return resultsModel, nil -} - -func parseExportScaVulnerability(types []wrappers.ScaType) *[]wrappers.ScaTypeCollection { - var scaTypes []wrappers.ScaTypeCollection - for _, t := range types { - scaTypes = append(scaTypes, wrappers.ScaTypeCollection(t)) - } - return &scaTypes -} - -func parseScaExportPackage(packages []wrappers.ScaPackage) *[]wrappers.ScaPackageCollection { - var scaPackages []wrappers.ScaPackageCollection - for _, pkg := range packages { - pkg := pkg - scaPackages = append(scaPackages, wrappers.ScaPackageCollection{ - ID: pkg.ID, - Locations: pkg.Locations, - DependencyPathArray: parsePackagePathToDependencyPath(&pkg), - Outdated: pkg.Outdated, - IsDirectDependency: pkg.IsDirectDependency, - IsDevelopmentDependency: pkg.IsDevelopmentDependency, - IsTestDependency: pkg.IsTestDependency, - }) - } - return &scaPackages -} - -func parsePackagePathToDependencyPath(pkg *wrappers.ScaPackage) [][]wrappers.DependencyPath { - var dependencyPathArray [][]wrappers.DependencyPath - for _, path := range pkg.PackagePathArray { - var dependencyPath []wrappers.DependencyPath - for _, dep := range path { - dependencyPath = append(dependencyPath, wrappers.DependencyPath{ - ID: dep.ID, - Name: dep.Name, - Version: dep.Version, - }) - } - dependencyPathArray = append(dependencyPathArray, dependencyPath) - } - - // We are doing this to maintain the same structure that was in risk-management api response - // in risk-management, if the length of the dependency path array is 1, it will be the main package - // in export service, if there are no dependencies, the package path array will be empty - if len(dependencyPathArray) == 0 { - appendMainPackageToDependencyPath(&dependencyPathArray, pkg) - } - return dependencyPathArray -} - -func appendMainPackageToDependencyPath(dependencyPathArray *[][]wrappers.DependencyPath, pkg *wrappers.ScaPackage) { - *dependencyPathArray = append(*dependencyPathArray, []wrappers.DependencyPath{{ - ID: pkg.ID, - Locations: pkg.Locations, - Name: pkg.Name, - IsDevelopment: pkg.IsDevelopmentDependency, - }}) -} - -func removeResultsByType(model *wrappers.ScanResultsCollection, resultType string) *wrappers.ScanResultsCollection { - var newResults []*wrappers.ScanResult - for _, result := range model.Results { - isResultType := result.Type == resultType - if resultType == commonParams.SscsType { - isResultType = strings.HasPrefix(result.Type, resultType) - } - if !isResultType { - newResults = append(newResults, result) - } - } - model.Results = newResults - model.TotalCount = uint(len(newResults)) - return model -} - -func exportSarifResults(targetFile string, results *wrappers.ScanResultsCollection) error { - var err error - var resultsJSON []byte - log.Println("Creating SARIF Report: ", targetFile) - var sarifResults = convertCxResultsToSarif(results) - resultsJSON, err = json.Marshal(sarifResults) - if err != nil { - return errors.Wrapf(err, "%s: failed to serialize results response ", failedGettingAll) - } - f, err := os.Create(targetFile) - if err != nil { - return errors.Wrapf(err, "%s: failed to create target file ", failedGettingAll) - } - _, _ = fmt.Fprintln(f, string(resultsJSON)) - _ = f.Close() - return nil -} -func exportGlSastResults(targetFile string, results *wrappers.ScanResultsCollection, summary *wrappers.ResultSummary) error { - log.Println("Creating gl-sast Report: ", targetFile) - var glSast = new(wrappers.GlSastResultsCollection) - glSast.Vulnerabilities = []wrappers.GlVulnerabilities{} - err := addScanToGlSastReport(summary, glSast) - if err != nil { - return errors.Wrapf(err, "%s: failed to add scan to gl-sast report", failedListingResults) - } - convertCxResultToGlSastVulnerability(results, glSast, summary) - resultsJSON, err := json.Marshal(glSast) - if err != nil { - return errors.Wrapf(err, "%s: failed to serialize gl-sast report ", failedListingResults) - } - f, err := os.Create(targetFile) - if err != nil { - return errors.Wrapf(err, "%s: failed to create target file ", failedListingResults) - } - defer func() { _ = f.Close() }() - _, _ = fmt.Fprintln(f, string(resultsJSON)) - return nil -} - -func exportGlScaResults(targetFile string, results *wrappers.ScanResultsCollection, summary *wrappers.ResultSummary) error { - log.Println("Creating Gl-sca Report: ", targetFile) - glScaResult := &wrappers.GlScaResultsCollection{ - Vulnerabilities: []wrappers.GlScaDepVulnerabilities{}, // Initialize arrays to prevent GitLab schema validation errors. - ScaDependencyFiles: []wrappers.ScaDependencyFile{}, - } - err := addScanToGlScaReport(summary, glScaResult) - if err != nil { - return errors.Wrapf(err, "%s: failed to denerate GL-Sca report ", failedListingResults) - } - convertCxResultToGlScaVulnerability(results, glScaResult) - convertCxResultToGlScaFiles(results, glScaResult) - resultsJSON, err := json.Marshal(glScaResult) - if err != nil { - return errors.Wrapf(err, "%s: failed to serialize GL-Sca report ", failedListingResults) - } - f, err := os.Create(targetFile) - if err != nil { - return errors.Wrapf(err, "%s: failed to create target file ", failedListingResults) - } - defer func() { _ = f.Close() }() - _, _ = fmt.Fprintln(f, string(resultsJSON)) - - return nil -} - -func addScanToGlScaReport(summary *wrappers.ResultSummary, glScaResult *wrappers.GlScaResultsCollection) error { - createdAt, err := time.Parse(summaryCreatedAtLayout, summary.CreatedAt) - if err != nil { - return err - } - - glScaResult.Schema = wrappers.ScaSchema - glScaResult.Version = wrappers.SchemaVersion - glScaResult.Scan.Analyzer.VendorGlSCA.VendorGlname = wrappers.AnalyzerScaID - glScaResult.Scan.Analyzer.Name = wrappers.AnalyzerScaID - glScaResult.Scan.Analyzer.Name = wrappers.AnalyzerScaID - glScaResult.Scan.Analyzer.ID = wrappers.ScannerID - glScaResult.Scan.Scanner.ID = wrappers.ScannerID - glScaResult.Scan.Scanner.Name = wrappers.AnalyzerScaID - glScaResult.Scan.Scanner.VendorGlSCA.VendorGlname = wrappers.AnalyzerScaID - glScaResult.Scan.Status = commonParams.Success - glScaResult.Scan.Type = wrappers.ScannerType - glScaResult.Scan.StartTime = createdAt.Format(glTimeFormat) - glScaResult.Scan.EndTime = createdAt.Format(glTimeFormat) - glScaResult.Scan.Scanner.Name = wrappers.AnalyzerScaID - glScaResult.Scan.Scanner.VersionGlSca = commonParams.Version - glScaResult.Scan.Analyzer.VersionGlSca = commonParams.Version - - return nil -} - -func addScanToGlSastReport(summary *wrappers.ResultSummary, glSast *wrappers.GlSastResultsCollection) error { - createdAt, err := time.Parse(summaryCreatedAtLayout, summary.CreatedAt) - if err != nil { - return err - } - - glSast.Scan = wrappers.ScanGlReport{} - glSast.Schema = wrappers.SastSchema - glSast.Version = wrappers.SastSchemaVersion - glSast.Scan.Analyzer.URL = wrappers.AnalyzerURL - glSast.Scan.Analyzer.Name = wrappers.VendorName - glSast.Scan.Analyzer.Vendor.Name = wrappers.VendorName - glSast.Scan.Analyzer.ID = wrappers.AnalyzerID - glSast.Scan.Scanner.ID = wrappers.AnalyzerID - glSast.Scan.Scanner.Name = wrappers.VendorName - glSast.Scan.Status = commonParams.Success - glSast.Scan.Type = commonParams.SastType - glSast.Scan.StartTime = createdAt.Format(glTimeFormat) - glSast.Scan.EndTime = createdAt.Format(glTimeFormat) - glSast.Scan.Scanner.Vendor.Name = wrappers.VendorName - glSast.Scan.Scanner.Version = commonParams.Version - glSast.Scan.Analyzer.Version = commonParams.Version - - return nil -} -func exportSonarResults(targetFile string, results *wrappers.ScanResultsCollection) error { - var err error - var resultsJSON []byte - log.Println("Creating SONAR Report: ", targetFile) - var sonarResults = convertCxResultsToSonar(results) - resultsJSON, err = json.Marshal(sonarResults) - if err != nil { - return errors.Wrapf(err, "%s: failed to serialize results response ", failedGettingAll) - } - f, err := os.Create(targetFile) - if err != nil { - return errors.Wrapf(err, "%s: failed to create target file ", failedGettingAll) - } - _, _ = fmt.Fprintln(f, string(resultsJSON)) - _ = f.Close() - return nil -} - -// Function to decode HTML entities in the ScanResultsCollection -func decodeHTMLEntitiesInResults(results *wrappers.ScanResultsCollection) { - for _, result := range results.Results { - result.Description = html.UnescapeString(result.Description) - result.DescriptionHTML = html.UnescapeString(result.DescriptionHTML) - for _, node := range result.ScanResultData.Nodes { - node.FullName = html.UnescapeString(node.FullName) - node.Name = html.UnescapeString(node.Name) - } - } -} - -func exportJSONResults(targetFile string, results *wrappers.ScanResultsCollection) error { - decodeHTMLEntitiesInResults(results) - var err error - var resultsJSON []byte - log.Println("Creating JSON Report: ", targetFile) - resultsJSON, err = json.Marshal(results) - if err != nil { - return errors.Wrapf(err, "%s: failed to serialize results response ", failedGettingAll) - } - f, err := os.Create(targetFile) - if err != nil { - return errors.Wrapf(err, "%s: failed to create target file ", failedGettingAll) - } - _, _ = fmt.Fprintln(f, string(resultsJSON)) - _ = f.Close() - return nil -} - -func exportJSONReportResults(jsonWrapper wrappers.ResultsJSONWrapper, summary *wrappers.ResultSummary, summaryRpt string, featureFlagsWrapper wrappers.FeatureFlagsWrapper) error { - jsonReportsPayload := &wrappers.JSONReportsPayload{} - pollingResp := &wrappers.JSONPollingResponse{} - jsonReportsPayload.ReportName = reportNameImprovedScanReport - - jsonOptionsSections, jsonOptionsEngines := parseJSONOptions(summary.EnginesEnabled, jsonReportsPayload.ReportName) - - jsonReportsPayload.ReportType = CliType - jsonReportsPayload.FileFormat = printer.FormatJSON - jsonReportsPayload.Data.ScanID = summary.ScanID - jsonReportsPayload.Data.ProjectID = summary.ProjectID - jsonReportsPayload.Data.BranchName = summary.BranchName - jsonReportsPayload.Data.Scanners = jsonOptionsEngines - jsonReportsPayload.Data.Sections = jsonOptionsSections - - jsonReportID, webErr, err := jsonWrapper.GenerateJSONReport(jsonReportsPayload) - if webErr != nil { - return errors.Errorf("Error generating JSON report - %s", webErr.Message) - } - if err != nil { - return errors.Errorf("Error generating JSON report - %s", err.Error()) - } - log.Println("Generating JSON report") - pollingResp.Status = startedStatus - for pollingResp.Status == startedStatus || pollingResp.Status == requestedStatus { - pollingResp, webErr, err = jsonWrapper.CheckJSONReportStatus(jsonReportID.ReportID) - if err != nil || webErr != nil { - return errors.Wrapf(err, "%v", webErr) - } - logger.PrintfIfVerbose("JSON report status: %s", pollingResp.Status) - time.Sleep(delayValueForReport * time.Millisecond) - } - if pollingResp.Status != completedStatus { - return errors.Errorf("JSON generating failed - Current status: %s", pollingResp.Status) - } - - minioEnabled, _ := wrappers.GetSpecificFeatureFlag(featureFlagsWrapper, wrappers.MinioEnabled) - infoPathType := "" - if minioEnabled.Status { - infoPathType = jsonReportID.ReportID - } else { - infoPathType = pollingResp.URL - } - err = jsonWrapper.DownloadJSONReport(infoPathType, summaryRpt, minioEnabled.Status) - if err != nil { - return errors.Wrapf(err, "%s", "Failed downloading JSON report") - } - return nil -} - -func parseJSONOptions(enabledEngines []string, reportName string) (jsonOptionsSections, jsonOptionsEngines []string) { - jsonOptionsSections = []string{ - sectionScanSummary, - sectionExecutiveSummary, - sectionScanResults, - } - - var jsonOptionsEnginesMap = map[string]string{ - commonParams.ScaType: scaEngineLabel, - commonParams.SastType: sastEngineLabel, - commonParams.KicsType: kicsEngineLabel, - commonParams.IacType: kicsEngineLabel, - commonParams.ContainersType: "Containers", - commonParams.ScsType: "Microengines", - } - if jsonOptionsEngines == nil { - for _, engine := range enabledEngines { - if jsonOptionsEnginesMap[engine] != "" { - jsonOptionsEngines = append(jsonOptionsEngines, jsonOptionsEnginesMap[engine]) - } - } - } - - if reportName == reportNameImprovedScanReport { - jsonOptionsSections = translateReportSectionsForImproved(jsonOptionsSections) - } - - return jsonOptionsSections, jsonOptionsEngines -} - -func exportJSONSummaryResults(targetFile string, results *wrappers.ResultSummary) error { - var err error - var resultsJSON []byte - log.Println("Creating summary JSON Report: ", targetFile) - resultsJSON, err = json.Marshal(results) - if err != nil { - return errors.Wrapf(err, "%s: failed to serialize results response ", failedGettingAll) - } - f, err := os.Create(targetFile) - if err != nil { - return errors.Wrapf(err, "%s: failed to create target file ", failedGettingAll) - } - _, _ = fmt.Fprintln(f, string(resultsJSON)) - _ = f.Close() - return nil -} - -func exportPdfResults(pdfWrapper wrappers.ResultsPdfWrapper, summary *wrappers.ResultSummary, summaryRpt, formatPdfToEmail, - pdfOptions string, featureFlagsWrapper wrappers.FeatureFlagsWrapper) error { - pdfReportsPayload := &wrappers.PdfReportsPayload{} - pollingResp := &wrappers.PdfPollingResponse{} - pdfReportsPayload.ReportName = reportNameImprovedScanReport - pdfOptionsSections, pdfOptionsEngines, err := parsePDFOptions(pdfOptions, summary.EnginesEnabled, pdfReportsPayload.ReportName) - if err != nil { - return err - } - pdfReportsPayload.ReportType = CliType - pdfReportsPayload.FileFormat = printer.FormatPDF - pdfReportsPayload.Data.ScanID = summary.ScanID - pdfReportsPayload.Data.ProjectID = summary.ProjectID - pdfReportsPayload.Data.BranchName = summary.BranchName - pdfReportsPayload.Data.Scanners = pdfOptionsEngines - pdfReportsPayload.Data.Sections = pdfOptionsSections - - // will generate pdf report and send it to the email list - // instead of saving it to the file system - if formatPdfToEmail != "" { - emailList, validateErr := validateEmails(formatPdfToEmail) - if validateErr != nil { - return validateErr - } - pdfReportsPayload.ReportType = reportTypeEmail - pdfReportsPayload.Data.Email = emailList - } - pdfReportID, webErr, err := pdfWrapper.GeneratePdfReport(pdfReportsPayload) - if webErr != nil { - return errors.Errorf("Error generating PDF report - %s", webErr.Message) - } - if err != nil { - return errors.Errorf("Error generating PDF report - %s", err.Error()) - } - if pdfReportsPayload.ReportType == reportTypeEmail { - log.Println("Sending PDF report to: ", pdfReportsPayload.Data.Email) - return nil - } - log.Println("Generating PDF report") - pollingResp.Status = startedStatus - for pollingResp.Status == startedStatus || pollingResp.Status == requestedStatus { - pollingResp, webErr, err = pdfWrapper.CheckPdfReportStatus(pdfReportID.ReportID) - if err != nil || webErr != nil { - return errors.Wrapf(err, "%v", webErr) - } - logger.PrintfIfVerbose("PDF report status: %s", pollingResp.Status) - time.Sleep(delayValueForReport * time.Millisecond) - } - if pollingResp.Status != completedStatus { - return errors.Errorf("PDF generating failed - Current status: %s", pollingResp.Status) - } - - minioEnabled, _ := wrappers.GetSpecificFeatureFlag(featureFlagsWrapper, wrappers.MinioEnabled) - infoPathType := "" - if minioEnabled.Status { - infoPathType = pdfReportID.ReportID - } else { - infoPathType = pollingResp.URL - } - err = pdfWrapper.DownloadPdfReport(infoPathType, summaryRpt, minioEnabled.Status) - if err != nil { - return errors.Wrapf(err, "%s", "Failed downloading PDF report") - } - return nil -} - -func parsePDFOptions(pdfOptions string, enabledEngines []string, reportName string) (pdfOptionsSections, pdfOptionsEngines []string, err error) { - var pdfOptionsSectionsMap = map[string]string{ - "scansummary": sectionScanSummary, - "executivesummary": sectionExecutiveSummary, - "scanresults": sectionScanResults, - } - - var pdfOptionsEnginesMap = map[string]string{ - commonParams.ScaType: scaEngineLabel, - commonParams.SastType: sastEngineLabel, - commonParams.KicsType: kicsEngineLabel, - commonParams.IacType: kicsEngineLabel, - } - - pdfOptions = strings.ToLower(strings.ReplaceAll(pdfOptions, " ", "")) - options := strings.Split(strings.ReplaceAll(pdfOptions, "\n", ""), ",") - for _, s := range options { - if pdfOptionsEnginesMap[s] != "" { - pdfOptionsEngines = append(pdfOptionsEngines, pdfOptionsEnginesMap[s]) - } else if pdfOptionsSectionsMap[s] != "" { - pdfOptionsSections = append(pdfOptionsSections, pdfOptionsSectionsMap[s]) - } else { - return nil, nil, errors.Errorf("report option \"%s\" unavailable", s) - } - } - if pdfOptionsEngines == nil { - for _, engine := range enabledEngines { - if pdfOptionsEnginesMap[engine] != "" { - pdfOptionsEngines = append(pdfOptionsEngines, pdfOptionsEnginesMap[engine]) - } - } - } - - if reportName == reportNameImprovedScanReport { - pdfOptionsSections = translateReportSectionsForImproved(pdfOptionsSections) - } - - return pdfOptionsSections, pdfOptionsEngines, nil -} - -func translateReportSectionsForImproved(sections []string) []string { - var resultSections = make([]string, 0) - - var pdfOptionsSectionsImprovedTranslation = map[string][]string{ - sectionScanSummary: {"scan-information"}, - sectionExecutiveSummary: {"results-overview"}, - sectionScanResults: {"scan-results", "categories", "resolved-results", "vulnerability-details"}, - } - - for _, section := range sections { - if translatedSections := pdfOptionsSectionsImprovedTranslation[section]; translatedSections != nil { - resultSections = append(resultSections, translatedSections...) - } - } - - return resultSections -} - -func convertCxResultsToSarif(results *wrappers.ScanResultsCollection) *wrappers.SarifResultsCollection { - var sarif = new(wrappers.SarifResultsCollection) - sarif.Schema = "https://raw.githubusercontent.com/oasis-tcs/sarif-spec/master/Schemata/sarif-schema-2.1.0.json" - sarif.Version = "2.1.0" - sarif.Runs = []wrappers.SarifRun{} - sarif.Runs = append(sarif.Runs, createSarifRun(results)) - return sarif -} - -func convertCxResultToGlSastVulnerability(results *wrappers.ScanResultsCollection, glSast *wrappers.GlSastResultsCollection, summary *wrappers.ResultSummary) { - for _, result := range results.Results { - if strings.TrimSpace(result.Type) == commonParams.SastType { - glSast = parseGlSastVulnerability(result, glSast, summary) - } - } -} - -func convertCxResultToGlScaVulnerability(results *wrappers.ScanResultsCollection, glScaResult *wrappers.GlScaResultsCollection) { - for _, result := range results.Results { - if strings.TrimSpace(result.Type) == commonParams.ScaType { - glScaResult = parseGlscaVulnerability(result, glScaResult) - } - } -} - -func convertCxResultToGlScaFiles(results *wrappers.ScanResultsCollection, glScaResult *wrappers.GlScaResultsCollection) { - for _, result := range results.Results { - if strings.TrimSpace(result.Type) == commonParams.ScaType { - glScaResult = parseGlScaFiles(result, glScaResult) - } - } -} -func parseGlSastVulnerability(result *wrappers.ScanResult, glSast *wrappers.GlSastResultsCollection, summary *wrappers.ResultSummary) *wrappers.GlSastResultsCollection { - hostName := parseURI(summary.BaseURI) - - queryName := result.ScanResultData.QueryName - fileName := result.ScanResultData.Nodes[0].FileName - lineNumber := strconv.FormatUint(uint64(result.ScanResultData.Nodes[0].Line), 10) - startLine := result.ScanResultData.Nodes[0].Line - endLine := result.ScanResultData.Nodes[0].Line + result.ScanResultData.Nodes[0].Length - ID := fmt.Sprintf("%s:%s:%s", queryName, fileName, lineNumber) - category := fmt.Sprintf("%s-%s", wrappers.VendorName, result.Type) - message := fmt.Sprintf("%s@%s:%s", queryName, fileName, lineNumber) - QueryDescriptionLink := fmt.Sprintf("%s/results/%s/%s/sast/description/%s/%s", hostName, summary.ScanID, summary.ProjectID, result.VulnerabilityDetails.CweID, result.ScanResultData.QueryID) - - glSast.Vulnerabilities = append(glSast.Vulnerabilities, wrappers.GlVulnerabilities{ - ID: ID, - Category: category, - Name: queryName, - Message: message, - Description: result.Description + " \n" + QueryDescriptionLink, - CVE: ID, - Severity: cases.Title(language.English).String(result.Severity), - Confidence: cases.Title(language.English).String(result.Severity), - Solution: "", - - Scanner: wrappers.GlScanner{ - ID: category, - Name: category, - }, - Identifiers: []wrappers.Identifier{ - { - Type: "cxOneScan", - Name: "CxOne Scan", - URL: summary.BaseURI, - Value: result.ID, - }, - }, - Links: make([]string, 0), - Tracking: wrappers.Tracking{ - Type: "source", - Items: []wrappers.Item{ - { - Signatures: []wrappers.Signature{{Algorithm: result.Type + "-Algorithm ", Value: notAvailableValue}}, - File: fileName, - EndLine: endLine, - StartLine: startLine, - }, - }, - }, - Flags: make([]wrappers.Flag, 0), - Location: wrappers.Location{ - File: fileName, - StartLine: startLine, - EndLine: endLine, - }, - }) - return glSast -} -func parseGlscaVulnerability(result *wrappers.ScanResult, glDependencyResult *wrappers.GlScaResultsCollection) *wrappers.GlScaResultsCollection { - if result.ScanResultData.ScaPackageCollection != nil { - glDependencyResult.Vulnerabilities = append(glDependencyResult.Vulnerabilities, wrappers.GlScaDepVulnerabilities{ - ID: result.ID, - Name: result.VulnerabilityDetails.CveName, - Description: result.Description, - Severity: cases.Title(language.English).String(result.Severity), - Solution: result.ScanResultData.RecommendedVersion, - Identifiers: collectScaPackageData(result), - Links: collectScaPackageLinks(result), - TrackingDep: wrappers.TrackingDep{ - Items: collectScaPackageItemsDep(result), - }, - Flags: make([]string, 0), - LocationDep: wrappers.GlScaDepVulnerabilityLocation{ - File: parseGlDependencyLocation(result), - Dependency: wrappers.ScaDependencyLocation{ - Package: wrappers.PackageName{Name: result.ScanResultData.PackageIdentifier}, - ScaDependencyLocationVersion: "", - Direct: result.ScanResultData.ScaPackageCollection.IsDirectDependency, - ScaDependencyPath: result.ScanResultData.Line, - }, - }, - }) - } - return glDependencyResult -} -func parseGlDependencyLocation(result *wrappers.ScanResult) string { - var location string - if result != nil && result.ScanResultData.ScaPackageCollection != nil && result.ScanResultData.ScaPackageCollection.Locations != nil { - location = *result.ScanResultData.ScaPackageCollection.Locations[0] - } else { - location = "" - } - return location -} -func parseGlScaFiles(result *wrappers.ScanResult, glScaResult *wrappers.GlScaResultsCollection) *wrappers.GlScaResultsCollection { - if result.ScanResultData.ScaPackageCollection != nil && result.ScanResultData.ScaPackageCollection.Locations != nil { - glScaResult.ScaDependencyFiles = append(glScaResult.ScaDependencyFiles, wrappers.ScaDependencyFile{ - Path: *result.ScanResultData.ScaPackageCollection.Locations[0], - PackageManager: result.ScanResultData.ScaPackageCollection.ID, - Dependencies: collectScaFileLocations(result), - }) - } - return glScaResult -} -func collectScaFileLocations(result *wrappers.ScanResult) []wrappers.ScaDependencyLocation { - allScaIdentifierLocations := []wrappers.ScaDependencyLocation{} - for _, packageInfo := range result.ScanResultData.PackageData { - allScaIdentifierLocations = append(allScaIdentifierLocations, wrappers.ScaDependencyLocation{ - Package: wrappers.PackageName{ - Name: packageInfo.Type, - }, - ScaDependencyLocationVersion: packageInfo.URL, - Direct: true, - ScaDependencyPath: result.ScanResultData.Line, - }) - } - return allScaIdentifierLocations -} -func collectScaPackageItemsDep(result *wrappers.ScanResult) []wrappers.ItemDep { - allScaPackageItemDep := []wrappers.ItemDep{} - allScaPackageItemDep = append(allScaPackageItemDep, wrappers.ItemDep{ - Signature: []wrappers.SignatureDep{{Algorithm: "SCA-Algorithm ", Value: notAvailableValue}}, - File: result.VulnerabilityDetails.CveName, - EndLine: 0, - StartLine: 0, - }) - return allScaPackageItemDep -} -func collectScaPackageLinks(result *wrappers.ScanResult) []wrappers.LinkDep { - allScaPackageLinks := []wrappers.LinkDep{} - for _, packageInfo := range result.ScanResultData.PackageData { - allScaPackageLinks = append(allScaPackageLinks, wrappers.LinkDep{ - Name: packageInfo.Type, - URL: packageInfo.URL, - }) - } - return allScaPackageLinks -} -func collectScaPackageData(result *wrappers.ScanResult) []wrappers.IdentifierDep { - allIdentifierDep := []wrappers.IdentifierDep{} - for _, packageInfo := range result.ScanResultData.PackageData { - allIdentifierDep = append(allIdentifierDep, wrappers.IdentifierDep{ - Type: packageInfo.Type, - Value: packageInfo.URL, - Name: packageInfo.URL, - }) - } - return allIdentifierDep -} - -func convertCxResultsToSonar(results *wrappers.ScanResultsCollection) *wrappers.ScanResultsSonar { - var sonar = new(wrappers.ScanResultsSonar) - sonar.Issues, sonar.Rules = parseSonar(results) - return sonar -} - -func createSarifRun(results *wrappers.ScanResultsCollection) wrappers.SarifRun { - var sarifRun wrappers.SarifRun - sarifRun.Tool.Driver.Name = wrappers.SarifName - sarifRun.Tool.Driver.Version = wrappers.SarifVersion - sarifRun.Tool.Driver.InformationURI = wrappers.SarifInformationURI - sarifRun.Tool.Driver.Rules, sarifRun.Results = parseResults(results) - return sarifRun -} - -func parseResults(results *wrappers.ScanResultsCollection) ([]wrappers.SarifDriverRule, []wrappers.SarifScanResult) { - var sarifRules = make([]wrappers.SarifDriverRule, 0) - var sarifResults = make([]wrappers.SarifScanResult, 0) - if results != nil { - ruleIds := map[interface{}]bool{} - for _, result := range results.Results { - if rule := findRule(ruleIds, result); rule != nil { - sarifRules = append(sarifRules, *rule) - } - if sarifResult := findResult(result); sarifResult != nil { - sarifResults = append(sarifResults, sarifResult...) - } - } - } - return sarifRules, sarifResults -} - -func parseSonar(results *wrappers.ScanResultsCollection) ([]wrappers.SonarIssues, []wrappers.SonarRules) { - var sonarIssues []wrappers.SonarIssues - var sonarRules []wrappers.SonarRules - seenRuleIDs := make(map[string]bool) // Track already added rule IDs - - if results != nil { - for _, result := range results.Results { - var auxRules = initSonarRules(result) - var auxIssue = initSonarIssue(result) - - if !seenRuleIDs[auxRules.ID] { - sonarRules = append(sonarRules, auxRules) - seenRuleIDs[auxRules.ID] = true - } - - engineType := strings.TrimSpace(result.Type) - - if engineType == commonParams.SastType { - auxIssue.PrimaryLocation = parseSonarPrimaryLocation(result) - auxIssue.SecondaryLocations = parseSonarSecondaryLocations(result) - sonarIssues = append(sonarIssues, auxIssue) - } else if engineType == commonParams.KicsType { - auxIssue.PrimaryLocation = parseLocationKics(result) - sonarIssues = append(sonarIssues, auxIssue) - } else if engineType == commonParams.ScaType { - sonarIssuesByLocation := parseScaSonarLocations(result) - sonarIssues = append(sonarIssues, sonarIssuesByLocation...) - } else if wrappers.IsContainersEnabled && engineType == commonParams.ContainersType { - auxIssue.PrimaryLocation = parseContainersSonar(result) - sonarIssues = append(sonarIssues, auxIssue) - } else if strings.HasPrefix(engineType, commonParams.SscsType) { - sscsSonarIssue := parseSscsSonar(result, &auxIssue) - sonarIssues = append(sonarIssues, sscsSonarIssue) - } - } - } - return sonarIssues, sonarRules -} - -func parseContainersSonar(result *wrappers.ScanResult) wrappers.SonarLocation { - var auxLocation wrappers.SonarLocation - auxLocation.FilePath = result.ScanResultData.ImageFilePath - auxLocation.Message = html.UnescapeString(result.Description) - var textRange wrappers.SonarTextRange - textRange.StartColumn = 1 - textRange.EndColumn = 2 - textRange.StartLine = 1 - textRange.EndLine = 2 - auxLocation.TextRange = textRange - return auxLocation -} - -func parseSscsSonar(result *wrappers.ScanResult, sonarIssue *wrappers.SonarIssues) wrappers.SonarIssues { - sonarIssue.PrimaryLocation.FilePath = result.ScanResultData.Filename - - sonarIssue.PrimaryLocation.Message = html.UnescapeString(result.ScanResultData.Remediation) - var textRange wrappers.SonarTextRange - textRange.StartColumn = 1 - textRange.EndColumn = 2 - textRange.StartLine = result.ScanResultData.Line - sonarIssue.PrimaryLocation.TextRange = textRange - return *sonarIssue -} - -func initSonarIssue(result *wrappers.ScanResult) wrappers.SonarIssues { - var sonarIssue wrappers.SonarIssues - engineType := strings.TrimSpace(result.Type) - if engineType == commonParams.SastType { - sonarIssue.RuleID = result.ScanResultData.LanguageName + " - " + result.ScanResultData.QueryName - } else if engineType == commonParams.KicsType { - sonarIssue.RuleID = result.ScanResultData.QueryName - } else if engineType == commonParams.ScaType { - sonarIssue.RuleID = result.ID - } else if wrappers.IsContainersEnabled && engineType == commonParams.ContainersType { - sonarIssue.RuleID = result.ID - } else if strings.HasPrefix(engineType, commonParams.SscsType) { - sonarIssue.RuleID = result.ID - } - - sonarIssue.PrimaryLocation.Message = html.UnescapeString(result.Description) - sonarIssue.EffortMinutes = 0 - - return sonarIssue -} - -func initSonarRules(result *wrappers.ScanResult) wrappers.SonarRules { - var sonarRules wrappers.SonarRules - var sonarImpacts wrappers.SonarImpacts - - sonarImpacts.Severity = sonarSeverities[result.Severity] - sonarImpacts.SoftwareQuality = vulnerabilitySonar - - sonarRules.EngineID = result.Type - sonarRules.CleanCodeAttribute = cleanCodeAttribute - - engineType := strings.TrimSpace(result.Type) - if engineType == commonParams.SastType { - sonarRules.Name = result.ScanResultData.QueryName - sonarRules.Description = html.UnescapeString(result.Description) - sonarRules.ID = result.ScanResultData.LanguageName + " - " + result.ScanResultData.QueryName - } else if engineType == commonParams.KicsType { - sonarRules.Name = result.ScanResultData.QueryName - sonarRules.Description = html.UnescapeString(result.Description) - sonarRules.ID = result.ScanResultData.QueryName - } else if engineType == commonParams.ScaType { - sonarRules.Name = result.ScanResultData.PackageIdentifier - sonarRules.Description = html.UnescapeString(result.Description) - sonarRules.ID = result.ID - } else if wrappers.IsContainersEnabled && engineType == commonParams.ContainersType { - sonarRules.Name = result.ScanResultData.ImageTag - sonarRules.Description = html.UnescapeString(result.Description) - sonarRules.ID = result.ID - } else if strings.HasPrefix(engineType, commonParams.SscsType) { - sonarRules.Name = result.ScanResultData.RuleName - sonarRules.Description = html.UnescapeString(result.ScanResultData.RuleDescription) - sonarRules.ID = result.ID - } - - sonarRules.Impacts = []wrappers.SonarImpacts{sonarImpacts} - - return sonarRules -} - -func parseScaSonarLocations(result *wrappers.ScanResult) []wrappers.SonarIssues { - if result == nil || result.ScanResultData.ScaPackageCollection == nil || result.ScanResultData.ScaPackageCollection.Locations == nil { - return []wrappers.SonarIssues{} - } - - var issuesByLocation []wrappers.SonarIssues - - for _, location := range result.ScanResultData.ScaPackageCollection.Locations { - issueByLocation := initSonarIssue(result) - - var primaryLocation wrappers.SonarLocation - - primaryLocation.FilePath = *location - _, _, primaryLocation.Message = findRuleID(result) - - var textRange wrappers.SonarTextRange - textRange.StartColumn = 1 - textRange.EndColumn = 2 - textRange.StartLine = 1 - textRange.EndLine = 2 - - primaryLocation.TextRange = textRange - - issueByLocation.PrimaryLocation = primaryLocation - - issuesByLocation = append(issuesByLocation, issueByLocation) - } - - return issuesByLocation -} - -func parseLocationKics(results *wrappers.ScanResult) wrappers.SonarLocation { - var auxLocation wrappers.SonarLocation - auxLocation.FilePath = strings.TrimLeft(results.ScanResultData.Filename, "/") - auxLocation.Message = html.UnescapeString(results.ScanResultData.Value) - var auxTextRange wrappers.SonarTextRange - auxTextRange.StartLine = results.ScanResultData.Line - auxTextRange.StartColumn = 0 - auxTextRange.EndColumn = 1 - auxLocation.TextRange = auxTextRange - return auxLocation -} - -func parseSonarPrimaryLocation(results *wrappers.ScanResult) wrappers.SonarLocation { - var auxLocation wrappers.SonarLocation - // fill the details in the primary Location - if len(results.ScanResultData.Nodes) > 0 { - auxLocation.FilePath = strings.TrimLeft(results.ScanResultData.Nodes[0].FileName, "/") - auxLocation.Message = html.UnescapeString(strings.ReplaceAll(results.ScanResultData.QueryName, "_", " ")) - auxLocation.TextRange = parseSonarTextRange(results.ScanResultData.Nodes[0]) - } - return auxLocation -} - -func parseSonarSecondaryLocations(results *wrappers.ScanResult) []wrappers.SonarLocation { - var auxSecondaryLocations []wrappers.SonarLocation - // Traverse all the rest of the scan result nodes into secondary location of sonar - if len(results.ScanResultData.Nodes) >= 1 { - for _, node := range results.ScanResultData.Nodes[1:] { - var auxSecondaryLocation wrappers.SonarLocation - auxSecondaryLocation.FilePath = strings.TrimLeft(node.FileName, "/") - auxSecondaryLocation.Message = html.UnescapeString(strings.ReplaceAll(results.ScanResultData.QueryName, "_", " ")) - auxSecondaryLocation.TextRange = parseSonarTextRange(node) - auxSecondaryLocations = append(auxSecondaryLocations, auxSecondaryLocation) - } - } - return auxSecondaryLocations -} - -func parseSonarTextRange(results *wrappers.ScanResultNode) wrappers.SonarTextRange { - var auxTextRange wrappers.SonarTextRange - auxTextRange.StartLine = results.Line - startColumn := getSastStartColumn(results.Column) - - auxTextRange.StartColumn = startColumn - auxTextRange.EndColumn = startColumn + results.Length - - if auxTextRange.StartColumn == auxTextRange.EndColumn { - auxTextRange.EndColumn++ - } - - return auxTextRange -} - -func findRule(ruleIds map[interface{}]bool, result *wrappers.ScanResult) *wrappers.SarifDriverRule { - var sarifRule wrappers.SarifDriverRule - sarifRule.ID, sarifRule.Name, _ = findRuleID(result) - sarifRule.FullDescription = findFullDescription(result) - sarifRule.Help = findHelp(result) - sarifRule.HelpURI = findHelpURI(result) - sarifRule.Properties = findProperties(result) - - if !ruleIds[sarifRule.ID] { - ruleIds[sarifRule.ID] = true - return &sarifRule - } - - return nil -} - -func getSastStartColumn(column uint) uint { - if column == 0 { - return 0 - } - return column - 1 -} - -func findRuleID(result *wrappers.ScanResult) (ruleID, ruleName, shortMessage string) { - caser := cases.Title(language.English) - - if result.ScanResultData.QueryID == nil && result.ScanResultData.RuleID == nil { - return fmt.Sprintf("%s (%s)", result.ID, result.Type), - caser.String(strings.ToLower(strings.ReplaceAll(result.ID, "-", ""))), - html.UnescapeString(fmt.Sprintf("%s (%s)", result.ScanResultData.PackageIdentifier, result.ID)) - } - - if result.ScanResultData.RuleID != nil { - ruleName = strings.ReplaceAll(result.ScanResultData.RuleName, "_", " ") - return fmt.Sprintf("%s - %s (%s)", ruleName, *result.ScanResultData.RuleID, result.Type), - ruleName, - ruleName - } - - ruleName = strings.ReplaceAll(result.ScanResultData.QueryName, "_", " ") - return fmt.Sprintf("%v - %s (%s)", ruleName, result.ScanResultData.QueryID, result.Type), - ruleName, - ruleName -} - -func findFullDescription(result *wrappers.ScanResult) wrappers.SarifDescription { - var sarifDescription wrappers.SarifDescription - sarifDescription.Text = findDescriptionText(result) - return sarifDescription -} - -func findHelp(result *wrappers.ScanResult) wrappers.SarifHelp { - var sarifHelp wrappers.SarifHelp - sarifHelp.Text = findHelpText(result) - sarifHelp.Markdown = findHelpMarkdownText(result) - - return sarifHelp -} - -func findHelpURI(result *wrappers.ScanResult) string { - if strings.HasPrefix(result.Type, commonParams.SscsType) { - if result.ScanResultData.RemediationLink != "" { - return result.ScanResultData.RemediationLink - } - } - - return wrappers.SarifInformationURI -} - -func findDescriptionText(result *wrappers.ScanResult) string { - if result.Type == commonParams.KicsType { - return fmt.Sprintf( - "%s Value: %s Excepted value: %s", - result.Description, result.ScanResultData.Value, result.ScanResultData.ExpectedValue, - ) - } else if strings.HasPrefix(result.Type, commonParams.SscsType) { - return result.ScanResultData.RuleDescription - } - - return result.Description -} - -func findHelpText(result *wrappers.ScanResult) string { - if strings.HasPrefix(result.Type, commonParams.SscsType) { - return findHelpMarkdownText(result) - } - - return findDescriptionText(result) -} - -func findHelpMarkdownText(result *wrappers.ScanResult) string { - if result.Type == commonParams.KicsType { - return fmt.Sprintf( - "%s

Value: %s
Excepted value: %s", - result.Description, result.ScanResultData.Value, result.ScanResultData.ExpectedValue, - ) - } else if strings.HasPrefix(result.Type, commonParams.SscsType) { - return result.ScanResultData.Remediation - } - - return result.Description -} - -func findProperties(result *wrappers.ScanResult) wrappers.SarifProperties { - var sarifProperties wrappers.SarifProperties - sarifProperties.ID, sarifProperties.Name, _ = findRuleID(result) - sarifProperties.Description = findDescriptionText(result) - sarifProperties.SecuritySeverity = securities[result.Severity] - sarifProperties.Tags = []string{"security", "checkmarx", result.Type} - return sarifProperties -} - -func findSarifLevel(result *wrappers.ScanResult) string { - level := map[string]string{ - infoCx: infoLowSarif, - lowCx: infoLowSarif, - mediumCx: mediumSarif, - highCx: highSarif, - criticalCx: highSarif, - } - return level[result.Severity] -} - -func initSarifResult(result *wrappers.ScanResult) wrappers.SarifScanResult { - var scanResult wrappers.SarifScanResult - scanResult.RuleID, _, scanResult.Message.Text = findRuleID(result) - scanResult.Level = findSarifLevel(result) - scanResult.Locations = []wrappers.SarifLocation{} - - return scanResult -} - -func findResult(result *wrappers.ScanResult) []wrappers.SarifScanResult { - var scanResults []wrappers.SarifScanResult - - if len(result.ScanResultData.Nodes) > 0 { - scanResults = parseSarifResultSast(result, scanResults) - } else if result.Type == commonParams.KicsType { - scanResults = parseSarifResultKics(result, scanResults) - } else if result.Type == commonParams.ScaType { - scanResults = parseSarifResultsSca(result, scanResults) - } else if result.Type == commonParams.ContainersType && wrappers.IsContainersEnabled { - scanResults = parseSarifResultsContainers(result, scanResults) - } else if strings.HasPrefix(result.Type, commonParams.SscsType) { - scanResults = parseSarifResultsSscs(result, scanResults) - } - - if len(scanResults) > 0 { - return scanResults - } - return nil -} - -func parseSarifResultsContainers(result *wrappers.ScanResult, scanResults []wrappers.SarifScanResult) []wrappers.SarifScanResult { - var scanResult = initSarifResult(result) - var scanLocation wrappers.SarifLocation - - scanLocation.PhysicalLocation.ArtifactLocation.URI = result.ScanResultData.ImageFilePath - scanLocation.PhysicalLocation.Region = &wrappers.SarifRegion{} - scanLocation.PhysicalLocation.Region.StartLine = 1 - scanLocation.PhysicalLocation.Region.StartColumn = 1 - scanLocation.PhysicalLocation.Region.EndColumn = 2 - scanResult.Locations = append(scanResult.Locations, scanLocation) - - scanResults = append(scanResults, scanResult) - return scanResults -} - -func parseSarifResultsSca(result *wrappers.ScanResult, scanResults []wrappers.SarifScanResult) []wrappers.SarifScanResult { - if result == nil || result.ScanResultData.ScaPackageCollection == nil || result.ScanResultData.ScaPackageCollection.Locations == nil { - return scanResults - } - for _, location := range result.ScanResultData.ScaPackageCollection.Locations { - var scanResult = initSarifResult(result) - - var scanLocation wrappers.SarifLocation - scanLocation.PhysicalLocation.ArtifactLocation.URI = *location - scanLocation.PhysicalLocation.Region = &wrappers.SarifRegion{} - scanLocation.PhysicalLocation.Region.StartLine = 1 - scanLocation.PhysicalLocation.Region.StartColumn = 1 - scanLocation.PhysicalLocation.Region.EndColumn = 2 - scanResult.Locations = append(scanResult.Locations, scanLocation) - - scanResults = append(scanResults, scanResult) - } - return scanResults -} - -func parseSarifResultKics(result *wrappers.ScanResult, scanResults []wrappers.SarifScanResult) []wrappers.SarifScanResult { - var scanResult = initSarifResult(result) - var scanLocation wrappers.SarifLocation - - scanLocation.PhysicalLocation.ArtifactLocation.URI = strings.Replace( - result.ScanResultData.Filename, - "/", - "", - 1, - ) - scanLocation.PhysicalLocation.Region = &wrappers.SarifRegion{} - scanLocation.PhysicalLocation.Region.StartLine = result.ScanResultData.Line - scanLocation.PhysicalLocation.Region.StartColumn = 1 - scanLocation.PhysicalLocation.Region.EndColumn = 2 - scanResult.Locations = append(scanResult.Locations, scanLocation) - - scanResults = append(scanResults, scanResult) - return scanResults -} - -func parseSarifResultSast(result *wrappers.ScanResult, scanResults []wrappers.SarifScanResult) []wrappers.SarifScanResult { - if result == nil || result.ScanResultData.Nodes == nil { - return scanResults - } - var scanResult = initSarifResult(result) - - var allLocations []wrappers.SarifLocation - for _, node := range result.ScanResultData.Nodes { - var scanLocation wrappers.SarifLocation - if len(node.FileName) >= sarifNodeFileLength { - scanLocation.PhysicalLocation.ArtifactLocation.URI = node.FileName[1:] - if node.Line <= 0 { - continue - } - scanLocation.PhysicalLocation.Region = &wrappers.SarifRegion{} - scanLocation.PhysicalLocation.Region.StartLine = node.Line - column := node.Column - length := node.Length - scanLocation.PhysicalLocation.Region.StartColumn = column - scanLocation.PhysicalLocation.Region.EndColumn = column + length - - allLocations = append(allLocations, scanLocation) - } - } - - if len(allLocations) > 0 { - var threadFlowLocations []wrappers.SarifThreadFlowLocation - for _, loc := range allLocations { - threadFlowLocations = append(threadFlowLocations, wrappers.SarifThreadFlowLocation{Location: loc}) - } - scanResult.CodeFlows = []wrappers.SarifCodeFlow{ - { - ThreadFlows: []wrappers.SarifThreadFlow{ - { - Locations: threadFlowLocations, - }, - }, - }, - } - } - - scanResults = append(scanResults, scanResult) - return scanResults -} - -func parseSarifResultsSscs(result *wrappers.ScanResult, scanResults []wrappers.SarifScanResult) []wrappers.SarifScanResult { - var scanResult = initSarifResult(result) - scanResult.Message.Text = result.Description - - var scanLocation wrappers.SarifLocation - - trimOsSeparatorFromFileName(result) - if result.Type == commonParams.SCSScorecardType && result.ScanResultData.Filename == noFileForScorecardResultString { - scanLocation.PhysicalLocation.ArtifactLocation.URI = artifactLocationURIString - scanLocation.PhysicalLocation.ArtifactLocation.Description = &wrappers.SarifMessage{} - scanLocation.PhysicalLocation.ArtifactLocation.Description.Text = result.ScanResultData.Filename - } else { - scanLocation.PhysicalLocation.ArtifactLocation.URI = result.ScanResultData.Filename - } - - scanLocation.PhysicalLocation.Region = &wrappers.SarifRegion{} - scanLocation.PhysicalLocation.Region.StartLine = result.ScanResultData.Line - scanLocation.PhysicalLocation.Region.StartColumn = 1 - scanLocation.PhysicalLocation.Region.EndColumn = 2 - if result.ScanResultData.Snippet != "" { - scanLocation.PhysicalLocation.Region.Snippet = &wrappers.SarifSnippet{} - scanLocation.PhysicalLocation.Region.Snippet.Text = result.ScanResultData.Snippet - } - - scanResult.Locations = append(scanResult.Locations, scanLocation) - - var properties wrappers.SarifResultProperties - properties.Severity = result.Severity - properties.Validity = result.ScanResultData.Validity - properties.IsInSource = result.ScanResultData.IsInSource - properties.CommitURL = result.ScanResultData.CommitURL - scanResult.Properties = &properties - - scanResults = append(scanResults, scanResult) - return scanResults -} - -func convertNotAvailableNumberToZero(summary *wrappers.ResultSummary) { - if summary.KicsIssues == notAvailableNumber { - summary.KicsIssues = 0 - } else if summary.SastIssues == notAvailableNumber { - summary.SastIssues = 0 - } else if summary.ScaIssues == notAvailableNumber { - summary.ScaIssues = 0 - } else if wrappers.IsContainersEnabled && *summary.ContainersIssues == notAvailableNumber { - *summary.ContainersIssues = 0 - } -} - -func buildAuxiliaryScaMaps(resultsModel *wrappers.ScanResultsCollection, scaPackageModel *[]wrappers.ScaPackageCollection, - scaTypeModel *[]wrappers.ScaTypeCollection) (locationsByID map[string][]*string, typesByCVE map[string]wrappers.ScaTypeCollection) { - locationsByID = make(map[string][]*string) - typesByCVE = make(map[string]wrappers.ScaTypeCollection) - // Create map to be used to populate locations for each package path - for _, result := range resultsModel.Results { - if result.Type == commonParams.ScaType { - for i := range *scaPackageModel { - pkg := &(*scaPackageModel)[i] - locationsByID[pkg.ID] = pkg.Locations - } - for _, types := range *scaTypeModel { - identifier := fmt.Sprintf("%s:%s", types.ID, types.PackageID) - typesByCVE[identifier] = types - } - } - } - return locationsByID, typesByCVE -} - -func buildScaType(typesByCVE map[string]wrappers.ScaTypeCollection, result *wrappers.ScanResult) string { - identifier := buildVulnerabilityIdentifier(result) - types, ok := typesByCVE[identifier] - if ok && types.Type == "SupplyChain" { - return "Supply Chain" - } - return "Vulnerability" -} - -func buildScaState(typesByCVE map[string]wrappers.ScaTypeCollection, result *wrappers.ScanResult) string { - identifier := buildVulnerabilityIdentifier(result) - types, ok := typesByCVE[identifier] - if ok && types.IsIgnored { - return notExploitable - } - return result.State -} - -func buildVulnerabilityIdentifier(result *wrappers.ScanResult) string { - return fmt.Sprintf("%s:%s", result.ID, result.ScanResultData.PackageIdentifier) -} - -func addPackageInformation( - resultsModel *wrappers.ScanResultsCollection, - scaPackageModel *[]wrappers.ScaPackageCollection, - scaTypeModel *[]wrappers.ScaTypeCollection, -) *wrappers.ScanResultsCollection { - locationsByID, typesByCVE := buildAuxiliaryScaMaps(resultsModel, scaPackageModel, scaTypeModel) - scaPackageMap := buildScaPackageMap(*scaPackageModel) - - for _, result := range resultsModel.Results { - if result.Type == commonParams.ScaType { - processResult(result, locationsByID, typesByCVE, scaPackageMap) - } - } - - return resultsModel -} - -func processResult( - result *wrappers.ScanResult, - locationsByID map[string][]*string, - typesByCVE map[string]wrappers.ScaTypeCollection, - scaPackageMap map[string]wrappers.ScaPackageCollection, // Updated parameter -) { - const precision = 1 - - currentID := result.ScanResultData.PackageIdentifier - result.VulnerabilityDetails.CvssScore = util.RoundFloat(result.VulnerabilityDetails.CvssScore, precision) - result.ScaType = buildScaType(typesByCVE, result) - result.State = buildScaState(typesByCVE, result) - - updatePackages(result, scaPackageMap, locationsByID, currentID) -} - -func updatePackages( - result *wrappers.ScanResult, - scaPackageMap map[string]wrappers.ScaPackageCollection, - locationsByID map[string][]*string, - currentID string, -) { - packages, found := scaPackageMap[currentID] - if !found { - return - } - - updateDependencyPaths(packages.DependencyPathArray, locationsByID) - if !packages.SupportsQuickFix { - packages.SupportsQuickFix = hasQuickFix(packages.DependencyPathArray) - } - - if packages.IsDirectDependency { - packages.TypeOfDependency = directDependencyType - } else { - packages.TypeOfDependency = indirectDependencyType - } - - packages.FixLink = buildFixLink(result) - result.ScanResultData.ScaPackageCollection = &packages -} - -func hasQuickFix(dependencyPaths [][]wrappers.DependencyPath) bool { - for i := range dependencyPaths { - head := &dependencyPaths[i][0] - if head.SupportsQuickFix { - return true - } - } - return false -} - -func buildScaPackageMap(scaPackageModel []wrappers.ScaPackageCollection) map[string]wrappers.ScaPackageCollection { - scaPackageMap := make(map[string]wrappers.ScaPackageCollection) - for i := range scaPackageModel { - scaPackageMap[scaPackageModel[i].ID] = scaPackageModel[i] - } - return scaPackageMap -} - -func updateDependencyPaths(dependencyPaths [][]wrappers.DependencyPath, locationsByID map[string][]*string) { - for i := range dependencyPaths { - head := &dependencyPaths[i][0] - head.Locations = locationsByID[head.ID] - head.SupportsQuickFix = len(dependencyPaths[i]) == 1 - - for _, location := range locationsByID[head.ID] { - head.SupportsQuickFix = head.SupportsQuickFix && util.IsPackageFileSupported(*location) - } - } -} - -func buildFixLink(result *wrappers.ScanResult) string { - if result.ID != "" { - return fmt.Sprint(fixLinkPrefix, result.ID) - } - return "" -} - -func filterViolatedRules(policyModel wrappers.PolicyResponseModel) *wrappers.PolicyResponseModel { - i := 0 - for _, policy := range policyModel.Policies { - if len(policy.RulesViolated) > 0 { - policyModel.Policies[i] = policy - i++ - } - } - policyModel.Policies = policyModel.Policies[:i] - return &policyModel -} - -func trimOsSeparatorFromFileName(result *wrappers.ScanResult) { - if result.ScanResultData.Filename != "" { - result.ScanResultData.Filename = strings.TrimPrefix(result.ScanResultData.Filename, "/") - result.ScanResultData.Filename = strings.TrimPrefix(result.ScanResultData.Filename, "\\") - } -} - -// ScannerResponse is the per-scanner status info returned by the results exit-code subcommand. -type ScannerResponse struct { - ScanID string `json:"ScanID,omitempty"` - Name string `json:"Name,omitempty"` - Status string `json:"Status,omitempty"` - Details string `json:"Details,omitempty"` - ErrorCode string `json:"ErrorCode,omitempty"` -} - -func parseURI(summaryBaseURI string) (hostName string) { - parsedURL, err := url.Parse(summaryBaseURI) - if err != nil { - return "" - } - hostName = fmt.Sprintf("%s://%s", parsedURL.Scheme, parsedURL.Host) - - return hostName -} - -func printWarningIfIgnorePolicyOmiited() { - fmt.Printf("\n Warning: The --ignore-policy flag was not implemented because you don't have the required permission.\n Only users with 'override-policy-management' permission can use this flag. \n\n") -} - -func getFilterResultsForAPISecScanner(risksOverviewWrapper wrappers.RisksOverviewWrapper, scanID string, resultsParams map[string]string) (aPISecSeveritySummary *wrappers.APISecFilteredResult, err error) { - var apiSecRiskEntriesResult wrappers.APISecRiskEntriesResult - var errorModel *wrappers.WebError - - apiSecRiskEntriesResult, errorModel, err = risksOverviewWrapper.GetFilterResultForAPISecByScanID(scanID, resultsParams) - if err != nil { - return nil, errors.Wrapf(err, "%s", failedListingResults) - } - if errorModel != nil { - return nil, errors.Errorf("%s: CODE: %d, %s", failedListingResults, errorModel.Code, errorModel.Message) - } - if len(apiSecRiskEntriesResult.Entries) > 0 { - entries := apiSecRiskEntriesResult.Entries - severityCount := make(map[string]int) - originCount := make(map[string]int) - totalRecords := 0 - for i := range entries { - entry := &entries[i] - if !isExploitable(entry.State) { - continue - } - sev := strings.ToLower(entry.Severity) - severityCount[sev]++ - orig := strings.ToLower(entry.Origin) - originCount[orig]++ - totalRecords++ - } - var riskDistribution []wrappers.RiskDistributionEntry - if originCount[originCode] > 0 { - riskDistribution = append(riskDistribution, wrappers.RiskDistributionEntry{Origin: originCode, Total: originCount[originCode]}) - } - if originCount[originDocumentation] > 0 { - riskDistribution = append(riskDistribution, wrappers.RiskDistributionEntry{Origin: originDocumentation, Total: originCount[originDocumentation]}) - } - return &wrappers.APISecFilteredResult{ - SeverityCount: severityCount, - RiskDistribution: riskDistribution, - TotalRisksCount: totalRecords, - }, nil - } - return nil, nil -} +package commands + +import ( + "encoding/json" + "fmt" + "html" + "log" + "net/url" + "os" + "path/filepath" + "regexp" + "slices" + "strconv" + "strings" + "text/template" + "time" + + "github.com/MakeNowJust/heredoc" + "github.com/checkmarx/ast-cli/internal/commands/util" + "github.com/checkmarx/ast-cli/internal/commands/util/printer" + errorConstants "github.com/checkmarx/ast-cli/internal/constants/errors" + "github.com/checkmarx/ast-cli/internal/logger" + "github.com/checkmarx/ast-cli/internal/services" + "github.com/checkmarx/ast-cli/internal/wrappers" + "github.com/checkmarx/ast-cli/internal/wrappers/utils" + "golang.org/x/text/cases" + "golang.org/x/text/language" + + commonParams "github.com/checkmarx/ast-cli/internal/params" + + "github.com/pkg/errors" + "github.com/spf13/cobra" +) + +const ( + failedCreatingSummary = "Failed creating summary" + failedGettingScan = "Failed getting scan" + failedListingResults = "Failed listing results" + failedListingCodeBashing = "Failed codebashing link" + mediumLabel = "medium" + criticalLabel = "critical" + highLabel = "high" + lowLabel = "low" + infoLabel = "info" + sonarTypeLabel = "_sonar" + glSastTypeLabel = ".gl-sast-report" + glScaTypeLabel = ".gl-sca-report" + directoryPermission = 0700 + infoSonar = "INFO" + lowSonar = "LOW" + mediumSonar = "MEDIUM" + highSonar = "HIGH" + criticalSonar = "BLOCKER" + infoLowSarif = "note" + mediumSarif = "warning" + highSarif = "error" + vulnerabilitySonar = "SECURITY" + cleanCodeAttribute = "FORMATTED" + infoCx = "INFO" + lowCx = "LOW" + mediumCx = "MEDIUM" + highCx = "HIGH" + criticalCx = "CRITICAL" + tableResultsFormat = " | %-10s %6v %5d %6d %5d %4d %-9s |\n" + stringTableResultsFormat = " | %-10s %5s %6s %6s %5s %4s %5s |\n" + // TableTitleFormat is the printf format string for the scan results summary table title row. + TableTitleFormat = " | %-11s %4s %4s %6s %4s %4s %6s |\n" + twoNewLines = "\n\n" + tableLine = " --------------------------------------------------------------------- " + codeBashingKey = "cb-url" + failedGettingBfl = "Failed getting BFL" + notAvailableString = "-" + disabledString = "N/A" + scanFailedString = "Failed " + scanCanceledString = "Canceled" + scanSuccessString = "Completed" + scanPartialString = "Partial" + scsScanUnavailableString = "" + notAvailableNumber = -1 + scanFailedNumber = -2 + scanCanceledNumber = -3 + scanPartialNumber = -4 + defaultPaddingSize = -13 + scanPendingMessage = "Scan triggered in asynchronous mode or still running. Click more details to get the full status." + directDependencyType = "Direct Dependency" + indirectDependencyType = "Transitive Dependency" + startedStatus = "started" + requestedStatus = "requested" + completedStatus = "completed" + pdfToEmailFlagDescription = "Send the PDF report to the specified email address." + + " Use \",\" as the delimiter for multiple emails" + pdfOptionsFlagDescription = "Sections to generate PDF report. Available options: Iac-Security,Sast,Sca," + + defaultPdfOptionsDataSections + sbomReportFlagDescription = "Sections to generate SBOM report. Available options: CycloneDxJson,CycloneDxXml,SpdxJson" + reportNameScanReport = "scan-report" + reportNameImprovedScanReport = "improved-scan-report" + reportTypeEmail = "email" + defaultPdfOptionsDataSections = "ScanSummary,ExecutiveSummary,ScanResults" + exploitablePathFlagDescription = "Enable or disable exploitable path in scan. Available options: true,false" + scaLastScanTimeFlagDescription = "SCA last scan time. Available options: integer above 1" + projectPrivatePackageFlagDescription = "Enable or disable project private package. Available options: true,false" + scaPrivatePackageVersionFlagDescription = "SCA project private package version. Example: 0.1.1" + scaHideDevAndTestDepFlagDescription = "Filter SCA results to exclude dev and test dependencies" + policeManagementNoneStatus = "none" + apiDocumentationFlagDescription = "Swagger folder/file filter for API-Security scan. Example: ./swagger.json" + summaryCreatedAtLayout = "2006-01-02, 15:04:05" + glTimeFormat = "2006-01-02T15:04:05" + sarifNodeFileLength = 2 + fixLabel = "fix" + redundantLabel = "redundant" + delayValueForReport = 10 + fixLinkPrefix = "https://devhub.checkmarx.com/cve-details/" + // ScaDevAndTestExclusionParam is the SCA exclude-result-types value used to filter out dev and test dependencies. + ScaDevAndTestExclusionParam = "DEV_AND_TEST" + // ScaExcludeResultTypesParam is the SCA query parameter name used to exclude specific result types. + ScaExcludeResultTypesParam = "exclude-result-types" + noFileForScorecardResultString = "Issue Found in your GitHub repository" + // CliType identifies the report type used when generating reports through the CLI. + CliType = "cli" + artifactLocationURIString = "This alert has no associated file" + commandDocAnnotation = "command:doc" + showSubCommand = "show" + sectionScanSummary = "ScanSummary" + sectionExecutiveSummary = "ExecutiveSummary" + sectionScanResults = "ScanResults" + scaEngineLabel = "SCA" + sastEngineLabel = "SAST" + kicsEngineLabel = "KICS" + notAvailableValue = "NA" + originCode = "code" + originDocumentation = "documentation" + statusCompleted = "Completed" + statusPartial = "Partial" + statusFailed = "Failed" +) + +var ( + summaryFormats = []string{ + printer.FormatSummaryConsole, + printer.FormatSummary, + printer.FormatSummaryJSON, + printer.FormatPDF, + printer.FormatSummaryMarkdown, + printer.FormatSbom, + printer.FormatGLSast, + printer.FormatGLSca, + printer.FormatSonar, + } + + filterResultsListFlagUsage = fmt.Sprintf( + "Filter the list of results. Use ';' as the delimiter for arrays. Available filters are: %s", + strings.Join( + []string{ + commonParams.ScanIDQueryParam, + commonParams.LimitQueryParam, + commonParams.OffsetQueryParam, + commonParams.SortQueryParam, + commonParams.IncludeNodesQueryParam, + commonParams.NodeIDsQueryParam, + commonParams.QueryQueryParam, + commonParams.GroupQueryParam, + commonParams.StatusQueryParam, + commonParams.SeverityQueryParam, + commonParams.StateQueryParam, + }, ",", + ), + ) + + // Follows: over 9.0 is critical, 7.0 to 8.9 is high, 4.0 to 6.9 is medium and 3.9 or less is low. + securities = map[string]string{ + infoCx: "1.0", + lowCx: "2.0", + mediumCx: "4.0", + highCx: "7.0", + criticalCx: "9.0", + } + + // Match cx severity with sonar severity + sonarSeverities = map[string]string{ + infoCx: infoSonar, + lowCx: lowSonar, + mediumCx: mediumSonar, + highCx: highSonar, + criticalCx: criticalSonar, + } + + containerEngineUnsupportedAgents = []string{ + commonParams.JetbrainsAgent, commonParams.VSCodeAgent, commonParams.VisualStudioAgent, commonParams.EclipseAgent, + } + + sscsEngineToOverviewEngineMap = map[string]string{ + commonParams.SCSScorecardType: commonParams.SCSScorecardOverviewType, + commonParams.SCSSecretDetectionType: commonParams.SCSSecretDetectionOverviewType, + } +) + +// NewResultsCommand returns the `results` Cobra command tree with all subcommands attached. +func NewResultsCommand( + resultsWrapper wrappers.ResultsWrapper, + scanWrapper wrappers.ScansWrapper, + exportWrapper wrappers.ExportWrapper, + resultsPdfReportsWrapper wrappers.ResultsPdfWrapper, + resultsJSONReportsWrapper wrappers.ResultsJSONWrapper, + codeBashingWrapper wrappers.CodeBashingWrapper, + bflWrapper wrappers.BflWrapper, + risksOverviewWrapper wrappers.RisksOverviewWrapper, + riskManagementWrapper wrappers.RiskManagementWrapper, + scsScanOverviewWrapper wrappers.ScanOverviewWrapper, + policyWrapper wrappers.PolicyWrapper, + featureFlagsWrapper wrappers.FeatureFlagsWrapper, + jwtWrapper wrappers.JWTWrapper, +) *cobra.Command { + resultCmd := &cobra.Command{ + Use: "results", + Short: "Retrieve results", + Annotations: map[string]string{ + commandDocAnnotation: heredoc.Doc( + ` + https://checkmarx.com/resource/documents/en/34965-68640-results.html + `, + ), + }, + } + showResultCmd := resultShowSubCommand(resultsWrapper, scanWrapper, exportWrapper, resultsPdfReportsWrapper, resultsJSONReportsWrapper, + risksOverviewWrapper, scsScanOverviewWrapper, policyWrapper, featureFlagsWrapper, jwtWrapper) + codeBashingCmd := resultCodeBashing(codeBashingWrapper) + bflResultCmd := resultBflSubCommand(bflWrapper) + exitCodeSubcommand := exitCodeSubCommand(scanWrapper) + riskManagementSubCommand := riskManagementSubCommand(riskManagementWrapper, featureFlagsWrapper) + resultCmd.AddCommand( + showResultCmd, bflResultCmd, codeBashingCmd, exitCodeSubcommand, riskManagementSubCommand, + ) + return resultCmd +} + +func exitCodeSubCommand(scanWrapper wrappers.ScansWrapper) *cobra.Command { + exitCodeCmd := &cobra.Command{ + Use: "exit-code", + Short: "Get exit code and details of a scan", + Long: "The exit-code command enables you to get the exit code and failure details of a requested scan in Checkmarx One", + Example: heredoc.Doc( + ` + $ cx results exit-code --scan-id --scan-types + `, + ), + RunE: runGetExitCodeCommand(scanWrapper), + } + + exitCodeCmd.PersistentFlags().String(commonParams.ScanIDFlag, "", "Scan ID") + exitCodeCmd.PersistentFlags().String(commonParams.ScanTypes, "", "Scan types") + + return exitCodeCmd +} +func riskManagementSubCommand(riskManagement wrappers.RiskManagementWrapper, featureFlagsWrapper wrappers.FeatureFlagsWrapper, +) *cobra.Command { + riskManagementCmd := &cobra.Command{ + Use: "risk-management", + Short: "Show risk-management results of a project", + Long: "The risk-management command displays risk management results for a specific project in Checkmarx One", + Example: heredoc.Doc( + ` + $ cx results risk-management --project-id --scan-id --limit (1-50, default: 50) + `, + ), + RunE: runRiskManagementCommand(riskManagement, featureFlagsWrapper), + } + + riskManagementCmd.PersistentFlags().String(commonParams.ProjectIDFlag, "", "Project ID") + riskManagementCmd.PersistentFlags().String(commonParams.ScanIDFlag, "", "Scan ID") + riskManagementCmd.PersistentFlags().Int(commonParams.LimitFlag, -1, "Limit") + + addFormatFlag(riskManagementCmd, printer.FormatJSON, printer.FormatTable, printer.FormatList) + + return riskManagementCmd +} + +func resultShowSubCommand( + resultsWrapper wrappers.ResultsWrapper, + scanWrapper wrappers.ScansWrapper, + exportWrapper wrappers.ExportWrapper, + resultsPdfReportsWrapper wrappers.ResultsPdfWrapper, + resultsJSONReportsWrapper wrappers.ResultsJSONWrapper, + risksOverviewWrapper wrappers.RisksOverviewWrapper, + scsScanOverviewWrapper wrappers.ScanOverviewWrapper, + policyWrapper wrappers.PolicyWrapper, + featureFlagsWrapper wrappers.FeatureFlagsWrapper, + jwtWrapper wrappers.JWTWrapper, +) *cobra.Command { + resultShowCmd := &cobra.Command{ + Use: showSubCommand, + Short: "Show results of a scan", + Long: "The show command enables the ability to show results about a requested scan in Checkmarx One", + Example: heredoc.Doc( + ` + $ cx results show --scan-id + `, + ), + RunE: runGetResultCommand(resultsWrapper, scanWrapper, exportWrapper, resultsPdfReportsWrapper, resultsJSONReportsWrapper, risksOverviewWrapper, scsScanOverviewWrapper, policyWrapper, featureFlagsWrapper, jwtWrapper), + } + addScanIDFlag(resultShowCmd, "ID to report on") + addResultFormatFlag( + resultShowCmd, + printer.FormatJSON, + printer.FormatJSONv2, + printer.FormatSummary, + printer.FormatSummaryConsole, + printer.FormatSarif, + printer.FormatSummaryJSON, + printer.FormatSbom, + printer.FormatPDF, + printer.FormatSummaryMarkdown, + printer.FormatGLSast, + printer.FormatGLSca, + printer.FormatSonar, + ) + resultShowCmd.PersistentFlags().String(commonParams.ReportFormatPdfToEmailFlag, "", pdfToEmailFlagDescription) + resultShowCmd.PersistentFlags().String(commonParams.ReportSbomFormatFlag, services.DefaultSbomOption, sbomReportFlagDescription) + resultShowCmd.PersistentFlags().String(commonParams.ReportFormatPdfOptionsFlag, defaultPdfOptionsDataSections, pdfOptionsFlagDescription) + resultShowCmd.PersistentFlags().String(commonParams.TargetFlag, "cx_result", "Output file") + resultShowCmd.PersistentFlags().String(commonParams.TargetPathFlag, ".", "Output Path") + resultShowCmd.PersistentFlags().StringSlice(commonParams.FilterFlag, []string{}, filterResultsListFlagUsage) + + resultShowCmd.PersistentFlags().IntP( + commonParams.WaitDelayFlag, + "", + commonParams.WaitDelayDefault, + "Polling wait time in seconds", + ) + resultShowCmd.PersistentFlags().Int( + commonParams.PolicyTimeoutFlag, + commonParams.ResultPolicyDefaultTimeout, + "Cancel the policy evaluation and fail after the timeout in minutes", + ) + resultShowCmd.PersistentFlags().Bool(commonParams.IgnorePolicyFlag, false, "Skip policy evaluation. Requires override-policy-management permission.") + resultShowCmd.PersistentFlags().Bool(commonParams.SastRedundancyFlag, false, + "Populate SAST results 'data.redundancy' with values '"+fixLabel+"' (to fix) or '"+redundantLabel+"' (no need to fix)") + resultShowCmd.PersistentFlags().Bool(commonParams.ScaHideDevAndTestDepFlag, false, scaHideDevAndTestDepFlagDescription) + + return resultShowCmd +} + +func resultBflSubCommand(bflWrapper wrappers.BflWrapper) *cobra.Command { + resultBflCmd := &cobra.Command{ + Use: "bfl", + Short: "Show best fix location for a query id within the scan result", + Long: "The bfl command enables the ability to show best fix location for a querid within the scan result", + Example: heredoc.Doc( + ` + $ cx results bfl --scan-id --query-id + `, + ), + RunE: runGetBestFixLocationCommand(bflWrapper), + } + addScanIDFlag(resultBflCmd, "ID to report on") + addQueryIDFlag(resultBflCmd, "Query Id from the result") + addFormatFlag(resultBflCmd, printer.FormatList, printer.FormatJSON) + + markFlagAsRequired(resultBflCmd, commonParams.ScanIDFlag) + markFlagAsRequired(resultBflCmd, commonParams.QueryIDFlag) + + return resultBflCmd +} + +func runGetExitCodeCommand(scanWrapper wrappers.ScansWrapper) func(cmd *cobra.Command, args []string) error { + return func(cmd *cobra.Command, args []string) error { + scanID, _ := cmd.Flags().GetString(commonParams.ScanIDFlag) + if scanID == "" { + return errors.New(errorConstants.ScanIDRequired) + } + scanTypesFlagValue, _ := cmd.Flags().GetString(commonParams.ScanTypes) + results, err := GetScannerResults(scanWrapper, scanID, scanTypesFlagValue) + if err != nil { + return err + } + + if len(results) == 0 { + return nil + } + + return printer.Print(cmd.OutOrStdout(), results, printer.FormatIndentedJSON) + } +} + +func runRiskManagementCommand(riskManagement wrappers.RiskManagementWrapper, featureFlagsWrapper wrappers.FeatureFlagsWrapper, +) func(cmd *cobra.Command, args []string) error { + return func(cmd *cobra.Command, args []string) error { + projectID, _ := cmd.Flags().GetString(commonParams.ProjectIDFlag) + scanID, _ := cmd.Flags().GetString(commonParams.ScanIDFlag) + + limit, _ := cmd.Flags().GetInt(commonParams.LimitFlag) + + flagResponse, _ := wrappers.GetSpecificFeatureFlag(featureFlagsWrapper, wrappers.RiskManagementEnabled) + ASPMEnabled := flagResponse.Status + if !ASPMEnabled { + return errors.Errorf("%s", "Risk management results are currently unavailable for your tenant.") + } + results, err := getRiskManagementResults(riskManagement, projectID, scanID) + if err != nil { + return err + } + results.Results = utils.LimitSlice(results.Results, limit) + err = printByFormat(cmd, results) + return err + } +} + +func getRiskManagementResults(riskManagement wrappers.RiskManagementWrapper, projectID, scanID string) (*wrappers.ASPMResult, error) { + ASPMResult, errorModel, err := riskManagement.GetTopVulnerabilitiesByProjectID(projectID, scanID) + if err != nil { + return nil, errors.Wrapf(err, "%s", failedListingResults) + } + if errorModel != nil { + return nil, errors.Errorf("%s: CODE: %d, %s", failedListingResults, errorModel.Code, errorModel.Message) + } + return ASPMResult, nil +} + +// GetScannerResults returns per-scanner status entries for the given scan, optionally filtered by scan types. +func GetScannerResults(scanWrapper wrappers.ScansWrapper, scanID, scanTypesFlagValue string) ([]ScannerResponse, error) { + scanResponseModel, errorModel, err := scanWrapper.GetByID(scanID) + if err != nil { + return nil, errors.Wrapf(err, "%s", failedGetting) + } + if errorModel != nil { + return nil, errors.Errorf("%s: CODE: %d, %s", failedGettingScan, errorModel.Code, errorModel.Message) + } + results := getScannerResponse(scanTypesFlagValue, scanResponseModel) + return results, nil +} + +func getScannerResponse(scanTypesFlagValue string, scanResponseModel *wrappers.ScanResponseModel) []ScannerResponse { + var results []ScannerResponse + + if scanResponseModel.Status == wrappers.ScanCanceled || + scanResponseModel.Status == wrappers.ScanRunning || + scanResponseModel.Status == wrappers.ScanQueued || + scanResponseModel.Status == wrappers.ScanPartial || + scanResponseModel.Status == wrappers.ScanCompleted { + result := ScannerResponse{ + ScanID: scanResponseModel.ID, + Status: string(scanResponseModel.Status), + } + results = append(results, result) + return results + } + + if scanTypesFlagValue == "" { + results = createAllFailedScannersResponse(scanResponseModel) + } else { + scanTypes := sanitizeScannerNames(scanTypesFlagValue) + results = createRequestedScannersResponse(scanTypes, scanResponseModel) + } + + return results +} + +func createRequestedScannersResponse(scanTypes map[string]string, scanResponseModel *wrappers.ScanResponseModel) []ScannerResponse { + var results []ScannerResponse + for i := range scanResponseModel.StatusDetails { + if _, ok := scanTypes[scanResponseModel.StatusDetails[i].Name]; ok { + results = append(results, createScannerResponse(&scanResponseModel.StatusDetails[i])) + } + } + return results +} + +func createAllFailedScannersResponse(scanResponseModel *wrappers.ScanResponseModel) []ScannerResponse { + var results []ScannerResponse + for i := range scanResponseModel.StatusDetails { + if scanResponseModel.StatusDetails[i].Status == wrappers.ScanFailed { + results = append(results, createScannerResponse(&scanResponseModel.StatusDetails[i])) + } + } + return results +} + +func sanitizeScannerNames(scanTypes string) map[string]string { + scanTypeSlice := strings.Split(scanTypes, ",") + scanTypeMap := make(map[string]string) + for i := range scanTypeSlice { + lowered := strings.ToLower(scanTypeSlice[i]) + scanTypeMap[lowered] = lowered + } + + return scanTypeMap +} + +func createScannerResponse(statusDetails *wrappers.StatusInfo) ScannerResponse { + return ScannerResponse{ + Name: statusDetails.Name, + Status: statusDetails.Status, + Details: statusDetails.Details, + ErrorCode: stringifyErrorCode(statusDetails.ErrorCode), + } +} + +func stringifyErrorCode(errorCode int) string { + if errorCode == 0 { + return "" + } + return strconv.Itoa(errorCode) +} + +func runGetBestFixLocationCommand(bflWrapper wrappers.BflWrapper) func(cmd *cobra.Command, args []string) error { + return func(cmd *cobra.Command, args []string) error { + var bflResponseModel *wrappers.BFLResponseModel + var errorModel *wrappers.WebError + var err error + + scanID, _ := cmd.Flags().GetString(commonParams.ScanIDFlag) + queryID, _ := cmd.Flags().GetString(commonParams.QueryIDFlag) + + scanIds := strings.Split(scanID, ",") + if len(scanIds) > 1 { + return errors.Errorf("%s", "Multiple scan-ids are not allowed.") + } + queryIds := strings.Split(queryID, ",") + if len(queryIds) > 1 { + return errors.Errorf("%s", "Multiple query-ids are not allowed.") + } + + params := make(map[string]string) + params[commonParams.ScanIDQueryParam] = scanID + params[commonParams.QueryIDQueryParam] = queryID + + bflResponseModel, errorModel, err = bflWrapper.GetBflByScanIDAndQueryID(params) + + if err != nil { + return errors.Wrapf(err, "%s", failedGettingBfl) + } + + // Checking the response + if errorModel != nil { + return errors.Errorf("%s: CODE: %d, %s", failedGettingBfl, errorModel.Code, errorModel.Message) + } else if bflResponseModel != nil { + err = printByFormat(cmd, toBflView(*bflResponseModel)) + if err != nil { + return err + } + } + + return nil + } +} + +func toBflView(bflResponseModel wrappers.BFLResponseModel) []wrappers.ScanResultNode { + if (bflResponseModel.TotalCount) > 0 { + views := make([]wrappers.ScanResultNode, bflResponseModel.TotalCount) + + for i := 0; i < bflResponseModel.TotalCount; i++ { + views[i] = wrappers.ScanResultNode{ + Name: bflResponseModel.Trees[i].BFL.Name, + FileName: bflResponseModel.Trees[i].BFL.FileName, + FullName: bflResponseModel.Trees[i].BFL.FullName, + Column: bflResponseModel.Trees[i].BFL.Column, + Length: bflResponseModel.Trees[i].BFL.Length, + Line: bflResponseModel.Trees[i].BFL.Line, + MethodLine: bflResponseModel.Trees[i].BFL.MethodLine, + Method: bflResponseModel.Trees[i].BFL.Method, + DomType: bflResponseModel.Trees[i].BFL.DomType, + } + } + return views + } + views := make([]wrappers.ScanResultNode, 0) + return views +} + +func resultCodeBashing(codeBashingWrapper wrappers.CodeBashingWrapper) *cobra.Command { + // Create a codeBashing wrapper + resultCmd := &cobra.Command{ + Use: "codebashing", + Short: "Get codebashing lesson link", + Long: "The codebashing command enables the ability to retrieve the link about a specific vulnerability", + Example: heredoc.Doc( + ` + $ cx results codebashing --language --vulnerability-type --cwe-id --format + `, + ), + RunE: runGetCodeBashingCommand(codeBashingWrapper), + } + resultCmd.PersistentFlags().String(commonParams.LanguageFlag, "", "Language of the vulnerability") + err := resultCmd.MarkPersistentFlagRequired(commonParams.LanguageFlag) + if err != nil { + log.Fatal(err) + } + resultCmd.PersistentFlags().String(commonParams.VulnerabilityTypeFlag, "", "Vulnerability type") + err = resultCmd.MarkPersistentFlagRequired(commonParams.VulnerabilityTypeFlag) + if err != nil { + log.Fatal(err) + } + resultCmd.PersistentFlags().String(commonParams.CweIDFlag, "", "CWE ID for the vulnerability") + err = resultCmd.MarkPersistentFlagRequired(commonParams.CweIDFlag) + if err != nil { + log.Fatal(err) + } + addFormatFlag(resultCmd, printer.FormatJSON, printer.FormatTable, printer.FormatList) + return resultCmd +} + +func convertScanToResultsSummary(scanInfo *wrappers.ScanResponseModel, resultsWrapper wrappers.ResultsWrapper) (*wrappers.ResultSummary, error) { + if scanInfo == nil { + return nil, errors.New(failedCreatingSummary) + } + + scanInfo.ReplaceMicroEnginesWithSCS() + + sastIssues := 0 + scaIssues := 0 + kicsIssues := 0 + var containersIssues *int + var scsIssues *int + enginesStatusCode := map[string]int{ + commonParams.SastType: 0, + commonParams.ScaType: 0, + commonParams.KicsType: 0, + commonParams.APISecType: 0, + commonParams.ScsType: 0, + commonParams.ContainersType: 0, + } + if wrappers.IsContainersEnabled { + containersIssues = new(int) + *containersIssues = 0 + enginesStatusCode[commonParams.ContainersType] = 0 + } + + scsIssues = new(int) + *scsIssues = 0 + enginesStatusCode[commonParams.ScsType] = 0 + + if len(scanInfo.StatusDetails) > 0 { + applyScanStatusDetails(scanInfo.StatusDetails, &sastIssues, &scaIssues, &kicsIssues, scsIssues, containersIssues, enginesStatusCode) + } + summary := &wrappers.ResultSummary{ + ScanID: scanInfo.ID, + Status: string(scanInfo.Status), + CreatedAt: scanInfo.CreatedAt.Format("2006-01-02, 15:04:05"), + ProjectID: scanInfo.ProjectID, + RiskStyle: "", + RiskMsg: "", + CriticalIssues: 0, + HighIssues: 0, + MediumIssues: 0, + LowIssues: 0, + InfoIssues: 0, + SastIssues: sastIssues, + KicsIssues: kicsIssues, + ScaIssues: scaIssues, + ScsIssues: scsIssues, + ContainersIssues: containersIssues, + Tags: scanInfo.Tags, + ProjectName: scanInfo.ProjectName, + BranchName: scanInfo.Branch, + EnginesEnabled: scanInfo.Engines, + EnginesResult: map[string]*wrappers.EngineResultSummary{ + commonParams.SastType: {StatusCode: enginesStatusCode[commonParams.SastType]}, + commonParams.ScaType: {StatusCode: enginesStatusCode[commonParams.ScaType]}, + commonParams.KicsType: {StatusCode: enginesStatusCode[commonParams.KicsType]}, + commonParams.APISecType: {StatusCode: enginesStatusCode[commonParams.APISecType]}, + commonParams.ContainersType: {StatusCode: enginesStatusCode[commonParams.ContainersType]}, + }, + } + if wrappers.IsContainersEnabled { + summary.EnginesResult[commonParams.ContainersType] = &wrappers.EngineResultSummary{StatusCode: enginesStatusCode[commonParams.ContainersType]} + } + + summary.EnginesResult[commonParams.ScsType] = &wrappers.EngineResultSummary{StatusCode: enginesStatusCode[commonParams.ScsType]} + + baseURI, err := resultsWrapper.GetResultsURL(summary.ProjectID) + if err != nil { + return nil, err + } + + summary.BaseURI = baseURI + summary.BaseURI = generateScanSummaryURL(summary) + if isScanPending(summary.Status) { + summary.ScanInfoMessage = scanPendingMessage + } + + return summary, nil +} + +func applyScanStatusDetails( + statusDetails []wrappers.StatusInfo, + sastIssues, scaIssues, kicsIssues *int, + scsIssues, containersIssues *int, + enginesStatusCode map[string]int, +) { + for _, statusDetailItem := range statusDetails { + if statusDetailItem.Status == wrappers.ScanFailed || statusDetailItem.Status == wrappers.ScanCanceled { + markEngineNotAvailable(statusDetailItem.Name, sastIssues, scaIssues, kicsIssues, scsIssues, containersIssues) + } + switch statusDetailItem.Status { + case wrappers.ScanFailed: + handleScanStatus(statusDetailItem, enginesStatusCode, scanFailedNumber) + case wrappers.ScanCanceled: + handleScanStatus(statusDetailItem, enginesStatusCode, scanCanceledNumber) + } + } +} + +func markEngineNotAvailable(name string, sastIssues, scaIssues, kicsIssues, scsIssues, containersIssues *int) { + switch name { + case commonParams.SastType: + *sastIssues = notAvailableNumber + case commonParams.ScaType: + *scaIssues = notAvailableNumber + case commonParams.KicsType: + *kicsIssues = notAvailableNumber + case commonParams.ScsType: + *scsIssues = notAvailableNumber + case commonParams.ContainersType: + if wrappers.IsContainersEnabled { + *containersIssues = notAvailableNumber + } + } +} + +func handleScanStatus(statusDetailItem wrappers.StatusInfo, targetTypes map[string]int, statusCode int) { + if _, ok := targetTypes[statusDetailItem.Name]; ok { + targetTypes[statusDetailItem.Name] = statusCode + } +} + +func summaryReport( + summary *wrappers.ResultSummary, + policies *wrappers.PolicyResponseModel, + risksOverviewWrapper wrappers.RisksOverviewWrapper, + scsScanOverviewWrapper wrappers.ScanOverviewWrapper, + featureFlagsWrapper wrappers.FeatureFlagsWrapper, + results *wrappers.ScanResultsCollection, + resultsParams map[string]string, +) (*wrappers.ResultSummary, error) { + if summary.HasAPISecurity() { + apiSecFilterRisks, err := getFilterResultsForAPISecScanner(risksOverviewWrapper, summary.ScanID, resultsParams) + if err != nil { + return nil, err + } + if apiSecFilterRisks != nil { + summary.APISecurity = *apiSecFilterRisks + } + apiSecRisks, err := getResultsForAPISecScanner(risksOverviewWrapper, summary.ScanID) + if err != nil { + return nil, err + } + if apiSecRisks != nil { + summary.APISecurity.APICount = apiSecRisks.APICount + } + } + if summary.HasSCS() { + // Getting the base SCS overview. Results counts are overwritten in enhanceWithScanSummary->countResult + SCSOverview, err := getScanOverviewForSCSScanner(scsScanOverviewWrapper, summary.ScanID) + if err != nil { + return nil, err + } + summary.SCSOverview = SCSOverview + } + + if policies != nil { + summary.Policies = filterViolatedRules(*policies) + } + + enhanceWithScanSummary(summary, results, featureFlagsWrapper) + + setNotAvailableNumberIfZero(summary, &summary.SastIssues, commonParams.SastType) + setNotAvailableNumberIfZero(summary, &summary.ScaIssues, commonParams.ScaType) + setNotAvailableNumberIfZero(summary, &summary.KicsIssues, commonParams.KicsType) + setNotAvailableNumberIfZero(summary, summary.ScsIssues, commonParams.ScsType) + + if wrappers.IsContainersEnabled { + setNotAvailableNumberIfZero(summary, summary.ContainersIssues, commonParams.ContainersType) + } + + setRiskMsgAndStyle(summary) + setNotAvailableEnginesStatusCode(summary) + + return summary, nil +} + +func setNotAvailableEnginesStatusCode(summary *wrappers.ResultSummary) { + for engineName, engineResult := range summary.EnginesResult { + setNotAvailableNumberIfZero(summary, &engineResult.StatusCode, engineName) + } +} + +func setRiskMsgAndStyle(summary *wrappers.ResultSummary) { + if summary.CriticalIssues > 0 { + summary.RiskStyle = criticalLabel + summary.RiskMsg = "Critical Risk" + } else if summary.HighIssues > 0 { + summary.RiskStyle = highLabel + summary.RiskMsg = "High Risk" + } else if summary.MediumIssues > 0 { + summary.RiskStyle = mediumLabel + summary.RiskMsg = "Medium Risk" + } else if summary.LowIssues > 0 { + summary.RiskStyle = lowLabel + summary.RiskMsg = "Low Risk" + } else if summary.TotalIssues == 0 { + summary.RiskMsg = "No Risk" + } +} + +func setNotAvailableNumberIfZero(summary *wrappers.ResultSummary, counter *int, engineType string) { + if *counter == 0 && !contains(summary.EnginesEnabled, engineType) { + *counter = notAvailableNumber + } +} + +func enhanceWithScanSummary(summary *wrappers.ResultSummary, results *wrappers.ScanResultsCollection, featureFlagsWrapper wrappers.FeatureFlagsWrapper) { + for _, result := range results.Results { + countResult(summary, result) + } + // Set critical count for a specific engine if critical is disabled + flagResponse, _ := wrappers.GetSpecificFeatureFlag(featureFlagsWrapper, wrappers.CVSSV3Enabled) + criticalEnabled := flagResponse.Status + if summary.HasAPISecurity() { + summary.EnginesResult[commonParams.APISecType].Low = summary.APISecurity.SeverityCount["low"] + summary.EnginesResult[commonParams.APISecType].Medium = summary.APISecurity.SeverityCount["medium"] + summary.EnginesResult[commonParams.APISecType].High = summary.APISecurity.SeverityCount["high"] + if !criticalEnabled { + summary.EnginesResult[commonParams.APISecType].Critical = notAvailableNumber + } else { + summary.EnginesResult[commonParams.APISecType].Critical = summary.APISecurity.SeverityCount["critical"] + } + } + + summary.TotalIssues = summary.SastIssues + summary.ScaIssues + summary.KicsIssues + summary.GetAPISecurityDocumentationTotal() + + if summary.HasSCS() { + // Special case for SCS where status is partial if any microengines failed + if summary.SCSOverview.Status == scanPartialString { + summary.EnginesResult[commonParams.ScsType].StatusCode = scanPartialNumber + } + if !criticalEnabled { + summary.EnginesResult[commonParams.ScsType].Critical = notAvailableNumber + removeCriticalFromSCSOverview(summary) + } + if *summary.ScsIssues >= 0 { + summary.TotalIssues += *summary.ScsIssues + } + } + if wrappers.IsContainersEnabled { + if *summary.ContainersIssues >= 0 { + summary.TotalIssues += *summary.ContainersIssues + } + } + if !criticalEnabled { + summary.EnginesResult[commonParams.SastType].Critical = notAvailableNumber + summary.EnginesResult[commonParams.KicsType].Critical = notAvailableNumber + summary.EnginesResult[commonParams.ScaType].Critical = notAvailableNumber + summary.EnginesResult[commonParams.ContainersType].Critical = notAvailableNumber + } +} + +func removeCriticalFromSCSOverview(summary *wrappers.ResultSummary) { + criticalCount := summary.SCSOverview.RiskSummary[criticalLabel] + summary.SCSOverview.TotalRisksCount -= criticalCount + summary.SCSOverview.RiskSummary[criticalLabel] = notAvailableNumber + for _, microEngineOverview := range summary.SCSOverview.MicroEngineOverviews { + if microEngineOverview.RiskSummary != nil && microEngineOverview.RiskSummary[criticalLabel] != nil { + engineCriticalCount := microEngineOverview.RiskSummary[criticalLabel] + microEngineOverview.TotalRisks -= engineCriticalCount.(int) + microEngineOverview.RiskSummary[criticalLabel] = disabledString + } + } +} + +func writeHTMLSummary(targetFile string, summary *wrappers.ResultSummary) error { + log.Println("Creating Summary Report: ", targetFile) + summaryTemp, err := template.New("summaryTemplate").Parse(wrappers.SummaryTemplate(isScanPending(summary.Status))) + if err == nil { + f, err := os.Create(targetFile) + if err == nil { + _ = summaryTemp.ExecuteTemplate(f, "SummaryTemplate", summary) + _ = f.Close() + } + return err + } + return nil +} +func writeMarkdownSummary(targetFile string, data *wrappers.ResultSummary) error { + log.Println("Creating Markdown Summary Report: ", targetFile) + tmpl, err := template.New(printer.FormatSummaryMarkdown).Parse(wrappers.SummaryMarkdownTemplate(isScanPending(data.Status))) + if err != nil { + return err + } + file, err := os.Create(targetFile) + if err != nil { + return err + } + defer func() { _ = file.Close() }() + + err = tmpl.Execute(file, &data) + if err != nil { + return err + } + return nil +} + +// nolint: whitespace +func writeConsoleSummary(summary *wrappers.ResultSummary, ignorePolicyFlagOmit bool) error { + if !isScanPending(summary.Status) { + fmt.Printf(" Scan Summary: \n") + fmt.Printf(" Created At: %s\n", summary.CreatedAt) + fmt.Printf(" Project Name: %s \n", summary.ProjectName) + fmt.Printf(" Scan ID: %s \n\n", summary.ScanID) + fmt.Printf(" Results Summary: \n") + fmt.Printf( + " Risk Level: %s \n", + summary.RiskMsg, + ) + if summary.Policies != nil && !strings.EqualFold(summary.Policies.Status, policeManagementNoneStatus) { + printPoliciesSummary(summary, ignorePolicyFlagOmit) + } + + printResultsSummaryTable(summary) + + if summary.HasAPISecurity() { + printAPIsSecuritySummary(summary) + } + + if summary.HasSCS() { + printSCSSummary(summary.SCSOverview.MicroEngineOverviews) + } + + 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") + fmt.Printf("For more information: %s\n", summary.BaseURI) + } + return nil +} + +func printPoliciesSummary(summary *wrappers.ResultSummary, ignorePolicyFlagOmit bool) { + hasViolations := false + for _, policy := range summary.Policies.Policies { + if len(policy.RulesViolated) > 0 { + hasViolations = true + break + } + } + if hasViolations { + fmt.Printf(tableLine + "\n") + if ignorePolicyFlagOmit { + printWarningIfIgnorePolicyOmiited() + } + if summary.Policies.BreakBuild { + fmt.Printf(" Policy Management Violation - Break Build Enabled: \n") + } else { + fmt.Printf(" Policy Management Violation: \n") + } + for _, police := range summary.Policies.Policies { + if len(police.RulesViolated) > 0 { + fmt.Printf(" Policy: %s | Break Build: %t | Violated Rules: ", police.Name, police.BreakBuild) + for _, violatedRule := range police.RulesViolated { + fmt.Printf("%s;", violatedRule) + } + } + fmt.Printf("\n") + } + fmt.Printf("\n") + } +} + +func printAPIsSecuritySummary(summary *wrappers.ResultSummary) { + fmt.Printf(" API Security - Total Detected APIs: %d \n", summary.APISecurity.APICount) + fmt.Printf(" APIS WITH RISK: %*d \n", defaultPaddingSize, summary.APISecurity.TotalRisksCount) + if summary.HasAPISecurityDocumentation() { + fmt.Printf(" APIS DOCUMENTATION: %*d \n", defaultPaddingSize, summary.GetAPISecurityDocumentationTotal()) + } + fmt.Printf(tableLine + twoNewLines) +} + +func printTableRow(title string, counts *wrappers.EngineResultSummary, statusNumber int) { + switch statusNumber { + case notAvailableNumber: + fmt.Printf(stringTableResultsFormat, title, notAvailableString, notAvailableString, notAvailableString, notAvailableString, notAvailableString, notAvailableString) + case scanFailedNumber: + fmt.Printf(tableResultsFormat, title, getCountValue(counts.Critical), counts.High, counts.Medium, counts.Low, counts.Info, scanFailedString) + case scanCanceledNumber: + fmt.Printf(tableResultsFormat, title, getCountValue(counts.Critical), counts.High, counts.Medium, counts.Low, counts.Info, scanCanceledString) + case scanPartialNumber: + fmt.Printf(tableResultsFormat, title, getCountValue(counts.Critical), counts.High, counts.Medium, counts.Low, counts.Info, scanPartialString) + default: + fmt.Printf(tableResultsFormat, title, getCountValue(counts.Critical), counts.High, counts.Medium, counts.Low, counts.Info, scanSuccessString) + } +} + +func printSCSSummary(microEngineOverviews []*wrappers.MicroEngineOverview) { + fmt.Printf(" Supply Chain Security Results\n") + fmt.Printf(" -------------------------------------------------------------------------- \n") + fmt.Println(" | Critical High Medium Low Info Status |") + for _, microEngineOverview := range microEngineOverviews { + printSCSTableRow(microEngineOverview) + } + fmt.Printf(" -------------------------------------------------------------------------- \n\n") +} + +func printSCSTableRow(microEngineOverview *wrappers.MicroEngineOverview) { + formatString := " | %-20s %4v %4v %6v %4v %4v %-9s |\n" + notAvailableFormatString := " | %-20s %4v %4s %6s %4s %4s %5s |\n" + + riskSummary := microEngineOverview.RiskSummary + microEngineName := microEngineOverview.FullName + + switch microEngineOverview.Status { + case scsScanUnavailableString: + fmt.Printf(notAvailableFormatString, microEngineName, notAvailableString, notAvailableString, notAvailableString, notAvailableString, notAvailableString, notAvailableString) + default: + fmt.Printf(formatString, microEngineName, riskSummary[criticalLabel], riskSummary[highLabel], riskSummary[mediumLabel], riskSummary[lowLabel], + riskSummary[infoLabel], microEngineOverview.Status) + } +} + +func getCountValue(count int) interface{} { + if count < 0 { + return disabledString + } + return count +} + +func printResultsSummaryTable(summary *wrappers.ResultSummary) { + totalCriticalIssues := summary.EnginesResult.GetCriticalIssues() + totalHighIssues := summary.EnginesResult.GetHighIssues() + totalMediumIssues := summary.EnginesResult.GetMediumIssues() + totalLowIssues := summary.EnginesResult.GetLowIssues() + totalInfoIssues := summary.EnginesResult.GetInfoIssues() + fmt.Printf(tableLine + twoNewLines) + fmt.Printf(" Total Results: %d (Total Results includes only API documentation vulnerabilities\n and does not include API code vulnerabilities.)\n", summary.TotalIssues) + fmt.Println(tableLine) + fmt.Printf(TableTitleFormat, " ", "Critical", "High", "Medium", "Low", "Info", "Status") + + printTableRow("APIs", summary.EnginesResult[commonParams.APISecType], summary.EnginesResult[commonParams.APISecType].StatusCode) + printTableRow("IAC", summary.EnginesResult[commonParams.KicsType], summary.EnginesResult[commonParams.KicsType].StatusCode) + printTableRow("SAST", summary.EnginesResult[commonParams.SastType], summary.EnginesResult[commonParams.SastType].StatusCode) + printTableRow("SCA", summary.EnginesResult[commonParams.ScaType], summary.EnginesResult[commonParams.ScaType].StatusCode) + printTableRow("SCS", summary.EnginesResult[commonParams.ScsType], summary.EnginesResult[commonParams.ScsType].StatusCode) + + if wrappers.IsContainersEnabled { + printTableRow("CONTAINERS", summary.EnginesResult[commonParams.ContainersType], summary.EnginesResult[commonParams.ContainersType].StatusCode) + } + + fmt.Println(tableLine) + fmt.Printf(tableResultsFormat, + "TOTAL", getCountValue(totalCriticalIssues), totalHighIssues, totalMediumIssues, totalLowIssues, totalInfoIssues, summary.Status) + fmt.Printf(tableLine + twoNewLines) +} + +func generateScanSummaryURL(summary *wrappers.ResultSummary) string { + summaryURL := fmt.Sprintf( + strings.Replace(summary.BaseURI, "overview", "scans?id=%s&branch=%s", 1), + summary.ScanID, url.QueryEscape(summary.BranchName), + ) + return summaryURL +} + +func runGetResultCommand( + resultsWrapper wrappers.ResultsWrapper, + scanWrapper wrappers.ScansWrapper, + exportWrapper wrappers.ExportWrapper, + resultsPdfReportsWrapper wrappers.ResultsPdfWrapper, + resultsJSONReportsWrapper wrappers.ResultsJSONWrapper, + risksOverviewWrapper wrappers.RisksOverviewWrapper, + scsScanOverviewWrapper wrappers.ScanOverviewWrapper, + policyWrapper wrappers.PolicyWrapper, + featureFlagsWrapper wrappers.FeatureFlagsWrapper, + jwtWrapper wrappers.JWTWrapper, +) func(cmd *cobra.Command, args []string) error { + return func(cmd *cobra.Command, args []string) error { + targetFile, _ := cmd.Flags().GetString(commonParams.TargetFlag) + targetPath, _ := cmd.Flags().GetString(commonParams.TargetPathFlag) + format, _ := cmd.Flags().GetString(commonParams.TargetFormatFlag) + formatPdfToEmail, _ := cmd.Flags().GetString(commonParams.ReportFormatPdfToEmailFlag) + formatPdfOptions, _ := cmd.Flags().GetString(commonParams.ReportFormatPdfOptionsFlag) + formatSbomOptions, _ := cmd.Flags().GetString(commonParams.ReportSbomFormatFlag) + sastRedundancy, _ := cmd.Flags().GetBool(commonParams.SastRedundancyFlag) + agent, _ := cmd.Flags().GetString(commonParams.AgentFlag) + scaHideDevAndTestDep, _ := cmd.Flags().GetBool(commonParams.ScaHideDevAndTestDepFlag) + ignorePolicy, _ := cmd.Flags().GetBool(commonParams.IgnorePolicyFlag) + // Check if the user has permission to override policy management if --ignore-policy is set + ignorePolicyFlagOmit := false + if ignorePolicy { + overridePolicyManagementPer, err := jwtWrapper.CheckPermissionByAccessToken(OverridePolicyManagement) + if err != nil { + return err + } + if !overridePolicyManagementPer { + ignorePolicyFlagOmit = true + ignorePolicy = false + } + } + waitDelay, _ := cmd.Flags().GetInt(commonParams.WaitDelayFlag) + policyTimeout, _ := cmd.Flags().GetInt(commonParams.PolicyTimeoutFlag) + + scanID, _ := cmd.Flags().GetString(commonParams.ScanIDFlag) + if scanID == "" { + return errors.Errorf("%s: Please provide a scan ID", failedListingResults) + } + + resultsParams, err := getFilters(cmd) + if err != nil { + return errors.Wrapf(err, "%s", failedListingResults) + } + + if scaHideDevAndTestDep { + resultsParams[ScaExcludeResultTypesParam] = ScaDevAndTestExclusionParam + } + + scan, errorModel, scanErr := scanWrapper.GetByID(scanID) + if scanErr != nil { + return errors.Wrapf(scanErr, "%s", failedGetting) + } + if errorModel != nil { + return errors.Errorf("%s: CODE: %d, %s", failedGettingScan, errorModel.Code, errorModel.Message) + } + + var policyResponseModel *wrappers.PolicyResponseModel + if !isScanPending(string(scan.Status)) { + policyResponseModel, err = services.HandlePolicyEvaluation(cmd, policyWrapper, scan, ignorePolicy, agent, waitDelay, policyTimeout) + if err != nil { + return err + } + } else { + logger.PrintIfVerbose("Policy violations aren't returned in the pipeline for scans run in async mode.") + } + + if sastRedundancy { + resultsParams[commonParams.SastRedundancyFlag] = "" + } + + _, err = CreateScanReport(resultsWrapper, risksOverviewWrapper, scsScanOverviewWrapper, exportWrapper, + policyResponseModel, resultsPdfReportsWrapper, resultsJSONReportsWrapper, scan, format, formatPdfToEmail, formatPdfOptions, + formatSbomOptions, targetFile, targetPath, agent, resultsParams, featureFlagsWrapper, ignorePolicyFlagOmit) + return err + } +} + +func runGetCodeBashingCommand( + codeBashingWrapper wrappers.CodeBashingWrapper, +) func(cmd *cobra.Command, args []string) error { + return func(cmd *cobra.Command, args []string) error { + lang, _ := cmd.Flags().GetString(commonParams.LanguageFlag) + cwe, _ := cmd.Flags().GetString(commonParams.CweIDFlag) + vulType, _ := cmd.Flags().GetString(commonParams.VulnerabilityTypeFlag) + params, err := codeBashingWrapper.BuildCodeBashingParams( + []wrappers.CodeBashingParamsCollection{ + { + CweID: "CWE-" + cwe, + Language: lang, + CxQueryName: strings.ReplaceAll(vulType, " ", "_"), + }, + }, + ) + if err != nil { + return err + } + // Fetch the cached token or a new one to obtain the codebashing URL incoded in the jwt token + codeBashingURL, err := codeBashingWrapper.GetCodeBashingURL(codeBashingKey) + if err != nil { + return err + } + // Make the request to the api to obtain the codebashing link and send the codebashing url to enrich the path + CodeBashingModel, webError, err := codeBashingWrapper.GetCodeBashingLinks(params, codeBashingURL) + if err != nil { + return err + } + if webError != nil { + return errors.New(webError.Message) + } + err = printByFormat(cmd, *CodeBashingModel) + if err != nil { + return errors.Wrapf(err, "%s", failedListingCodeBashing) + } + return nil + } +} + +func setIsContainersEnabled(agent string) { + wrappers.IsContainersEnabled = !containsIgnoreCase(containerEngineUnsupportedAgents, agent) +} + +func filterResultsByType(results *wrappers.ScanResultsCollection, excludedTypes map[string]struct{}) *wrappers.ScanResultsCollection { + var filteredResults []*wrappers.ScanResult + + for _, result := range results.Results { + if _, shouldExclude := excludedTypes[result.Type]; shouldExclude { + results.TotalCount-- + } else { + filteredResults = append(filteredResults, result) + } + } + results.Results = filteredResults + return results +} + +func filterScsResultsByAgent(results *wrappers.ScanResultsCollection, agent string) *wrappers.ScanResultsCollection { + unsupportedTypesByAgent := map[string][]string{ + commonParams.VSCodeAgent: {commonParams.SCSScorecardType}, + commonParams.JetbrainsAgent: {commonParams.SCSScorecardType}, + commonParams.EclipseAgent: {commonParams.SCSScorecardType, commonParams.SCSSecretDetectionType}, + commonParams.VisualStudioAgent: {commonParams.SCSScorecardType}, + } + + excludedTypes := make(map[string]struct{}) + + if typesToExclude, exists := unsupportedTypesByAgent[agent]; exists { + for _, excludeType := range typesToExclude { + excludedTypes[excludeType] = struct{}{} + } + } + + results = filterResultsByType(results, excludedTypes) + + return results +} + +// CreateScanReport produces the requested report formats for a scan and writes them to the target path. +func CreateScanReport( + resultsWrapper wrappers.ResultsWrapper, + risksOverviewWrapper wrappers.RisksOverviewWrapper, + scsScanOverviewWrapper wrappers.ScanOverviewWrapper, + exportWrapper wrappers.ExportWrapper, + policyResponseModel *wrappers.PolicyResponseModel, + resultsPdfReportsWrapper wrappers.ResultsPdfWrapper, + resultsJSONReportsWrapper wrappers.ResultsJSONWrapper, + scan *wrappers.ScanResponseModel, + reportTypes, + formatPdfToEmail, + formatPdfOptions, + formatSbomOptions, + targetFile, + targetPath string, + agent string, + resultsParams map[string]string, + featureFlagsWrapper wrappers.FeatureFlagsWrapper, + ignorePolicyFlagOmit bool, +) (*wrappers.ScanResultsCollection, error) { + reportList := strings.Split(reportTypes, ",") + results := &wrappers.ScanResultsCollection{} + setIsContainersEnabled(agent) + summary, err := convertScanToResultsSummary(scan, resultsWrapper) + if err != nil { + return nil, err + } + scanPending := isScanPending(summary.Status) + + err = createDirectory(targetPath) + if err != nil { + return nil, err + } + if !scanPending { + results, err = ReadResults(resultsWrapper, exportWrapper, scan, resultsParams, agent, featureFlagsWrapper) + if err != nil { + return nil, err + } + } + isSummaryNeeded := verifyFormatsByReportList(reportList, summaryFormats...) + if isSummaryNeeded && !scanPending { + summary, err = summaryReport(summary, policyResponseModel, risksOverviewWrapper, scsScanOverviewWrapper, featureFlagsWrapper, results, resultsParams) + if err != nil { + return nil, err + } + } + for _, reportType := range reportList { + err = createReport(reportType, formatPdfToEmail, formatPdfOptions, formatSbomOptions, targetFile, + targetPath, results, summary, exportWrapper, resultsPdfReportsWrapper, resultsJSONReportsWrapper, featureFlagsWrapper, ignorePolicyFlagOmit) + if err != nil { + return nil, err + } + } + return results, nil +} + +func countResult(summary *wrappers.ResultSummary, result *wrappers.ScanResult) { + engineType := strings.TrimSpace(result.Type) + severity := strings.ToLower(result.Severity) + if contains(summary.EnginesEnabled, engineType) && isExploitable(result.State) { + if engineType == commonParams.SastType { + summary.SastIssues++ + summary.TotalIssues++ + } else if engineType == commonParams.ScaType { + summary.ScaIssues++ + summary.TotalIssues++ + } else if engineType == commonParams.KicsType { + summary.KicsIssues++ + summary.TotalIssues++ + } else if engineType == commonParams.ContainersType { + if wrappers.IsContainersEnabled { + *summary.ContainersIssues++ + summary.TotalIssues++ + } else { + return + } + } else if strings.HasPrefix(engineType, commonParams.SscsType) { + addResultToSCSOverview(summary, result) + engineType = commonParams.ScsType + *summary.ScsIssues++ + summary.TotalIssues++ + } else { + return + } + + switch severity { + case criticalLabel: + summary.CriticalIssues++ + case highLabel: + summary.HighIssues++ + case mediumLabel: + summary.MediumIssues++ + case lowLabel: + summary.LowIssues++ + case infoLabel: + summary.InfoIssues++ + } + + summary.UpdateEngineResultSummary(engineType, severity) + } +} + +func addResultToSCSOverview(summary *wrappers.ResultSummary, result *wrappers.ScanResult) { + if engineOverviewName, engineExists := sscsEngineToOverviewEngineMap[result.Type]; engineExists { + for _, microEngineOverview := range summary.SCSOverview.MicroEngineOverviews { + if microEngineOverview.Name == engineOverviewName { + if microEngineOverview.RiskSummary != nil { + severity := strings.ToLower(result.Severity) + if severityCount, exists := microEngineOverview.RiskSummary[severity]; exists { + summary.SCSOverview.RiskSummary[severity]++ + microEngineOverview.TotalRisks++ + summary.SCSOverview.TotalRisksCount++ + microEngineOverview.RiskSummary[severity] = severityCount.(int) + 1 + } + } + } + } + } +} + +func verifyFormatsByReportList(reportFormats []string, formats ...string) bool { + for _, reportFormat := range reportFormats { + for _, format := range formats { + if printer.IsFormat(reportFormat, format) { + return true + } + } + } + return false +} + +func validateEmails(emailString string) ([]string, error) { + re := regexp.MustCompile(`^[a-zA-Z0-9_.+-]+@[a-zA-Z0-9-]+\.[a-zA-Z0-9-.]+$`) + emails := strings.Split(emailString, ",") + var validEmails []string + for _, emailStr := range emails { + email := strings.TrimSpace(emailStr) + if re.MatchString(email) { + validEmails = append(validEmails, email) + } else { + return nil, errors.Errorf("report not sent, invalid email address: %s", email) + } + } + return validEmails, nil +} + +func getResultsForAPISecScanner( + risksOverviewWrapper wrappers.RisksOverviewWrapper, + scanID string, +) (results *wrappers.APISecResult, err error) { + var apiSecResultsModel *wrappers.APISecResult + var errorModel *wrappers.WebError + + apiSecResultsModel, errorModel, err = risksOverviewWrapper.GetAllAPISecRisksByScanID(scanID) + if err != nil { + return nil, errors.Wrapf(err, "%s", failedListingResults) + } + if errorModel != nil { + return nil, errors.Errorf("%s: CODE: %d, %s", failedListingResults, errorModel.Code, errorModel.Message) + } else if apiSecResultsModel != nil { + return apiSecResultsModel, nil + } + return nil, nil +} + +func getScanOverviewForSCSScanner( + scsScanOverviewWrapper wrappers.ScanOverviewWrapper, + scanID string, +) (results *wrappers.SCSOverview, err error) { + var scsOverview *wrappers.SCSOverview + var errorModel *wrappers.WebError + + scsOverview, errorModel, err = scsScanOverviewWrapper.GetSCSOverviewByScanID(scanID) + if err != nil { + return nil, errors.Wrapf(err, "SCS: %s", failedListingResults) + } + if errorModel != nil { + return nil, errors.Errorf("SCS: %s: CODE: %d, %s", failedListingResults, errorModel.Code, errorModel.Message) + } else if scsOverview != nil { + // Setting all counts to 0. Results are recounted in enhanceWithScanSummary->countResult + scsOverview.TotalRisksCount = 0 + for key := range scsOverview.RiskSummary { + scsOverview.RiskSummary[key] = 0 + } + for _, microEngineOverview := range scsOverview.MicroEngineOverviews { + microEngineOverview.TotalRisks = 0 + if microEngineOverview.RiskSummary != nil { + for severity := range microEngineOverview.RiskSummary { + microEngineOverview.RiskSummary[severity] = 0 + } + } + } + return scsOverview, nil + } + return nil, nil +} + +func isScanPending(scanStatus string) bool { + return !strings.EqualFold(scanStatus, statusCompleted) && + !strings.EqualFold(scanStatus, statusPartial) && + !strings.EqualFold(scanStatus, statusFailed) +} + +func createRawReport( + format, targetFile, targetPath string, + results *wrappers.ScanResultsCollection, + summary *wrappers.ResultSummary, + resultsJSONReportsWrapper wrappers.ResultsJSONWrapper, + featureFlagsWrapper wrappers.FeatureFlagsWrapper, +) (handled bool, err error) { + if printer.IsFormat(format, printer.FormatIndentedJSON) { + return true, nil + } + if printer.IsFormat(format, printer.FormatSarif) && isValidScanStatus(summary.Status, printer.FormatSarif) { + sarifRpt := createTargetName(targetFile, targetPath, printer.FormatSarif) + return true, exportSarifResults(sarifRpt, results) + } + if printer.IsFormat(format, printer.FormatSonar) && isValidScanStatus(summary.Status, printer.FormatSonar) { + sonarRpt := createTargetName(fmt.Sprintf("%s%s", targetFile, sonarTypeLabel), targetPath, printer.FormatJSON) + return true, exportSonarResults(sonarRpt, results) + } + if printer.IsFormat(format, printer.FormatJSON) && isValidScanStatus(summary.Status, printer.FormatJSON) { + jsonRpt := createTargetName(targetFile, targetPath, printer.FormatJSON) + return true, exportJSONResults(jsonRpt, results) + } + if printer.IsFormat(format, printer.FormatJSONv2) && isValidScanStatus(summary.Status, printer.FormatJSONv2) { + summaryRpt := createTargetName(targetFile, targetPath, printer.FormatJSON) + return true, exportJSONReportResults(resultsJSONReportsWrapper, summary, summaryRpt, featureFlagsWrapper) + } + if printer.IsFormat(format, printer.FormatGLSast) { + jsonRpt := createTargetName(fmt.Sprintf("%s%s", targetFile, glSastTypeLabel), targetPath, printer.FormatJSON) + return true, exportGlSastResults(jsonRpt, results, summary) + } + if printer.IsFormat(format, printer.FormatGLSca) { + jsonRpt := createTargetName(fmt.Sprintf("%s%s", targetFile, glScaTypeLabel), targetPath, printer.FormatJSON) + return true, exportGlScaResults(jsonRpt, results, summary) + } + return false, nil +} + +func isValidScanStatus(status, format string) bool { + if isScanPending(status) { + log.Printf("Result format file %s not create because scan status is %s", format, status) + return false + } + return true +} + +func createReport(format, + formatPdfToEmail, + formatPdfOptions, + formatSbomOptions, + targetFile, + targetPath string, + results *wrappers.ScanResultsCollection, + summary *wrappers.ResultSummary, + exportWrapper wrappers.ExportWrapper, + resultsPdfReportsWrapper wrappers.ResultsPdfWrapper, + resultsJSONReportsWrapper wrappers.ResultsJSONWrapper, + featureFlagsWrapper wrappers.FeatureFlagsWrapper, + ignorePolicyFlagOmit bool) error { + if handled, err := createRawReport(format, targetFile, targetPath, results, summary, resultsJSONReportsWrapper, featureFlagsWrapper); handled { + return err + } + + if printer.IsFormat(format, printer.FormatSummaryConsole) { + return writeConsoleSummary(summary, ignorePolicyFlagOmit) + } + if printer.IsFormat(format, printer.FormatSummary) { + summaryRpt := createTargetName(targetFile, targetPath, printer.FormatHTML) + convertNotAvailableNumberToZero(summary) + return writeHTMLSummary(summaryRpt, summary) + } + if printer.IsFormat(format, printer.FormatSummaryJSON) { + summaryRpt := createTargetName(targetFile, targetPath, printer.FormatJSON) + convertNotAvailableNumberToZero(summary) + return exportJSONSummaryResults(summaryRpt, summary) + } + if printer.IsFormat(format, printer.FormatPDF) && isValidScanStatus(summary.Status, printer.FormatPDF) { + summaryRpt := createTargetName(targetFile, targetPath, printer.FormatPDF) + return exportPdfResults(resultsPdfReportsWrapper, summary, summaryRpt, formatPdfToEmail, formatPdfOptions, featureFlagsWrapper) + } + if printer.IsFormat(format, printer.FormatSummaryMarkdown) { + summaryRpt := createTargetName(targetFile, targetPath, "md") + convertNotAvailableNumberToZero(summary) + return writeMarkdownSummary(summaryRpt, summary) + } + if printer.IsFormat(format, printer.FormatSbom) && isValidScanStatus(summary.Status, printer.FormatSbom) { + targetType := printer.FormatJSON + if strings.Contains(strings.ToLower(formatSbomOptions), printer.FormatXML) { + targetType = printer.FormatXML + } + summaryRpt := createTargetName(fmt.Sprintf("%s_%s", targetFile, printer.FormatSbom), targetPath, targetType) + convertNotAvailableNumberToZero(summary) + + if !contains(summary.EnginesEnabled, commonParams.ScaType) { + return fmt.Errorf("unable to generate %s report - SCA engine must be enabled on scan summary", printer.FormatSbom) + } + + if summary.ScaIssues == notAvailableNumber { + return fmt.Errorf("unable to generate %s report - SCA engine did not complete successfully", printer.FormatSbom) + } + + return services.ExportSbomResults(exportWrapper, summaryRpt, summary, formatSbomOptions) + } + return fmt.Errorf("bad report format %s", format) +} + +func createTargetName(targetFile, targetPath, targetType string) string { + return filepath.Join(targetPath, targetFile+"."+targetType) +} + +func createDirectory(targetPath string) error { + if _, err := os.Stat(targetPath); os.IsNotExist(err) { + log.Printf("\nOutput path not found: %s\n", targetPath) + log.Printf("Creating directory: %s\n", targetPath) + err = os.Mkdir(targetPath, directoryPermission) + if err != nil { + return err + } + } + return nil +} + +// ReadResults fetches all scan results for the given scan and enriches them with SCA and SCS data as applicable. +func ReadResults( + resultsWrapper wrappers.ResultsWrapper, + exportWrapper wrappers.ExportWrapper, + scan *wrappers.ScanResponseModel, + resultsParams map[string]string, + agent string, featureflagsWrappers wrappers.FeatureFlagsWrapper) (results *wrappers.ScanResultsCollection, err error) { + var resultsModel *wrappers.ScanResultsCollection + var errorModel *wrappers.WebError + + resultsParams[commonParams.ScanIDQueryParam] = scan.ID + _, sastRedundancy := resultsParams[commonParams.SastRedundancyFlag] + + scaHideDevAndTestDep := resultsParams[ScaExcludeResultTypesParam] == ScaDevAndTestExclusionParam + + resultsModel, errorModel, err = resultsWrapper.GetAllResultsByScanID(resultsParams) + + if err != nil { + return nil, errors.Wrapf(err, "%s", failedListingResults) + } + if errorModel != nil { + return nil, errors.Errorf("%s: CODE: %d, %s", failedListingResults, errorModel.Code, errorModel.Message) + } + + if resultsModel != nil { + if slices.Contains(scan.Engines, commonParams.SastType) && sastRedundancy { + // Compute SAST results redundancy + resultsModel = ComputeRedundantSastResults(resultsModel) + } + resultsModel, err = enrichScaResults(exportWrapper, scan, resultsModel, scaHideDevAndTestDep, featureflagsWrappers) + if err != nil { + return nil, err + } + + if slices.Contains(scan.Engines, commonParams.ScsType) { + resultsModel = filterScsResultsByAgent(resultsModel, agent) + } + + resultsModel.ScanID = scan.ID + return resultsModel, nil + } + return nil, nil +} + +func enrichScaResults( + exportWrapper wrappers.ExportWrapper, + scan *wrappers.ScanResponseModel, + resultsModel *wrappers.ScanResultsCollection, + scaHideDevAndTestDep bool, featureflagWrapper wrappers.FeatureFlagsWrapper) (*wrappers.ScanResultsCollection, error) { + if slices.Contains(scan.Engines, commonParams.ScaType) { + scaExportDetails, err := services.GetExportPackage(exportWrapper, scan.ID, scaHideDevAndTestDep, featureflagWrapper) + if err != nil { + return nil, errors.Wrapf(err, "%s", failedListingResults) + } + scaPackageModel := parseScaExportPackage(scaExportDetails.Packages) + scaTypeModel := parseExportScaVulnerability(scaExportDetails.ScaTypes) + if scaPackageModel != nil { + resultsModel = addPackageInformation(resultsModel, scaPackageModel, scaTypeModel) + } + } + if slices.Contains(scan.Engines, commonParams.ContainersType) && !wrappers.IsContainersEnabled { + resultsModel = removeResultsByType(resultsModel, commonParams.ContainersType) + } + return resultsModel, nil +} + +func parseExportScaVulnerability(types []wrappers.ScaType) *[]wrappers.ScaTypeCollection { + var scaTypes []wrappers.ScaTypeCollection + for _, t := range types { + scaTypes = append(scaTypes, wrappers.ScaTypeCollection(t)) + } + return &scaTypes +} + +func parseScaExportPackage(packages []wrappers.ScaPackage) *[]wrappers.ScaPackageCollection { + var scaPackages []wrappers.ScaPackageCollection + for _, pkg := range packages { + pkg := pkg + scaPackages = append(scaPackages, wrappers.ScaPackageCollection{ + ID: pkg.ID, + Locations: pkg.Locations, + DependencyPathArray: parsePackagePathToDependencyPath(&pkg), + Outdated: pkg.Outdated, + IsDirectDependency: pkg.IsDirectDependency, + IsDevelopmentDependency: pkg.IsDevelopmentDependency, + IsTestDependency: pkg.IsTestDependency, + }) + } + return &scaPackages +} + +func parsePackagePathToDependencyPath(pkg *wrappers.ScaPackage) [][]wrappers.DependencyPath { + var dependencyPathArray [][]wrappers.DependencyPath + for _, path := range pkg.PackagePathArray { + var dependencyPath []wrappers.DependencyPath + for _, dep := range path { + dependencyPath = append(dependencyPath, wrappers.DependencyPath{ + ID: dep.ID, + Name: dep.Name, + Version: dep.Version, + }) + } + dependencyPathArray = append(dependencyPathArray, dependencyPath) + } + + // We are doing this to maintain the same structure that was in risk-management api response + // in risk-management, if the length of the dependency path array is 1, it will be the main package + // in export service, if there are no dependencies, the package path array will be empty + if len(dependencyPathArray) == 0 { + appendMainPackageToDependencyPath(&dependencyPathArray, pkg) + } + return dependencyPathArray +} + +func appendMainPackageToDependencyPath(dependencyPathArray *[][]wrappers.DependencyPath, pkg *wrappers.ScaPackage) { + *dependencyPathArray = append(*dependencyPathArray, []wrappers.DependencyPath{{ + ID: pkg.ID, + Locations: pkg.Locations, + Name: pkg.Name, + IsDevelopment: pkg.IsDevelopmentDependency, + }}) +} + +func removeResultsByType(model *wrappers.ScanResultsCollection, resultType string) *wrappers.ScanResultsCollection { + var newResults []*wrappers.ScanResult + for _, result := range model.Results { + isResultType := result.Type == resultType + if resultType == commonParams.SscsType { + isResultType = strings.HasPrefix(result.Type, resultType) + } + if !isResultType { + newResults = append(newResults, result) + } + } + model.Results = newResults + model.TotalCount = uint(len(newResults)) + return model +} + +func exportSarifResults(targetFile string, results *wrappers.ScanResultsCollection) error { + var err error + var resultsJSON []byte + log.Println("Creating SARIF Report: ", targetFile) + var sarifResults = convertCxResultsToSarif(results) + resultsJSON, err = json.Marshal(sarifResults) + if err != nil { + return errors.Wrapf(err, "%s: failed to serialize results response ", failedGettingAll) + } + f, err := os.Create(targetFile) + if err != nil { + return errors.Wrapf(err, "%s: failed to create target file ", failedGettingAll) + } + _, _ = fmt.Fprintln(f, string(resultsJSON)) + _ = f.Close() + return nil +} +func exportGlSastResults(targetFile string, results *wrappers.ScanResultsCollection, summary *wrappers.ResultSummary) error { + log.Println("Creating gl-sast Report: ", targetFile) + var glSast = new(wrappers.GlSastResultsCollection) + glSast.Vulnerabilities = []wrappers.GlVulnerabilities{} + err := addScanToGlSastReport(summary, glSast) + if err != nil { + return errors.Wrapf(err, "%s: failed to add scan to gl-sast report", failedListingResults) + } + convertCxResultToGlSastVulnerability(results, glSast, summary) + resultsJSON, err := json.Marshal(glSast) + if err != nil { + return errors.Wrapf(err, "%s: failed to serialize gl-sast report ", failedListingResults) + } + f, err := os.Create(targetFile) + if err != nil { + return errors.Wrapf(err, "%s: failed to create target file ", failedListingResults) + } + defer func() { _ = f.Close() }() + _, _ = fmt.Fprintln(f, string(resultsJSON)) + return nil +} + +func exportGlScaResults(targetFile string, results *wrappers.ScanResultsCollection, summary *wrappers.ResultSummary) error { + log.Println("Creating Gl-sca Report: ", targetFile) + glScaResult := &wrappers.GlScaResultsCollection{ + Vulnerabilities: []wrappers.GlScaDepVulnerabilities{}, // Initialize arrays to prevent GitLab schema validation errors. + ScaDependencyFiles: []wrappers.ScaDependencyFile{}, + } + err := addScanToGlScaReport(summary, glScaResult) + if err != nil { + return errors.Wrapf(err, "%s: failed to denerate GL-Sca report ", failedListingResults) + } + convertCxResultToGlScaVulnerability(results, glScaResult) + convertCxResultToGlScaFiles(results, glScaResult) + resultsJSON, err := json.Marshal(glScaResult) + if err != nil { + return errors.Wrapf(err, "%s: failed to serialize GL-Sca report ", failedListingResults) + } + f, err := os.Create(targetFile) + if err != nil { + return errors.Wrapf(err, "%s: failed to create target file ", failedListingResults) + } + defer func() { _ = f.Close() }() + _, _ = fmt.Fprintln(f, string(resultsJSON)) + + return nil +} + +func addScanToGlScaReport(summary *wrappers.ResultSummary, glScaResult *wrappers.GlScaResultsCollection) error { + createdAt, err := time.Parse(summaryCreatedAtLayout, summary.CreatedAt) + if err != nil { + return err + } + + glScaResult.Schema = wrappers.ScaSchema + glScaResult.Version = wrappers.SchemaVersion + glScaResult.Scan.Analyzer.VendorGlSCA.VendorGlname = wrappers.AnalyzerScaID + glScaResult.Scan.Analyzer.Name = wrappers.AnalyzerScaID + glScaResult.Scan.Analyzer.Name = wrappers.AnalyzerScaID + glScaResult.Scan.Analyzer.ID = wrappers.ScannerID + glScaResult.Scan.Scanner.ID = wrappers.ScannerID + glScaResult.Scan.Scanner.Name = wrappers.AnalyzerScaID + glScaResult.Scan.Scanner.VendorGlSCA.VendorGlname = wrappers.AnalyzerScaID + glScaResult.Scan.Status = commonParams.Success + glScaResult.Scan.Type = wrappers.ScannerType + glScaResult.Scan.StartTime = createdAt.Format(glTimeFormat) + glScaResult.Scan.EndTime = createdAt.Format(glTimeFormat) + glScaResult.Scan.Scanner.Name = wrappers.AnalyzerScaID + glScaResult.Scan.Scanner.VersionGlSca = commonParams.Version + glScaResult.Scan.Analyzer.VersionGlSca = commonParams.Version + + return nil +} + +func addScanToGlSastReport(summary *wrappers.ResultSummary, glSast *wrappers.GlSastResultsCollection) error { + createdAt, err := time.Parse(summaryCreatedAtLayout, summary.CreatedAt) + if err != nil { + return err + } + + glSast.Scan = wrappers.ScanGlReport{} + glSast.Schema = wrappers.SastSchema + glSast.Version = wrappers.SastSchemaVersion + glSast.Scan.Analyzer.URL = wrappers.AnalyzerURL + glSast.Scan.Analyzer.Name = wrappers.VendorName + glSast.Scan.Analyzer.Vendor.Name = wrappers.VendorName + glSast.Scan.Analyzer.ID = wrappers.AnalyzerID + glSast.Scan.Scanner.ID = wrappers.AnalyzerID + glSast.Scan.Scanner.Name = wrappers.VendorName + glSast.Scan.Status = commonParams.Success + glSast.Scan.Type = commonParams.SastType + glSast.Scan.StartTime = createdAt.Format(glTimeFormat) + glSast.Scan.EndTime = createdAt.Format(glTimeFormat) + glSast.Scan.Scanner.Vendor.Name = wrappers.VendorName + glSast.Scan.Scanner.Version = commonParams.Version + glSast.Scan.Analyzer.Version = commonParams.Version + + return nil +} +func exportSonarResults(targetFile string, results *wrappers.ScanResultsCollection) error { + var err error + var resultsJSON []byte + log.Println("Creating SONAR Report: ", targetFile) + var sonarResults = convertCxResultsToSonar(results) + resultsJSON, err = json.Marshal(sonarResults) + if err != nil { + return errors.Wrapf(err, "%s: failed to serialize results response ", failedGettingAll) + } + f, err := os.Create(targetFile) + if err != nil { + return errors.Wrapf(err, "%s: failed to create target file ", failedGettingAll) + } + _, _ = fmt.Fprintln(f, string(resultsJSON)) + _ = f.Close() + return nil +} + +// Function to decode HTML entities in the ScanResultsCollection +func decodeHTMLEntitiesInResults(results *wrappers.ScanResultsCollection) { + for _, result := range results.Results { + result.Description = html.UnescapeString(result.Description) + result.DescriptionHTML = html.UnescapeString(result.DescriptionHTML) + for _, node := range result.ScanResultData.Nodes { + node.FullName = html.UnescapeString(node.FullName) + node.Name = html.UnescapeString(node.Name) + } + } +} + +func exportJSONResults(targetFile string, results *wrappers.ScanResultsCollection) error { + decodeHTMLEntitiesInResults(results) + var err error + var resultsJSON []byte + log.Println("Creating JSON Report: ", targetFile) + resultsJSON, err = json.Marshal(results) + if err != nil { + return errors.Wrapf(err, "%s: failed to serialize results response ", failedGettingAll) + } + f, err := os.Create(targetFile) + if err != nil { + return errors.Wrapf(err, "%s: failed to create target file ", failedGettingAll) + } + _, _ = fmt.Fprintln(f, string(resultsJSON)) + _ = f.Close() + return nil +} + +func exportJSONReportResults(jsonWrapper wrappers.ResultsJSONWrapper, summary *wrappers.ResultSummary, summaryRpt string, featureFlagsWrapper wrappers.FeatureFlagsWrapper) error { + jsonReportsPayload := &wrappers.JSONReportsPayload{} + pollingResp := &wrappers.JSONPollingResponse{} + jsonReportsPayload.ReportName = reportNameImprovedScanReport + + jsonOptionsSections, jsonOptionsEngines := parseJSONOptions(summary.EnginesEnabled, jsonReportsPayload.ReportName) + + jsonReportsPayload.ReportType = CliType + jsonReportsPayload.FileFormat = printer.FormatJSON + jsonReportsPayload.Data.ScanID = summary.ScanID + jsonReportsPayload.Data.ProjectID = summary.ProjectID + jsonReportsPayload.Data.BranchName = summary.BranchName + jsonReportsPayload.Data.Scanners = jsonOptionsEngines + jsonReportsPayload.Data.Sections = jsonOptionsSections + + jsonReportID, webErr, err := jsonWrapper.GenerateJSONReport(jsonReportsPayload) + if webErr != nil { + return errors.Errorf("Error generating JSON report - %s", webErr.Message) + } + if err != nil { + return errors.Errorf("Error generating JSON report - %s", err.Error()) + } + log.Println("Generating JSON report") + pollingResp.Status = startedStatus + for pollingResp.Status == startedStatus || pollingResp.Status == requestedStatus { + pollingResp, webErr, err = jsonWrapper.CheckJSONReportStatus(jsonReportID.ReportID) + if err != nil || webErr != nil { + return errors.Wrapf(err, "%v", webErr) + } + logger.PrintfIfVerbose("JSON report status: %s", pollingResp.Status) + time.Sleep(delayValueForReport * time.Millisecond) + } + if pollingResp.Status != completedStatus { + return errors.Errorf("JSON generating failed - Current status: %s", pollingResp.Status) + } + + minioEnabled, _ := wrappers.GetSpecificFeatureFlag(featureFlagsWrapper, wrappers.MinioEnabled) + infoPathType := "" + if minioEnabled.Status { + infoPathType = jsonReportID.ReportID + } else { + infoPathType = pollingResp.URL + } + err = jsonWrapper.DownloadJSONReport(infoPathType, summaryRpt, minioEnabled.Status) + if err != nil { + return errors.Wrapf(err, "%s", "Failed downloading JSON report") + } + return nil +} + +func parseJSONOptions(enabledEngines []string, reportName string) (jsonOptionsSections, jsonOptionsEngines []string) { + jsonOptionsSections = []string{ + sectionScanSummary, + sectionExecutiveSummary, + sectionScanResults, + } + + var jsonOptionsEnginesMap = map[string]string{ + commonParams.ScaType: scaEngineLabel, + commonParams.SastType: sastEngineLabel, + commonParams.KicsType: kicsEngineLabel, + commonParams.IacType: kicsEngineLabel, + commonParams.ContainersType: "Containers", + commonParams.ScsType: "Microengines", + } + if jsonOptionsEngines == nil { + for _, engine := range enabledEngines { + if jsonOptionsEnginesMap[engine] != "" { + jsonOptionsEngines = append(jsonOptionsEngines, jsonOptionsEnginesMap[engine]) + } + } + } + + if reportName == reportNameImprovedScanReport { + jsonOptionsSections = translateReportSectionsForImproved(jsonOptionsSections) + } + + return jsonOptionsSections, jsonOptionsEngines +} + +func exportJSONSummaryResults(targetFile string, results *wrappers.ResultSummary) error { + var err error + var resultsJSON []byte + log.Println("Creating summary JSON Report: ", targetFile) + resultsJSON, err = json.Marshal(results) + if err != nil { + return errors.Wrapf(err, "%s: failed to serialize results response ", failedGettingAll) + } + f, err := os.Create(targetFile) + if err != nil { + return errors.Wrapf(err, "%s: failed to create target file ", failedGettingAll) + } + _, _ = fmt.Fprintln(f, string(resultsJSON)) + _ = f.Close() + return nil +} + +func exportPdfResults(pdfWrapper wrappers.ResultsPdfWrapper, summary *wrappers.ResultSummary, summaryRpt, formatPdfToEmail, + pdfOptions string, featureFlagsWrapper wrappers.FeatureFlagsWrapper) error { + pdfReportsPayload := &wrappers.PdfReportsPayload{} + pollingResp := &wrappers.PdfPollingResponse{} + pdfReportsPayload.ReportName = reportNameImprovedScanReport + pdfOptionsSections, pdfOptionsEngines, err := parsePDFOptions(pdfOptions, summary.EnginesEnabled, pdfReportsPayload.ReportName) + if err != nil { + return err + } + pdfReportsPayload.ReportType = CliType + pdfReportsPayload.FileFormat = printer.FormatPDF + pdfReportsPayload.Data.ScanID = summary.ScanID + pdfReportsPayload.Data.ProjectID = summary.ProjectID + pdfReportsPayload.Data.BranchName = summary.BranchName + pdfReportsPayload.Data.Scanners = pdfOptionsEngines + pdfReportsPayload.Data.Sections = pdfOptionsSections + + // will generate pdf report and send it to the email list + // instead of saving it to the file system + if formatPdfToEmail != "" { + emailList, validateErr := validateEmails(formatPdfToEmail) + if validateErr != nil { + return validateErr + } + pdfReportsPayload.ReportType = reportTypeEmail + pdfReportsPayload.Data.Email = emailList + } + pdfReportID, webErr, err := pdfWrapper.GeneratePdfReport(pdfReportsPayload) + if webErr != nil { + return errors.Errorf("Error generating PDF report - %s", webErr.Message) + } + if err != nil { + return errors.Errorf("Error generating PDF report - %s", err.Error()) + } + if pdfReportsPayload.ReportType == reportTypeEmail { + log.Println("Sending PDF report to: ", pdfReportsPayload.Data.Email) + return nil + } + log.Println("Generating PDF report") + pollingResp.Status = startedStatus + for pollingResp.Status == startedStatus || pollingResp.Status == requestedStatus { + pollingResp, webErr, err = pdfWrapper.CheckPdfReportStatus(pdfReportID.ReportID) + if err != nil || webErr != nil { + return errors.Wrapf(err, "%v", webErr) + } + logger.PrintfIfVerbose("PDF report status: %s", pollingResp.Status) + time.Sleep(delayValueForReport * time.Millisecond) + } + if pollingResp.Status != completedStatus { + return errors.Errorf("PDF generating failed - Current status: %s", pollingResp.Status) + } + + minioEnabled, _ := wrappers.GetSpecificFeatureFlag(featureFlagsWrapper, wrappers.MinioEnabled) + infoPathType := "" + if minioEnabled.Status { + infoPathType = pdfReportID.ReportID + } else { + infoPathType = pollingResp.URL + } + err = pdfWrapper.DownloadPdfReport(infoPathType, summaryRpt, minioEnabled.Status) + if err != nil { + return errors.Wrapf(err, "%s", "Failed downloading PDF report") + } + return nil +} + +func parsePDFOptions(pdfOptions string, enabledEngines []string, reportName string) (pdfOptionsSections, pdfOptionsEngines []string, err error) { + var pdfOptionsSectionsMap = map[string]string{ + "scansummary": sectionScanSummary, + "executivesummary": sectionExecutiveSummary, + "scanresults": sectionScanResults, + } + + var pdfOptionsEnginesMap = map[string]string{ + commonParams.ScaType: scaEngineLabel, + commonParams.SastType: sastEngineLabel, + commonParams.KicsType: kicsEngineLabel, + commonParams.IacType: kicsEngineLabel, + } + + pdfOptions = strings.ToLower(strings.ReplaceAll(pdfOptions, " ", "")) + options := strings.Split(strings.ReplaceAll(pdfOptions, "\n", ""), ",") + for _, s := range options { + if pdfOptionsEnginesMap[s] != "" { + pdfOptionsEngines = append(pdfOptionsEngines, pdfOptionsEnginesMap[s]) + } else if pdfOptionsSectionsMap[s] != "" { + pdfOptionsSections = append(pdfOptionsSections, pdfOptionsSectionsMap[s]) + } else { + return nil, nil, errors.Errorf("report option \"%s\" unavailable", s) + } + } + if pdfOptionsEngines == nil { + for _, engine := range enabledEngines { + if pdfOptionsEnginesMap[engine] != "" { + pdfOptionsEngines = append(pdfOptionsEngines, pdfOptionsEnginesMap[engine]) + } + } + } + + if reportName == reportNameImprovedScanReport { + pdfOptionsSections = translateReportSectionsForImproved(pdfOptionsSections) + } + + return pdfOptionsSections, pdfOptionsEngines, nil +} + +func translateReportSectionsForImproved(sections []string) []string { + var resultSections = make([]string, 0) + + var pdfOptionsSectionsImprovedTranslation = map[string][]string{ + sectionScanSummary: {"scan-information"}, + sectionExecutiveSummary: {"results-overview"}, + sectionScanResults: {"scan-results", "categories", "resolved-results", "vulnerability-details"}, + } + + for _, section := range sections { + if translatedSections := pdfOptionsSectionsImprovedTranslation[section]; translatedSections != nil { + resultSections = append(resultSections, translatedSections...) + } + } + + return resultSections +} + +func convertCxResultsToSarif(results *wrappers.ScanResultsCollection) *wrappers.SarifResultsCollection { + var sarif = new(wrappers.SarifResultsCollection) + sarif.Schema = "https://raw.githubusercontent.com/oasis-tcs/sarif-spec/master/Schemata/sarif-schema-2.1.0.json" + sarif.Version = "2.1.0" + sarif.Runs = []wrappers.SarifRun{} + sarif.Runs = append(sarif.Runs, createSarifRun(results)) + return sarif +} + +func convertCxResultToGlSastVulnerability(results *wrappers.ScanResultsCollection, glSast *wrappers.GlSastResultsCollection, summary *wrappers.ResultSummary) { + for _, result := range results.Results { + if strings.TrimSpace(result.Type) == commonParams.SastType { + glSast = parseGlSastVulnerability(result, glSast, summary) + } + } +} + +func convertCxResultToGlScaVulnerability(results *wrappers.ScanResultsCollection, glScaResult *wrappers.GlScaResultsCollection) { + for _, result := range results.Results { + if strings.TrimSpace(result.Type) == commonParams.ScaType { + glScaResult = parseGlscaVulnerability(result, glScaResult) + } + } +} + +func convertCxResultToGlScaFiles(results *wrappers.ScanResultsCollection, glScaResult *wrappers.GlScaResultsCollection) { + for _, result := range results.Results { + if strings.TrimSpace(result.Type) == commonParams.ScaType { + glScaResult = parseGlScaFiles(result, glScaResult) + } + } +} +func parseGlSastVulnerability(result *wrappers.ScanResult, glSast *wrappers.GlSastResultsCollection, summary *wrappers.ResultSummary) *wrappers.GlSastResultsCollection { + hostName := parseURI(summary.BaseURI) + + queryName := result.ScanResultData.QueryName + fileName := result.ScanResultData.Nodes[0].FileName + lineNumber := strconv.FormatUint(uint64(result.ScanResultData.Nodes[0].Line), 10) + startLine := result.ScanResultData.Nodes[0].Line + endLine := result.ScanResultData.Nodes[0].Line + result.ScanResultData.Nodes[0].Length + ID := fmt.Sprintf("%s:%s:%s", queryName, fileName, lineNumber) + category := fmt.Sprintf("%s-%s", wrappers.VendorName, result.Type) + message := fmt.Sprintf("%s@%s:%s", queryName, fileName, lineNumber) + QueryDescriptionLink := fmt.Sprintf("%s/results/%s/%s/sast/description/%s/%s", hostName, summary.ScanID, summary.ProjectID, result.VulnerabilityDetails.CweID, result.ScanResultData.QueryID) + + glSast.Vulnerabilities = append(glSast.Vulnerabilities, wrappers.GlVulnerabilities{ + ID: ID, + Category: category, + Name: queryName, + Message: message, + Description: result.Description + " \n" + QueryDescriptionLink, + CVE: ID, + Severity: cases.Title(language.English).String(result.Severity), + Confidence: cases.Title(language.English).String(result.Severity), + Solution: "", + + Scanner: wrappers.GlScanner{ + ID: category, + Name: category, + }, + Identifiers: []wrappers.Identifier{ + { + Type: "cxOneScan", + Name: "CxOne Scan", + URL: summary.BaseURI, + Value: result.ID, + }, + }, + Links: make([]string, 0), + Tracking: wrappers.Tracking{ + Type: "source", + Items: []wrappers.Item{ + { + Signatures: []wrappers.Signature{{Algorithm: result.Type + "-Algorithm ", Value: notAvailableValue}}, + File: fileName, + EndLine: endLine, + StartLine: startLine, + }, + }, + }, + Flags: make([]wrappers.Flag, 0), + Location: wrappers.Location{ + File: fileName, + StartLine: startLine, + EndLine: endLine, + }, + }) + return glSast +} +func parseGlscaVulnerability(result *wrappers.ScanResult, glDependencyResult *wrappers.GlScaResultsCollection) *wrappers.GlScaResultsCollection { + if result.ScanResultData.ScaPackageCollection != nil { + glDependencyResult.Vulnerabilities = append(glDependencyResult.Vulnerabilities, wrappers.GlScaDepVulnerabilities{ + ID: result.ID, + Name: result.VulnerabilityDetails.CveName, + Description: result.Description, + Severity: cases.Title(language.English).String(result.Severity), + Solution: result.ScanResultData.RecommendedVersion, + Identifiers: collectScaPackageData(result), + Links: collectScaPackageLinks(result), + TrackingDep: wrappers.TrackingDep{ + Items: collectScaPackageItemsDep(result), + }, + Flags: make([]string, 0), + LocationDep: wrappers.GlScaDepVulnerabilityLocation{ + File: parseGlDependencyLocation(result), + Dependency: wrappers.ScaDependencyLocation{ + Package: wrappers.PackageName{Name: result.ScanResultData.PackageIdentifier}, + ScaDependencyLocationVersion: "", + Direct: result.ScanResultData.ScaPackageCollection.IsDirectDependency, + ScaDependencyPath: result.ScanResultData.Line, + }, + }, + }) + } + return glDependencyResult +} +func parseGlDependencyLocation(result *wrappers.ScanResult) string { + var location string + if result != nil && result.ScanResultData.ScaPackageCollection != nil && result.ScanResultData.ScaPackageCollection.Locations != nil { + location = *result.ScanResultData.ScaPackageCollection.Locations[0] + } else { + location = "" + } + return location +} +func parseGlScaFiles(result *wrappers.ScanResult, glScaResult *wrappers.GlScaResultsCollection) *wrappers.GlScaResultsCollection { + if result.ScanResultData.ScaPackageCollection != nil && result.ScanResultData.ScaPackageCollection.Locations != nil { + glScaResult.ScaDependencyFiles = append(glScaResult.ScaDependencyFiles, wrappers.ScaDependencyFile{ + Path: *result.ScanResultData.ScaPackageCollection.Locations[0], + PackageManager: result.ScanResultData.ScaPackageCollection.ID, + Dependencies: collectScaFileLocations(result), + }) + } + return glScaResult +} +func collectScaFileLocations(result *wrappers.ScanResult) []wrappers.ScaDependencyLocation { + allScaIdentifierLocations := []wrappers.ScaDependencyLocation{} + for _, packageInfo := range result.ScanResultData.PackageData { + allScaIdentifierLocations = append(allScaIdentifierLocations, wrappers.ScaDependencyLocation{ + Package: wrappers.PackageName{ + Name: packageInfo.Type, + }, + ScaDependencyLocationVersion: packageInfo.URL, + Direct: true, + ScaDependencyPath: result.ScanResultData.Line, + }) + } + return allScaIdentifierLocations +} +func collectScaPackageItemsDep(result *wrappers.ScanResult) []wrappers.ItemDep { + allScaPackageItemDep := []wrappers.ItemDep{} + allScaPackageItemDep = append(allScaPackageItemDep, wrappers.ItemDep{ + Signature: []wrappers.SignatureDep{{Algorithm: "SCA-Algorithm ", Value: notAvailableValue}}, + File: result.VulnerabilityDetails.CveName, + EndLine: 0, + StartLine: 0, + }) + return allScaPackageItemDep +} +func collectScaPackageLinks(result *wrappers.ScanResult) []wrappers.LinkDep { + allScaPackageLinks := []wrappers.LinkDep{} + for _, packageInfo := range result.ScanResultData.PackageData { + allScaPackageLinks = append(allScaPackageLinks, wrappers.LinkDep{ + Name: packageInfo.Type, + URL: packageInfo.URL, + }) + } + return allScaPackageLinks +} +func collectScaPackageData(result *wrappers.ScanResult) []wrappers.IdentifierDep { + allIdentifierDep := []wrappers.IdentifierDep{} + for _, packageInfo := range result.ScanResultData.PackageData { + allIdentifierDep = append(allIdentifierDep, wrappers.IdentifierDep{ + Type: packageInfo.Type, + Value: packageInfo.URL, + Name: packageInfo.URL, + }) + } + return allIdentifierDep +} + +func convertCxResultsToSonar(results *wrappers.ScanResultsCollection) *wrappers.ScanResultsSonar { + var sonar = new(wrappers.ScanResultsSonar) + sonar.Issues, sonar.Rules = parseSonar(results) + return sonar +} + +func createSarifRun(results *wrappers.ScanResultsCollection) wrappers.SarifRun { + var sarifRun wrappers.SarifRun + sarifRun.Tool.Driver.Name = wrappers.SarifName + sarifRun.Tool.Driver.Version = wrappers.SarifVersion + sarifRun.Tool.Driver.InformationURI = wrappers.SarifInformationURI + sarifRun.Tool.Driver.Rules, sarifRun.Results = parseResults(results) + return sarifRun +} + +func parseResults(results *wrappers.ScanResultsCollection) ([]wrappers.SarifDriverRule, []wrappers.SarifScanResult) { + var sarifRules = make([]wrappers.SarifDriverRule, 0) + var sarifResults = make([]wrappers.SarifScanResult, 0) + if results != nil { + ruleIds := map[interface{}]bool{} + for _, result := range results.Results { + if rule := findRule(ruleIds, result); rule != nil { + sarifRules = append(sarifRules, *rule) + } + if sarifResult := findResult(result); sarifResult != nil { + sarifResults = append(sarifResults, sarifResult...) + } + } + } + return sarifRules, sarifResults +} + +func parseSonar(results *wrappers.ScanResultsCollection) ([]wrappers.SonarIssues, []wrappers.SonarRules) { + var sonarIssues []wrappers.SonarIssues + var sonarRules []wrappers.SonarRules + seenRuleIDs := make(map[string]bool) // Track already added rule IDs + + if results != nil { + for _, result := range results.Results { + var auxRules = initSonarRules(result) + var auxIssue = initSonarIssue(result) + + if !seenRuleIDs[auxRules.ID] { + sonarRules = append(sonarRules, auxRules) + seenRuleIDs[auxRules.ID] = true + } + + engineType := strings.TrimSpace(result.Type) + + if engineType == commonParams.SastType { + auxIssue.PrimaryLocation = parseSonarPrimaryLocation(result) + auxIssue.SecondaryLocations = parseSonarSecondaryLocations(result) + sonarIssues = append(sonarIssues, auxIssue) + } else if engineType == commonParams.KicsType { + auxIssue.PrimaryLocation = parseLocationKics(result) + sonarIssues = append(sonarIssues, auxIssue) + } else if engineType == commonParams.ScaType { + sonarIssuesByLocation := parseScaSonarLocations(result) + sonarIssues = append(sonarIssues, sonarIssuesByLocation...) + } else if wrappers.IsContainersEnabled && engineType == commonParams.ContainersType { + auxIssue.PrimaryLocation = parseContainersSonar(result) + sonarIssues = append(sonarIssues, auxIssue) + } else if strings.HasPrefix(engineType, commonParams.SscsType) { + sscsSonarIssue := parseSscsSonar(result, &auxIssue) + sonarIssues = append(sonarIssues, sscsSonarIssue) + } + } + } + return sonarIssues, sonarRules +} + +func parseContainersSonar(result *wrappers.ScanResult) wrappers.SonarLocation { + var auxLocation wrappers.SonarLocation + auxLocation.FilePath = result.ScanResultData.ImageFilePath + auxLocation.Message = html.UnescapeString(result.Description) + var textRange wrappers.SonarTextRange + textRange.StartColumn = 1 + textRange.EndColumn = 2 + textRange.StartLine = 1 + textRange.EndLine = 2 + auxLocation.TextRange = textRange + return auxLocation +} + +func parseSscsSonar(result *wrappers.ScanResult, sonarIssue *wrappers.SonarIssues) wrappers.SonarIssues { + sonarIssue.PrimaryLocation.FilePath = result.ScanResultData.Filename + + sonarIssue.PrimaryLocation.Message = html.UnescapeString(result.ScanResultData.Remediation) + var textRange wrappers.SonarTextRange + textRange.StartColumn = 1 + textRange.EndColumn = 2 + textRange.StartLine = result.ScanResultData.Line + sonarIssue.PrimaryLocation.TextRange = textRange + return *sonarIssue +} + +func initSonarIssue(result *wrappers.ScanResult) wrappers.SonarIssues { + var sonarIssue wrappers.SonarIssues + engineType := strings.TrimSpace(result.Type) + if engineType == commonParams.SastType { + sonarIssue.RuleID = result.ScanResultData.LanguageName + " - " + result.ScanResultData.QueryName + } else if engineType == commonParams.KicsType { + sonarIssue.RuleID = result.ScanResultData.QueryName + } else if engineType == commonParams.ScaType { + sonarIssue.RuleID = result.ID + } else if wrappers.IsContainersEnabled && engineType == commonParams.ContainersType { + sonarIssue.RuleID = result.ID + } else if strings.HasPrefix(engineType, commonParams.SscsType) { + sonarIssue.RuleID = result.ID + } + + sonarIssue.PrimaryLocation.Message = html.UnescapeString(result.Description) + sonarIssue.EffortMinutes = 0 + + return sonarIssue +} + +func initSonarRules(result *wrappers.ScanResult) wrappers.SonarRules { + var sonarRules wrappers.SonarRules + var sonarImpacts wrappers.SonarImpacts + + sonarImpacts.Severity = sonarSeverities[result.Severity] + sonarImpacts.SoftwareQuality = vulnerabilitySonar + + sonarRules.EngineID = result.Type + sonarRules.CleanCodeAttribute = cleanCodeAttribute + + engineType := strings.TrimSpace(result.Type) + if engineType == commonParams.SastType { + sonarRules.Name = result.ScanResultData.QueryName + sonarRules.Description = html.UnescapeString(result.Description) + sonarRules.ID = result.ScanResultData.LanguageName + " - " + result.ScanResultData.QueryName + } else if engineType == commonParams.KicsType { + sonarRules.Name = result.ScanResultData.QueryName + sonarRules.Description = html.UnescapeString(result.Description) + sonarRules.ID = result.ScanResultData.QueryName + } else if engineType == commonParams.ScaType { + sonarRules.Name = result.ScanResultData.PackageIdentifier + sonarRules.Description = html.UnescapeString(result.Description) + sonarRules.ID = result.ID + } else if wrappers.IsContainersEnabled && engineType == commonParams.ContainersType { + sonarRules.Name = result.ScanResultData.ImageTag + sonarRules.Description = html.UnescapeString(result.Description) + sonarRules.ID = result.ID + } else if strings.HasPrefix(engineType, commonParams.SscsType) { + sonarRules.Name = result.ScanResultData.RuleName + sonarRules.Description = html.UnescapeString(result.ScanResultData.RuleDescription) + sonarRules.ID = result.ID + } + + sonarRules.Impacts = []wrappers.SonarImpacts{sonarImpacts} + + return sonarRules +} + +func parseScaSonarLocations(result *wrappers.ScanResult) []wrappers.SonarIssues { + if result == nil || result.ScanResultData.ScaPackageCollection == nil || result.ScanResultData.ScaPackageCollection.Locations == nil { + return []wrappers.SonarIssues{} + } + + var issuesByLocation []wrappers.SonarIssues + + for _, location := range result.ScanResultData.ScaPackageCollection.Locations { + issueByLocation := initSonarIssue(result) + + var primaryLocation wrappers.SonarLocation + + primaryLocation.FilePath = *location + _, _, primaryLocation.Message = findRuleID(result) + + var textRange wrappers.SonarTextRange + textRange.StartColumn = 1 + textRange.EndColumn = 2 + textRange.StartLine = 1 + textRange.EndLine = 2 + + primaryLocation.TextRange = textRange + + issueByLocation.PrimaryLocation = primaryLocation + + issuesByLocation = append(issuesByLocation, issueByLocation) + } + + return issuesByLocation +} + +func parseLocationKics(results *wrappers.ScanResult) wrappers.SonarLocation { + var auxLocation wrappers.SonarLocation + auxLocation.FilePath = strings.TrimLeft(results.ScanResultData.Filename, "/") + auxLocation.Message = html.UnescapeString(results.ScanResultData.Value) + var auxTextRange wrappers.SonarTextRange + auxTextRange.StartLine = results.ScanResultData.Line + auxTextRange.StartColumn = 0 + auxTextRange.EndColumn = 1 + auxLocation.TextRange = auxTextRange + return auxLocation +} + +func parseSonarPrimaryLocation(results *wrappers.ScanResult) wrappers.SonarLocation { + var auxLocation wrappers.SonarLocation + // fill the details in the primary Location + if len(results.ScanResultData.Nodes) > 0 { + auxLocation.FilePath = strings.TrimLeft(results.ScanResultData.Nodes[0].FileName, "/") + auxLocation.Message = html.UnescapeString(strings.ReplaceAll(results.ScanResultData.QueryName, "_", " ")) + auxLocation.TextRange = parseSonarTextRange(results.ScanResultData.Nodes[0]) + } + return auxLocation +} + +func parseSonarSecondaryLocations(results *wrappers.ScanResult) []wrappers.SonarLocation { + var auxSecondaryLocations []wrappers.SonarLocation + // Traverse all the rest of the scan result nodes into secondary location of sonar + if len(results.ScanResultData.Nodes) >= 1 { + for _, node := range results.ScanResultData.Nodes[1:] { + var auxSecondaryLocation wrappers.SonarLocation + auxSecondaryLocation.FilePath = strings.TrimLeft(node.FileName, "/") + auxSecondaryLocation.Message = html.UnescapeString(strings.ReplaceAll(results.ScanResultData.QueryName, "_", " ")) + auxSecondaryLocation.TextRange = parseSonarTextRange(node) + auxSecondaryLocations = append(auxSecondaryLocations, auxSecondaryLocation) + } + } + return auxSecondaryLocations +} + +func parseSonarTextRange(results *wrappers.ScanResultNode) wrappers.SonarTextRange { + var auxTextRange wrappers.SonarTextRange + auxTextRange.StartLine = results.Line + startColumn := getSastStartColumn(results.Column) + + auxTextRange.StartColumn = startColumn + auxTextRange.EndColumn = startColumn + results.Length + + if auxTextRange.StartColumn == auxTextRange.EndColumn { + auxTextRange.EndColumn++ + } + + return auxTextRange +} + +func findRule(ruleIds map[interface{}]bool, result *wrappers.ScanResult) *wrappers.SarifDriverRule { + var sarifRule wrappers.SarifDriverRule + sarifRule.ID, sarifRule.Name, _ = findRuleID(result) + sarifRule.FullDescription = findFullDescription(result) + sarifRule.Help = findHelp(result) + sarifRule.HelpURI = findHelpURI(result) + sarifRule.Properties = findProperties(result) + + if !ruleIds[sarifRule.ID] { + ruleIds[sarifRule.ID] = true + return &sarifRule + } + + return nil +} + +func getSastStartColumn(column uint) uint { + if column == 0 { + return 0 + } + return column - 1 +} + +func findRuleID(result *wrappers.ScanResult) (ruleID, ruleName, shortMessage string) { + caser := cases.Title(language.English) + + if result.ScanResultData.QueryID == nil && result.ScanResultData.RuleID == nil { + return fmt.Sprintf("%s (%s)", result.ID, result.Type), + caser.String(strings.ToLower(strings.ReplaceAll(result.ID, "-", ""))), + html.UnescapeString(fmt.Sprintf("%s (%s)", result.ScanResultData.PackageIdentifier, result.ID)) + } + + if result.ScanResultData.RuleID != nil { + ruleName = strings.ReplaceAll(result.ScanResultData.RuleName, "_", " ") + return fmt.Sprintf("%s - %s (%s)", ruleName, *result.ScanResultData.RuleID, result.Type), + ruleName, + ruleName + } + + ruleName = strings.ReplaceAll(result.ScanResultData.QueryName, "_", " ") + return fmt.Sprintf("%v - %s (%s)", ruleName, result.ScanResultData.QueryID, result.Type), + ruleName, + ruleName +} + +func findFullDescription(result *wrappers.ScanResult) wrappers.SarifDescription { + var sarifDescription wrappers.SarifDescription + sarifDescription.Text = findDescriptionText(result) + return sarifDescription +} + +func findHelp(result *wrappers.ScanResult) wrappers.SarifHelp { + var sarifHelp wrappers.SarifHelp + sarifHelp.Text = findHelpText(result) + sarifHelp.Markdown = findHelpMarkdownText(result) + + return sarifHelp +} + +func findHelpURI(result *wrappers.ScanResult) string { + if strings.HasPrefix(result.Type, commonParams.SscsType) { + if result.ScanResultData.RemediationLink != "" { + return result.ScanResultData.RemediationLink + } + } + + return wrappers.SarifInformationURI +} + +func findDescriptionText(result *wrappers.ScanResult) string { + if result.Type == commonParams.KicsType { + return fmt.Sprintf( + "%s Value: %s Excepted value: %s", + result.Description, result.ScanResultData.Value, result.ScanResultData.ExpectedValue, + ) + } else if strings.HasPrefix(result.Type, commonParams.SscsType) { + return result.ScanResultData.RuleDescription + } + + return result.Description +} + +func findHelpText(result *wrappers.ScanResult) string { + if strings.HasPrefix(result.Type, commonParams.SscsType) { + return findHelpMarkdownText(result) + } + + return findDescriptionText(result) +} + +func findHelpMarkdownText(result *wrappers.ScanResult) string { + if result.Type == commonParams.KicsType { + return fmt.Sprintf( + "%s

Value: %s
Excepted value: %s", + result.Description, result.ScanResultData.Value, result.ScanResultData.ExpectedValue, + ) + } else if strings.HasPrefix(result.Type, commonParams.SscsType) { + return result.ScanResultData.Remediation + } + + return result.Description +} + +func findProperties(result *wrappers.ScanResult) wrappers.SarifProperties { + var sarifProperties wrappers.SarifProperties + sarifProperties.ID, sarifProperties.Name, _ = findRuleID(result) + sarifProperties.Description = findDescriptionText(result) + sarifProperties.SecuritySeverity = securities[result.Severity] + sarifProperties.Tags = []string{"security", "checkmarx", result.Type} + return sarifProperties +} + +func findSarifLevel(result *wrappers.ScanResult) string { + level := map[string]string{ + infoCx: infoLowSarif, + lowCx: infoLowSarif, + mediumCx: mediumSarif, + highCx: highSarif, + criticalCx: highSarif, + } + return level[result.Severity] +} + +func initSarifResult(result *wrappers.ScanResult) wrappers.SarifScanResult { + var scanResult wrappers.SarifScanResult + scanResult.RuleID, _, scanResult.Message.Text = findRuleID(result) + scanResult.Level = findSarifLevel(result) + scanResult.Locations = []wrappers.SarifLocation{} + + return scanResult +} + +func findResult(result *wrappers.ScanResult) []wrappers.SarifScanResult { + var scanResults []wrappers.SarifScanResult + + if len(result.ScanResultData.Nodes) > 0 { + scanResults = parseSarifResultSast(result, scanResults) + } else if result.Type == commonParams.KicsType { + scanResults = parseSarifResultKics(result, scanResults) + } else if result.Type == commonParams.ScaType { + scanResults = parseSarifResultsSca(result, scanResults) + } else if result.Type == commonParams.ContainersType && wrappers.IsContainersEnabled { + scanResults = parseSarifResultsContainers(result, scanResults) + } else if strings.HasPrefix(result.Type, commonParams.SscsType) { + scanResults = parseSarifResultsSscs(result, scanResults) + } + + if len(scanResults) > 0 { + return scanResults + } + return nil +} + +func parseSarifResultsContainers(result *wrappers.ScanResult, scanResults []wrappers.SarifScanResult) []wrappers.SarifScanResult { + var scanResult = initSarifResult(result) + var scanLocation wrappers.SarifLocation + + scanLocation.PhysicalLocation.ArtifactLocation.URI = result.ScanResultData.ImageFilePath + scanLocation.PhysicalLocation.Region = &wrappers.SarifRegion{} + scanLocation.PhysicalLocation.Region.StartLine = 1 + scanLocation.PhysicalLocation.Region.StartColumn = 1 + scanLocation.PhysicalLocation.Region.EndColumn = 2 + scanResult.Locations = append(scanResult.Locations, scanLocation) + + scanResults = append(scanResults, scanResult) + return scanResults +} + +func parseSarifResultsSca(result *wrappers.ScanResult, scanResults []wrappers.SarifScanResult) []wrappers.SarifScanResult { + if result == nil || result.ScanResultData.ScaPackageCollection == nil || result.ScanResultData.ScaPackageCollection.Locations == nil { + return scanResults + } + for _, location := range result.ScanResultData.ScaPackageCollection.Locations { + var scanResult = initSarifResult(result) + + var scanLocation wrappers.SarifLocation + scanLocation.PhysicalLocation.ArtifactLocation.URI = *location + scanLocation.PhysicalLocation.Region = &wrappers.SarifRegion{} + scanLocation.PhysicalLocation.Region.StartLine = 1 + scanLocation.PhysicalLocation.Region.StartColumn = 1 + scanLocation.PhysicalLocation.Region.EndColumn = 2 + scanResult.Locations = append(scanResult.Locations, scanLocation) + + scanResults = append(scanResults, scanResult) + } + return scanResults +} + +func parseSarifResultKics(result *wrappers.ScanResult, scanResults []wrappers.SarifScanResult) []wrappers.SarifScanResult { + var scanResult = initSarifResult(result) + var scanLocation wrappers.SarifLocation + + scanLocation.PhysicalLocation.ArtifactLocation.URI = strings.Replace( + result.ScanResultData.Filename, + "/", + "", + 1, + ) + scanLocation.PhysicalLocation.Region = &wrappers.SarifRegion{} + scanLocation.PhysicalLocation.Region.StartLine = result.ScanResultData.Line + scanLocation.PhysicalLocation.Region.StartColumn = 1 + scanLocation.PhysicalLocation.Region.EndColumn = 2 + scanResult.Locations = append(scanResult.Locations, scanLocation) + + scanResults = append(scanResults, scanResult) + return scanResults +} + +func parseSarifResultSast(result *wrappers.ScanResult, scanResults []wrappers.SarifScanResult) []wrappers.SarifScanResult { + if result == nil || result.ScanResultData.Nodes == nil { + return scanResults + } + var scanResult = initSarifResult(result) + + var allLocations []wrappers.SarifLocation + for _, node := range result.ScanResultData.Nodes { + var scanLocation wrappers.SarifLocation + if len(node.FileName) >= sarifNodeFileLength { + scanLocation.PhysicalLocation.ArtifactLocation.URI = node.FileName[1:] + if node.Line <= 0 { + continue + } + scanLocation.PhysicalLocation.Region = &wrappers.SarifRegion{} + scanLocation.PhysicalLocation.Region.StartLine = node.Line + column := node.Column + length := node.Length + scanLocation.PhysicalLocation.Region.StartColumn = column + scanLocation.PhysicalLocation.Region.EndColumn = column + length + + allLocations = append(allLocations, scanLocation) + } + } + + if len(allLocations) > 0 { + var threadFlowLocations []wrappers.SarifThreadFlowLocation + for _, loc := range allLocations { + threadFlowLocations = append(threadFlowLocations, wrappers.SarifThreadFlowLocation{Location: loc}) + } + scanResult.CodeFlows = []wrappers.SarifCodeFlow{ + { + ThreadFlows: []wrappers.SarifThreadFlow{ + { + Locations: threadFlowLocations, + }, + }, + }, + } + } + + scanResults = append(scanResults, scanResult) + return scanResults +} + +func parseSarifResultsSscs(result *wrappers.ScanResult, scanResults []wrappers.SarifScanResult) []wrappers.SarifScanResult { + var scanResult = initSarifResult(result) + scanResult.Message.Text = result.Description + + var scanLocation wrappers.SarifLocation + + trimOsSeparatorFromFileName(result) + if result.Type == commonParams.SCSScorecardType && result.ScanResultData.Filename == noFileForScorecardResultString { + scanLocation.PhysicalLocation.ArtifactLocation.URI = artifactLocationURIString + scanLocation.PhysicalLocation.ArtifactLocation.Description = &wrappers.SarifMessage{} + scanLocation.PhysicalLocation.ArtifactLocation.Description.Text = result.ScanResultData.Filename + } else { + scanLocation.PhysicalLocation.ArtifactLocation.URI = result.ScanResultData.Filename + } + + scanLocation.PhysicalLocation.Region = &wrappers.SarifRegion{} + scanLocation.PhysicalLocation.Region.StartLine = result.ScanResultData.Line + scanLocation.PhysicalLocation.Region.StartColumn = 1 + scanLocation.PhysicalLocation.Region.EndColumn = 2 + if result.ScanResultData.Snippet != "" { + scanLocation.PhysicalLocation.Region.Snippet = &wrappers.SarifSnippet{} + scanLocation.PhysicalLocation.Region.Snippet.Text = result.ScanResultData.Snippet + } + + scanResult.Locations = append(scanResult.Locations, scanLocation) + + var properties wrappers.SarifResultProperties + properties.Severity = result.Severity + properties.Validity = result.ScanResultData.Validity + properties.IsInSource = result.ScanResultData.IsInSource + properties.CommitURL = result.ScanResultData.CommitURL + scanResult.Properties = &properties + + scanResults = append(scanResults, scanResult) + return scanResults +} + +func convertNotAvailableNumberToZero(summary *wrappers.ResultSummary) { + if summary.KicsIssues == notAvailableNumber { + summary.KicsIssues = 0 + } else if summary.SastIssues == notAvailableNumber { + summary.SastIssues = 0 + } else if summary.ScaIssues == notAvailableNumber { + summary.ScaIssues = 0 + } else if wrappers.IsContainersEnabled && *summary.ContainersIssues == notAvailableNumber { + *summary.ContainersIssues = 0 + } +} + +func buildAuxiliaryScaMaps(resultsModel *wrappers.ScanResultsCollection, scaPackageModel *[]wrappers.ScaPackageCollection, + scaTypeModel *[]wrappers.ScaTypeCollection) (locationsByID map[string][]*string, typesByCVE map[string]wrappers.ScaTypeCollection) { + locationsByID = make(map[string][]*string) + typesByCVE = make(map[string]wrappers.ScaTypeCollection) + // Create map to be used to populate locations for each package path + for _, result := range resultsModel.Results { + if result.Type == commonParams.ScaType { + for i := range *scaPackageModel { + pkg := &(*scaPackageModel)[i] + locationsByID[pkg.ID] = pkg.Locations + } + for _, types := range *scaTypeModel { + identifier := fmt.Sprintf("%s:%s", types.ID, types.PackageID) + typesByCVE[identifier] = types + } + } + } + return locationsByID, typesByCVE +} + +func buildScaType(typesByCVE map[string]wrappers.ScaTypeCollection, result *wrappers.ScanResult) string { + identifier := buildVulnerabilityIdentifier(result) + types, ok := typesByCVE[identifier] + if ok && types.Type == "SupplyChain" { + return "Supply Chain" + } + return "Vulnerability" +} + +func buildScaState(typesByCVE map[string]wrappers.ScaTypeCollection, result *wrappers.ScanResult) string { + identifier := buildVulnerabilityIdentifier(result) + types, ok := typesByCVE[identifier] + if ok && types.IsIgnored { + return notExploitable + } + return result.State +} + +func buildVulnerabilityIdentifier(result *wrappers.ScanResult) string { + return fmt.Sprintf("%s:%s", result.ID, result.ScanResultData.PackageIdentifier) +} + +func addPackageInformation( + resultsModel *wrappers.ScanResultsCollection, + scaPackageModel *[]wrappers.ScaPackageCollection, + scaTypeModel *[]wrappers.ScaTypeCollection, +) *wrappers.ScanResultsCollection { + locationsByID, typesByCVE := buildAuxiliaryScaMaps(resultsModel, scaPackageModel, scaTypeModel) + scaPackageMap := buildScaPackageMap(*scaPackageModel) + + for _, result := range resultsModel.Results { + if result.Type == commonParams.ScaType { + processResult(result, locationsByID, typesByCVE, scaPackageMap) + } + } + + return resultsModel +} + +func processResult( + result *wrappers.ScanResult, + locationsByID map[string][]*string, + typesByCVE map[string]wrappers.ScaTypeCollection, + scaPackageMap map[string]wrappers.ScaPackageCollection, // Updated parameter +) { + const precision = 1 + + currentID := result.ScanResultData.PackageIdentifier + result.VulnerabilityDetails.CvssScore = util.RoundFloat(result.VulnerabilityDetails.CvssScore, precision) + result.ScaType = buildScaType(typesByCVE, result) + result.State = buildScaState(typesByCVE, result) + + updatePackages(result, scaPackageMap, locationsByID, currentID) +} + +func updatePackages( + result *wrappers.ScanResult, + scaPackageMap map[string]wrappers.ScaPackageCollection, + locationsByID map[string][]*string, + currentID string, +) { + packages, found := scaPackageMap[currentID] + if !found { + return + } + + updateDependencyPaths(packages.DependencyPathArray, locationsByID) + if !packages.SupportsQuickFix { + packages.SupportsQuickFix = hasQuickFix(packages.DependencyPathArray) + } + + if packages.IsDirectDependency { + packages.TypeOfDependency = directDependencyType + } else { + packages.TypeOfDependency = indirectDependencyType + } + + packages.FixLink = buildFixLink(result) + result.ScanResultData.ScaPackageCollection = &packages +} + +func hasQuickFix(dependencyPaths [][]wrappers.DependencyPath) bool { + for i := range dependencyPaths { + head := &dependencyPaths[i][0] + if head.SupportsQuickFix { + return true + } + } + return false +} + +func buildScaPackageMap(scaPackageModel []wrappers.ScaPackageCollection) map[string]wrappers.ScaPackageCollection { + scaPackageMap := make(map[string]wrappers.ScaPackageCollection) + for i := range scaPackageModel { + scaPackageMap[scaPackageModel[i].ID] = scaPackageModel[i] + } + return scaPackageMap +} + +func updateDependencyPaths(dependencyPaths [][]wrappers.DependencyPath, locationsByID map[string][]*string) { + for i := range dependencyPaths { + head := &dependencyPaths[i][0] + head.Locations = locationsByID[head.ID] + head.SupportsQuickFix = len(dependencyPaths[i]) == 1 + + for _, location := range locationsByID[head.ID] { + head.SupportsQuickFix = head.SupportsQuickFix && util.IsPackageFileSupported(*location) + } + } +} + +func buildFixLink(result *wrappers.ScanResult) string { + if result.ID != "" { + return fmt.Sprint(fixLinkPrefix, result.ID) + } + return "" +} + +func filterViolatedRules(policyModel wrappers.PolicyResponseModel) *wrappers.PolicyResponseModel { + i := 0 + for _, policy := range policyModel.Policies { + if len(policy.RulesViolated) > 0 { + policyModel.Policies[i] = policy + i++ + } + } + policyModel.Policies = policyModel.Policies[:i] + return &policyModel +} + +func trimOsSeparatorFromFileName(result *wrappers.ScanResult) { + if result.ScanResultData.Filename != "" { + result.ScanResultData.Filename = strings.TrimPrefix(result.ScanResultData.Filename, "/") + result.ScanResultData.Filename = strings.TrimPrefix(result.ScanResultData.Filename, "\\") + } +} + +// ScannerResponse is the per-scanner status info returned by the results exit-code subcommand. +type ScannerResponse struct { + ScanID string `json:"ScanID,omitempty"` + Name string `json:"Name,omitempty"` + Status string `json:"Status,omitempty"` + Details string `json:"Details,omitempty"` + ErrorCode string `json:"ErrorCode,omitempty"` +} + +func parseURI(summaryBaseURI string) (hostName string) { + parsedURL, err := url.Parse(summaryBaseURI) + if err != nil { + return "" + } + hostName = fmt.Sprintf("%s://%s", parsedURL.Scheme, parsedURL.Host) + + return hostName +} + +func printWarningIfIgnorePolicyOmiited() { + fmt.Printf("\n Warning: The --ignore-policy flag was not implemented because you do not have the required permission.\n Only users with 'override-policy-management' permission can use this flag. \n\n") +} + +func getFilterResultsForAPISecScanner(risksOverviewWrapper wrappers.RisksOverviewWrapper, scanID string, resultsParams map[string]string) (aPISecSeveritySummary *wrappers.APISecFilteredResult, err error) { + var apiSecRiskEntriesResult wrappers.APISecRiskEntriesResult + var errorModel *wrappers.WebError + + apiSecRiskEntriesResult, errorModel, err = risksOverviewWrapper.GetFilterResultForAPISecByScanID(scanID, resultsParams) + if err != nil { + return nil, errors.Wrapf(err, "%s", failedListingResults) + } + if errorModel != nil { + return nil, errors.Errorf("%s: CODE: %d, %s", failedListingResults, errorModel.Code, errorModel.Message) + } + if len(apiSecRiskEntriesResult.Entries) > 0 { + entries := apiSecRiskEntriesResult.Entries + severityCount := make(map[string]int) + originCount := make(map[string]int) + totalRecords := 0 + for i := range entries { + entry := &entries[i] + if !isExploitable(entry.State) { + continue + } + sev := strings.ToLower(entry.Severity) + severityCount[sev]++ + orig := strings.ToLower(entry.Origin) + originCount[orig]++ + totalRecords++ + } + var riskDistribution []wrappers.RiskDistributionEntry + if originCount[originCode] > 0 { + riskDistribution = append(riskDistribution, wrappers.RiskDistributionEntry{Origin: originCode, Total: originCount[originCode]}) + } + if originCount[originDocumentation] > 0 { + riskDistribution = append(riskDistribution, wrappers.RiskDistributionEntry{Origin: originDocumentation, Total: originCount[originDocumentation]}) + } + return &wrappers.APISecFilteredResult{ + SeverityCount: severityCount, + RiskDistribution: riskDistribution, + TotalRisksCount: totalRecords, + }, nil + } + return nil, nil +} diff --git a/internal/commands/result_test.go b/internal/commands/result_test.go index dc0063351..5bd0fe670 100644 --- a/internal/commands/result_test.go +++ b/internal/commands/result_test.go @@ -1591,7 +1591,8 @@ func TestIgnorePolicyWithNoPermission(t *testing.T) { t.Fatalf("failed to copy output: %v", err) // Handle the error if io.Copy fails } output := buf.String() - assert.Assert(t, strings.Contains(output, "Warning: The --ignore-policy flag was not implemented because you don’t have the required permission."), "'Ignore Policy flag omitted because you dont have permission' should not be present in the output") + expectedWarning := "Warning: The --ignore-policy flag was not implemented because you do not have the required permission." + assert.Assert(t, strings.Contains(output, expectedWarning), "’Ignore Policy flag omitted because you dont have permission’ should not be present in the output") } func TestIgnorePolicyWithPermission(t *testing.T) { @@ -1625,7 +1626,8 @@ func TestIgnorePolicyWithPermission(t *testing.T) { t.Fatalf("failed to copy output: %v", err) // Handle the error if io.Copy fails } output := buf.String() - assert.Assert(t, !strings.Contains(output, "Warning: The --ignore-policy flag was not implemented because you don’t have the required permission."), "'Ignore Policy flag omitted because you dont have permission' should not be present in the output") + expectedWarning := "Warning: The --ignore-policy flag was not implemented because you do not have the required permission." + assert.Assert(t, !strings.Contains(output, expectedWarning), "’Ignore Policy flag omitted because you dont have permission’ should not be present in the output") } func TestParseGlSastVulnerability_QueryDescriptionLink_Succeed(t *testing.T) { From 787783ab1527eda0f73fe3744221d23c17fd7c53 Mon Sep 17 00:00:00 2001 From: atishj99 <141334503+cx-atish-jadhav@users.noreply.github.com> Date: Thu, 28 May 2026 21:06:27 +0530 Subject: [PATCH 24/27] Fix CVE vulnerabilities and lint issues - Upgrade golang.org/x/image to v0.39.0 (CVE-2026-33813) - Upgrade github.com/go-jose/go-jose/v3 to v3.0.5 (CVE-2026-34986) - Upgrade github.com/opencontainers/runc to v1.3.4 (CVE-2025-52881) - Extract repeated string to constant in result_test.go (goconst lint fix) --- go.mod | 17 ++++++++++ go.sum | 54 ++++++++++++++++++++++++++++++++ internal/commands/result_test.go | 25 +++++++-------- 3 files changed, 83 insertions(+), 13 deletions(-) diff --git a/go.mod b/go.mod index 593b653b0..6e8afd8c1 100644 --- a/go.mod +++ b/go.mod @@ -45,6 +45,7 @@ require ( cloud.google.com/go/iam v1.5.3 // indirect cloud.google.com/go/monitoring v1.24.3 // indirect cloud.google.com/go/storage v1.61.3 // indirect + cyphar.com/go-pathrs v0.2.1 // indirect github.com/GoogleCloudPlatform/opentelemetry-operations-go/detectors/gcp v1.31.0 // indirect github.com/GoogleCloudPlatform/opentelemetry-operations-go/exporter/metric v0.55.0 // indirect github.com/GoogleCloudPlatform/opentelemetry-operations-go/internal/resourcemapping v0.55.0 // indirect @@ -78,17 +79,24 @@ require ( github.com/bodgit/sevenzip v1.6.1 // indirect github.com/bodgit/windows v1.0.1 // indirect github.com/cespare/xxhash/v2 v2.3.0 // indirect + github.com/checkpoint-restore/go-criu/v6 v6.3.0 // indirect + github.com/cilium/ebpf v0.17.3 // indirect github.com/clipperhouse/displaywidth v0.10.0 // indirect github.com/clipperhouse/uax29/v2 v2.6.0 // indirect github.com/cncf/xds/go v0.0.0-20251210132809-ee656c7534f5 // indirect + github.com/containerd/console v1.0.5 // indirect github.com/containerd/containerd/v2 v2.3.1 // indirect github.com/containerd/plugin v1.1.0 // indirect + github.com/coreos/go-systemd/v22 v22.7.0 // indirect + github.com/cpuguy83/go-md2man/v2 v2.0.7 // indirect github.com/diskfs/go-diskfs v1.7.0 // indirect github.com/distribution/distribution/v3 v3.1.1 // indirect github.com/envoyproxy/go-control-plane/envoy v1.36.0 // indirect github.com/envoyproxy/protoc-gen-validate v1.3.0 // indirect + github.com/go-jose/go-jose/v3 v3.0.5 // indirect github.com/go-jose/go-jose/v4 v4.1.4 // indirect github.com/goccy/go-yaml v1.19.2 // indirect + github.com/godbus/dbus/v5 v5.1.0 // indirect github.com/gohugoio/hashstructure v0.6.0 // indirect github.com/google/s2a-go v0.1.9 // indirect github.com/googleapis/enterprise-certificate-proxy v0.3.14 // indirect @@ -106,17 +114,26 @@ require ( github.com/minio/minlz v1.0.1 // indirect github.com/moby/moby/api v1.54.1 // indirect github.com/moby/moby/client v0.4.0 // indirect + github.com/moby/sys/capability v0.4.0 // indirect + github.com/mrunalp/fileutils v0.5.1 // indirect github.com/nix-community/go-nix v0.0.0-20250101154619-4bdde671e0a1 // indirect github.com/nwaples/rardecode/v2 v2.2.0 // indirect github.com/olekukonko/cat v0.0.0-20250911104152-50322a0618f6 // indirect github.com/olekukonko/errors v1.2.0 // indirect github.com/olekukonko/ll v0.1.6 // indirect + github.com/opencontainers/cgroups v0.0.4 // indirect + github.com/opencontainers/runc v1.3.4 // indirect + github.com/opencontainers/selinux v1.13.1 // indirect github.com/pkg/xattr v0.4.9 // indirect github.com/planetscale/vtprotobuf v0.6.1-0.20240319094008-0393e58bdf10 // indirect github.com/prometheus/procfs v0.20.1 // indirect + github.com/seccomp/libseccomp-golang v0.10.0 // indirect github.com/smallnest/ringbuffer v0.0.0-20241116012123-461381446e3d // indirect github.com/sorairolake/lzip-go v0.3.8 // indirect github.com/spiffe/go-spiffe/v2 v2.6.0 // indirect + github.com/urfave/cli v1.22.16 // indirect + github.com/vishvananda/netlink v1.3.1 // indirect + github.com/vishvananda/netns v0.0.5 // indirect go.opentelemetry.io/contrib/detectors/gcp v1.39.0 // indirect go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.68.0 // indirect go.opentelemetry.io/otel/exporters/stdout/stdoutmetric v1.42.0 // indirect diff --git a/go.sum b/go.sum index 0a4e739f9..cdf0a48f3 100644 --- a/go.sum +++ b/go.sum @@ -67,6 +67,8 @@ cloud.google.com/go/storage v1.61.3 h1:VS//ZfBuPGDvakfD9xyPW1RGF1Vy3BWUoVZXgW1KM cloud.google.com/go/storage v1.61.3/go.mod h1:JtqK8BBB7TWv0HVGHubtUdzYYrakOQIsMLffZ2Z/HWk= cloud.google.com/go/trace v1.11.7 h1:kDNDX8JkaAG3R2nq1lIdkb7FCSi1rCmsEtKVsty7p+U= cloud.google.com/go/trace v1.11.7/go.mod h1:TNn9d5V3fQVf6s4SCveVMIBS2LJUqo73GACmq/Tky0s= +cyphar.com/go-pathrs v0.2.1 h1:9nx1vOgwVvX1mNBWDu93+vaceedpbsDqo+XuBGL40b8= +cyphar.com/go-pathrs v0.2.1/go.mod h1:y8f1EMG7r+hCuFf/rXsKqMJrJAUoADZGNh5/vZPKcGc= dario.cat/mergo v1.0.2 h1:85+piFYR1tMbRrLcDwR18y4UKJ3aH1Tbzi24VRW1TK8= dario.cat/mergo v1.0.2/go.mod h1:E/hbnu0NxMFBjpMIE34DRGLWqDy0g5FuKDhCb31ngxA= dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU= @@ -80,6 +82,7 @@ github.com/BobuSumisu/aho-corasick v1.0.3 h1:uuf+JHwU9CHP2Vx+wAy6jcksJThhJS9ehR8 github.com/BobuSumisu/aho-corasick v1.0.3/go.mod h1:hm4jLcvZKI2vRF2WDU1N4p/jpWtpOzp3nLmi9AzX/XE= github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= github.com/BurntSushi/toml v0.4.1/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbicEuybxQ= +github.com/BurntSushi/toml v1.4.0/go.mod h1:ukJfTF/6rtPPRCnwkur4qwRxa8vTRFBF0uk2lLoLwho= github.com/BurntSushi/toml v1.6.0 h1:dRaEfpa2VI55EwlIW72hMRHdWouJeRF7TPYhI+AUQjk= github.com/BurntSushi/toml v1.6.0/go.mod h1:ukJfTF/6rtPPRCnwkur4qwRxa8vTRFBF0uk2lLoLwho= github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo= @@ -297,6 +300,8 @@ github.com/charmbracelet/x/term v0.2.2 h1:xVRT/S2ZcKdhhOuSP4t5cLi5o+JxklsoEObBSg github.com/charmbracelet/x/term v0.2.2/go.mod h1:kF8CY5RddLWrsgVwpw4kAa6TESp6EB5y3uxGLeCqzAI= github.com/checkmarx/2ms/v3 v3.21.0 h1:EcabeDypNMsSidISQbziZ062HjMZQ+Hm/uOJ5AOxK8o= github.com/checkmarx/2ms/v3 v3.21.0/go.mod h1:e8f4F94MZ+iCetR/G3aw7nXdPe6TgPI92Zzk/NG1l0o= +github.com/checkpoint-restore/go-criu/v6 v6.3.0 h1:mIdrSO2cPNWQY1truPg6uHLXyKHk3Z5Odx4wjKOASzA= +github.com/checkpoint-restore/go-criu/v6 v6.3.0/go.mod h1:rrRTN/uSwY2X+BPRl/gkulo9gsKOSAeVp9/K2tv7xZI= github.com/chromedp/cdproto v0.0.0-20230802225258-3cf4e6d46a89/go.mod h1:GKljq0VrfU4D5yc+2qA6OVr8pmO/MBbPEWqWQ/oqGEs= github.com/chromedp/chromedp v0.9.2/go.mod h1:LkSXJKONWTCHAfQasKFUZI+mxqS4tZqhmtGzzhLsnLs= github.com/chromedp/sysutil v1.0.0/go.mod h1:kgWmDdq8fTzXYcKIBqIYvRRTnYb9aNS9moAV0xufSww= @@ -306,6 +311,8 @@ github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5P github.com/chzyer/readline v1.5.1/go.mod h1:Eh+b79XXUwfKfcPLepksvw2tcLE/Ct21YObkaSkeBlk= github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU= github.com/chzyer/test v1.0.0/go.mod h1:2JlltgoNkt4TW/z9V/IzDdFaMTM2JPIi26O1pF38GC8= +github.com/cilium/ebpf v0.17.3 h1:FnP4r16PWYSE4ux6zN+//jMcW4nMVRvuTLVTvCjyyjg= +github.com/cilium/ebpf v0.17.3/go.mod h1:G5EDHij8yiLzaqn0WjyfJHvRa+3aDlReIaLVRMvOyJk= github.com/circonus-labs/circonus-gometrics v2.3.1+incompatible/go.mod h1:nmEj6Dob7S7YxXgwXpfOuvO54S+tGdZdw9fuRZt25Ag= github.com/circonus-labs/circonusllhist v0.1.3/go.mod h1:kMXHVDlOchFAehlya5ePtbp5jckzBHf4XRpQvBOLI+I= github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= @@ -329,6 +336,8 @@ github.com/cncf/xds/go v0.0.0-20251210132809-ee656c7534f5 h1:6xNmx7iTtyBRev0+D/T github.com/cncf/xds/go v0.0.0-20251210132809-ee656c7534f5/go.mod h1:KdCmV+x/BuvyMxRnYBlmVaq4OLiKW6iRQfvC62cvdkI= github.com/containerd/cgroups/v3 v3.1.3 h1:eUNflyMddm18+yrDmZPn3jI7C5hJ9ahABE5q6dyLYXQ= github.com/containerd/cgroups/v3 v3.1.3/go.mod h1:PKZ2AcWmSBsY/tJUVhtS/rluX0b1uq1GmPO1ElCmbOw= +github.com/containerd/console v1.0.5 h1:R0ymNeydRqH2DmakFNdmjR2k0t7UPuiOV/N/27/qqsc= +github.com/containerd/console v1.0.5/go.mod h1:YynlIjWYF8myEu6sdkwKIvGQq+cOckRm6So2avqoYAk= github.com/containerd/containerd v1.7.32 h1:S54xuVcPxeLaYgaRABtpJ2VyVUVsy0IGf7qHBs+sbY8= github.com/containerd/containerd v1.7.32/go.mod h1:jdwD6s/BhV4XVJGrvtziNPVA+83n66TwptVaPKprq4E= github.com/containerd/containerd/api v1.11.1 h1:h8nfoDW9+fNsC/9TwiAHj8B1GzXKtR4eFtkhi/X5RLU= @@ -361,7 +370,11 @@ github.com/coreos/go-systemd/v22 v22.5.0/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSV github.com/coreos/go-systemd/v22 v22.7.0 h1:LAEzFkke61DFROc7zNLX/WA2i5J8gYqe0rSj9KI28KA= github.com/coreos/go-systemd/v22 v22.7.0/go.mod h1:xNUYtjHu2EDXbsxz1i41wouACIwT7Ybq9o0BQhMwD0w= github.com/cpuguy83/go-md2man/v2 v2.0.1/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= +github.com/cpuguy83/go-md2man/v2 v2.0.2/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= +github.com/cpuguy83/go-md2man/v2 v2.0.5/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= github.com/cpuguy83/go-md2man/v2 v2.0.6/go.mod h1:oOW0eioCTA6cOiMLiUPZOpcVxMig6NIQQ7OS05n1F4g= +github.com/cpuguy83/go-md2man/v2 v2.0.7 h1:zbFlGlXEAKlwXpmvle3d8Oe3YnkKIK4xSRTd3sHPnBo= +github.com/cpuguy83/go-md2man/v2 v2.0.7/go.mod h1:oOW0eioCTA6cOiMLiUPZOpcVxMig6NIQQ7OS05n1F4g= github.com/creack/pty v1.1.24 h1:bJrF4RRfyJnbTJqzRLHzcGaZK1NeM5kTC9jGgovnR1s= github.com/creack/pty v1.1.24/go.mod h1:08sCNb52WyoAwi2QDyzUCTgcvVFhUzewun7wtTfvcwE= github.com/cyphar/filepath-securejoin v0.6.1 h1:5CeZ1jPXEiYt3+Z6zqprSAgSWiggmpVyciv8syjIpVE= @@ -495,6 +508,8 @@ github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2 github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= github.com/go-gorp/gorp/v3 v3.1.0 h1:ItKF/Vbuj31dmV4jxA1qblpSwkl9g1typ24xoe70IGs= github.com/go-gorp/gorp/v3 v3.1.0/go.mod h1:dLEjIyyRNiXvNZ8PSmzpt1GsWAUK8kjVhEpjH8TixEw= +github.com/go-jose/go-jose/v3 v3.0.5 h1:BLLJWbC4nMZOfuPVxoZIxeYsn6Nl2r1fITaJ78UQlVQ= +github.com/go-jose/go-jose/v3 v3.0.5/go.mod h1:5b+7YgP7ZICgJDBdfjZaIt+H/9L9T/YQrVfLAMboGkQ= github.com/go-jose/go-jose/v4 v4.1.4 h1:moDMcTHmvE6Groj34emNPLs/qtYXRVcd6S7NHbHz3kA= github.com/go-jose/go-jose/v4 v4.1.4/go.mod h1:x4oUasVrzR7071A4TnHLGSPpNOm2a21K9Kf04k1rs08= github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= @@ -534,6 +549,8 @@ github.com/gobwas/ws v1.2.1/go.mod h1:hRKAFb8wOxFROYNsT1bqfWnhX+b5MFeJM9r2ZSwg/K github.com/goccy/go-yaml v1.19.2 h1:PmFC1S6h8ljIz6gMRBopkjP1TVT7xuwrButHID66PoM= github.com/goccy/go-yaml v1.19.2/go.mod h1:XBurs7gK8ATbW4ZPGKgcbrY1Br56PdM69F7LkFRi1kA= github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= +github.com/godbus/dbus/v5 v5.1.0 h1:4KLkAxT3aOY8Li4FRJe/KvhoNFFxo0m6fNuFUO8QJUk= +github.com/godbus/dbus/v5 v5.1.0/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= github.com/gofrs/flock v0.13.0 h1:95JolYOvGMqeH31+FC7D2+uULf6mG61mEZ/A8dRYMzw= github.com/gofrs/flock v0.13.0/go.mod h1:jxeyy9R1auM5S6JYDBhDt+E2TCo7DkratH4Pgi8P+Z0= github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= @@ -599,6 +616,7 @@ github.com/google/go-cmp v0.5.3/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/ github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8= github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU= github.com/google/go-containerregistry v0.21.5 h1:KTJG9Pn/jC0VdZR6ctV3/jcN+q6/Iqlx0sTVz3ywZlM= @@ -873,6 +891,8 @@ github.com/moby/moby/api v1.54.1 h1:TqVzuJkOLsgLDDwNLmYqACUuTehOHRGKiPhvH8V3Nn4= github.com/moby/moby/api v1.54.1/go.mod h1:+RQ6wluLwtYaTd1WnPLykIDPekkuyD/ROWQClE83pzs= github.com/moby/moby/client v0.4.0 h1:S+2XegzHQrrvTCvF6s5HFzcrywWQmuVnhOXe2kiWjIw= github.com/moby/moby/client v0.4.0/go.mod h1:QWPbvWchQbxBNdaLSpoKpCdf5E+WxFAgNHogCWDoa7g= +github.com/moby/sys/capability v0.4.0 h1:4D4mI6KlNtWMCM1Z/K0i7RV1FkX+DBDHKVJpCndZoHk= +github.com/moby/sys/capability v0.4.0/go.mod h1:4g9IK291rVkms3LKCDOoYlnV8xKwoDTpIrNEE35Wq0I= github.com/moby/sys/mountinfo v0.7.2 h1:1shs6aH5s4o5H2zQLn796ADW1wMrIwHsyJ2v9KouLrg= github.com/moby/sys/mountinfo v0.7.2/go.mod h1:1YOa8w8Ih7uW0wALDUgT1dTTSBrZ+HiBLGws92L2RU4= github.com/moby/sys/sequential v0.6.0 h1:qrx7XFUd/5DxtqcoH1h438hF5TmOvzC/lspjy7zgvCU= @@ -895,6 +915,8 @@ github.com/modern-go/reflect2 v1.0.3-0.20250322232337-35a7c28c31ee h1:W5t00kpgFd github.com/modern-go/reflect2 v1.0.3-0.20250322232337-35a7c28c31ee/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk= github.com/monochromegane/go-gitignore v0.0.0-20200626010858-205db1a8cc00 h1:n6/2gBQ3RWajuToeY6ZtZTIKv2v7ThUy5KKusIT0yc0= github.com/monochromegane/go-gitignore v0.0.0-20200626010858-205db1a8cc00/go.mod h1:Pm3mSP3c5uWn86xMLZ5Sa7JB9GsEZySvHYXCTK4E9q4= +github.com/mrunalp/fileutils v0.5.1 h1:F+S7ZlNKnrwHfSwdlgNSkKo67ReVf8o9fel6C3dkm/Q= +github.com/mrunalp/fileutils v0.5.1/go.mod h1:M1WthSahJixYnrXQl/DFQuteStB1weuxD2QJNHXfbSQ= github.com/mssola/user_agent v0.6.0 h1:uwPR4rtWlCHRFyyP9u2KOV0u8iQXmS7Z7feTrstQwk4= github.com/mssola/user_agent v0.6.0/go.mod h1:TTPno8LPY3wAIEKRpAtkdMT0f8SE24pLRGPahjCH4uw= github.com/muesli/ansi v0.0.0-20230316100256-276c6243b2f6 h1:ZK8zHtRHOkbHy6Mmr5D264iyp3TiX5OmNcI5cIARiQI= @@ -926,12 +948,18 @@ github.com/onsi/ginkgo/v2 v2.28.1 h1:S4hj+HbZp40fNKuLUQOYLDgZLwNUVn19N3Atb98NCyI github.com/onsi/ginkgo/v2 v2.28.1/go.mod h1:CLtbVInNckU3/+gC8LzkGUb9oF+e8W8TdUsxPwvdOgE= github.com/onsi/gomega v1.39.1 h1:1IJLAad4zjPn2PsnhH70V4DKRFlrCzGBNrNaru+Vf28= github.com/onsi/gomega v1.39.1/go.mod h1:hL6yVALoTOxeWudERyfppUcZXjMwIMLnuSfruD2lcfg= +github.com/opencontainers/cgroups v0.0.4 h1:XVj8P/IHVms/j+7eh8ggdkTLAxjz84ZzuFyGoE28DR4= +github.com/opencontainers/cgroups v0.0.4/go.mod h1:s8lktyhlGUqM7OSRL5P7eAW6Wb+kWPNvt4qvVfzA5vs= github.com/opencontainers/go-digest v1.0.0 h1:apOUWs51W5PlhuyGyz9FCeeBIOUDA/6nW8Oi/yOhh5U= github.com/opencontainers/go-digest v1.0.0/go.mod h1:0JzlMkj0TRzQZfJkVvzbP0HBR3IKzErnv2BNG4W4MAM= github.com/opencontainers/image-spec v1.1.1 h1:y0fUlFfIZhPF1W537XOLg0/fcx6zcHCJwooC2xJA040= github.com/opencontainers/image-spec v1.1.1/go.mod h1:qpqAh3Dmcf36wStyyWU+kCeDgrGnAve2nCC8+7h8Q0M= +github.com/opencontainers/runc v1.3.4 h1:+lwmPUTzbgv0JFqu8zBU2WtHYbm+JPPS9hxB/PvWd30= +github.com/opencontainers/runc v1.3.4/go.mod h1:o1wyv76EDlTkcf0KTFgN8bMWLPvgF/HfX709lDv+rr4= github.com/opencontainers/runtime-spec v1.3.0 h1:YZupQUdctfhpZy3TM39nN9Ika5CBWT5diQ8ibYCRkxg= github.com/opencontainers/runtime-spec v1.3.0/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0= +github.com/opencontainers/selinux v1.13.0 h1:Zza88GWezyT7RLql12URvoxsbLfjFx988+LGaWfbL84= +github.com/opencontainers/selinux v1.13.0/go.mod h1:XxWTed+A/s5NNq4GmYScVy+9jzXhGBVEOAyucdRUY8s= github.com/orisano/pixelmatch v0.0.0-20220722002657-fb0b55479cde/go.mod h1:nZgzbfBr3hhjoZnS66nKrHmduYNpc34ny7RK4z5/HM0= github.com/pascaldekloe/goe v0.0.0-20180627143212-57f6aae5913c/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc= github.com/pascaldekloe/goe v0.1.0/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc= @@ -1033,6 +1061,8 @@ github.com/scylladb/go-set v1.0.3-0.20200225121959-cc7b2070d91e/go.mod h1:DkpGd7 github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529/go.mod h1:DxrIzT+xaE7yg65j358z/aeFdxmN0P9QXhEzd20vsDc= github.com/sebdah/goldie/v2 v2.8.0 h1:dZb9wR8q5++oplmEiJT+U/5KyotVD+HNGCAc5gNr8rc= github.com/sebdah/goldie/v2 v2.8.0/go.mod h1:oZ9fp0+se1eapSRjfYbsV/0Hqhbuu3bJVvKI/NNtssI= +github.com/seccomp/libseccomp-golang v0.10.0 h1:aA4bp+/Zzi0BnWZ2F1wgNBs5gTpm+na2rWM6M9YjLpY= +github.com/seccomp/libseccomp-golang v0.10.0/go.mod h1:JA8cRccbGaA1s33RQf7Y1+q9gHmZX1yB/z9WDN1C6fg= github.com/sergi/go-diff v1.1.0/go.mod h1:STckp+ISIX8hZLjrqAeVduY0gWCT9IjLuqbuNXdaHfM= github.com/sergi/go-diff v1.2.0/go.mod h1:STckp+ISIX8hZLjrqAeVduY0gWCT9IjLuqbuNXdaHfM= github.com/sergi/go-diff v1.4.0 h1:n/SP9D5ad1fORl+llWyN+D6qoUETXNZARKjyY2/KVCw= @@ -1069,6 +1099,7 @@ github.com/spf13/cast v1.4.1/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkU github.com/spf13/cast v1.10.0 h1:h2x0u2shc1QuLHfxi+cTJvs30+ZAHOGRic8uyGTDWxY= github.com/spf13/cast v1.10.0/go.mod h1:jNfB8QC9IA6ZuY2ZjDp0KtFO2LZZlg4S/7bzP6qqeHo= github.com/spf13/cobra v1.3.0/go.mod h1:BrRVncBjOJa/eUcVVm9CE+oC6as8k+VYr4NY7WCi9V4= +github.com/spf13/cobra v1.5.0/go.mod h1:dWXEIy2H428czQCjInthrTRUg7yKbok+2Qi/yBIJoUM= github.com/spf13/cobra v1.10.2 h1:DMTTonx5m65Ic0GOoRY2c16WCbHxOOw6xxezuLaBpcU= github.com/spf13/cobra v1.10.2/go.mod h1:7C1pvHqHw5A4vrJfjNwvOdzYu0Gml16OCs2GRiTUUS4= github.com/spf13/jwalterweatherman v1.1.0/go.mod h1:aNWZUN0dPAAO/Ljvb5BEdw96iTZ0EXowPYD95IqWIGo= @@ -1096,6 +1127,8 @@ github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/ github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= +github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= +github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= github.com/stretchr/testify v1.11.1 h1:7s2iGBzp5EwR7/aIZr8ao5+dra3wiQyKjjFuvgVKu7U= github.com/stretchr/testify v1.11.1/go.mod h1:wZwfW3scLgRK+23gO65QZefKpKQRnfz6sD981Nm4B6U= github.com/subosito/gotenv v1.2.0/go.mod h1:N0PQaV/YGNqwC0u51sEeR/aUtSLEXKX9iv69rRypqCw= @@ -1123,12 +1156,18 @@ github.com/tv42/httpunix v0.0.0-20150427012821-b75d8614f926/go.mod h1:9ESjWnEqri github.com/ulikunitz/xz v0.5.8/go.mod h1:nbz6k7qbPmH4IRqmfOplQw/tblSgqTqBwxkY0oWt/14= github.com/ulikunitz/xz v0.5.15 h1:9DNdB5s+SgV3bQ2ApL10xRc35ck0DuIX/isZvIk+ubY= github.com/ulikunitz/xz v0.5.15/go.mod h1:nbz6k7qbPmH4IRqmfOplQw/tblSgqTqBwxkY0oWt/14= +github.com/urfave/cli v1.22.16 h1:MH0k6uJxdwdeWQTwhSO42Pwr4YLrNLwBtg1MRgTqPdQ= +github.com/urfave/cli v1.22.16/go.mod h1:EeJR6BKodywf4zciqrdw6hpCPk68JO9z5LazXZMn5Po= github.com/vbatts/go-mtree v0.7.0 h1:ytmOc3MTRidZiBi9VBCyZ2BHe4fZS47L5v7BVXDWW4E= github.com/vbatts/go-mtree v0.7.0/go.mod h1:EjdpFC+LZy1TXbRGNa1MKKgjQ+7ew3foMFJK8o4/TdY= github.com/vbatts/tar-split v0.12.2 h1:w/Y6tjxpeiFMR47yzZPlPj/FcPLpXbTUi/9H7d3CPa4= github.com/vbatts/tar-split v0.12.2/go.mod h1:eF6B6i6ftWQcDqEn3/iGFRFRo8cBIMSJVOpnNdfTMFA= github.com/vifraa/gopom v1.0.0 h1:L9XlKbyvid8PAIK8nr0lihMApJQg/12OBvMA28BcWh0= github.com/vifraa/gopom v1.0.0/go.mod h1:oPa1dcrGrtlO37WPDBm5SqHAT+wTgF8An1Q71Z6Vv4o= +github.com/vishvananda/netlink v1.3.1 h1:3AEMt62VKqz90r0tmNhog0r/PpWKmrEShJU0wJW6bV0= +github.com/vishvananda/netlink v1.3.1/go.mod h1:ARtKouGSTGchR8aMwmkzC0qiNPrrWO5JS/XMVl45+b4= +github.com/vishvananda/netns v0.0.5 h1:DfiHV+j8bA32MFM7bfEunvT8IAqQ/NzSJHtcmW5zdEY= +github.com/vishvananda/netns v0.0.5/go.mod h1:SpkAiCQRtJ6TvvxPnOSyH3BMl6unz3xZlaprSwhNNJM= github.com/wagoodman/go-partybus v0.0.0-20230516145632-8ccac152c651 h1:jIVmlAFIqV3d+DOxazTR9v+zgj8+VYuQBzPgBZvWBHA= github.com/wagoodman/go-partybus v0.0.0-20230516145632-8ccac152c651/go.mod h1:b26F2tHLqaoRQf8DywqzVaV1MQ9yvjb0OMcNl7Nxu20= github.com/wagoodman/go-progress v0.0.0-20260303201901-10176f79b2c0 h1:EHsPe0Q0ANoLOZff1dBLAyeWLTA4sbPTpGI+2zb0FnM= @@ -1256,6 +1295,7 @@ golang.org/x/crypto v0.0.0-20210817164053-32db794688a5/go.mod h1:GvvjBRRGRdwPK5y golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/crypto v0.0.0-20220622213112-05595931fe9d/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= golang.org/x/crypto v0.6.0/go.mod h1:OFC/31mSvZgRz0V1QTNCzfAI1aIRzbiufJtkMIlEp58= +golang.org/x/crypto v0.19.0/go.mod h1:Iy9bg/ha4yyC70EfRS8jz+B6ybOBKMaSxLj6P6oBDfU= golang.org/x/crypto v0.50.0 h1:zO47/JPrL6vsNkINmLoo/PH1gcxpls50DNogFvB5ZGI= golang.org/x/crypto v0.50.0/go.mod h1:3muZ7vA7PBCE6xgPX7nkzzjiUq87kRItoJQM1Yo8S+Q= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= @@ -1297,6 +1337,7 @@ golang.org/x/mod v0.4.1/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.5.0/go.mod h1:5OXOZSfqPIIbmVBIIKWRFfZjPR0E5r58TLhUjH0a2Ro= golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= +golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= golang.org/x/mod v0.35.0 h1:Ww1D637e6Pg+Zb2KrWfHQUnH2dQRLBQyAtpr/haaJeM= golang.org/x/mod v0.35.0/go.mod h1:+GwiRhIInF8wPm+4AoT6L0FA1QWAad3OMdTRx4tFYlU= golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= @@ -1344,6 +1385,7 @@ golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qx golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= golang.org/x/net v0.7.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= +golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg= golang.org/x/net v0.53.0 h1:d+qAbo5L0orcWAr0a9JweQpjXF19LMXJE8Ey7hwOdUA= golang.org/x/net v0.53.0/go.mod h1:JvMuJH7rrdiCfbeHoo3fCQU24Lf5JJwT9W3sJFulfgs= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= @@ -1377,6 +1419,7 @@ golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJ golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.20.0 h1:e0PTpb7pjO8GAtTs2dQ6jYa5BWYlMuX047Dco/pItO4= golang.org/x/sync v0.20.0/go.mod h1:9xrNwdLfx4jkKbNva9FpL6vEN7evnE43NNNJQ2LF3+0= golang.org/x/sys v0.0.0-20180823144017-11551d06cbcc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= @@ -1452,14 +1495,21 @@ golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.2.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.10.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.17.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/sys v0.43.0 h1:Rlag2XtaFTxp19wS8MXlJwTvoh8ArU6ezoyFsMyCTNI= golang.org/x/sys v0.43.0/go.mod h1:4GL1E5IUh+htKOUEOaiffhrAeqysfVGipDYzABqnCmw= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k= +golang.org/x/term v0.8.0/go.mod h1:xPskH00ivmX89bAKVGSKKtLOWNx2+17Eiy94tnKShWo= +golang.org/x/term v0.17.0/go.mod h1:lLRBjIVuehSbZlaOtGMbcMncT+aqLLLmKrsjNrUguwk= golang.org/x/term v0.42.0 h1:UiKe+zDFmJobeJ5ggPwOshJIVt6/Ft0rcfrXZDLWAWY= golang.org/x/term v0.42.0/go.mod h1:Dq/D+snpsbazcBG5+F9Q1n2rXV8Ma+71xEjTRufARgY= golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= @@ -1472,6 +1522,8 @@ golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= +golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= +golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= golang.org/x/text v0.36.0 h1:JfKh3XmcRPqZPKevfXVpI1wXPTqbkE5f7JA92a55Yxg= golang.org/x/text v0.36.0/go.mod h1:NIdBknypM8iqVmPiuco0Dh6P5Jcdk8lJL0CUebqK164= golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= @@ -1534,6 +1586,7 @@ golang.org/x/tools v0.1.3/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= golang.org/x/tools v0.1.4/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= golang.org/x/tools v0.1.5/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= +golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU= golang.org/x/tools v0.44.0 h1:UP4ajHPIcuMjT1GqzDWRlalUEoY+uzoZKnhOjbIPD2c= golang.org/x/tools v0.44.0/go.mod h1:KA0AfVErSdxRZIsOVipbv3rQhVXTnlU6UhKxHd1seDI= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= @@ -1697,6 +1750,7 @@ google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlba google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= google.golang.org/protobuf v1.27.1/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= +google.golang.org/protobuf v1.28.1/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= google.golang.org/protobuf v1.36.12-0.20260120151049-f2248ac996af h1:+5/Sw3GsDNlEmu7TfklWKPdQ0Ykja5VEmq2i817+jbI= google.golang.org/protobuf v1.36.12-0.20260120151049-f2248ac996af/go.mod h1:HTf+CrKn2C3g5S8VImy6tdcUvCska2kB7j23XfzDpco= gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw= diff --git a/internal/commands/result_test.go b/internal/commands/result_test.go index 5bd0fe670..ed634427c 100644 --- a/internal/commands/result_test.go +++ b/internal/commands/result_test.go @@ -27,15 +27,16 @@ import ( const fileName = "cx_result" const ( - resultsCommand = "results" - codeBashingCommand = "codebashing" - vulnerabilityValue = "Reflected XSS All Clients" - languageValue = "PHP" - cweValue = "79" - jsonValue = "json" - tableValue = "table" - listValue = "list" - secretDetectionLine = "| Secret Detection 0 1 1 0 0 Completed |" + resultsCommand = "results" + codeBashingCommand = "codebashing" + vulnerabilityValue = "Reflected XSS All Clients" + languageValue = "PHP" + cweValue = "79" + jsonValue = "json" + tableValue = "table" + listValue = "list" + secretDetectionLine = "| Secret Detection 0 1 1 0 0 Completed |" + ignorePolicyWarningMessage = "Warning: The --ignore-policy flag was not implemented because you do not have the required permission." ) func flag(f string) string { @@ -1591,8 +1592,7 @@ func TestIgnorePolicyWithNoPermission(t *testing.T) { t.Fatalf("failed to copy output: %v", err) // Handle the error if io.Copy fails } output := buf.String() - expectedWarning := "Warning: The --ignore-policy flag was not implemented because you do not have the required permission." - assert.Assert(t, strings.Contains(output, expectedWarning), "’Ignore Policy flag omitted because you dont have permission’ should not be present in the output") + assert.Assert(t, strings.Contains(output, ignorePolicyWarningMessage), "’Ignore Policy flag omitted because you dont have permission’ should not be present in the output") } func TestIgnorePolicyWithPermission(t *testing.T) { @@ -1626,8 +1626,7 @@ func TestIgnorePolicyWithPermission(t *testing.T) { t.Fatalf("failed to copy output: %v", err) // Handle the error if io.Copy fails } output := buf.String() - expectedWarning := "Warning: The --ignore-policy flag was not implemented because you do not have the required permission." - assert.Assert(t, !strings.Contains(output, expectedWarning), "’Ignore Policy flag omitted because you dont have permission’ should not be present in the output") + assert.Assert(t, !strings.Contains(output, ignorePolicyWarningMessage), "’Ignore Policy flag omitted because you dont have permission’ should not be present in the output") } func TestParseGlSastVulnerability_QueryDescriptionLink_Succeed(t *testing.T) { From 1f068eb0fc545da337b14f4904f69f8f7adc5f2a Mon Sep 17 00:00:00 2001 From: atishj99 <141334503+cx-atish-jadhav@users.noreply.github.com> Date: Fri, 29 May 2026 12:24:10 +0530 Subject: [PATCH 25/27] Override transitive golang.org/x/image and update config - Add explicit requirement for golang.org/x/image v0.39.0 to override gonum.org/v1/gonum's transitive requirement of v0.25.0 (CVE-2026-33813) - Update result_test.go constant alignment - Add cx_config_file_path to integration config --- go.mod | 1 + go.sum | 2 ++ internal/commands/result_test.go | 20 ++++++++++---------- test/integration/data/config.yaml | 1 + 4 files changed, 14 insertions(+), 10 deletions(-) diff --git a/go.mod b/go.mod index 6e8afd8c1..6951e7fe2 100644 --- a/go.mod +++ b/go.mod @@ -140,6 +140,7 @@ require ( go.opentelemetry.io/otel/sdk v1.43.0 // indirect go.opentelemetry.io/otel/sdk/metric v1.43.0 // indirect go4.org v0.0.0-20230225012048-214862532bf5 // indirect + golang.org/x/image v0.39.0 // indirect gonum.org/v1/gonum v0.17.0 // indirect google.golang.org/api v0.271.0 // indirect google.golang.org/genproto/googleapis/api v0.0.0-20260401024825-9d38bb4040a9 // indirect diff --git a/go.sum b/go.sum index cdf0a48f3..c5165419b 100644 --- a/go.sum +++ b/go.sum @@ -1312,6 +1312,8 @@ golang.org/x/exp v0.0.0-20260410095643-746e56fc9e2f h1:W3F4c+6OLc6H2lb//N1q4WpJk golang.org/x/exp v0.0.0-20260410095643-746e56fc9e2f/go.mod h1:J1xhfL/vlindoeF/aINzNzt2Bket5bjo9sdOYzOsU80= golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js= golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= +golang.org/x/image v0.39.0 h1:skVYidAEVKgn8lZ602XO75asgXBgLj9G/FE3RbuPFww= +golang.org/x/image v0.39.0/go.mod h1:sIbmppfU+xFLPIG0FoVUTvyBMmgng1/XAMhQ2ft0hpA= golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU= golang.org/x/lint v0.0.0-20190301231843-5614ed5bae6f/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= diff --git a/internal/commands/result_test.go b/internal/commands/result_test.go index ed634427c..133d90516 100644 --- a/internal/commands/result_test.go +++ b/internal/commands/result_test.go @@ -27,16 +27,16 @@ import ( const fileName = "cx_result" const ( - resultsCommand = "results" - codeBashingCommand = "codebashing" - vulnerabilityValue = "Reflected XSS All Clients" - languageValue = "PHP" - cweValue = "79" - jsonValue = "json" - tableValue = "table" - listValue = "list" - secretDetectionLine = "| Secret Detection 0 1 1 0 0 Completed |" - ignorePolicyWarningMessage = "Warning: The --ignore-policy flag was not implemented because you do not have the required permission." + resultsCommand = "results" + codeBashingCommand = "codebashing" + vulnerabilityValue = "Reflected XSS All Clients" + languageValue = "PHP" + cweValue = "79" + jsonValue = "json" + tableValue = "table" + listValue = "list" + secretDetectionLine = "| Secret Detection 0 1 1 0 0 Completed |" + ignorePolicyWarningMessage = "Warning: The --ignore-policy flag was not implemented because you do not have the required permission." ) func flag(f string) string { diff --git a/test/integration/data/config.yaml b/test/integration/data/config.yaml index b01de3ac2..6d6b4c836 100644 --- a/test/integration/data/config.yaml +++ b/test/integration/data/config.yaml @@ -18,6 +18,7 @@ cx_byor_path: api/byor cx_client_id: example_client_id cx_client_secret: example_client_secret cx_codebashing_path: api/codebashing/lessons +cx_config_file_path: data/config.yaml cx_create_oath2_client_path: auth/realms/organization/pip/clients cx_custom_states_path: api/custom-states cx_descriptions_path: api/queries/descriptions From b99b73488d758061376f651541ce6ed64df34567 Mon Sep 17 00:00:00 2001 From: atishj99 <141334503+cx-atish-jadhav@users.noreply.github.com> Date: Tue, 2 Jun 2026 14:35:32 +0530 Subject: [PATCH 26/27] Vulnerability fixes and ci changes --- .github/workflows/release.yml | 2 -- README.md | 2 +- go.mod | 22 ++---------- go.sum | 64 +++-------------------------------- 4 files changed, 7 insertions(+), 83 deletions(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 5ed3bb8d1..567284a53 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -159,10 +159,8 @@ jobs: if [ "${{ inputs.dev }}" = "true" ]; then gh release create "${common[@]}" --prerelease - gh release edit "${{ inputs.tag }}" --draft=false else gh release create "${common[@]}" - gh release edit "${{ inputs.tag }}" --draft=false --latest fi - name: Cleanup draft release on failure diff --git a/README.md b/README.md index 5e9fde129..2ec87ba2d 100644 --- a/README.md +++ b/README.md @@ -119,7 +119,7 @@ Checkmarx One Integrations Team Project Link: [https://github.com/Checkmarx/ast-cli](https://github.com/Checkmarx/ast-cli). -© 2025 Checkmarx Ltd. All Rights Reserved. +© 2026 Checkmarx Ltd. All Rights Reserved. [docker-shield]: https://img.shields.io/docker/pulls/checkmarx/ast-cli diff --git a/go.mod b/go.mod index 6951e7fe2..67fe4128d 100644 --- a/go.mod +++ b/go.mod @@ -29,7 +29,7 @@ require ( github.com/xeipuuv/gojsonschema v1.2.0 golang.org/x/crypto v0.50.0 golang.org/x/sync v0.20.0 - golang.org/x/text v0.36.0 + golang.org/x/text v0.37.0 google.golang.org/grpc v1.80.0 google.golang.org/protobuf v1.36.12-0.20260120151049-f2248ac996af gopkg.in/yaml.v3 v3.0.1 @@ -45,7 +45,6 @@ require ( cloud.google.com/go/iam v1.5.3 // indirect cloud.google.com/go/monitoring v1.24.3 // indirect cloud.google.com/go/storage v1.61.3 // indirect - cyphar.com/go-pathrs v0.2.1 // indirect github.com/GoogleCloudPlatform/opentelemetry-operations-go/detectors/gcp v1.31.0 // indirect github.com/GoogleCloudPlatform/opentelemetry-operations-go/exporter/metric v0.55.0 // indirect github.com/GoogleCloudPlatform/opentelemetry-operations-go/internal/resourcemapping v0.55.0 // indirect @@ -79,24 +78,17 @@ require ( github.com/bodgit/sevenzip v1.6.1 // indirect github.com/bodgit/windows v1.0.1 // indirect github.com/cespare/xxhash/v2 v2.3.0 // indirect - github.com/checkpoint-restore/go-criu/v6 v6.3.0 // indirect - github.com/cilium/ebpf v0.17.3 // indirect github.com/clipperhouse/displaywidth v0.10.0 // indirect github.com/clipperhouse/uax29/v2 v2.6.0 // indirect github.com/cncf/xds/go v0.0.0-20251210132809-ee656c7534f5 // indirect - github.com/containerd/console v1.0.5 // indirect github.com/containerd/containerd/v2 v2.3.1 // indirect github.com/containerd/plugin v1.1.0 // indirect - github.com/coreos/go-systemd/v22 v22.7.0 // indirect - github.com/cpuguy83/go-md2man/v2 v2.0.7 // indirect github.com/diskfs/go-diskfs v1.7.0 // indirect github.com/distribution/distribution/v3 v3.1.1 // indirect github.com/envoyproxy/go-control-plane/envoy v1.36.0 // indirect github.com/envoyproxy/protoc-gen-validate v1.3.0 // indirect - github.com/go-jose/go-jose/v3 v3.0.5 // indirect github.com/go-jose/go-jose/v4 v4.1.4 // indirect github.com/goccy/go-yaml v1.19.2 // indirect - github.com/godbus/dbus/v5 v5.1.0 // indirect github.com/gohugoio/hashstructure v0.6.0 // indirect github.com/google/s2a-go v0.1.9 // indirect github.com/googleapis/enterprise-certificate-proxy v0.3.14 // indirect @@ -114,33 +106,23 @@ require ( github.com/minio/minlz v1.0.1 // indirect github.com/moby/moby/api v1.54.1 // indirect github.com/moby/moby/client v0.4.0 // indirect - github.com/moby/sys/capability v0.4.0 // indirect - github.com/mrunalp/fileutils v0.5.1 // indirect github.com/nix-community/go-nix v0.0.0-20250101154619-4bdde671e0a1 // indirect github.com/nwaples/rardecode/v2 v2.2.0 // indirect github.com/olekukonko/cat v0.0.0-20250911104152-50322a0618f6 // indirect github.com/olekukonko/errors v1.2.0 // indirect github.com/olekukonko/ll v0.1.6 // indirect - github.com/opencontainers/cgroups v0.0.4 // indirect - github.com/opencontainers/runc v1.3.4 // indirect - github.com/opencontainers/selinux v1.13.1 // indirect github.com/pkg/xattr v0.4.9 // indirect github.com/planetscale/vtprotobuf v0.6.1-0.20240319094008-0393e58bdf10 // indirect github.com/prometheus/procfs v0.20.1 // indirect - github.com/seccomp/libseccomp-golang v0.10.0 // indirect github.com/smallnest/ringbuffer v0.0.0-20241116012123-461381446e3d // indirect github.com/sorairolake/lzip-go v0.3.8 // indirect github.com/spiffe/go-spiffe/v2 v2.6.0 // indirect - github.com/urfave/cli v1.22.16 // indirect - github.com/vishvananda/netlink v1.3.1 // indirect - github.com/vishvananda/netns v0.0.5 // indirect go.opentelemetry.io/contrib/detectors/gcp v1.39.0 // indirect go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.68.0 // indirect go.opentelemetry.io/otel/exporters/stdout/stdoutmetric v1.42.0 // indirect go.opentelemetry.io/otel/sdk v1.43.0 // indirect go.opentelemetry.io/otel/sdk/metric v1.43.0 // indirect go4.org v0.0.0-20230225012048-214862532bf5 // indirect - golang.org/x/image v0.39.0 // indirect gonum.org/v1/gonum v0.17.0 // indirect google.golang.org/api v0.271.0 // indirect google.golang.org/genproto/googleapis/api v0.0.0-20260401024825-9d38bb4040a9 // indirect @@ -373,7 +355,7 @@ require ( go.yaml.in/yaml/v3 v3.0.4 // indirect golang.org/x/exp v0.0.0-20260410095643-746e56fc9e2f // indirect golang.org/x/mod v0.35.0 // indirect - golang.org/x/net v0.53.0 // indirect + golang.org/x/net v0.53.1-0.20260416132847-8c4c965e0284 // indirect golang.org/x/oauth2 v0.36.0 // indirect golang.org/x/sys v0.43.0 // indirect golang.org/x/term v0.42.0 // indirect diff --git a/go.sum b/go.sum index c5165419b..6a57bfefc 100644 --- a/go.sum +++ b/go.sum @@ -67,8 +67,6 @@ cloud.google.com/go/storage v1.61.3 h1:VS//ZfBuPGDvakfD9xyPW1RGF1Vy3BWUoVZXgW1KM cloud.google.com/go/storage v1.61.3/go.mod h1:JtqK8BBB7TWv0HVGHubtUdzYYrakOQIsMLffZ2Z/HWk= cloud.google.com/go/trace v1.11.7 h1:kDNDX8JkaAG3R2nq1lIdkb7FCSi1rCmsEtKVsty7p+U= cloud.google.com/go/trace v1.11.7/go.mod h1:TNn9d5V3fQVf6s4SCveVMIBS2LJUqo73GACmq/Tky0s= -cyphar.com/go-pathrs v0.2.1 h1:9nx1vOgwVvX1mNBWDu93+vaceedpbsDqo+XuBGL40b8= -cyphar.com/go-pathrs v0.2.1/go.mod h1:y8f1EMG7r+hCuFf/rXsKqMJrJAUoADZGNh5/vZPKcGc= dario.cat/mergo v1.0.2 h1:85+piFYR1tMbRrLcDwR18y4UKJ3aH1Tbzi24VRW1TK8= dario.cat/mergo v1.0.2/go.mod h1:E/hbnu0NxMFBjpMIE34DRGLWqDy0g5FuKDhCb31ngxA= dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU= @@ -82,7 +80,6 @@ github.com/BobuSumisu/aho-corasick v1.0.3 h1:uuf+JHwU9CHP2Vx+wAy6jcksJThhJS9ehR8 github.com/BobuSumisu/aho-corasick v1.0.3/go.mod h1:hm4jLcvZKI2vRF2WDU1N4p/jpWtpOzp3nLmi9AzX/XE= github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= github.com/BurntSushi/toml v0.4.1/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbicEuybxQ= -github.com/BurntSushi/toml v1.4.0/go.mod h1:ukJfTF/6rtPPRCnwkur4qwRxa8vTRFBF0uk2lLoLwho= github.com/BurntSushi/toml v1.6.0 h1:dRaEfpa2VI55EwlIW72hMRHdWouJeRF7TPYhI+AUQjk= github.com/BurntSushi/toml v1.6.0/go.mod h1:ukJfTF/6rtPPRCnwkur4qwRxa8vTRFBF0uk2lLoLwho= github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo= @@ -300,8 +297,6 @@ github.com/charmbracelet/x/term v0.2.2 h1:xVRT/S2ZcKdhhOuSP4t5cLi5o+JxklsoEObBSg github.com/charmbracelet/x/term v0.2.2/go.mod h1:kF8CY5RddLWrsgVwpw4kAa6TESp6EB5y3uxGLeCqzAI= github.com/checkmarx/2ms/v3 v3.21.0 h1:EcabeDypNMsSidISQbziZ062HjMZQ+Hm/uOJ5AOxK8o= github.com/checkmarx/2ms/v3 v3.21.0/go.mod h1:e8f4F94MZ+iCetR/G3aw7nXdPe6TgPI92Zzk/NG1l0o= -github.com/checkpoint-restore/go-criu/v6 v6.3.0 h1:mIdrSO2cPNWQY1truPg6uHLXyKHk3Z5Odx4wjKOASzA= -github.com/checkpoint-restore/go-criu/v6 v6.3.0/go.mod h1:rrRTN/uSwY2X+BPRl/gkulo9gsKOSAeVp9/K2tv7xZI= github.com/chromedp/cdproto v0.0.0-20230802225258-3cf4e6d46a89/go.mod h1:GKljq0VrfU4D5yc+2qA6OVr8pmO/MBbPEWqWQ/oqGEs= github.com/chromedp/chromedp v0.9.2/go.mod h1:LkSXJKONWTCHAfQasKFUZI+mxqS4tZqhmtGzzhLsnLs= github.com/chromedp/sysutil v1.0.0/go.mod h1:kgWmDdq8fTzXYcKIBqIYvRRTnYb9aNS9moAV0xufSww= @@ -311,8 +306,6 @@ github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5P github.com/chzyer/readline v1.5.1/go.mod h1:Eh+b79XXUwfKfcPLepksvw2tcLE/Ct21YObkaSkeBlk= github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU= github.com/chzyer/test v1.0.0/go.mod h1:2JlltgoNkt4TW/z9V/IzDdFaMTM2JPIi26O1pF38GC8= -github.com/cilium/ebpf v0.17.3 h1:FnP4r16PWYSE4ux6zN+//jMcW4nMVRvuTLVTvCjyyjg= -github.com/cilium/ebpf v0.17.3/go.mod h1:G5EDHij8yiLzaqn0WjyfJHvRa+3aDlReIaLVRMvOyJk= github.com/circonus-labs/circonus-gometrics v2.3.1+incompatible/go.mod h1:nmEj6Dob7S7YxXgwXpfOuvO54S+tGdZdw9fuRZt25Ag= github.com/circonus-labs/circonusllhist v0.1.3/go.mod h1:kMXHVDlOchFAehlya5ePtbp5jckzBHf4XRpQvBOLI+I= github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= @@ -336,8 +329,6 @@ github.com/cncf/xds/go v0.0.0-20251210132809-ee656c7534f5 h1:6xNmx7iTtyBRev0+D/T github.com/cncf/xds/go v0.0.0-20251210132809-ee656c7534f5/go.mod h1:KdCmV+x/BuvyMxRnYBlmVaq4OLiKW6iRQfvC62cvdkI= github.com/containerd/cgroups/v3 v3.1.3 h1:eUNflyMddm18+yrDmZPn3jI7C5hJ9ahABE5q6dyLYXQ= github.com/containerd/cgroups/v3 v3.1.3/go.mod h1:PKZ2AcWmSBsY/tJUVhtS/rluX0b1uq1GmPO1ElCmbOw= -github.com/containerd/console v1.0.5 h1:R0ymNeydRqH2DmakFNdmjR2k0t7UPuiOV/N/27/qqsc= -github.com/containerd/console v1.0.5/go.mod h1:YynlIjWYF8myEu6sdkwKIvGQq+cOckRm6So2avqoYAk= github.com/containerd/containerd v1.7.32 h1:S54xuVcPxeLaYgaRABtpJ2VyVUVsy0IGf7qHBs+sbY8= github.com/containerd/containerd v1.7.32/go.mod h1:jdwD6s/BhV4XVJGrvtziNPVA+83n66TwptVaPKprq4E= github.com/containerd/containerd/api v1.11.1 h1:h8nfoDW9+fNsC/9TwiAHj8B1GzXKtR4eFtkhi/X5RLU= @@ -370,11 +361,7 @@ github.com/coreos/go-systemd/v22 v22.5.0/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSV github.com/coreos/go-systemd/v22 v22.7.0 h1:LAEzFkke61DFROc7zNLX/WA2i5J8gYqe0rSj9KI28KA= github.com/coreos/go-systemd/v22 v22.7.0/go.mod h1:xNUYtjHu2EDXbsxz1i41wouACIwT7Ybq9o0BQhMwD0w= github.com/cpuguy83/go-md2man/v2 v2.0.1/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= -github.com/cpuguy83/go-md2man/v2 v2.0.2/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= -github.com/cpuguy83/go-md2man/v2 v2.0.5/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= github.com/cpuguy83/go-md2man/v2 v2.0.6/go.mod h1:oOW0eioCTA6cOiMLiUPZOpcVxMig6NIQQ7OS05n1F4g= -github.com/cpuguy83/go-md2man/v2 v2.0.7 h1:zbFlGlXEAKlwXpmvle3d8Oe3YnkKIK4xSRTd3sHPnBo= -github.com/cpuguy83/go-md2man/v2 v2.0.7/go.mod h1:oOW0eioCTA6cOiMLiUPZOpcVxMig6NIQQ7OS05n1F4g= github.com/creack/pty v1.1.24 h1:bJrF4RRfyJnbTJqzRLHzcGaZK1NeM5kTC9jGgovnR1s= github.com/creack/pty v1.1.24/go.mod h1:08sCNb52WyoAwi2QDyzUCTgcvVFhUzewun7wtTfvcwE= github.com/cyphar/filepath-securejoin v0.6.1 h1:5CeZ1jPXEiYt3+Z6zqprSAgSWiggmpVyciv8syjIpVE= @@ -508,8 +495,6 @@ github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2 github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= github.com/go-gorp/gorp/v3 v3.1.0 h1:ItKF/Vbuj31dmV4jxA1qblpSwkl9g1typ24xoe70IGs= github.com/go-gorp/gorp/v3 v3.1.0/go.mod h1:dLEjIyyRNiXvNZ8PSmzpt1GsWAUK8kjVhEpjH8TixEw= -github.com/go-jose/go-jose/v3 v3.0.5 h1:BLLJWbC4nMZOfuPVxoZIxeYsn6Nl2r1fITaJ78UQlVQ= -github.com/go-jose/go-jose/v3 v3.0.5/go.mod h1:5b+7YgP7ZICgJDBdfjZaIt+H/9L9T/YQrVfLAMboGkQ= github.com/go-jose/go-jose/v4 v4.1.4 h1:moDMcTHmvE6Groj34emNPLs/qtYXRVcd6S7NHbHz3kA= github.com/go-jose/go-jose/v4 v4.1.4/go.mod h1:x4oUasVrzR7071A4TnHLGSPpNOm2a21K9Kf04k1rs08= github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= @@ -549,8 +534,6 @@ github.com/gobwas/ws v1.2.1/go.mod h1:hRKAFb8wOxFROYNsT1bqfWnhX+b5MFeJM9r2ZSwg/K github.com/goccy/go-yaml v1.19.2 h1:PmFC1S6h8ljIz6gMRBopkjP1TVT7xuwrButHID66PoM= github.com/goccy/go-yaml v1.19.2/go.mod h1:XBurs7gK8ATbW4ZPGKgcbrY1Br56PdM69F7LkFRi1kA= github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= -github.com/godbus/dbus/v5 v5.1.0 h1:4KLkAxT3aOY8Li4FRJe/KvhoNFFxo0m6fNuFUO8QJUk= -github.com/godbus/dbus/v5 v5.1.0/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= github.com/gofrs/flock v0.13.0 h1:95JolYOvGMqeH31+FC7D2+uULf6mG61mEZ/A8dRYMzw= github.com/gofrs/flock v0.13.0/go.mod h1:jxeyy9R1auM5S6JYDBhDt+E2TCo7DkratH4Pgi8P+Z0= github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= @@ -616,7 +599,6 @@ github.com/google/go-cmp v0.5.3/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/ github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8= github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU= github.com/google/go-containerregistry v0.21.5 h1:KTJG9Pn/jC0VdZR6ctV3/jcN+q6/Iqlx0sTVz3ywZlM= @@ -891,8 +873,6 @@ github.com/moby/moby/api v1.54.1 h1:TqVzuJkOLsgLDDwNLmYqACUuTehOHRGKiPhvH8V3Nn4= github.com/moby/moby/api v1.54.1/go.mod h1:+RQ6wluLwtYaTd1WnPLykIDPekkuyD/ROWQClE83pzs= github.com/moby/moby/client v0.4.0 h1:S+2XegzHQrrvTCvF6s5HFzcrywWQmuVnhOXe2kiWjIw= github.com/moby/moby/client v0.4.0/go.mod h1:QWPbvWchQbxBNdaLSpoKpCdf5E+WxFAgNHogCWDoa7g= -github.com/moby/sys/capability v0.4.0 h1:4D4mI6KlNtWMCM1Z/K0i7RV1FkX+DBDHKVJpCndZoHk= -github.com/moby/sys/capability v0.4.0/go.mod h1:4g9IK291rVkms3LKCDOoYlnV8xKwoDTpIrNEE35Wq0I= github.com/moby/sys/mountinfo v0.7.2 h1:1shs6aH5s4o5H2zQLn796ADW1wMrIwHsyJ2v9KouLrg= github.com/moby/sys/mountinfo v0.7.2/go.mod h1:1YOa8w8Ih7uW0wALDUgT1dTTSBrZ+HiBLGws92L2RU4= github.com/moby/sys/sequential v0.6.0 h1:qrx7XFUd/5DxtqcoH1h438hF5TmOvzC/lspjy7zgvCU= @@ -915,8 +895,6 @@ github.com/modern-go/reflect2 v1.0.3-0.20250322232337-35a7c28c31ee h1:W5t00kpgFd github.com/modern-go/reflect2 v1.0.3-0.20250322232337-35a7c28c31ee/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk= github.com/monochromegane/go-gitignore v0.0.0-20200626010858-205db1a8cc00 h1:n6/2gBQ3RWajuToeY6ZtZTIKv2v7ThUy5KKusIT0yc0= github.com/monochromegane/go-gitignore v0.0.0-20200626010858-205db1a8cc00/go.mod h1:Pm3mSP3c5uWn86xMLZ5Sa7JB9GsEZySvHYXCTK4E9q4= -github.com/mrunalp/fileutils v0.5.1 h1:F+S7ZlNKnrwHfSwdlgNSkKo67ReVf8o9fel6C3dkm/Q= -github.com/mrunalp/fileutils v0.5.1/go.mod h1:M1WthSahJixYnrXQl/DFQuteStB1weuxD2QJNHXfbSQ= github.com/mssola/user_agent v0.6.0 h1:uwPR4rtWlCHRFyyP9u2KOV0u8iQXmS7Z7feTrstQwk4= github.com/mssola/user_agent v0.6.0/go.mod h1:TTPno8LPY3wAIEKRpAtkdMT0f8SE24pLRGPahjCH4uw= github.com/muesli/ansi v0.0.0-20230316100256-276c6243b2f6 h1:ZK8zHtRHOkbHy6Mmr5D264iyp3TiX5OmNcI5cIARiQI= @@ -948,18 +926,12 @@ github.com/onsi/ginkgo/v2 v2.28.1 h1:S4hj+HbZp40fNKuLUQOYLDgZLwNUVn19N3Atb98NCyI github.com/onsi/ginkgo/v2 v2.28.1/go.mod h1:CLtbVInNckU3/+gC8LzkGUb9oF+e8W8TdUsxPwvdOgE= github.com/onsi/gomega v1.39.1 h1:1IJLAad4zjPn2PsnhH70V4DKRFlrCzGBNrNaru+Vf28= github.com/onsi/gomega v1.39.1/go.mod h1:hL6yVALoTOxeWudERyfppUcZXjMwIMLnuSfruD2lcfg= -github.com/opencontainers/cgroups v0.0.4 h1:XVj8P/IHVms/j+7eh8ggdkTLAxjz84ZzuFyGoE28DR4= -github.com/opencontainers/cgroups v0.0.4/go.mod h1:s8lktyhlGUqM7OSRL5P7eAW6Wb+kWPNvt4qvVfzA5vs= github.com/opencontainers/go-digest v1.0.0 h1:apOUWs51W5PlhuyGyz9FCeeBIOUDA/6nW8Oi/yOhh5U= github.com/opencontainers/go-digest v1.0.0/go.mod h1:0JzlMkj0TRzQZfJkVvzbP0HBR3IKzErnv2BNG4W4MAM= github.com/opencontainers/image-spec v1.1.1 h1:y0fUlFfIZhPF1W537XOLg0/fcx6zcHCJwooC2xJA040= github.com/opencontainers/image-spec v1.1.1/go.mod h1:qpqAh3Dmcf36wStyyWU+kCeDgrGnAve2nCC8+7h8Q0M= -github.com/opencontainers/runc v1.3.4 h1:+lwmPUTzbgv0JFqu8zBU2WtHYbm+JPPS9hxB/PvWd30= -github.com/opencontainers/runc v1.3.4/go.mod h1:o1wyv76EDlTkcf0KTFgN8bMWLPvgF/HfX709lDv+rr4= github.com/opencontainers/runtime-spec v1.3.0 h1:YZupQUdctfhpZy3TM39nN9Ika5CBWT5diQ8ibYCRkxg= github.com/opencontainers/runtime-spec v1.3.0/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0= -github.com/opencontainers/selinux v1.13.0 h1:Zza88GWezyT7RLql12URvoxsbLfjFx988+LGaWfbL84= -github.com/opencontainers/selinux v1.13.0/go.mod h1:XxWTed+A/s5NNq4GmYScVy+9jzXhGBVEOAyucdRUY8s= github.com/orisano/pixelmatch v0.0.0-20220722002657-fb0b55479cde/go.mod h1:nZgzbfBr3hhjoZnS66nKrHmduYNpc34ny7RK4z5/HM0= github.com/pascaldekloe/goe v0.0.0-20180627143212-57f6aae5913c/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc= github.com/pascaldekloe/goe v0.1.0/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc= @@ -1061,8 +1033,6 @@ github.com/scylladb/go-set v1.0.3-0.20200225121959-cc7b2070d91e/go.mod h1:DkpGd7 github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529/go.mod h1:DxrIzT+xaE7yg65j358z/aeFdxmN0P9QXhEzd20vsDc= github.com/sebdah/goldie/v2 v2.8.0 h1:dZb9wR8q5++oplmEiJT+U/5KyotVD+HNGCAc5gNr8rc= github.com/sebdah/goldie/v2 v2.8.0/go.mod h1:oZ9fp0+se1eapSRjfYbsV/0Hqhbuu3bJVvKI/NNtssI= -github.com/seccomp/libseccomp-golang v0.10.0 h1:aA4bp+/Zzi0BnWZ2F1wgNBs5gTpm+na2rWM6M9YjLpY= -github.com/seccomp/libseccomp-golang v0.10.0/go.mod h1:JA8cRccbGaA1s33RQf7Y1+q9gHmZX1yB/z9WDN1C6fg= github.com/sergi/go-diff v1.1.0/go.mod h1:STckp+ISIX8hZLjrqAeVduY0gWCT9IjLuqbuNXdaHfM= github.com/sergi/go-diff v1.2.0/go.mod h1:STckp+ISIX8hZLjrqAeVduY0gWCT9IjLuqbuNXdaHfM= github.com/sergi/go-diff v1.4.0 h1:n/SP9D5ad1fORl+llWyN+D6qoUETXNZARKjyY2/KVCw= @@ -1099,7 +1069,6 @@ github.com/spf13/cast v1.4.1/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkU github.com/spf13/cast v1.10.0 h1:h2x0u2shc1QuLHfxi+cTJvs30+ZAHOGRic8uyGTDWxY= github.com/spf13/cast v1.10.0/go.mod h1:jNfB8QC9IA6ZuY2ZjDp0KtFO2LZZlg4S/7bzP6qqeHo= github.com/spf13/cobra v1.3.0/go.mod h1:BrRVncBjOJa/eUcVVm9CE+oC6as8k+VYr4NY7WCi9V4= -github.com/spf13/cobra v1.5.0/go.mod h1:dWXEIy2H428czQCjInthrTRUg7yKbok+2Qi/yBIJoUM= github.com/spf13/cobra v1.10.2 h1:DMTTonx5m65Ic0GOoRY2c16WCbHxOOw6xxezuLaBpcU= github.com/spf13/cobra v1.10.2/go.mod h1:7C1pvHqHw5A4vrJfjNwvOdzYu0Gml16OCs2GRiTUUS4= github.com/spf13/jwalterweatherman v1.1.0/go.mod h1:aNWZUN0dPAAO/Ljvb5BEdw96iTZ0EXowPYD95IqWIGo= @@ -1127,8 +1096,6 @@ github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/ github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= -github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= -github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= github.com/stretchr/testify v1.11.1 h1:7s2iGBzp5EwR7/aIZr8ao5+dra3wiQyKjjFuvgVKu7U= github.com/stretchr/testify v1.11.1/go.mod h1:wZwfW3scLgRK+23gO65QZefKpKQRnfz6sD981Nm4B6U= github.com/subosito/gotenv v1.2.0/go.mod h1:N0PQaV/YGNqwC0u51sEeR/aUtSLEXKX9iv69rRypqCw= @@ -1156,18 +1123,12 @@ github.com/tv42/httpunix v0.0.0-20150427012821-b75d8614f926/go.mod h1:9ESjWnEqri github.com/ulikunitz/xz v0.5.8/go.mod h1:nbz6k7qbPmH4IRqmfOplQw/tblSgqTqBwxkY0oWt/14= github.com/ulikunitz/xz v0.5.15 h1:9DNdB5s+SgV3bQ2ApL10xRc35ck0DuIX/isZvIk+ubY= github.com/ulikunitz/xz v0.5.15/go.mod h1:nbz6k7qbPmH4IRqmfOplQw/tblSgqTqBwxkY0oWt/14= -github.com/urfave/cli v1.22.16 h1:MH0k6uJxdwdeWQTwhSO42Pwr4YLrNLwBtg1MRgTqPdQ= -github.com/urfave/cli v1.22.16/go.mod h1:EeJR6BKodywf4zciqrdw6hpCPk68JO9z5LazXZMn5Po= github.com/vbatts/go-mtree v0.7.0 h1:ytmOc3MTRidZiBi9VBCyZ2BHe4fZS47L5v7BVXDWW4E= github.com/vbatts/go-mtree v0.7.0/go.mod h1:EjdpFC+LZy1TXbRGNa1MKKgjQ+7ew3foMFJK8o4/TdY= github.com/vbatts/tar-split v0.12.2 h1:w/Y6tjxpeiFMR47yzZPlPj/FcPLpXbTUi/9H7d3CPa4= github.com/vbatts/tar-split v0.12.2/go.mod h1:eF6B6i6ftWQcDqEn3/iGFRFRo8cBIMSJVOpnNdfTMFA= github.com/vifraa/gopom v1.0.0 h1:L9XlKbyvid8PAIK8nr0lihMApJQg/12OBvMA28BcWh0= github.com/vifraa/gopom v1.0.0/go.mod h1:oPa1dcrGrtlO37WPDBm5SqHAT+wTgF8An1Q71Z6Vv4o= -github.com/vishvananda/netlink v1.3.1 h1:3AEMt62VKqz90r0tmNhog0r/PpWKmrEShJU0wJW6bV0= -github.com/vishvananda/netlink v1.3.1/go.mod h1:ARtKouGSTGchR8aMwmkzC0qiNPrrWO5JS/XMVl45+b4= -github.com/vishvananda/netns v0.0.5 h1:DfiHV+j8bA32MFM7bfEunvT8IAqQ/NzSJHtcmW5zdEY= -github.com/vishvananda/netns v0.0.5/go.mod h1:SpkAiCQRtJ6TvvxPnOSyH3BMl6unz3xZlaprSwhNNJM= github.com/wagoodman/go-partybus v0.0.0-20230516145632-8ccac152c651 h1:jIVmlAFIqV3d+DOxazTR9v+zgj8+VYuQBzPgBZvWBHA= github.com/wagoodman/go-partybus v0.0.0-20230516145632-8ccac152c651/go.mod h1:b26F2tHLqaoRQf8DywqzVaV1MQ9yvjb0OMcNl7Nxu20= github.com/wagoodman/go-progress v0.0.0-20260303201901-10176f79b2c0 h1:EHsPe0Q0ANoLOZff1dBLAyeWLTA4sbPTpGI+2zb0FnM= @@ -1295,7 +1256,6 @@ golang.org/x/crypto v0.0.0-20210817164053-32db794688a5/go.mod h1:GvvjBRRGRdwPK5y golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/crypto v0.0.0-20220622213112-05595931fe9d/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= golang.org/x/crypto v0.6.0/go.mod h1:OFC/31mSvZgRz0V1QTNCzfAI1aIRzbiufJtkMIlEp58= -golang.org/x/crypto v0.19.0/go.mod h1:Iy9bg/ha4yyC70EfRS8jz+B6ybOBKMaSxLj6P6oBDfU= golang.org/x/crypto v0.50.0 h1:zO47/JPrL6vsNkINmLoo/PH1gcxpls50DNogFvB5ZGI= golang.org/x/crypto v0.50.0/go.mod h1:3muZ7vA7PBCE6xgPX7nkzzjiUq87kRItoJQM1Yo8S+Q= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= @@ -1312,8 +1272,6 @@ golang.org/x/exp v0.0.0-20260410095643-746e56fc9e2f h1:W3F4c+6OLc6H2lb//N1q4WpJk golang.org/x/exp v0.0.0-20260410095643-746e56fc9e2f/go.mod h1:J1xhfL/vlindoeF/aINzNzt2Bket5bjo9sdOYzOsU80= golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js= golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= -golang.org/x/image v0.39.0 h1:skVYidAEVKgn8lZ602XO75asgXBgLj9G/FE3RbuPFww= -golang.org/x/image v0.39.0/go.mod h1:sIbmppfU+xFLPIG0FoVUTvyBMmgng1/XAMhQ2ft0hpA= golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU= golang.org/x/lint v0.0.0-20190301231843-5614ed5bae6f/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= @@ -1339,7 +1297,6 @@ golang.org/x/mod v0.4.1/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.5.0/go.mod h1:5OXOZSfqPIIbmVBIIKWRFfZjPR0E5r58TLhUjH0a2Ro= golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= -golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= golang.org/x/mod v0.35.0 h1:Ww1D637e6Pg+Zb2KrWfHQUnH2dQRLBQyAtpr/haaJeM= golang.org/x/mod v0.35.0/go.mod h1:+GwiRhIInF8wPm+4AoT6L0FA1QWAad3OMdTRx4tFYlU= golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= @@ -1387,9 +1344,8 @@ golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qx golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= golang.org/x/net v0.7.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= -golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg= -golang.org/x/net v0.53.0 h1:d+qAbo5L0orcWAr0a9JweQpjXF19LMXJE8Ey7hwOdUA= -golang.org/x/net v0.53.0/go.mod h1:JvMuJH7rrdiCfbeHoo3fCQU24Lf5JJwT9W3sJFulfgs= +golang.org/x/net v0.53.1-0.20260416132847-8c4c965e0284 h1:1Cik9TO30xv+Uycc5dXzAct+LiGidZMVM1U4chCI6o4= +golang.org/x/net v0.53.1-0.20260416132847-8c4c965e0284/go.mod h1:JvMuJH7rrdiCfbeHoo3fCQU24Lf5JJwT9W3sJFulfgs= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= @@ -1421,7 +1377,6 @@ golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJ golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.20.0 h1:e0PTpb7pjO8GAtTs2dQ6jYa5BWYlMuX047Dco/pItO4= golang.org/x/sync v0.20.0/go.mod h1:9xrNwdLfx4jkKbNva9FpL6vEN7evnE43NNNJQ2LF3+0= golang.org/x/sys v0.0.0-20180823144017-11551d06cbcc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= @@ -1497,21 +1452,14 @@ golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.2.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.10.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.17.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/sys v0.43.0 h1:Rlag2XtaFTxp19wS8MXlJwTvoh8ArU6ezoyFsMyCTNI= golang.org/x/sys v0.43.0/go.mod h1:4GL1E5IUh+htKOUEOaiffhrAeqysfVGipDYzABqnCmw= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k= -golang.org/x/term v0.8.0/go.mod h1:xPskH00ivmX89bAKVGSKKtLOWNx2+17Eiy94tnKShWo= -golang.org/x/term v0.17.0/go.mod h1:lLRBjIVuehSbZlaOtGMbcMncT+aqLLLmKrsjNrUguwk= golang.org/x/term v0.42.0 h1:UiKe+zDFmJobeJ5ggPwOshJIVt6/Ft0rcfrXZDLWAWY= golang.org/x/term v0.42.0/go.mod h1:Dq/D+snpsbazcBG5+F9Q1n2rXV8Ma+71xEjTRufARgY= golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= @@ -1524,10 +1472,8 @@ golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= -golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= -golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= -golang.org/x/text v0.36.0 h1:JfKh3XmcRPqZPKevfXVpI1wXPTqbkE5f7JA92a55Yxg= -golang.org/x/text v0.36.0/go.mod h1:NIdBknypM8iqVmPiuco0Dh6P5Jcdk8lJL0CUebqK164= +golang.org/x/text v0.37.0 h1:Cqjiwd9eSg8e0QAkyCaQTNHFIIzWtidPahFWR83rTrc= +golang.org/x/text v0.37.0/go.mod h1:a5sjxXGs9hsn/AJVwuElvCAo9v8QYLzvavO5z2PiM38= golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= @@ -1588,7 +1534,6 @@ golang.org/x/tools v0.1.3/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= golang.org/x/tools v0.1.4/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= golang.org/x/tools v0.1.5/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= -golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU= golang.org/x/tools v0.44.0 h1:UP4ajHPIcuMjT1GqzDWRlalUEoY+uzoZKnhOjbIPD2c= golang.org/x/tools v0.44.0/go.mod h1:KA0AfVErSdxRZIsOVipbv3rQhVXTnlU6UhKxHd1seDI= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= @@ -1752,7 +1697,6 @@ google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlba google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= google.golang.org/protobuf v1.27.1/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= -google.golang.org/protobuf v1.28.1/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= google.golang.org/protobuf v1.36.12-0.20260120151049-f2248ac996af h1:+5/Sw3GsDNlEmu7TfklWKPdQ0Ykja5VEmq2i817+jbI= google.golang.org/protobuf v1.36.12-0.20260120151049-f2248ac996af/go.mod h1:HTf+CrKn2C3g5S8VImy6tdcUvCska2kB7j23XfzDpco= gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw= From c7a8e92ed2cb6daa7bda7cc3b2d390402574f1b6 Mon Sep 17 00:00:00 2001 From: atishj99 <141334503+cx-atish-jadhav@users.noreply.github.com> Date: Tue, 2 Jun 2026 15:02:53 +0530 Subject: [PATCH 27/27] Fix transitive CVE vulnerabilities without go mod tidy MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Add explicit golang.org/x/image v0.41.0 override (CVE-2026-33813, CVE-2026-46599) pulled transitively through gonum.org/v1/gonum v0.17.0 - Add explicit github.com/opencontainers/runc v1.3.4 (CVE-2025-52881) pulled transitively through github.com/Microsoft/hcsshim v0.15.0-rc.1 - Add explicit github.com/go-jose/go-jose/v3 v3.0.5 (CVE-2026-34986) pulled transitively through github.com/containerd/containerd v1.7.32 - Add explicit github.com/cilium/ebpf v0.17.3 (transitive upgrade) Note: do not run go mod tidy on this module — it strips these security overrides because the packages are indirect and not directly imported. Co-Authored-By: Claude Sonnet 4.6 (1M context) --- go.mod | 18 ++++++++++++++++++ go.sum | 56 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 74 insertions(+) diff --git a/go.mod b/go.mod index 67fe4128d..2c6b04c8d 100644 --- a/go.mod +++ b/go.mod @@ -45,6 +45,7 @@ require ( cloud.google.com/go/iam v1.5.3 // indirect cloud.google.com/go/monitoring v1.24.3 // indirect cloud.google.com/go/storage v1.61.3 // indirect + cyphar.com/go-pathrs v0.2.1 // indirect github.com/GoogleCloudPlatform/opentelemetry-operations-go/detectors/gcp v1.31.0 // indirect github.com/GoogleCloudPlatform/opentelemetry-operations-go/exporter/metric v0.55.0 // indirect github.com/GoogleCloudPlatform/opentelemetry-operations-go/internal/resourcemapping v0.55.0 // indirect @@ -78,17 +79,24 @@ require ( github.com/bodgit/sevenzip v1.6.1 // indirect github.com/bodgit/windows v1.0.1 // indirect github.com/cespare/xxhash/v2 v2.3.0 // indirect + github.com/checkpoint-restore/go-criu/v6 v6.3.0 // indirect + github.com/cilium/ebpf v0.17.3 // indirect github.com/clipperhouse/displaywidth v0.10.0 // indirect github.com/clipperhouse/uax29/v2 v2.6.0 // indirect github.com/cncf/xds/go v0.0.0-20251210132809-ee656c7534f5 // indirect + github.com/containerd/console v1.0.5 // indirect github.com/containerd/containerd/v2 v2.3.1 // indirect github.com/containerd/plugin v1.1.0 // indirect + github.com/coreos/go-systemd/v22 v22.7.0 // indirect + github.com/cpuguy83/go-md2man/v2 v2.0.7 // indirect github.com/diskfs/go-diskfs v1.7.0 // indirect github.com/distribution/distribution/v3 v3.1.1 // indirect github.com/envoyproxy/go-control-plane/envoy v1.36.0 // indirect github.com/envoyproxy/protoc-gen-validate v1.3.0 // indirect + github.com/go-jose/go-jose/v3 v3.0.5 // indirect github.com/go-jose/go-jose/v4 v4.1.4 // indirect github.com/goccy/go-yaml v1.19.2 // indirect + github.com/godbus/dbus/v5 v5.1.0 // indirect github.com/gohugoio/hashstructure v0.6.0 // indirect github.com/google/s2a-go v0.1.9 // indirect github.com/googleapis/enterprise-certificate-proxy v0.3.14 // indirect @@ -106,23 +114,33 @@ require ( github.com/minio/minlz v1.0.1 // indirect github.com/moby/moby/api v1.54.1 // indirect github.com/moby/moby/client v0.4.0 // indirect + github.com/moby/sys/capability v0.4.0 // indirect + github.com/mrunalp/fileutils v0.5.1 // indirect github.com/nix-community/go-nix v0.0.0-20250101154619-4bdde671e0a1 // indirect github.com/nwaples/rardecode/v2 v2.2.0 // indirect github.com/olekukonko/cat v0.0.0-20250911104152-50322a0618f6 // indirect github.com/olekukonko/errors v1.2.0 // indirect github.com/olekukonko/ll v0.1.6 // indirect + github.com/opencontainers/cgroups v0.0.4 // indirect + github.com/opencontainers/runc v1.3.4 // indirect + github.com/opencontainers/selinux v1.13.1 // indirect github.com/pkg/xattr v0.4.9 // indirect github.com/planetscale/vtprotobuf v0.6.1-0.20240319094008-0393e58bdf10 // indirect github.com/prometheus/procfs v0.20.1 // indirect + github.com/seccomp/libseccomp-golang v0.10.0 // indirect github.com/smallnest/ringbuffer v0.0.0-20241116012123-461381446e3d // indirect github.com/sorairolake/lzip-go v0.3.8 // indirect github.com/spiffe/go-spiffe/v2 v2.6.0 // indirect + github.com/urfave/cli v1.22.16 // indirect + github.com/vishvananda/netlink v1.3.1 // indirect + github.com/vishvananda/netns v0.0.5 // indirect go.opentelemetry.io/contrib/detectors/gcp v1.39.0 // indirect go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.68.0 // indirect go.opentelemetry.io/otel/exporters/stdout/stdoutmetric v1.42.0 // indirect go.opentelemetry.io/otel/sdk v1.43.0 // indirect go.opentelemetry.io/otel/sdk/metric v1.43.0 // indirect go4.org v0.0.0-20230225012048-214862532bf5 // indirect + golang.org/x/image v0.41.0 // indirect gonum.org/v1/gonum v0.17.0 // indirect google.golang.org/api v0.271.0 // indirect google.golang.org/genproto/googleapis/api v0.0.0-20260401024825-9d38bb4040a9 // indirect diff --git a/go.sum b/go.sum index 6a57bfefc..0ec5a9c97 100644 --- a/go.sum +++ b/go.sum @@ -67,6 +67,8 @@ cloud.google.com/go/storage v1.61.3 h1:VS//ZfBuPGDvakfD9xyPW1RGF1Vy3BWUoVZXgW1KM cloud.google.com/go/storage v1.61.3/go.mod h1:JtqK8BBB7TWv0HVGHubtUdzYYrakOQIsMLffZ2Z/HWk= cloud.google.com/go/trace v1.11.7 h1:kDNDX8JkaAG3R2nq1lIdkb7FCSi1rCmsEtKVsty7p+U= cloud.google.com/go/trace v1.11.7/go.mod h1:TNn9d5V3fQVf6s4SCveVMIBS2LJUqo73GACmq/Tky0s= +cyphar.com/go-pathrs v0.2.1 h1:9nx1vOgwVvX1mNBWDu93+vaceedpbsDqo+XuBGL40b8= +cyphar.com/go-pathrs v0.2.1/go.mod h1:y8f1EMG7r+hCuFf/rXsKqMJrJAUoADZGNh5/vZPKcGc= dario.cat/mergo v1.0.2 h1:85+piFYR1tMbRrLcDwR18y4UKJ3aH1Tbzi24VRW1TK8= dario.cat/mergo v1.0.2/go.mod h1:E/hbnu0NxMFBjpMIE34DRGLWqDy0g5FuKDhCb31ngxA= dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU= @@ -80,6 +82,7 @@ github.com/BobuSumisu/aho-corasick v1.0.3 h1:uuf+JHwU9CHP2Vx+wAy6jcksJThhJS9ehR8 github.com/BobuSumisu/aho-corasick v1.0.3/go.mod h1:hm4jLcvZKI2vRF2WDU1N4p/jpWtpOzp3nLmi9AzX/XE= github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= github.com/BurntSushi/toml v0.4.1/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbicEuybxQ= +github.com/BurntSushi/toml v1.4.0/go.mod h1:ukJfTF/6rtPPRCnwkur4qwRxa8vTRFBF0uk2lLoLwho= github.com/BurntSushi/toml v1.6.0 h1:dRaEfpa2VI55EwlIW72hMRHdWouJeRF7TPYhI+AUQjk= github.com/BurntSushi/toml v1.6.0/go.mod h1:ukJfTF/6rtPPRCnwkur4qwRxa8vTRFBF0uk2lLoLwho= github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo= @@ -297,6 +300,8 @@ github.com/charmbracelet/x/term v0.2.2 h1:xVRT/S2ZcKdhhOuSP4t5cLi5o+JxklsoEObBSg github.com/charmbracelet/x/term v0.2.2/go.mod h1:kF8CY5RddLWrsgVwpw4kAa6TESp6EB5y3uxGLeCqzAI= github.com/checkmarx/2ms/v3 v3.21.0 h1:EcabeDypNMsSidISQbziZ062HjMZQ+Hm/uOJ5AOxK8o= github.com/checkmarx/2ms/v3 v3.21.0/go.mod h1:e8f4F94MZ+iCetR/G3aw7nXdPe6TgPI92Zzk/NG1l0o= +github.com/checkpoint-restore/go-criu/v6 v6.3.0 h1:mIdrSO2cPNWQY1truPg6uHLXyKHk3Z5Odx4wjKOASzA= +github.com/checkpoint-restore/go-criu/v6 v6.3.0/go.mod h1:rrRTN/uSwY2X+BPRl/gkulo9gsKOSAeVp9/K2tv7xZI= github.com/chromedp/cdproto v0.0.0-20230802225258-3cf4e6d46a89/go.mod h1:GKljq0VrfU4D5yc+2qA6OVr8pmO/MBbPEWqWQ/oqGEs= github.com/chromedp/chromedp v0.9.2/go.mod h1:LkSXJKONWTCHAfQasKFUZI+mxqS4tZqhmtGzzhLsnLs= github.com/chromedp/sysutil v1.0.0/go.mod h1:kgWmDdq8fTzXYcKIBqIYvRRTnYb9aNS9moAV0xufSww= @@ -306,6 +311,8 @@ github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5P github.com/chzyer/readline v1.5.1/go.mod h1:Eh+b79XXUwfKfcPLepksvw2tcLE/Ct21YObkaSkeBlk= github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU= github.com/chzyer/test v1.0.0/go.mod h1:2JlltgoNkt4TW/z9V/IzDdFaMTM2JPIi26O1pF38GC8= +github.com/cilium/ebpf v0.17.3 h1:FnP4r16PWYSE4ux6zN+//jMcW4nMVRvuTLVTvCjyyjg= +github.com/cilium/ebpf v0.17.3/go.mod h1:G5EDHij8yiLzaqn0WjyfJHvRa+3aDlReIaLVRMvOyJk= github.com/circonus-labs/circonus-gometrics v2.3.1+incompatible/go.mod h1:nmEj6Dob7S7YxXgwXpfOuvO54S+tGdZdw9fuRZt25Ag= github.com/circonus-labs/circonusllhist v0.1.3/go.mod h1:kMXHVDlOchFAehlya5ePtbp5jckzBHf4XRpQvBOLI+I= github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= @@ -329,6 +336,8 @@ github.com/cncf/xds/go v0.0.0-20251210132809-ee656c7534f5 h1:6xNmx7iTtyBRev0+D/T github.com/cncf/xds/go v0.0.0-20251210132809-ee656c7534f5/go.mod h1:KdCmV+x/BuvyMxRnYBlmVaq4OLiKW6iRQfvC62cvdkI= github.com/containerd/cgroups/v3 v3.1.3 h1:eUNflyMddm18+yrDmZPn3jI7C5hJ9ahABE5q6dyLYXQ= github.com/containerd/cgroups/v3 v3.1.3/go.mod h1:PKZ2AcWmSBsY/tJUVhtS/rluX0b1uq1GmPO1ElCmbOw= +github.com/containerd/console v1.0.5 h1:R0ymNeydRqH2DmakFNdmjR2k0t7UPuiOV/N/27/qqsc= +github.com/containerd/console v1.0.5/go.mod h1:YynlIjWYF8myEu6sdkwKIvGQq+cOckRm6So2avqoYAk= github.com/containerd/containerd v1.7.32 h1:S54xuVcPxeLaYgaRABtpJ2VyVUVsy0IGf7qHBs+sbY8= github.com/containerd/containerd v1.7.32/go.mod h1:jdwD6s/BhV4XVJGrvtziNPVA+83n66TwptVaPKprq4E= github.com/containerd/containerd/api v1.11.1 h1:h8nfoDW9+fNsC/9TwiAHj8B1GzXKtR4eFtkhi/X5RLU= @@ -361,7 +370,11 @@ github.com/coreos/go-systemd/v22 v22.5.0/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSV github.com/coreos/go-systemd/v22 v22.7.0 h1:LAEzFkke61DFROc7zNLX/WA2i5J8gYqe0rSj9KI28KA= github.com/coreos/go-systemd/v22 v22.7.0/go.mod h1:xNUYtjHu2EDXbsxz1i41wouACIwT7Ybq9o0BQhMwD0w= github.com/cpuguy83/go-md2man/v2 v2.0.1/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= +github.com/cpuguy83/go-md2man/v2 v2.0.2/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= +github.com/cpuguy83/go-md2man/v2 v2.0.5/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= github.com/cpuguy83/go-md2man/v2 v2.0.6/go.mod h1:oOW0eioCTA6cOiMLiUPZOpcVxMig6NIQQ7OS05n1F4g= +github.com/cpuguy83/go-md2man/v2 v2.0.7 h1:zbFlGlXEAKlwXpmvle3d8Oe3YnkKIK4xSRTd3sHPnBo= +github.com/cpuguy83/go-md2man/v2 v2.0.7/go.mod h1:oOW0eioCTA6cOiMLiUPZOpcVxMig6NIQQ7OS05n1F4g= github.com/creack/pty v1.1.24 h1:bJrF4RRfyJnbTJqzRLHzcGaZK1NeM5kTC9jGgovnR1s= github.com/creack/pty v1.1.24/go.mod h1:08sCNb52WyoAwi2QDyzUCTgcvVFhUzewun7wtTfvcwE= github.com/cyphar/filepath-securejoin v0.6.1 h1:5CeZ1jPXEiYt3+Z6zqprSAgSWiggmpVyciv8syjIpVE= @@ -495,6 +508,8 @@ github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2 github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= github.com/go-gorp/gorp/v3 v3.1.0 h1:ItKF/Vbuj31dmV4jxA1qblpSwkl9g1typ24xoe70IGs= github.com/go-gorp/gorp/v3 v3.1.0/go.mod h1:dLEjIyyRNiXvNZ8PSmzpt1GsWAUK8kjVhEpjH8TixEw= +github.com/go-jose/go-jose/v3 v3.0.5 h1:BLLJWbC4nMZOfuPVxoZIxeYsn6Nl2r1fITaJ78UQlVQ= +github.com/go-jose/go-jose/v3 v3.0.5/go.mod h1:5b+7YgP7ZICgJDBdfjZaIt+H/9L9T/YQrVfLAMboGkQ= github.com/go-jose/go-jose/v4 v4.1.4 h1:moDMcTHmvE6Groj34emNPLs/qtYXRVcd6S7NHbHz3kA= github.com/go-jose/go-jose/v4 v4.1.4/go.mod h1:x4oUasVrzR7071A4TnHLGSPpNOm2a21K9Kf04k1rs08= github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= @@ -534,6 +549,8 @@ github.com/gobwas/ws v1.2.1/go.mod h1:hRKAFb8wOxFROYNsT1bqfWnhX+b5MFeJM9r2ZSwg/K github.com/goccy/go-yaml v1.19.2 h1:PmFC1S6h8ljIz6gMRBopkjP1TVT7xuwrButHID66PoM= github.com/goccy/go-yaml v1.19.2/go.mod h1:XBurs7gK8ATbW4ZPGKgcbrY1Br56PdM69F7LkFRi1kA= github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= +github.com/godbus/dbus/v5 v5.1.0 h1:4KLkAxT3aOY8Li4FRJe/KvhoNFFxo0m6fNuFUO8QJUk= +github.com/godbus/dbus/v5 v5.1.0/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= github.com/gofrs/flock v0.13.0 h1:95JolYOvGMqeH31+FC7D2+uULf6mG61mEZ/A8dRYMzw= github.com/gofrs/flock v0.13.0/go.mod h1:jxeyy9R1auM5S6JYDBhDt+E2TCo7DkratH4Pgi8P+Z0= github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= @@ -599,6 +616,7 @@ github.com/google/go-cmp v0.5.3/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/ github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8= github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU= github.com/google/go-containerregistry v0.21.5 h1:KTJG9Pn/jC0VdZR6ctV3/jcN+q6/Iqlx0sTVz3ywZlM= @@ -873,6 +891,8 @@ github.com/moby/moby/api v1.54.1 h1:TqVzuJkOLsgLDDwNLmYqACUuTehOHRGKiPhvH8V3Nn4= github.com/moby/moby/api v1.54.1/go.mod h1:+RQ6wluLwtYaTd1WnPLykIDPekkuyD/ROWQClE83pzs= github.com/moby/moby/client v0.4.0 h1:S+2XegzHQrrvTCvF6s5HFzcrywWQmuVnhOXe2kiWjIw= github.com/moby/moby/client v0.4.0/go.mod h1:QWPbvWchQbxBNdaLSpoKpCdf5E+WxFAgNHogCWDoa7g= +github.com/moby/sys/capability v0.4.0 h1:4D4mI6KlNtWMCM1Z/K0i7RV1FkX+DBDHKVJpCndZoHk= +github.com/moby/sys/capability v0.4.0/go.mod h1:4g9IK291rVkms3LKCDOoYlnV8xKwoDTpIrNEE35Wq0I= github.com/moby/sys/mountinfo v0.7.2 h1:1shs6aH5s4o5H2zQLn796ADW1wMrIwHsyJ2v9KouLrg= github.com/moby/sys/mountinfo v0.7.2/go.mod h1:1YOa8w8Ih7uW0wALDUgT1dTTSBrZ+HiBLGws92L2RU4= github.com/moby/sys/sequential v0.6.0 h1:qrx7XFUd/5DxtqcoH1h438hF5TmOvzC/lspjy7zgvCU= @@ -895,6 +915,8 @@ github.com/modern-go/reflect2 v1.0.3-0.20250322232337-35a7c28c31ee h1:W5t00kpgFd github.com/modern-go/reflect2 v1.0.3-0.20250322232337-35a7c28c31ee/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk= github.com/monochromegane/go-gitignore v0.0.0-20200626010858-205db1a8cc00 h1:n6/2gBQ3RWajuToeY6ZtZTIKv2v7ThUy5KKusIT0yc0= github.com/monochromegane/go-gitignore v0.0.0-20200626010858-205db1a8cc00/go.mod h1:Pm3mSP3c5uWn86xMLZ5Sa7JB9GsEZySvHYXCTK4E9q4= +github.com/mrunalp/fileutils v0.5.1 h1:F+S7ZlNKnrwHfSwdlgNSkKo67ReVf8o9fel6C3dkm/Q= +github.com/mrunalp/fileutils v0.5.1/go.mod h1:M1WthSahJixYnrXQl/DFQuteStB1weuxD2QJNHXfbSQ= github.com/mssola/user_agent v0.6.0 h1:uwPR4rtWlCHRFyyP9u2KOV0u8iQXmS7Z7feTrstQwk4= github.com/mssola/user_agent v0.6.0/go.mod h1:TTPno8LPY3wAIEKRpAtkdMT0f8SE24pLRGPahjCH4uw= github.com/muesli/ansi v0.0.0-20230316100256-276c6243b2f6 h1:ZK8zHtRHOkbHy6Mmr5D264iyp3TiX5OmNcI5cIARiQI= @@ -926,12 +948,18 @@ github.com/onsi/ginkgo/v2 v2.28.1 h1:S4hj+HbZp40fNKuLUQOYLDgZLwNUVn19N3Atb98NCyI github.com/onsi/ginkgo/v2 v2.28.1/go.mod h1:CLtbVInNckU3/+gC8LzkGUb9oF+e8W8TdUsxPwvdOgE= github.com/onsi/gomega v1.39.1 h1:1IJLAad4zjPn2PsnhH70V4DKRFlrCzGBNrNaru+Vf28= github.com/onsi/gomega v1.39.1/go.mod h1:hL6yVALoTOxeWudERyfppUcZXjMwIMLnuSfruD2lcfg= +github.com/opencontainers/cgroups v0.0.4 h1:XVj8P/IHVms/j+7eh8ggdkTLAxjz84ZzuFyGoE28DR4= +github.com/opencontainers/cgroups v0.0.4/go.mod h1:s8lktyhlGUqM7OSRL5P7eAW6Wb+kWPNvt4qvVfzA5vs= github.com/opencontainers/go-digest v1.0.0 h1:apOUWs51W5PlhuyGyz9FCeeBIOUDA/6nW8Oi/yOhh5U= github.com/opencontainers/go-digest v1.0.0/go.mod h1:0JzlMkj0TRzQZfJkVvzbP0HBR3IKzErnv2BNG4W4MAM= github.com/opencontainers/image-spec v1.1.1 h1:y0fUlFfIZhPF1W537XOLg0/fcx6zcHCJwooC2xJA040= github.com/opencontainers/image-spec v1.1.1/go.mod h1:qpqAh3Dmcf36wStyyWU+kCeDgrGnAve2nCC8+7h8Q0M= +github.com/opencontainers/runc v1.3.4 h1:+lwmPUTzbgv0JFqu8zBU2WtHYbm+JPPS9hxB/PvWd30= +github.com/opencontainers/runc v1.3.4/go.mod h1:o1wyv76EDlTkcf0KTFgN8bMWLPvgF/HfX709lDv+rr4= github.com/opencontainers/runtime-spec v1.3.0 h1:YZupQUdctfhpZy3TM39nN9Ika5CBWT5diQ8ibYCRkxg= github.com/opencontainers/runtime-spec v1.3.0/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0= +github.com/opencontainers/selinux v1.13.0 h1:Zza88GWezyT7RLql12URvoxsbLfjFx988+LGaWfbL84= +github.com/opencontainers/selinux v1.13.0/go.mod h1:XxWTed+A/s5NNq4GmYScVy+9jzXhGBVEOAyucdRUY8s= github.com/orisano/pixelmatch v0.0.0-20220722002657-fb0b55479cde/go.mod h1:nZgzbfBr3hhjoZnS66nKrHmduYNpc34ny7RK4z5/HM0= github.com/pascaldekloe/goe v0.0.0-20180627143212-57f6aae5913c/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc= github.com/pascaldekloe/goe v0.1.0/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc= @@ -1033,6 +1061,8 @@ github.com/scylladb/go-set v1.0.3-0.20200225121959-cc7b2070d91e/go.mod h1:DkpGd7 github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529/go.mod h1:DxrIzT+xaE7yg65j358z/aeFdxmN0P9QXhEzd20vsDc= github.com/sebdah/goldie/v2 v2.8.0 h1:dZb9wR8q5++oplmEiJT+U/5KyotVD+HNGCAc5gNr8rc= github.com/sebdah/goldie/v2 v2.8.0/go.mod h1:oZ9fp0+se1eapSRjfYbsV/0Hqhbuu3bJVvKI/NNtssI= +github.com/seccomp/libseccomp-golang v0.10.0 h1:aA4bp+/Zzi0BnWZ2F1wgNBs5gTpm+na2rWM6M9YjLpY= +github.com/seccomp/libseccomp-golang v0.10.0/go.mod h1:JA8cRccbGaA1s33RQf7Y1+q9gHmZX1yB/z9WDN1C6fg= github.com/sergi/go-diff v1.1.0/go.mod h1:STckp+ISIX8hZLjrqAeVduY0gWCT9IjLuqbuNXdaHfM= github.com/sergi/go-diff v1.2.0/go.mod h1:STckp+ISIX8hZLjrqAeVduY0gWCT9IjLuqbuNXdaHfM= github.com/sergi/go-diff v1.4.0 h1:n/SP9D5ad1fORl+llWyN+D6qoUETXNZARKjyY2/KVCw= @@ -1069,6 +1099,7 @@ github.com/spf13/cast v1.4.1/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkU github.com/spf13/cast v1.10.0 h1:h2x0u2shc1QuLHfxi+cTJvs30+ZAHOGRic8uyGTDWxY= github.com/spf13/cast v1.10.0/go.mod h1:jNfB8QC9IA6ZuY2ZjDp0KtFO2LZZlg4S/7bzP6qqeHo= github.com/spf13/cobra v1.3.0/go.mod h1:BrRVncBjOJa/eUcVVm9CE+oC6as8k+VYr4NY7WCi9V4= +github.com/spf13/cobra v1.5.0/go.mod h1:dWXEIy2H428czQCjInthrTRUg7yKbok+2Qi/yBIJoUM= github.com/spf13/cobra v1.10.2 h1:DMTTonx5m65Ic0GOoRY2c16WCbHxOOw6xxezuLaBpcU= github.com/spf13/cobra v1.10.2/go.mod h1:7C1pvHqHw5A4vrJfjNwvOdzYu0Gml16OCs2GRiTUUS4= github.com/spf13/jwalterweatherman v1.1.0/go.mod h1:aNWZUN0dPAAO/Ljvb5BEdw96iTZ0EXowPYD95IqWIGo= @@ -1096,6 +1127,8 @@ github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/ github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= +github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= +github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= github.com/stretchr/testify v1.11.1 h1:7s2iGBzp5EwR7/aIZr8ao5+dra3wiQyKjjFuvgVKu7U= github.com/stretchr/testify v1.11.1/go.mod h1:wZwfW3scLgRK+23gO65QZefKpKQRnfz6sD981Nm4B6U= github.com/subosito/gotenv v1.2.0/go.mod h1:N0PQaV/YGNqwC0u51sEeR/aUtSLEXKX9iv69rRypqCw= @@ -1123,12 +1156,18 @@ github.com/tv42/httpunix v0.0.0-20150427012821-b75d8614f926/go.mod h1:9ESjWnEqri github.com/ulikunitz/xz v0.5.8/go.mod h1:nbz6k7qbPmH4IRqmfOplQw/tblSgqTqBwxkY0oWt/14= github.com/ulikunitz/xz v0.5.15 h1:9DNdB5s+SgV3bQ2ApL10xRc35ck0DuIX/isZvIk+ubY= github.com/ulikunitz/xz v0.5.15/go.mod h1:nbz6k7qbPmH4IRqmfOplQw/tblSgqTqBwxkY0oWt/14= +github.com/urfave/cli v1.22.16 h1:MH0k6uJxdwdeWQTwhSO42Pwr4YLrNLwBtg1MRgTqPdQ= +github.com/urfave/cli v1.22.16/go.mod h1:EeJR6BKodywf4zciqrdw6hpCPk68JO9z5LazXZMn5Po= github.com/vbatts/go-mtree v0.7.0 h1:ytmOc3MTRidZiBi9VBCyZ2BHe4fZS47L5v7BVXDWW4E= github.com/vbatts/go-mtree v0.7.0/go.mod h1:EjdpFC+LZy1TXbRGNa1MKKgjQ+7ew3foMFJK8o4/TdY= github.com/vbatts/tar-split v0.12.2 h1:w/Y6tjxpeiFMR47yzZPlPj/FcPLpXbTUi/9H7d3CPa4= github.com/vbatts/tar-split v0.12.2/go.mod h1:eF6B6i6ftWQcDqEn3/iGFRFRo8cBIMSJVOpnNdfTMFA= github.com/vifraa/gopom v1.0.0 h1:L9XlKbyvid8PAIK8nr0lihMApJQg/12OBvMA28BcWh0= github.com/vifraa/gopom v1.0.0/go.mod h1:oPa1dcrGrtlO37WPDBm5SqHAT+wTgF8An1Q71Z6Vv4o= +github.com/vishvananda/netlink v1.3.1 h1:3AEMt62VKqz90r0tmNhog0r/PpWKmrEShJU0wJW6bV0= +github.com/vishvananda/netlink v1.3.1/go.mod h1:ARtKouGSTGchR8aMwmkzC0qiNPrrWO5JS/XMVl45+b4= +github.com/vishvananda/netns v0.0.5 h1:DfiHV+j8bA32MFM7bfEunvT8IAqQ/NzSJHtcmW5zdEY= +github.com/vishvananda/netns v0.0.5/go.mod h1:SpkAiCQRtJ6TvvxPnOSyH3BMl6unz3xZlaprSwhNNJM= github.com/wagoodman/go-partybus v0.0.0-20230516145632-8ccac152c651 h1:jIVmlAFIqV3d+DOxazTR9v+zgj8+VYuQBzPgBZvWBHA= github.com/wagoodman/go-partybus v0.0.0-20230516145632-8ccac152c651/go.mod h1:b26F2tHLqaoRQf8DywqzVaV1MQ9yvjb0OMcNl7Nxu20= github.com/wagoodman/go-progress v0.0.0-20260303201901-10176f79b2c0 h1:EHsPe0Q0ANoLOZff1dBLAyeWLTA4sbPTpGI+2zb0FnM= @@ -1256,6 +1295,7 @@ golang.org/x/crypto v0.0.0-20210817164053-32db794688a5/go.mod h1:GvvjBRRGRdwPK5y golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/crypto v0.0.0-20220622213112-05595931fe9d/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= golang.org/x/crypto v0.6.0/go.mod h1:OFC/31mSvZgRz0V1QTNCzfAI1aIRzbiufJtkMIlEp58= +golang.org/x/crypto v0.19.0/go.mod h1:Iy9bg/ha4yyC70EfRS8jz+B6ybOBKMaSxLj6P6oBDfU= golang.org/x/crypto v0.50.0 h1:zO47/JPrL6vsNkINmLoo/PH1gcxpls50DNogFvB5ZGI= golang.org/x/crypto v0.50.0/go.mod h1:3muZ7vA7PBCE6xgPX7nkzzjiUq87kRItoJQM1Yo8S+Q= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= @@ -1272,6 +1312,8 @@ golang.org/x/exp v0.0.0-20260410095643-746e56fc9e2f h1:W3F4c+6OLc6H2lb//N1q4WpJk golang.org/x/exp v0.0.0-20260410095643-746e56fc9e2f/go.mod h1:J1xhfL/vlindoeF/aINzNzt2Bket5bjo9sdOYzOsU80= golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js= golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= +golang.org/x/image v0.41.0 h1:8wS72eGJMJaBxK6okTzd4WaXumUlTVlb753MlsSvTCo= +golang.org/x/image v0.41.0/go.mod h1:uIc348UZMSvS5Z65CVZ7iDPaNobNFEPeJ4kbqTOszmA= golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU= golang.org/x/lint v0.0.0-20190301231843-5614ed5bae6f/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= @@ -1297,6 +1339,7 @@ golang.org/x/mod v0.4.1/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.5.0/go.mod h1:5OXOZSfqPIIbmVBIIKWRFfZjPR0E5r58TLhUjH0a2Ro= golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= +golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= golang.org/x/mod v0.35.0 h1:Ww1D637e6Pg+Zb2KrWfHQUnH2dQRLBQyAtpr/haaJeM= golang.org/x/mod v0.35.0/go.mod h1:+GwiRhIInF8wPm+4AoT6L0FA1QWAad3OMdTRx4tFYlU= golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= @@ -1344,6 +1387,7 @@ golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qx golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= golang.org/x/net v0.7.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= +golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg= golang.org/x/net v0.53.1-0.20260416132847-8c4c965e0284 h1:1Cik9TO30xv+Uycc5dXzAct+LiGidZMVM1U4chCI6o4= golang.org/x/net v0.53.1-0.20260416132847-8c4c965e0284/go.mod h1:JvMuJH7rrdiCfbeHoo3fCQU24Lf5JJwT9W3sJFulfgs= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= @@ -1377,6 +1421,7 @@ golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJ golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.20.0 h1:e0PTpb7pjO8GAtTs2dQ6jYa5BWYlMuX047Dco/pItO4= golang.org/x/sync v0.20.0/go.mod h1:9xrNwdLfx4jkKbNva9FpL6vEN7evnE43NNNJQ2LF3+0= golang.org/x/sys v0.0.0-20180823144017-11551d06cbcc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= @@ -1452,14 +1497,21 @@ golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.2.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.10.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.17.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/sys v0.43.0 h1:Rlag2XtaFTxp19wS8MXlJwTvoh8ArU6ezoyFsMyCTNI= golang.org/x/sys v0.43.0/go.mod h1:4GL1E5IUh+htKOUEOaiffhrAeqysfVGipDYzABqnCmw= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k= +golang.org/x/term v0.8.0/go.mod h1:xPskH00ivmX89bAKVGSKKtLOWNx2+17Eiy94tnKShWo= +golang.org/x/term v0.17.0/go.mod h1:lLRBjIVuehSbZlaOtGMbcMncT+aqLLLmKrsjNrUguwk= golang.org/x/term v0.42.0 h1:UiKe+zDFmJobeJ5ggPwOshJIVt6/Ft0rcfrXZDLWAWY= golang.org/x/term v0.42.0/go.mod h1:Dq/D+snpsbazcBG5+F9Q1n2rXV8Ma+71xEjTRufARgY= golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= @@ -1472,6 +1524,8 @@ golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= +golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= +golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= golang.org/x/text v0.37.0 h1:Cqjiwd9eSg8e0QAkyCaQTNHFIIzWtidPahFWR83rTrc= golang.org/x/text v0.37.0/go.mod h1:a5sjxXGs9hsn/AJVwuElvCAo9v8QYLzvavO5z2PiM38= golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= @@ -1534,6 +1588,7 @@ golang.org/x/tools v0.1.3/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= golang.org/x/tools v0.1.4/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= golang.org/x/tools v0.1.5/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= +golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU= golang.org/x/tools v0.44.0 h1:UP4ajHPIcuMjT1GqzDWRlalUEoY+uzoZKnhOjbIPD2c= golang.org/x/tools v0.44.0/go.mod h1:KA0AfVErSdxRZIsOVipbv3rQhVXTnlU6UhKxHd1seDI= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= @@ -1697,6 +1752,7 @@ google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlba google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= google.golang.org/protobuf v1.27.1/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= +google.golang.org/protobuf v1.28.1/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= google.golang.org/protobuf v1.36.12-0.20260120151049-f2248ac996af h1:+5/Sw3GsDNlEmu7TfklWKPdQ0Ykja5VEmq2i817+jbI= google.golang.org/protobuf v1.36.12-0.20260120151049-f2248ac996af/go.mod h1:HTf+CrKn2C3g5S8VImy6tdcUvCska2kB7j23XfzDpco= gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw=