-
Notifications
You must be signed in to change notification settings - Fork 10
feature: container-scan command to trivy scan containers #191
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 1 commit
c8c5182
25dcb9b
a7ac145
844da96
41cedbc
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||
|---|---|---|---|---|---|---|
| @@ -0,0 +1,155 @@ | ||||||
| package cmd | ||||||
|
|
||||||
| import ( | ||||||
| "fmt" | ||||||
| "os" | ||||||
| "os/exec" | ||||||
|
|
||||||
| "codacy/cli-v2/utils/logger" | ||||||
|
|
||||||
| "github.com/fatih/color" | ||||||
| "github.com/sirupsen/logrus" | ||||||
| "github.com/spf13/cobra" | ||||||
| ) | ||||||
|
|
||||||
| // Flag variables for container-scan command | ||||||
| var ( | ||||||
| severityFlag string | ||||||
| pkgTypesFlag string | ||||||
| ignoreUnfixedFlag bool | ||||||
| ) | ||||||
|
|
||||||
| func init() { | ||||||
| containerScanCmd.Flags().StringVar(&severityFlag, "severity", "", "Comma-separated list of severities to scan for (default: HIGH,CRITICAL)") | ||||||
| containerScanCmd.Flags().StringVar(&pkgTypesFlag, "pkg-types", "", "Comma-separated list of package types to scan (default: os)") | ||||||
| containerScanCmd.Flags().BoolVar(&ignoreUnfixedFlag, "ignore-unfixed", true, "Ignore unfixed vulnerabilities") | ||||||
| rootCmd.AddCommand(containerScanCmd) | ||||||
| } | ||||||
|
|
||||||
| var containerScanCmd = &cobra.Command{ | ||||||
| Use: "container-scan [FLAGS] <IMAGE_NAME>", | ||||||
| Short: "Scan container images for vulnerabilities using Trivy", | ||||||
| Long: `Scan container images for vulnerabilities using Trivy. | ||||||
|
|
||||||
| By default, scans for HIGH and CRITICAL vulnerabilities in OS packages, | ||||||
| ignoring unfixed issues. Use flags to override these defaults. | ||||||
|
|
||||||
| The --exit-code 1 flag is always applied (not user-configurable) to ensure | ||||||
| the command fails when vulnerabilities are found.`, | ||||||
| Example: ` # Default behavior (HIGH,CRITICAL severity, os packages only) | ||||||
| codacy-cli container-scan myapp:latest | ||||||
|
|
||||||
| # Scan only for CRITICAL vulnerabilities | ||||||
| codacy-cli container-scan --severity CRITICAL myapp:latest | ||||||
|
|
||||||
| # Scan all severities and package types | ||||||
| codacy-cli container-scan --severity LOW,MEDIUM,HIGH,CRITICAL --pkg-types os,library myapp:latest | ||||||
|
|
||||||
| # Include unfixed vulnerabilities | ||||||
| codacy-cli container-scan --ignore-unfixed=false myapp:latest`, | ||||||
| Args: cobra.ExactArgs(1), | ||||||
| Run: runContainerScan, | ||||||
| } | ||||||
|
|
||||||
| func runContainerScan(cmd *cobra.Command, args []string) { | ||||||
|
Check warning on line 54 in cmd/container_scan.go
|
||||||
| imageName := args[0] | ||||||
|
|
||||||
| logger.Info("Starting container scan", logrus.Fields{ | ||||||
| "image": imageName, | ||||||
| }) | ||||||
|
|
||||||
| // Check if Trivy is installed | ||||||
| trivyPath, err := exec.LookPath("trivy") | ||||||
| if err != nil { | ||||||
| logger.Error("Trivy not found", logrus.Fields{ | ||||||
| "error": err.Error(), | ||||||
| }) | ||||||
| color.Red("❌ Error: Trivy is not installed or not found in PATH") | ||||||
| fmt.Println("Please install Trivy to use container scanning.") | ||||||
| fmt.Println("Visit: https://trivy.dev/latest/getting-started/installation/") | ||||||
| os.Exit(1) | ||||||
| } | ||||||
|
|
||||||
| logger.Info("Found Trivy", logrus.Fields{ | ||||||
| "path": trivyPath, | ||||||
| }) | ||||||
|
|
||||||
| // Build Trivy command arguments | ||||||
| trivyArgs := buildTrivyArgs(imageName) | ||||||
|
|
||||||
| trivyCmd := exec.Command(trivyPath, trivyArgs...) | ||||||
|
Check failure on line 80 in cmd/container_scan.go
|
||||||
| trivyCmd.Stdout = os.Stdout | ||||||
| trivyCmd.Stderr = os.Stderr | ||||||
|
|
||||||
| logger.Info("Running Trivy container scan", logrus.Fields{ | ||||||
| "command": trivyCmd.String(), | ||||||
| }) | ||||||
|
|
||||||
| fmt.Printf("🔍 Scanning container image: %s\n\n", imageName) | ||||||
|
|
||||||
| err = trivyCmd.Run() | ||||||
| if err != nil { | ||||||
| // Check if the error is due to exit code 1 (vulnerabilities found) | ||||||
| if exitError, ok := err.(*exec.ExitError); ok { | ||||||
| exitCode := exitError.ExitCode() | ||||||
| logger.Warn("Container scan completed with vulnerabilities", logrus.Fields{ | ||||||
| "image": imageName, | ||||||
| "exit_code": exitCode, | ||||||
| }) | ||||||
| if exitCode == 1 { | ||||||
| fmt.Println() | ||||||
| color.Red("❌ Scanning failed: vulnerabilities found in the container image") | ||||||
| os.Exit(1) | ||||||
| } | ||||||
| } | ||||||
|
|
||||||
| // Other errors | ||||||
| logger.Error("Failed to run Trivy", logrus.Fields{ | ||||||
| "error": err.Error(), | ||||||
| }) | ||||||
| color.Red("❌ Error: Failed to run Trivy: %v", err) | ||||||
|
||||||
| color.Red("❌ Error: Failed to run Trivy: %v", err) | |
| color.Red(fmt.Sprintf("❌ Error: Failed to run Trivy: %v", err)) |
Copilot
AI
Jan 20, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The severityFlag and pkgTypesFlag values are passed directly to Trivy without validation. While exec.Command properly separates arguments and prevents shell injection, malicious or malformed values could still cause unexpected Trivy behavior. Consider adding validation to ensure these flags contain only expected characters (e.g., alphanumeric, commas for severity levels).
Copilot
AI
Jan 19, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This new command lacks test coverage. Similar commands in this repository have corresponding test files (e.g., analyze_test.go, config_test.go, init_test.go, upload_test.go). Consider adding a container_scan_test.go file to test the buildTrivyArgs function and the error handling logic in runContainerScan.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The error handling logic has a flaw. If exitError.ExitCode() returns a value other than 1 (e.g., 2 or higher), the code falls through without exiting, logging the same error twice and calling os.Exit(1) at line 111. This creates confusing duplicate error logs. The code should exit after handling any exit error, not just exit code 1, or add an else statement to prevent fall-through.