Skip to content

go-security

Five independent MR-time scanners for Go projects. Each is a separate job so consumers can opt one out (<job>: { rules: [{ when: never }] }) rather than disabling all of them. Tool images are pinned per input for Renovate-friendliness.

  • govulncheck — Go's official vulnerability scanner (build-graph aware, lower false-positive rate than CVE-database scans). Baked into go-tools; reuses the go.sum-keyed cache from go-test.
  • trivy — filesystem scan against the Aqua vulndb, catching transitive vulns govulncheck misses.
  • gitleaks — secret-pattern scan over the git history, scoped to the MR's own commit range.
  • osv-scanner — Google OSV-DB scan over go.mod.
  • analyze — semgrep static analysis (p/golang). Job name kept as analyze to match the GitHub CodeQL workflow's default job name, so any downstream dashboard or badge keying off that label keeps working.

Always-on — no change-detection input. See Explanation: security, always-on.

Jobs

Job What it runs
govulncheck govulncheck ./...
trivy trivy fs --exit-code 1 --severity $[[ inputs.trivy_severity ]] --no-progress .
gitleaks gitleaks detect, scoped to the MR diff base on an MR pipeline
osv-scanner /osv-scanner -L $[[ inputs.osv_scanner_target ]]
analyze semgrep --config $[[ inputs.semgrep_config ]] --error --severity $[[ inputs.semgrep_severity ]] .

Inputs

Input Type Default Description
stage string security GitLab CI stage.
if string '$CI_PIPELINE_SOURCE == "merge_request_event"' Gating rules:if: for every job.
govulncheck_image string go-tools:v0.1.0 Override with a golang:… tag to install govulncheck at runtime instead.
trivy_image string "ghcr.io/aquasecurity/trivy:0.72.0" Trivy image.
trivy_severity string "HIGH,CRITICAL" Severities trivy fails on.
gitleaks_image string "ghcr.io/gitleaks/gitleaks:v8.30.1" Gitleaks image.
osv_scanner_image string "ghcr.io/google/osv-scanner:v2.4.0" OSV-Scanner image.
osv_scanner_target string "go.mod" What osv-scanner walks (-L).
osv_scanner_call_analysis boolean false Run osv-scanner's own call-analysis (its built-in govulncheck pass). Off by default: that pass builds the module with the Go bundled in the scanner image under GOTOOLCHAIN=local, so it fails whenever go.mod requires a newer Go than the image ships — and osv-scanner then exits 127 even with zero remaining findings. Reachability is already covered by the dedicated govulncheck job, so leaving it off loses no coverage. Set true only if your go.mod's Go version matches the scanner image.
semgrep_image string "returntocorp/semgrep:1.172.0" Semgrep image.
semgrep_config string "p/golang" Semgrep ruleset/preset id.
semgrep_severity string "ERROR" Minimum severity semgrep fails on.
trivy_cache_dir string "/opt/ci-cache/trivy" Shared trivy vuln-DB cache. When a DB already exists here, trivy scans offline (--skip-db-update) instead of re-downloading the ~1.2 GB Aqua DB. Absent → downloads exactly as before.
osv_cache_dir string "/opt/ci-cache/osv" Shared osv-scanner offline-DB cache. When the Go OSV DB exists here, osv-scanner runs offline instead of calling api.osv.dev live. Absent → online exactly as before.

Hermetic scanning via a shared runner cache

trivy_cache_dir/osv_cache_dir default to a conventional path, but nothing changes unless a DB actually exists there — a runner that doesn't mount it downloads/queries online as today. To get the speedup, mount a shared writable dir across your runner's jobs and refresh it nightly (trivy image --download-db-only, osv-scanner … --download-offline-databases). Under a burst this removes the per-job DB pull and the live osv.dev calls. See the shared-cache spec.

Usage

include:
  - component: gitlab.com/phpboyscout/cicd/[email protected]

See also