Skip to content
Open
Show file tree
Hide file tree
Changes from 6 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
116 changes: 109 additions & 7 deletions internal/commands/scan.go
Original file line number Diff line number Diff line change
Expand Up @@ -864,6 +864,7 @@ func scanCreateSubCommand(
createScanCmd.PersistentFlags().String(commonParams.SCSRepoTokenFlag, "", "Provide a token with read permission for the repo that you are scanning (for scorecard scans)")
createScanCmd.PersistentFlags().String(commonParams.SCSRepoURLFlag, "", "The URL of the repo that you are scanning with scs (for scorecard scans)")
createScanCmd.PersistentFlags().String(commonParams.SCSEnginesFlag, "", "Specify which scs engines will run (default: all licensed engines)")
createScanCmd.PersistentFlags().String(commonParams.GitCommitHistoryFlag, "false", commonParams.GitCommitHistoryFlagDescription)
createScanCmd.PersistentFlags().Bool(commonParams.ScaHideDevAndTestDepFlag, false, scaHideDevAndTestDepFlagDescription)

// Container config flags
Expand Down Expand Up @@ -990,9 +991,8 @@ func setupScanTypeProjectAndConfig(
configArr = append(configArr, containersConfig)
}

scsLicensingV2Flag, _ := wrappers.GetSpecificFeatureFlag(featureFlagsWrapper, wrappers.ScsLicensingV2Enabled)
var SCSConfig, scsErr = addSCSScan(cmd, resubmitConfig, scsLicensingV2Flag.Status, userAllowedEngines[commonParams.RepositoryHealthType],
userAllowedEngines[commonParams.SecretDetectionType], userAllowedEngines[commonParams.EnterpriseSecretsType])
var SCSConfig, scsErr = addSCSScan(cmd, resubmitConfig, userAllowedEngines[commonParams.RepositoryHealthType],
userAllowedEngines[commonParams.SecretDetectionType], userAllowedEngines[commonParams.EnterpriseSecretsType], featureFlagsWrapper)
if scsErr != nil {
return scsErr
} else if SCSConfig != nil {
Expand Down Expand Up @@ -1368,11 +1368,12 @@ func isScorecardRunnable(isScsEnginesFlagSet, scsScorecardSelected bool, scsRepo
return isURLSupportedByScorecard(scsRepoURL), nil
}

func addSCSScan(cmd *cobra.Command, resubmitConfig []wrappers.Config, scsLicensingV2, hasRepositoryHealthLicense,
hasSecretDetectionLicense, hasEnterpriseSecretsLicense bool) (map[string]interface{}, error) {
func addSCSScan(cmd *cobra.Command, resubmitConfig []wrappers.Config, hasRepositoryHealthLicense,
hasSecretDetectionLicense, hasEnterpriseSecretsLicense bool, featureFlagsWrapper wrappers.FeatureFlagsWrapper) (map[string]interface{}, error) {
scsEnabled := scanTypeEnabled(commonParams.ScsType)
scsScorecardAllowed := isScsScorecardAllowed(scsLicensingV2, hasRepositoryHealthLicense, scsEnabled)
scsSecretDetectionAllowed := isScsSecretDetectionAllowed(scsLicensingV2, hasSecretDetectionLicense, hasEnterpriseSecretsLicense, scsEnabled)
scsLicensingV2Flag, _ := wrappers.GetSpecificFeatureFlag(featureFlagsWrapper, wrappers.ScsLicensingV2Enabled)
scsScorecardAllowed := isScsScorecardAllowed(scsLicensingV2Flag.Status, hasRepositoryHealthLicense, scsEnabled)
scsSecretDetectionAllowed := isScsSecretDetectionAllowed(scsLicensingV2Flag.Status, hasSecretDetectionLicense, hasEnterpriseSecretsLicense, scsEnabled)
if !scsScorecardAllowed && !scsSecretDetectionAllowed {
return nil, nil
}
Expand Down Expand Up @@ -1403,6 +1404,12 @@ func addSCSScan(cmd *cobra.Command, resubmitConfig []wrappers.Config, scsLicensi

if scsSecretDetectionSelected && scsSecretDetectionAllowed {
scsConfig.Twoms = trueString

// Set git commit history if enabled and all validations pass
commitHistoryFlag, _ := wrappers.GetSpecificFeatureFlag(featureFlagsWrapper, wrappers.SscsCommitHistoryEnabled)
if shouldEnableGitCommitHistory(cmd, commitHistoryFlag.Status) {
scsConfig.GitCommitHistory = trueString
}
}

isScsEnginesFlagSet := scsEngines != ""
Expand Down Expand Up @@ -3466,6 +3473,13 @@ func validateCreateScanFlags(cmd *cobra.Command) error {
}
}
}

// Validate git-commit-history flag
err = validateGitCommitHistoryFlag(cmd)
if err != nil {
return err
}

return nil
}

Expand Down Expand Up @@ -3729,6 +3743,94 @@ func validateBooleanString(value string) error {
return nil
}

// validateGitCommitHistoryFlag validates the git-commit-history flag (needed for Secret Detection)
func validateGitCommitHistoryFlag(cmd *cobra.Command) error {
gitCommitHistory, _ := cmd.Flags().GetString(commonParams.GitCommitHistoryFlag)

err := validateBooleanString(gitCommitHistory)
if err != nil {
return errors.Errorf("Invalid value for --git-commit-history. Use 'true' or 'false'.")
}

return nil
}

// shouldEnableGitCommitHistory checks if the git-commit-history flag should be enabled
func shouldEnableGitCommitHistory(cmd *cobra.Command, commitHistoryFlag bool) bool {
if !commitHistoryFlag {
fmt.Println("Warning: Git commit history scanning is not available. The flag will be ignored.")
return false
}

gitCommitHistory, _ := cmd.Flags().GetString(commonParams.GitCommitHistoryFlag)

// If flag is not set to true, return false
if strings.ToLower(strings.TrimSpace(gitCommitHistory)) != trueString {
return false
}

userScanTypes, _ := cmd.Flags().GetString(commonParams.ScanTypes)
if !strings.Contains(strings.ToLower(userScanTypes), commonParams.ScsType) {
fmt.Println("Warning: '--git-commit-history' was provided, but SCS is not selected. Ignoring this flag.")
return false
}

// Check if only scorecard is enabled (no secret detection)
scsEngines, _ := cmd.Flags().GetString(commonParams.SCSEnginesFlag)
scsScoreCardSelected, scsSecretDetectionSelected := getSCSEnginesSelected(scsEngines)
if scsScoreCardSelected && !scsSecretDetectionSelected {
fmt.Println("Warning: Commit History applies only to Secret Detection. The flag will be ignored.")
return false
}

// Check if there's a git repository context
source, _ := cmd.Flags().GetString(commonParams.SourcesFlag)
if !hasGitRepository(source) {
fmt.Println("Warning: No Git history found. Secret Detection will scan the working tree only.")
return false
}

return true
}

// hasGitRepository checks if the source directory contains a Git repository
func hasGitRepository(source string) bool {
if source == "" {
return false
}

sourceTrimmed := strings.TrimSpace(source)
info, err := os.Stat(sourceTrimmed)
if err != nil || !info.IsDir() {
return false
}

// Check if .git exists in the root directory
gitPath := filepath.Join(sourceTrimmed, ".git")
if _, err := os.Stat(gitPath); err == nil {
return true
}

// fallback: search for .git in subdirectories
return searchGitInSubdirectories(sourceTrimmed)
}

// searchGitInSubdirectories walks through subdirectories to find a .git folder
func searchGitInSubdirectories(sourcePath string) bool {
found := false
_ = filepath.Walk(sourcePath, func(path string, info os.FileInfo, err error) error {
if err != nil || found {
return nil
}
if info.IsDir() && info.Name() == ".git" {
found = true
return filepath.SkipAll
}
return nil
})
return found
}

func parseArgs(input string) []string {
var args []string
var current strings.Builder
Expand Down
Loading
Loading