Skip to content

Project to scan vulnerabilities over API repository dependencies

License

Notifications You must be signed in to change notification settings

Drafteame/modcheck

Repository files navigation

modcheck

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.

What it does

  • 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.

Installation

go install github.com/Drafteame/modcheck/cmd/modcheck@latest

Or build from source:

git clone https://github.com/Drafteame/modcheck.git
cd modcheck
go build -o modcheck ./cmd/modcheck

Quick start

# 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

Example output

  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

JSON output

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 }
  }
}

CLI reference

modcheck [flags] [path]

Arguments

Argument Description
path Path to a go.mod file or directory containing one. Defaults to . (current directory).

Flags

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.

Environment variables

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.

Exit codes

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.

Configuration file

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: false

CLI flags override config file values when both are specified.

How vulnerability scanning works

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.

How health classification works

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:

  1. Go module proxy (proxy.golang.org) -- Version list and publish timestamps. No authentication needed.
  2. GitHub API -- Archived status, last push date, stars, open issues. Works without a token (60 req/hr limit) but a GITHUB_TOKEN is recommended for larger projects.
  3. GitLab API -- Archived status, last activity. Requires GITLAB_TOKEN for private repos.
  4. 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=1 meta tag protocol. For gopkg.in modules, modcheck maps directly to GitHub: gopkg.in/pkg.vN resolves to github.com/go-pkg/pkg, and gopkg.in/user/pkg.vN resolves to github.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.

FAQ

Why do I need a GITHUB_TOKEN?

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_here

Why is a dependency classified as UNKNOWN?

This 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-import meta tag
  • Network connectivity issues

Does modcheck modify my project?

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.

How is this different from govulncheck?

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.

About

Project to scan vulnerabilities over API repository dependencies

Resources

License

Stars

Watchers

Forks

Packages

No packages published

Contributors 3

  •  
  •  
  •  

Languages