I scanned 20 top Go modules. Zero scored CRITICAL. Here’s why.
After finding publisher-concentration risk across npm, PyPI, and Cargo, Go was the first ecosystem where the structural pattern didn’t appear.
Over the past two weeks I’ve run behavioral commitment scoring on the most-downloaded packages in npm, PyPI, and Cargo. The pattern was the same every time: a handful of critical packages held by one person, millions of installs per week, one phished credential away from catastrophe.
Then I ran Go.
Zero CRITICAL scores. Not one.
The numbers
I audited 20 popular Go modules using Proof of Commitment. Scores range from 0 to 100 based on behavioral signals: project age, release consistency, contributor depth, GitHub backing, and community traction.
| Module | Score | Contributors | Risk |
|---|---|---|---|
hashicorp/terraform | 100 | 30+ | HEALTHY |
docker/docker | 98 | 30+ | HEALTHY |
sirupsen/logrus | 98 | 30+ | HEALTHY |
gin-gonic/gin | 96 | 30+ | HEALTHY |
spf13/cobra | 96 | 30+ | HEALTHY |
stretchr/testify | 96 | 30+ | HEALTHY |
gofiber/fiber | 95 | 30+ | HEALTHY |
prometheus/client_golang | 95 | 30+ | HEALTHY |
grpc/grpc-go | 94 | 30+ | HEALTHY |
gorilla/mux | 89 | 30+ | ⚠ WARN |
Average score: 93. Compare that to npm (where chalk, axios, and minimatch are all CRITICAL) or Cargo (where 11 of the top 20 crates have a sole owner). Go’s top modules are structurally healthier.
Why Go is different
The CRITICAL flag in npm, PyPI, and Cargo all measure the same thing: a single person controls publish access to a massively popular package. One compromised account could push malicious code to millions of downstream builds.
Go doesn’t have this problem because Go doesn’t have a publisher model.
There’s no go publish. There’s no crates.io account with a password. When you go get github.com/gin-gonic/gin, the Go toolchain fetches the code from Git, hashed and verified by sum.golang.org. Publishing is pushing a Git tag. The “credential” is your GitHub account, which is protected by 2FA, org-level access controls, and SSH keys — infrastructure the developer already maintains for everything else.
This isn’t better security through discipline. It’s better security through architecture. The attack surface that exists in npm (phish an npm token) simply doesn’t exist in Go.
Go’s actual risks are different
No CRITICAL doesn’t mean no risk. The Go ecosystem has its own failure modes — they just look different.
1. Abandonment
Several widely-used modules haven’t had a release in over a year:
- gorilla/mux (score 89) — archived by its maintainers. Still imported by thousands of projects. No security patches will come.
- mitchellh/mapstructure (score 74) — last release nearly 3 years ago. Mitchell Hashimoto moved on from active open-source maintenance.
- gopkg.in/yaml.v3 (score 71) — the lowest score in our scan. Over a year since the last release. Low OpenSSF Scorecard (3.6/10).
In npm, the primary risk is a compromised maintainer publishing bad code. In Go, the risk is that nobody is maintaining the code at all. Both are supply chain risks. They require different detection.
2. GitHub account compromise
Go’s publishing is Git-based, which means the attack vector shifts from registry credentials to GitHub accounts. Compromise a maintainer’s GitHub access, push a malicious tag, and sum.golang.org will happily verify the new module version.
The saving grace: GitHub 2FA adoption is much higher than npm token rotation, and GitHub has sophisticated anomaly detection. The attack cost is higher. But it’s not zero.
3. Vanity imports and typosquatting
Because Go modules are URLs, the namespace is infinite. There’s no approval process for creating github.com/gin-gon1c/gin. The Go proxy will cache and serve it. Typosquatting in Go doesn’t require a registry account — just a GitHub repo.
The cross-ecosystem pattern
Four ecosystems, four different risk profiles:
| Ecosystem | Primary risk | CRITICAL in top 20 | Avg score |
|---|---|---|---|
| npm | Publisher concentration | 26 of 91 | ~72 |
| Cargo | Owner concentration | 11 of 20 | ~78 |
| PyPI | Maintainer concentration | 7 of 20 | ~80 |
| Go | Abandonment | 0 of 20 | ~93 |
The pattern is clear: ecosystems with centralized publish credentials (npm, PyPI, Cargo) have structural concentration risk. Go’s decentralized model avoids this category entirely. The tradeoff is that Go has weaker protection against abandonment and namespace attacks.
Scan your own go.mod
# Audit any Go module
npx proof-of-commitment --golang github.com/gin-gonic/gin golang.org/x/net
# Scan a go.mod file
npx proof-of-commitment --file go.mod
# Full transitive set from go.sum
npx proof-of-commitment --file go.sum
# API
curl -s https://poc-backend.amdal-dev.workers.dev/api/audit \
-H 'Content-Type: application/json' \
-d '{"packages": ["github.com/gin-gonic/gin"], "ecosystem": "golang"}' Web view (no install): getcommit.dev/audit
go mod verify checks hashes. It won’t tell you that gorilla/mux is archived or that yaml.v3 hasn’t been updated in a year. Those are commitment signals, not integrity checks. Different tools, different risks.
Proof of Commitment is open-source. Now supports npm, PyPI, Cargo, and Go. Web audit at getcommit.dev/audit.
Also: The same analysis on Rust · Python · npm