# Govulncheck > The`golang.org/x/vuln/scan`package provides programmatic access to govulncheck functionality for integration into Go applications. --- # Govulncheck API Reference ## Overview The `golang.org/x/vuln/scan` package provides programmatic access to govulncheck functionality for integration into Go applications. **Package Documentation:** [pkg.go.dev/golang.org/x/vuln/scan](https://pkg.go.dev/golang.org/x/vuln/scan) ## Basic Usage ### Running Govulncheck via API ```go package main import ( "context" "golang.org/x/vuln/scan" ) func main() { // Create a command to scan the current module cmd := scan.Command(context.Background(), "./...") // Run the command if err := cmd.Run(); err != nil { panic(err) } } ``` ## Cmd Type The `Cmd` type represents an external govulncheck command, similar to `exec.Cmd`. ### Fields ```go type Cmd struct { // Stdin specifies the standard input. // If provided, it is expected to be the output of govulncheck -json. Stdin io.Reader // Stdout specifies the standard output. // If nil, Run connects os.Stdout. Stdout io.Writer // Stderr specifies the standard error. // If nil, Run connects os.Stderr. Stderr io.Writer // Env is the environment to use. // If Env is nil, the current environment is used. // To specify the setting of only a few variables, // append to the current environment: // // opt.Env = append(os.Environ(), // "GOOS=plan9", "GOARCH=386") Env []string } ``` ### Methods #### Command ```go func Command(ctx context.Context, arg ...string) *Cmd ``` Returns the Cmd struct to execute govulncheck with the given arguments. **Parameters:** - `ctx`: Context for cancellation and timeout - `arg...`: Arguments to pass to govulncheck (e.g., "./...", "-tags", "linux") **Example:** ```go cmd := scan.Command(context.Background(), "-test", "./...") ``` #### Run ```go func (c *Cmd) Run() error ``` Runs the govulncheck command. It blocks until the command completes. **Returns:** - Error if the command execution fails **Example:** ```go cmd := scan.Command(context.Background(), "./...") if err := cmd.Run(); err != nil { log.Fatalf("govulncheck failed: %v", err) } ``` #### Start ```go func (c *Cmd) Start() error ``` Starts the govulncheck command but does not wait for it to complete. **Returns:** - Error if the command fails to start **Example:** ```go cmd := scan.Command(context.Background(), "./...") if err := cmd.Start(); err != nil { log.Fatal(err) } // Do other work while govulncheck runs... ``` #### Wait ```go func (c *Cmd) Wait() error ``` Waits for the command to complete. Must be called after Start(). **Example:** ```go cmd := scan.Command(context.Background(), "./...") if err := cmd.Start(); err != nil { log.Fatal(err) } // Do other work... if err := cmd.Wait(); err != nil { log.Fatal(err) } ``` #### Output ```go func (c *Cmd) Output() ([]byte, error) ``` Runs the command and returns its standard output. **Example:** ```go cmd := scan.Command(context.Background(), "-json", "./...") output, err := cmd.Output() if err != nil { log.Fatal(err) } fmt.Println(string(output)) ``` #### CombinedOutput ```go func (c *Cmd) CombinedOutput() ([]byte, error) ``` Runs the command and returns its combined standard output and standard error. **Example:** ```go cmd := scan.Command(context.Background(), "./...") output, err := cmd.CombinedOutput() if err != nil { log.Fatal(err) } ``` ## Examples ### Scanning a Module ```go package main import ( "context" "golang.org/x/vuln/scan" "log" ) func main() { cmd := scan.Command(context.Background(), "./...") if err := cmd.Run(); err != nil { log.Fatal(err) } } ``` ### Capturing JSON Output ```go package main import ( "context" "encoding/json" "golang.org/x/vuln/scan" "log" ) func main() { cmd := scan.Command(context.Background(), "-json", "./...") output, err := cmd.Output() if err != nil { log.Fatal(err) } var results []interface{} if err := json.Unmarshal(output, &results); err != nil { log.Fatal(err) } log.Printf("Found %d results", len(results)) } ``` ### Custom Stdout/Stderr ```go package main import ( "context" "golang.org/x/vuln/scan" "log" "os" ) func main() { cmd := scan.Command(context.Background(), "./...") cmd.Stdout = os.Stdout cmd.Stderr = os.Stderr if err := cmd.Run(); err != nil { log.Fatal(err) } } ``` ### With Build Tags ```go package main import ( "context" "golang.org/x/vuln/scan" "log" ) func main() { cmd := scan.Command(context.Background(), "-tags", "linux,amd64", "./...") if err := cmd.Run(); err != nil { log.Fatal(err) } } ``` ### With Timeout ```go package main import ( "context" "golang.org/x/vuln/scan" "log" "time" ) func main() { ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second) defer cancel() cmd := scan.Command(ctx, "./...") if err := cmd.Run(); err != nil { log.Fatal(err) } } ``` ### Binary Analysis ```go package main import ( "context" "golang.org/x/vuln/scan" "log" ) func main() { cmd := scan.Command(context.Background(), "-mode", "binary", "./my-binary") if err := cmd.Run(); err != nil { log.Fatal(err) } } ``` ### Environment Variables ```go package main import ( "context" "golang.org/x/vuln/scan" "log" "os" ) func main() { cmd := scan.Command(context.Background(), "./...") // Add custom environment variables cmd.Env = append(os.Environ(), "GOOS=linux", "GOARCH=amd64") if err := cmd.Run(); err != nil { log.Fatal(err) } } ``` ### Parsing JSON Output ```go package main import ( "context" "encoding/json" "golang.org/x/vuln/scan" "log" ) type Result struct { OSV string `json:"osv,omitempty"` Type string `json:"type,omitempty"` Data interface{} `json:"data,omitempty"` } func main() { cmd := scan.Command(context.Background(), "-json", "./...") output, err := cmd.Output() if err != nil { log.Fatal(err) } var results []Result if err := json.Unmarshal(output, &results); err != nil { log.Fatal(err) } for _, r := range results { if r.Type == "VULNERABILITY" { log.Printf("Found vulnerability: %s", r.OSV) } } } ``` ### Context Cancellation ```go package main import ( "context" "golang.org/x/vuln/scan" "log" "time" ) func main() { ctx, cancel := context.WithCancel(context.Background()) // Cancel after 10 seconds go func() { time.Sleep(10 * time.Second) cancel() }() cmd := scan.Command(ctx, "./...") if err := cmd.Run(); err != nil { log.Printf("Command cancelled or failed: %v", err) } } ``` ## JSON Output Format When using `-json` flag, govulncheck outputs JSON lines. Each line is a JSON object with the following structure: ```json { "osv": "GO-2021-1234", "type": "VULNERABILITY", "data": { "Calls": [ { "Module": "golang.org/x/text", "Version": "v0.3.6", "Package": "golang.org/x/text/language", "Function": "Parse", "Receiver": "", "StackTrace": [ { "Function": "main", "Package": "main" } ] } ] } } ``` ## Integration Patterns ### As Part of Build Process ```go // buildtool.go func runVulnCheck() error { cmd := scan.Command(context.Background(), "./...") return cmd.Run() } ``` ### Custom Security Scanner ```go type Scanner struct { // fields } func (s *Scanner) Scan() error { cmd := scan.Command(context.Background(), "-json", "./...") output, err := cmd.Output() if err != nil { return err } return s.processOutput(output) } ``` ### CI/CD Pipeline ```go func runInCICD() error { // Timeout after 5 minutes ctx, cancel := context.WithTimeout(context.Background(), 5*time.Minute) defer cancel() cmd := scan.Command(ctx, "-json", "./...") output, err := cmd.Output() if err != nil { return err } // Process and report results return reportResults(output) } ``` ## Related Packages - `golang.org/x/vuln/internal/govulncheck` - Internal govulncheck implementation - `golang.org/x/vuln/internal/sarif` - SARIF output format - `golang.org/x/vuln/internal/openvex` - OpenVEX output format ## Error Handling The package returns standard Go errors. Common error scenarios: ```go cmd := scan.Command(context.Background(), "./...") if err := cmd.Run(); err != nil { switch err { case context.Canceled: log.Println("Scan was cancelled") case context.DeadlineExceeded: log.Println("Scan timed out") default: log.Printf("Scan failed: %v", err) } } ``` ## See Also - [Official API Documentation](https://pkg.go.dev/golang.org/x/vuln/scan) - [Command Line Reference](./README.md) - [Usage Guide](./USAGE_GUIDE.md) --- # Govulncheck Usage Guide ## Quick Start ### 1. Installation ```bash go install golang.org/x/vuln/cmd/govulncheck@latest ``` Verify installation: ```bash govulncheck version ``` ### 2. Basic Scan ```bash cd your-go-module govulncheck ./... ``` ### 3. Interpreting Results If vulnerabilities are found, you'll see output like: ``` Vulnerability GO-2021-1234 in golang.org/x/text: The Parse function in language.Parse has a vulnerability main.go:42:5: main.myFunc calls golang.org/x/text/language.Parse ``` ## Common Workflows ### Scanning Specific Packages ```bash # Scan only the current package govulncheck . # Scan a specific package govulncheck ./pkg/mypackage # Scan multiple packages govulncheck ./cmd/... ./pkg/... ``` ### Including Test Files ```bash govulncheck -test ./... ``` ### Using Build Tags ```bash # Scan with specific build tags govulncheck -tags=linux ./... # Multiple tags govulncheck -tags=linux,amd64 ./... ``` ### Detailed Output Show full call stacks: ```bash govulncheck -show traces ./... ``` Show progress and detailed information: ```bash govulncheck -show verbose ./... ``` ### JSON Output For programmatic processing: ```bash govulncheck -json ./... > results.json ``` Parse with jq: ```bash govulncheck -json ./... | jq '.[] | select(.type == "VULNERABILITY")' ``` ## Binary Analysis ### Scanning a Compiled Binary ```bash # Direct binary scan govulncheck -mode binary ./my-binary # With detailed output govulncheck -mode binary -show verbose ./my-binary ``` ### Binary Extraction For large binaries, extract vulnerability information: ```bash # Extract minimal information govulncheck -mode extract ./my-binary > info.blob # Later, scan the extracted information govulncheck -mode binary info.blob ``` ### When to Use Binary Mode - The binary is the only artifact available - Source code is not available - You need to scan already-built artifacts in CI/CD ## Output Formats ### Standard Text Output ```bash govulncheck ./... ``` Provides: - Module path - Vulnerability ID - Affected version range - Call stack summary - Recommendation ### JSON Output ```bash govulncheck -format json ./... ``` Useful for: - CI/CD integration - Automated vulnerability reports - Tool integration ### SARIF Output ```bash govulncheck -format sarif ./... ``` Benefits: - Standard format for static analysis tools - Integration with GitHub Code Scanning - Integration with other SAST platforms ### VEX Output ```bash govulncheck -format openvex ./... ``` Use for: - Vulnerability exchange and tracking - Multi-tool vulnerability correlation - Standard compliance ## Custom Database Configuration ### Using a Custom Vulnerability Database ```bash # Point to a custom database endpoint govulncheck -db https://custom-vuln-db.example.com ./... ``` Database must implement the specification at: https://go.dev/security/vuln/database ### Common Custom Database Scenarios - Internal vulnerability tracking - Air-gapped environments - Custom vulnerability feeds - Compliance requirements ## CI/CD Integration ### GitHub Actions ```yaml name: Security Check on: [push, pull_request] jobs: vulncheck: runs-on: ubuntu-latest steps: - uses: actions/checkout@v3 - uses: actions/setup-go@v4 - uses: golang/govulncheck-action@v1 ``` ### Manual CI/CD Integration ```bash #!/bin/bash set -e # Run govulncheck govulncheck ./... # Check exit code if [ $? -ne 0 ]; then echo "Vulnerabilities found!" exit 1 fi echo "No vulnerabilities detected" ``` ### JSON-Based CI/CD ```bash #!/bin/bash # Run and capture JSON VULNS=$(govulncheck -json ./... | jq '[.[] | select(.type == "VULNERABILITY")] | length') if [ "$VULNS" -gt 0 ]; then echo "Found $VULNS vulnerabilities" govulncheck -json ./... | jq '.[] | select(.type == "VULNERABILITY")' exit 1 fi ``` ## Troubleshooting ### "Command not found" Ensure govulncheck is in your PATH: ```bash # Check installation which govulncheck # Add to PATH if needed (for bash) export PATH="$PATH:$(go env GOPATH)/bin" ``` ### "No vulnerabilities found" vs. Empty results - **Message but no output**: No vulnerabilities detected - **Empty JSON array**: No vulnerabilities detected (with `-json`) ### Module Not Found Errors Ensure go.mod exists and dependencies are downloaded: ```bash cd your-module go mod download govulncheck ./... ``` ### Build Configuration Mismatch Specify the build configuration: ```bash # For specific Go version go get golang.org/x/vuln/cmd/govulncheck@latest # For specific platform/OS GOOS=linux GOARCH=amd64 govulncheck ./... ``` ### False Positives Govulncheck may report false positives with: - Function pointers - Interface method calls - Dynamic code (via `reflect` package) Review call stacks with `-show traces`: ```bash govulncheck -show traces ./... ``` ## Performance Tips ### Large Projects ```bash # Scan specific packages instead of entire project govulncheck ./cmd/... ./pkg/... # Parallel processing (go command handles automatically) # But useful for CI/CD time govulncheck ./... ``` ### Binary Extraction for Repeated Scans ```bash # Extract once govulncheck -mode extract ./my-binary > cache.blob # Reuse for multiple scans govulncheck -mode binary cache.blob ``` ## Examples ### Scanning a Web Service ```bash cd myservice govulncheck -test -show verbose ./... ``` ### Scanning a CLI Tool ```bash # Build then scan binary go build -o myapp ./cmd/main.go govulncheck -mode binary ./myapp ``` ### Scanning with Specific Go Version ```bash # Use go1.21 go1.21 run govulncheck@latest ./... ``` ### Integration with go.dev Visit https://pkg.go.dev for more information on any reported vulnerabilities: ```bash # Look up vulnerability # https://pkg.go.dev/vuln/GO-2021-1234 ``` ## Additional Resources - [Go Security Vulnerabilities](https://go.dev/security/vuln) - [Govulncheck Tutorial](https://go.dev/doc/tutorial/govulncheck) - [Vulnerability Database](https://vuln.go.dev) - [GitHub Repository](https://github.com/golang/vuln)