Check Go dependencies for known vulnerabilities and evaluate their maintenance health.
modcheck reads your go.mod file, queries vulnerability databases, and checks whether your dependencies are still actively maintained. It produces a single actionable report telling you which dependencies need attention.
- Vulnerability scanning -- Queries the OSV.dev vulnerability database to find known CVEs and Go vulnerability advisories affecting your dependencies.
- Deep analysis (optional) -- Runs govulncheck for call-graph-aware analysis that tells you if your code actually calls vulnerable functions.
- Health classification -- Checks whether dependency repositories are archived, stale, or showing signs of abandonment by querying GitHub/GitLab APIs and the Go module proxy.
- Stdlib separation -- Standard library vulnerabilities are listed separately at the end so they don't add noise to actionable third-party issues.
go install github.com/Drafteame/modcheck/cmd/modcheck@latestOr build from source:
git clone https://github.com/Drafteame/modcheck.git
cd modcheck
go build -o modcheck ./cmd/modcheck# Scan the current directory
modcheck
# Scan a specific go.mod file
modcheck ./path/to/go.mod
# Scan a directory containing go.mod
modcheck ./path/to/project
# Include indirect dependencies
modcheck --indirect
# Run with govulncheck deep analysis
modcheck --deep ./path/to/project
# Output as JSON (for CI pipelines or jq)
modcheck --output json
# Disable colors (for CI or piping)
modcheck --no-color modcheck — dependency health & vulnerability report
Module: github.com/example/myapp
Go: 1.25 | Direct: 42 | Indirect: 156
── VULNERABILITIES ──────────────────────────────────────────
CRITICAL golang.org/x/crypto v0.17.0 CVE-2024-45337
Improper validation of certificate chains
Fixed in: 0.31.0
HIGH github.com/jackc/pgx/v5 v5.4.0 GO-2024-2605
SQL injection in query parameters
Fixed in: v5.5.4
── UNMAINTAINED DEPENDENCIES ────────────────────────────────
ARCHIVED github.com/mitchellh/mapstructure
Repository is archived on github
Using: v1.5.0 | Latest: v1.5.0
STALE github.com/pkg/errors
No releases in 5 years | Last push: 4 years ago
WARNING github.com/some/dep
No releases in 14 months | 83 open issues
── NOTES ────────────────────────────────────────────────────
NOTE github.com/google/go-github/v60
Newer major version available: v68.0.0
── STDLIB NOTES ─────────────────────────────────────────────
Note: The following affect the Go standard library. Upgrade
your Go toolchain to resolve these.
MEDIUM stdlib GO-2025-1234
HTTP/2 rapid reset vulnerability
Fixed in: 1.25.1
── SUMMARY ──────────────────────────────────────────────────
Vulnerabilities: 1 critical, 1 high, 1 medium
Unmaintained: 1 archived, 1 stale, 1 warnings, 38 healthy
Notes: 1 dependency with actionable notes
42 dependencies checked in 4.2s
Use --output json to get structured JSON, ideal for CI pipelines, dashboards, or piping into jq:
modcheck --output json . | jq .{
"module": "github.com/example/myapp",
"go_version": "1.25",
"dependencies": { "direct": 42, "indirect": 156, "scanned": 42 },
"duration": "4.2s",
"has_issues": true,
"vulnerabilities": [
{
"id": "GO-2024-2605",
"aliases": ["CVE-2024-45337"],
"severity": "CRITICAL",
"cvss_score": 9.1,
"module": "golang.org/x/crypto",
"installed_version": "v0.17.0",
"fixed_version": "v0.31.0",
"summary": "Improper validation of certificate chains",
"is_stdlib": false,
"source": "osv"
}
],
"unmaintained": [
{
"module": "github.com/mitchellh/mapstructure",
"version": "v1.5.0",
"classification": "ARCHIVED",
"reason": "Repository is archived on github",
"is_archived": true,
"last_release": "2022-07-28T00:00:00Z",
"last_commit": "2022-08-15T00:00:00Z",
"latest_version": "v1.5.0"
}
],
"notes": [
{
"module": "github.com/google/go-github/v60",
"version": "v60.0.0",
"classification": "HEALTHY",
"reason": "Old tag but repo active",
"newer_major_version": "v68.0.0"
}
],
"summary": {
"vulnerabilities": { "critical": 1, "high": 1, "medium": 1, "low": 0, "unknown": 0 },
"health": { "archived": 1, "stale": 1, "warning": 1, "healthy": 38 }
}
}modcheck [flags] [path]
| Argument | Description |
|---|---|
path |
Path to a go.mod file or directory containing one. Defaults to . (current directory). |
| Flag | Default | Description |
|---|---|---|
--indirect |
false |
Include indirect (transitive) dependencies in the analysis. |
--deep |
false |
Run govulncheck for call-graph-aware analysis. Requires the full project source to be available at the given path. |
--output |
console |
Output format. console for styled terminal output, json for structured JSON. |
--stale-threshold |
2y |
Duration after which a dependency with no new release is flagged as STALE. Supports: Ny (years), Nm (months), Nd (days), or combinations like 2y3m. |
--no-color |
false |
Disable colored terminal output. |
--verbose |
false |
Show healthy dependencies in the output. |
--config |
.modcheck.yml |
Path to the configuration file. |
--version |
Print version and exit. | |
--help |
Print help and exit. |
| Variable | Description |
|---|---|
GITHUB_TOKEN |
GitHub personal access token. Increases API rate limit from 60 to 5,000 requests/hour. Recommended for projects with many dependencies. |
GITLAB_TOKEN |
GitLab personal access token. Required for private GitLab repositories. |
| Code | Meaning |
|---|---|
0 |
Program executed successfully (regardless of findings). |
2 |
Error (invalid input, missing go.mod, etc.). |
The exit code reflects whether modcheck ran correctly, not whether issues were found. Vulnerability findings and unmaintained dependencies are reported in the output but do not affect the exit code.
Create a .modcheck.yml file in your project root to configure persistent settings.
# Dependencies to skip during analysis.
# Supports exact paths and prefix patterns with trailing *.
ignore:
- github.com/your-org/internal-fork
- golang.org/x/exp
- github.com/some-org/*
# Duration after which a dep with no new release is flagged STALE.
# Format: Ny, Nm, Nd, or combinations (e.g., 2y, 6m, 2y3m, 30d).
# Default: 2y
stale_threshold: 2y
# Duration after which a dep with no new release triggers WARNING.
# Default: 1y
warning_threshold: 1y
# Include indirect dependencies.
# Default: false
indirect: falseCLI flags override config file values when both are specified.
modcheck queries the OSV.dev API to check each dependency for known vulnerabilities. OSV.dev aggregates data from multiple sources:
- Go Vulnerability Database (vuln.go.dev) -- Official Go security advisories
- GitHub Security Advisories (GHSA) -- Community-reported vulnerabilities
- National Vulnerability Database (NVD) -- CVE records
The query is done as a single batch request containing all dependencies with their exact versions. This is fast and requires no external tools.
Vulnerability severity is derived from CVSS v3.1 vector strings included in the OSV response. modcheck computes base scores from these vectors using the FIRST specification. When a vulnerability has no severity data in OSV (common for Go-specific advisories), modcheck falls back to the NVD API to fetch CVSS scores by CVE alias. If NVD is also unavailable, the vulnerability is reported with UNKNOWN severity.
When --deep is passed, modcheck additionally runs govulncheck which performs call-graph analysis to determine whether your code actually calls the vulnerable functions. This is more precise but requires the full project source code.
Each dependency is classified into one of these categories:
| Classification | Criteria | What it means |
|---|---|---|
| ARCHIVED | Repository is marked as archived on GitHub/GitLab | Dead project. Find a replacement. |
| STALE | No new release in > stale threshold (default: 2 years) | Likely abandoned. Plan a migration. |
| WARNING | No new release in > warning threshold (default: 1 year) | Losing momentum. Monitor it. |
| HEALTHY | None of the above | Active and maintained. |
| UNKNOWN | Could not fetch health data | Check manually. |
Data sources for classification:
- Go module proxy (
proxy.golang.org) -- Version list and publish timestamps. No authentication needed. - GitHub API -- Archived status, last push date, stars, open issues. Works without a token (60 req/hr limit) but a
GITHUB_TOKENis recommended for larger projects. - GitLab API -- Archived status, last activity. Requires
GITLAB_TOKENfor private repos. - Vanity URL resolution -- For modules like
gorm.io/gorm, modcheck resolves the actual repository URL via the proxy's Origin field or the standard?go-get=1meta tag protocol. Forgopkg.inmodules, modcheck maps directly to GitHub:gopkg.in/pkg.vNresolves togithub.com/go-pkg/pkg, andgopkg.in/user/pkg.vNresolves togithub.com/user/pkg.
When a data source is unavailable (no token, network error, unknown host), modcheck degrades gracefully and classifies based on whatever data it can collect.
Without a token, GitHub's API allows 60 requests per hour. If your project has more than ~50 dependencies, you'll hit the rate limit. With a token, the limit is 5,000 requests per hour.
Create a token at https://github.com/settings/tokens with no special scopes (public repo access is sufficient).
export GITHUB_TOKEN=ghp_your_token_hereThis happens when modcheck can't fetch data from either the Go module proxy or the repository host. Common causes:
- The module is hosted on a platform other than GitHub/GitLab
- The module's vanity URL doesn't serve the
go-importmeta tag - Network connectivity issues
No. modcheck is read-only. It reads your go.mod file and queries external APIs. It never modifies files, installs packages, or makes any changes to your project.
govulncheck focuses exclusively on known vulnerabilities and performs call-graph analysis to determine reachability. modcheck does vulnerability scanning too (via the OSV.dev API, which includes the same Go vulnerability database), but also checks for unmaintained dependencies -- archived repos, stale projects, and dependencies that may no longer receive security patches.
You can use modcheck's --deep flag to additionally run govulncheck for the most comprehensive analysis.