Dosu LogoDosu Logo
Ask
Join our Discord
PersonalPublic
CloudNativePG
DocumentsPersonal
Go Dependency License Compliance
Go Dependency License Compliance
Type
Topic
Status
Published
Created
Oct 1, 2026
Updated
Oct 1, 2026
Updated by
Dosu Bot

Go Dependency License Compliance#

CloudNativePG manages two overlapping but distinct scans for Go dependency licenses: go-licenses (covers the full module graph) and Snyk (vulnerability + license scanning). A key nuance is that Go module tooling does not distinguish test-only imports from production imports in go.mod—every require directive is visible to scanners regardless of whether the dependency ends up in the shipped binary.


The pgregory.net/rapid MPL-2.0 Case#

pgregory.net/rapid v1.3.0 was added to go.mod by PR #11494 as a direct dependency for property-based tests in pkg/postgres/status_rapid_test.go. It was imported only in that single _test.go file and was not linked into the operator binary or image.

Despite being test-only, pgregory.net/rapid appeared as a direct require in go.mod, which meant:

  • Downstream SCA tools saw it. Snyk flagged it as SNYK:LIC:GOLANG:PGREGORY.NET:RAPID:MPL-2.0 in the plugin-barman-cloud repo's PR checks, attributed via github.com/cloudnative-pg/cloudnative-pg@v1.30.1. Any project depending on the CloudNativePG module inherited the finding.
  • go-licenses did not surface it. The licenses/go-licenses directory had no pgregory.net/ entry. The make licenses target runs go-licenses save ./... , which skips test-only imports when determining what to save.

This divergence is by design in go-licenses (it tracks packages that appear in the compiled binary), while Snyk inspects the raw module graph and flags any go.mod entry with a non-permissive license.

The issue was tracked in #11591. The MPL-2.0 compliance issue was resolved in PR #11592, which replaced pgregory.net/rapid with a deterministic standard-library seeded loop in pkg/postgres/status_property_test.go. Each iteration uses its index as seed for reproducibility. The dependency was removed from go.mod entirely.


License Scanning Infrastructure#

ToolTriggerScopeOutput
go-licensesWeekly schedule + workflow_dispatch via refresh-licenses.yml; make licensesFull ./... module graph, compiled-binary perspectivelicenses/go-licenses/ directory, auto-PRed
SnykPush to main + workflow_dispatch via snyk.ymlStatic code analysis + raw go.mod module graphSARIF uploaded to GitHub Code Scanning

make licenses (Makefile:382–389):

  • Runs $(GO_LICENSES) save ./... --save_path licenses/go-licenses --force || true
  • The || true is intentional: go-licenses exits non-zero because it cannot identify the project's own Apache-2.0 license header.
  • Removes .mod and .go files from the output, keeping only license text files.
  • A weekly GitHub Actions workflow (refresh-licenses.yml) runs make licenses and opens an automated PR if the result changes.

Snyk (snyk.yml):

  • Runs two steps: snyk code test (static analysis → snyk-static.sarif) and snyk test (dependency/license scan → snyk-test.sarif).
  • The GOTOOLCHAIN: auto env var is set so go list can fetch a newer toolchain than what is bundled in the Snyk Docker image.
  • Both steps use continue-on-error: true; findings are uploaded to GitHub Code Scanning rather than hard-failing the build.

Key Nuances for Engineers and SCA Operators#

  1. Test-only ≠ absent from module graph. A dependency used only in _test.go files is still a direct require in go.mod and will appear in Snyk findings.

  2. go-licenses and Snyk do not agree by design. go-licenses operates on compiled packages; Snyk scans the raw dependency manifest. Expect Snyk to surface licenses that go-licenses omits.

  3. Downstream consumers inherit the finding. If a library (e.g., plugin-barman-cloud) imports CloudNativePG as a module, its Snyk scan will include all of CloudNativePG's go.mod entries—including test-only ones.

  4. MPL-2.0 is not on the CNCF allowlist (to maintainers' knowledge). Even for test-only use, a resolution (replacing the dependency or obtaining an explicit exception) is required.

  5. Prefer stdlib or Apache/MIT-licensed test helpers to avoid introducing non-permissive licenses into the module graph. The rapid MPL-2.0 dependency was removed by replacing it with a standard-library seeded loop rather than seeking an exception.


Key Files#

PathPurpose
go.modModule graph; all require entries are visible to SCA tools
Makefile (licenses target)Runs go-licenses save ./...
.github/workflows/refresh-licenses.ymlWeekly automation for make licenses + auto-PR
.github/workflows/snyk.ymlSnyk static + dependency scan on push to main
licenses/go-licenses/Checked-in license texts for compiled dependencies
pkg/postgres/status_property_test.goProperty-based tests using stdlib random generation; replaced the former status_rapid_test.go (which used pgregory.net/rapid) in PR #11592
Documents
CloudNativePG Cluster Recovery
CloudNativePG Helm Chart
CloudNativePG Job Management
CloudNativePG Primary Switchover
CloudNativePG Synchronous Replication
CNPG-I Backup Plugin Architecture
Controller Requeue Semantics
Go Dependency License Compliance
Node Drain Switchover
Object Store Credential Redaction
Pod Security Context
PodMonitor Management
PostgreSQL Major Version Upgrades
Scheduled Backup Retention
Volume Snapshot Backup
WAL Archiving