Skip to content
Back to skills

Dependency Vulnerability Scanning

ASecurity

Use when a repo needs dependency CVE scanning (SCA) in CI, a team is choosing between native audits (npm audit, pip-audit, cargo audit), OSV-Scanner and Snyk, or findings need triage. Scans lockfiles with thresholds, checks packages were seen, outputs SARIF and allows only expiring ignores.

  • 13 stars
  • 0 votes
  • 0 copies
  • 0 views
  • Added November 11, 2026
testingpythonrustgorubybashnodedockergitdatabasesecurity

Works with

  • cli

Security analysis

A100/100

Pro scans all 9 files and shows the line behind each finding

Scanned November 11, 2026

npx -y skills add testland/qa --skill dependency-vulnerability-scanning --agent claude-code

Installs into .claude/skills of the current project.

Are you the author of Dependency Vulnerability Scanning?

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

Security grade badge for Dependency Vulnerability Scanning
[![Security: A — Skills Directory](https://www.skillsdirectory.com/api/skills/testland-dependency-vulnerability-scanning/badge)](https://www.skillsdirectory.com/skills/testland-dependency-vulnerability-scanning)

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-scanning
description: "Use when a repo needs dependency CVE scanning (SCA) in CI, a team is choosing between native audits (npm audit, pip-audit, cargo audit), OSV-Scanner and Snyk, or findings need triage. Scans lockfiles with thresholds, checks packages were seen, outputs SARIF and allows only expiring ignores."
metadata:
  keywords: "sca, dependency-scanning, osv-scanner, snyk, npm-audit, pip-audit, cargo-audit, bundler-audit, owasp-dependency-check"
  version: "1.0.1"
---

# dependency-vulnerability-scanning

## Overview

Software composition analysis (SCA) matches the dependencies a repo
declares (lockfiles, manifests, SBOMs) against vulnerability advisory
databases. Each scanner family reads a different database, so their
coverage differs:

| Family | Database | Cost |
|---|---|---|
| Native audits (`npm audit`, `pip-audit`, `cargo audit`, `bundle-audit`, Dependency-Check) | The ecosystem's own advisory feed (npm, PyPA, RustSec, RubySec, NVD) | Free; usually already installed |
| OSV-Scanner | OSV.dev, aggregated across ecosystems ([OSV-Scanner usage][osv-usage]) | Free, open source |
| Snyk | Snyk's own database, plus `snyk monitor` alerts ([Snyk CLI][sn-gh]) | Commercial license |

The workflow below is the same for all three; the per-tool detail is
in the references.

## When to use

- A repo has no dependency scanning in CI yet.
- The team must choose between native audits, OSV-Scanner and Snyk, or
  layer two of them.
- A scanner reports findings and someone wants to suppress, waive or
  gate on them.

## Step 1 - Pick the scanner

| Repo situation | Start with | Reference |
|---|---|---|
| One ecosystem, fastest first gate, nothing extra to install | That ecosystem's native audit | [references/native-audits.md](references/native-audits.md) |
| Several ecosystems, open source only, or an SBOM as input | OSV-Scanner | [references/osv-scanner.md](references/osv-scanner.md) |
| A Snyk license, or alerts on new CVEs against pinned versions | Snyk | [references/snyk.md](references/snyk.md) |

For full coverage run one native audit plus one cross-ecosystem
scanner (OSV-Scanner or Snyk): each database misses advisories the
others carry.

## Step 2 - Scan the committed lockfile

Scan lockfiles, not loose manifests: a manifest range resolves to
whatever is newest today, a lockfile is what actually ships.

```bash
npm audit --audit-level=high                     # npm; also yarn npm audit / pnpm audit
pip-audit -r requirements.txt                    # Python
cargo audit                                      # Rust
bundle-audit check --update                      # Ruby; --update refreshes the advisory DB
osv-scanner scan -L package-lock.json            # one lockfile
osv-scanner scan -r ./                           # every lockfile and SBOM under ./
snyk test --all-projects --severity-threshold=high
```

SBOM input: OSV-Scanner picks up SBOMs whose names follow the SPDX or
CycloneDX patterns (`*.spdx.json`, `bom.json`, `*.cdx.json`) and scans
one directly with `osv-scanner scan source -L my-app.cdx.json`; the
components need Package URLs ([OSV-Scanner source scanning][osv-src]).
Snyk scans one with `snyk sbom test --file=my-app.cdx.json` (CycloneDX
1.4-1.6 JSON or SPDX 2.3 JSON, Enterprise plans) ([Snyk sbom test][sn-sbom]).
`syft-generation` produces the SBOM.

## Step 3 - Check the scan saw packages

A scan that found no lockfile passes silently. Before trusting a green
result, confirm the scanner reported the packages you expect.

OSV-Scanner makes this explicit with its exit codes
([OSV-Scanner output][osv-out]):

| Exit code | Meaning | CI action |
|---|---|---|
| 0 | Packages found, no known vulnerabilities | Pass |
| 1 | Packages found, vulnerabilities found | Fail (or triage, Step 5) |
| 127 | General error | Fail |
| 128 | No packages found | Fail: the scan did nothing; fix the path or lockfile name |

For the other scanners, read the JSON report's dependency count, or
run once against a branch with a known-vulnerable pin and confirm the
job goes red.

## Step 4 - Emit machine-readable output

```bash
osv-scanner scan -r ./ --format sarif --output-file osv.sarif
snyk test --sarif-file-output=snyk.sarif
pip-audit --format sarif --output pip-audit.sarif
npm audit --json > npm-audit.json
```

`--format` and `--output-file` are OSV-Scanner's output flags
([OSV-Scanner usage][osv-usage]); the container image takes the same
arguments ([installation][osv-install]). Upload SARIF to code scanning, and
pass two or more reports to `multi-tool-finding-triage` (or the
`security-finding-triager` agent) to dedupe findings across scanners.

## Step 5 - False-positive triage

Suppress a finding only in a committed file, per advisory, with a
reason, an approver and an expiry date, so it comes back for review:

| Scanner | Suppression | Expiry |
|---|---|---|
| Snyk | `.snyk` `ignore:` entry | `expires:` (required) |
| OSV-Scanner | `osv-scanner.toml` `[[IgnoredVulns]]` | `ignoreUntil` |
| pip-audit | `--ignore-vuln <id>` | Record in a committed ignore list |
| Dependency-Check | `dependency-check-suppressions.xml` | `<suppress until="2026-12-31Z">` ([suppression docs][dc-supp]) |
| cargo audit | `.cargo/audit.toml` `[advisories] ignore` | Record in the justification |
| bundler-audit | `.bundler-audit.yml` `ignore:` | Record in the justification |

Before suppressing as "not exploitable", prove it: `reachability-analyzer`
checks whether the vulnerable function is called, and
`cve-exploitability-triage` weighs EPSS and KEV. A severity threshold
(`--audit-level`, `--severity-threshold`) is a scan filter, not a
suppression. Templates per tool: [references/snyk-policy-and-triage.md](references/snyk-policy-and-triage.md),
[references/osv-scanner-config-and-ci.md](references/osv-scanner-config-and-ci.md),
[references/ecosystem-config-and-triage.md](references/ecosystem-config-and-triage.md),
[references/cargo-bundle-audit.md](references/cargo-bundle-audit.md).

## Step 6 - Gate CI

```yaml
jobs:
  sca:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v5
      - if: hashFiles('package-lock.json') != ''
        run: npm audit --audit-level=high
      - if: hashFiles('requirements.txt') != ''
        run: pipx run pip-audit -r requirements.txt
      - name: OSV-Scanner (fails on findings and on exit 128)
        run: |
          docker run --rm -v "$PWD:/src" ghcr.io/google/osv-scanner:latest \
            scan -r /src --format sarif --output-file /src/osv.sarif
      - if: always()
        uses: github/codeql-action/upload-sarif@v3
        with: { sarif_file: osv.sarif }
```

With a Snyk license, add `snyk test --severity-threshold=high` on pull
requests and `snyk monitor` on the default branch, which snapshots the
dependency tree and alerts on CVEs disclosed later
([Snyk CLI][sn-gh]); the full job is in [references/snyk.md](references/snyk.md).

## Worked example

A Node + Python service has no SCA. Step 1: two ecosystems, no Snyk
license, so `npm audit` and `pip-audit` as the fast gate plus
OSV-Scanner for cross-ecosystem coverage. The first OSV run exits 128:
the Python lockfile is `requirements-lock.txt`, a name OSV-Scanner does
not detect, so the job is pointed at it with `-L requirements-lock.txt`
and now exits 1 with two findings. One is a `lodash` advisory in a
function the service never calls; `reachability-analyzer` confirms it,
and an `[[IgnoredVulns]]` entry with `ignoreUntil` 90 days out and the
approver's name goes into `osv-scanner.toml`. The other is upgraded.
The job goes green, and the ignore resurfaces when it expires.

## Anti-patterns

| Anti-pattern | Why it fails | Fix |
|---|---|---|
| No severity threshold on the first run | Low-severity noise; the team turns the job off | `--audit-level=high` / `--severity-threshold=high` |
| Treating any non-1 exit as green | OSV exit 128 means nothing was scanned | Fail on 128 (Step 3) |
| Suppression with no expiry | Debt never comes back for review | `expires:` / `ignoreUntil` (Step 5) |
| One scanner only | Each advisory database has gaps | Native audit plus OSV-Scanner or Snyk (Step 1) |
| `npm audit fix --force` in CI | Silently bumps major versions | Review forced upgrades by hand |
| Token in scripts | Leaks `SNYK_TOKEN` | CI secret |

## Limitations

- No scanner here does reachability: every advisory on a declared
  dependency counts, used or not. Use `reachability-analyzer`.
- Coverage differs by ecosystem in every database.
- Container images need `trivy-image` or the Grype flow in
  `syft-generation`.
- Automated upgrade PRs are `dependabot-config` and `renovate-config`.

## References

- [OSV-Scanner usage][osv-usage] - `-L`, `-r`, `--format`, `--output-file`, `--config`.
- [OSV-Scanner source scanning][osv-src] - SBOM file-name patterns, `scan source -L`.
- [OSV-Scanner output][osv-out] - output formats and exit codes.
- [OSV-Scanner installation][osv-install] - `ghcr.io/google/osv-scanner` image.
- [Dependency-Check suppression][dc-supp] - suppression file, `until` expiry.
- [Snyk CLI][sn-gh] - `snyk test`, `snyk monitor`, subcommands.
- [Snyk sbom test][sn-sbom] - `snyk sbom test --file`, supported formats, Enterprise plans.
- Per-tool references: [references/native-audits.md](references/native-audits.md),
  [references/osv-scanner.md](references/osv-scanner.md),
  [references/snyk.md](references/snyk.md).
- Sibling skills: `syft-generation` (SBOMs), `reachability-analyzer`,
  `cve-exploitability-triage`, `multi-tool-finding-triage`,
  `dependabot-config`, `renovate-config`, `trivy-image`.

[osv-usage]: https://google.github.io/osv-scanner/usage/
[osv-src]: https://github.com/google/osv-scanner/blob/main/docs/scan-source.md
[osv-out]: https://google.github.io/osv-scanner/output/
[osv-install]: https://github.com/google/osv-scanner/blob/main/docs/installation.md
[dc-supp]: https://jeremylong.github.io/DependencyCheck/general/suppression.html
[sn-gh]: https://github.com/snyk/snyk
[sn-sbom]: https://docs.snyk.io/developer-tools/snyk-cli/commands/sbom-test

Files in this skill

  • .tessl-plugin/plugin.json440 B
  • SKILL.md9.8 KB
  • references/cargo-bundle-audit.md7.2 KB
  • references/ecosystem-config-and-triage.md2.9 KB
  • references/native-audits.md7.2 KB
  • references/osv-scanner-config-and-ci.md2.6 KB
  • references/osv-scanner.md5.5 KB
  • references/snyk-policy-and-triage.md1.6 KB
  • references/snyk.md6.7 KB

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.

View all in testing →

Comments

Loading comments…

Newsletter

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