Skip to content
Back to skills

Dependency Vulnerability Audit

ASecurity

Use when auditing project dependencies for known vulnerabilities, supply chain risk, or provenance issues — covers Go modules, Maven/JVM, and CI integration for automated scanning

  • 104 stars
  • 0 votes
  • 0 copies
  • 4 views
  • Added May 26, 2026
developmentpythonrustgorubybashgitapidatabase

Works with

  • api

Security analysis

A100/100

Scanned May 27, 2026

npx -y skills add Habitat-Thinking/ai-literacy-superpowers --skill dependency-vulnerability-audit --agent claude-code

Installs into .claude/skills of the current project.

Are you the author of Dependency Vulnerability Audit?

Add the live security badge to your README. It updates with every re-scan.

Security grade badge for Dependency Vulnerability Audit
[![Security: A — Skills Directory](https://www.skillsdirectory.com/api/skills/habitat-thinking-dependency-vulnerability-audit/badge)](https://www.skillsdirectory.com/skills/habitat-thinking-dependency-vulnerability-audit)

More formats (shields.io, HTML) on the badges page. Keep it an A: scan every change in CI with Pro.

Download with Pro
SKILL.md
---
name: dependency-vulnerability-audit
description: Use when auditing project dependencies for known vulnerabilities, supply chain risk, or provenance issues — covers Go modules, Maven/JVM, and CI integration for automated scanning
---

# Dependency Vulnerability Audit

## Overview

Dependencies are the largest attack surface in most projects. This skill provides a structured audit process for Go and Maven/JVM projects, combining static manifest review with tool-driven vulnerability scanning.

**Critical rule: Never judge a dependency as safe or unsafe based on your knowledge of its version number. Version numbers in your training data are stale. Always run the tools.**

---

## Audit Checklist

### For every project

- [ ] Automated vulnerability scanner is run in CI (not just locally)
- [ ] Direct dependencies are intentional and documented
- [ ] No `replace` directives in `go.mod` pointing to local paths or forks
- [ ] Dependency manifest is committed (not generated at build time)

### Go-specific

- [ ] `go.sum` is committed alongside `go.mod`
- [ ] `govulncheck` runs in CI and fails the build on known CVEs
- [ ] No `replace` directives substituting public modules with local or private alternatives
- [ ] `go mod verify` passes (confirms module content matches go.sum hashes)

### Maven/JVM-specific

- [ ] Dependency versions are pinned (no version ranges: `[1.0,2.0)`)
- [ ] OWASP Dependency-Check (or equivalent) runs in CI
- [ ] No dependencies with legacy or low-trust group IDs without provenance verification
- [ ] Transitive dependency tree has been reviewed (`mvn dependency:tree`)

---

## Go: Running the Audit

### Check for known CVEs

```bash
# Install once:
go install golang.org/x/vuln/cmd/govulncheck@latest

# Run from the module root:
govulncheck ./...
```

`govulncheck` cross-references the Go vulnerability database (`https://vuln.go.dev/`) against the specific functions your code actually calls — not just which modules are present. This means fewer false positives than tools that flag any version of a module with any CVE.

### Verify module integrity

```bash
# Confirms every module in the build matches its go.sum hash.
# Fails if any module has been tampered with or if go.sum is stale.
go mod verify
```

### Check for suspicious replace directives

```bash
# Print any replace directives in go.mod:
grep -A1 "^replace" go.mod
```

A `replace` directive substituting a public module with a local path (`=> ../local-fork`) or a private fork is a supply chain red flag — it bypasses the module proxy and checksum verification.

### List all modules including transitive

```bash
go list -m all
```

Review the output for unfamiliar or unexpected module paths.

---

## Maven/JVM: Running the Audit

### Check for known CVEs (OWASP Dependency-Check)

```bash
# Run from the project root (downloads NVD data on first run — takes ~5 min):
mvn org.owasp:dependency-check-maven:check

# HTML report is generated at:
# target/dependency-check-report.html
```

### Review the dependency tree

```bash
# Show all direct and transitive dependencies with versions:
mvn dependency:tree
```

Look for:

- Unexpectedly old versions of well-known libraries
- Multiple versions of the same library (version conflicts)
- Unfamiliar group IDs — especially legacy namespaces (`com.googlecode.*`, `org.codehaus.*`) where maintainer continuity may be uncertain

### Check for version ranges (prohibited)

```bash
# Version ranges in pom.xml allow Maven to silently pull newer versions:
grep -E "\[|,|\)" pom.xml
```

Any match is a risk: Maven may resolve a different version than was tested.

---

## CI Integration

### Go: Add govulncheck to CI

```yaml
- name: Run vulnerability scan
  working-directory: go-tui
  run: |
    go install golang.org/x/vuln/cmd/govulncheck@latest
    govulncheck ./...
```

### Maven: Add OWASP Dependency-Check to CI

Add the plugin to `pom.xml` under `<build><plugins>`:

```xml
<plugin>
  <groupId>org.owasp</groupId>
  <artifactId>dependency-check-maven</artifactId>
  <version>9.0.9</version>
  <executions>
    <execution>
      <goals><goal>check</goal></goals>
    </execution>
  </executions>
  <configuration>
    <!-- Fail build if any dependency has a CVSS score >= 7 (high) -->
    <failBuildOnCVSS>7</failBuildOnCVSS>
  </configuration>
</plugin>
```

Then in the CI workflow:

```yaml
- name: Run OWASP dependency scan
  working-directory: tui
  run: mvn -B org.owasp:dependency-check-maven:check
```

### Dependabot for package updates

```yaml
# .github/dependabot.yml
version: 2
updates:
  - package-ecosystem: gomod
    directory: /go-tui
    schedule:
      interval: weekly

  - package-ecosystem: maven
    directory: /tui
    schedule:
      interval: weekly
```

---

## Dependency Age (libyear)

CVE scanners tell you whether a dependency has a *known* vulnerability.
They do not tell you how stale your dependency set is overall. A project
can pass every CVE check while silently accumulating years of staleness
across dozens of libraries — each one a growing risk window for
undiscovered vulnerabilities, breaking API changes, and lost upstream
support.

The **libyear** metric fills this gap. It sums, for every direct
dependency, the number of years between the version you use and the
latest release. A project at 2 libyears is reasonably current; a project
at 15 libyears has significant staleness risk even if no individual
dependency has a CVE today.

### Commands per ecosystem

#### npm

```bash
npx libyear
```

Produces a table showing each dependency, its current version, latest
version, and age in years. The final line gives the total libyear score.

#### Ruby

```bash
bundle exec libyear-bundler
```

Same tabular output for Bundler-managed gems.

#### Python

```bash
pip list --outdated --format=columns
```

Python has no single libyear tool with broad adoption. Use
`pip list --outdated` to get current vs. latest versions, then calculate
the age delta manually: for each outdated package, find the release date
of your pinned version and the release date of latest on PyPI, and sum
the differences.

#### Go

```bash
go list -m -u all
```

This lists every module dependency and flags those with available
updates. As with Python, calculate libyears manually: compare the date
of your current version tag with the date of the latest version tag for
each module that shows an update.

### Recommended thresholds

| Project size | Budget |
| --- | --- |
| Small (fewer than 20 direct dependencies) | < 10 libyears |
| Large (20+ direct dependencies) | < 20 libyears |

These are starting points. Adjust based on your risk tolerance and
release cadence.

### How to read the output

- **Total libyears** is the headline number — track it over time.
- **Single-dependency hotspots** over 3 libyears indicate concentrated
  risk. Prioritise those updates even if the total is within budget.
- **Week-over-week increase** means staleness is accumulating faster
  than you are updating. The GC rule flags this trend automatically.

---

## Report Format

After completing the audit, produce a findings table:

```markdown
## Dependency Audit

| Ecosystem | Finding | Severity | Fix |
| --- | --- | --- | --- |
| Go | `govulncheck` not in CI | Medium | Add govulncheck step to go-tui-tests.yml |
| Maven | OWASP Dependency-Check not in CI | Medium | Add plugin + CI step |
| Maven | `lanterna:3.1.1` — legacy com.googlecode group ID | Low | Verify provenance once; monitor for updates |
| All | No dependabot.yml for packages | Medium | Add gomod + maven ecosystems to dependabot.yml |
```

Severity guide:

- **Critical** — actively exploited CVE in a direct dependency
- **High** — CVE with CVSS ≥ 7 in direct or transitive dependency
- **Medium** — no scanner in CI; unverified provenance; stale unpinned dependency
- **Low** — legacy group ID with no known CVE; minor hygiene

---

## What the Tools Cannot Catch

- **Malicious code with no published CVE** — a new supply chain attack has no CVE until discovered. Tools only know about known vulnerabilities.
- **Your knowledge of version numbers** — do not assert that a version "doesn't exist" or "seems wrong" based on training data. Module proxy and go.sum are the ground truth; tool output is the authority.
- **Semantic correctness of a dependency** — tools verify identity and known CVEs, not whether a library does what its README claims.

For highest assurance, generate an SBOM and sign it:

```bash
# Using Syft (install from https://github.com/anchore/syft):
syft dir:. -o cyclonedx-json > sbom.json
```

Attribution

Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.

Comments

Loading comments…

Newsletter

Get the weekly list of safe new skills, and the ones we pulled.