DEV Community

Shixian Sheng
Shixian Sheng

Posted on

I ran npm audit and DepGra on the same project — here's what each one caught

I wanted to see how different tools handle the same dependency tree, so I ran both npm audit and my open-source tool DepGra against a real Next.js project with 1,312 packages. Here's what actually happened.

The project

The test subject is a production Next.js app with a 19,000-line package-lock.json. 1,312 packages, 3,792 dependency relationships. A pretty typical mid-size project.

npm audit results

npm audit
Enter fullscreen mode Exit fullscreen mode

npm audit reported 10 vulnerabilities (3 moderate, 7 high) across 8 packages:

  • serialize-javascript@6.0.2 — RCE via RegExp.flags (high)
  • next@15.5.9 — 2 advisories (high)
  • minimatch@3.1.2 and minimatch@9.0.5 — 3 ReDoS advisories each (high)
  • flatted@3.3.3 — unbounded recursion DoS (high)
  • rollup@4.54.0 — arbitrary file write via path traversal (high)
  • ai@4.3.19 — filetype whitelist bypass (moderate)
  • jsondiffpatch@0.6.0 — XSS via HtmlFormatter (moderate)
  • ajv@6.12.6 and ajv@8.17.1 — ReDoS with $data option (moderate)

npm audit also tells you which vulnerabilities have fixes available and whether they'd require breaking changes. That's useful context DepGra doesn't provide.

DepGra results

DepGra scanned the same package-lock.json in 6.5 seconds. It found 12 unique advisories across 10 packages:

CRITICAL  GHSA-5c6j-r48x-rmvq  serialize-javascript@6.0.2
HIGH      GHSA-23c5-xmqv-rm74  minimatch@3.1.2, minimatch@9.0.5
HIGH      GHSA-25h7-pfq9-p65f  flatted@3.3.3
HIGH      GHSA-3ppc-4f35-3m26  minimatch@3.1.2, minimatch@9.0.5
HIGH      GHSA-7r86-cg39-jmmj  minimatch@3.1.2, minimatch@9.0.5
HIGH      GHSA-h25m-26qc-wcjf  next@15.5.9
HIGH      GHSA-mw96-cpmx-2vgc  rollup@4.54.0
MEDIUM    GHSA-33vc-wfww-vjfv  jsondiffpatch@0.6.0
MEDIUM    GHSA-5f7q-jpqc-wp7h  next@15.5.9
MEDIUM    GHSA-9g9p-9gw9-jx7f  next@15.5.9
MEDIUM    GHSA-rwvc-j5jr-mgvh  ai@4.3.19
UNKNOWN   GHSA-2g4f-4pwh-qvx6  ajv@6.12.6, ajv@8.17.1
Enter fullscreen mode Exit fullscreen mode

What was different

All 11 advisories from npm audit showed up in DepGra's results. But DepGra found one extra:

GHSA-5f7q-jpqc-wp7h (CVE-2025-59472) — Next.js Unbounded Memory Consumption via PPR Resume Endpoint. Published January 28, 2026. npm audit didn't report it.

Why? DepGra queries OSV.dev, which aggregates vulnerability data from multiple sources. npm audit queries the GitHub Advisory Database. Sometimes one source has advisories the other hasn't ingested yet. In this case, OSV.dev had this CVE and GitHub's advisory database didn't surface it through npm audit at the time I tested.

This isn't a knock on npm audit — advisory databases update at different speeds and there will always be timing differences. Tomorrow npm audit might catch something OSV.dev doesn't. The point is that checking against multiple data sources catches more.

A few other differences worth noting:

  • npm audit classified serialize-javascript as "high." DepGra pulled the full CVSS vector and scored it as CRITICAL. Same vulnerability, different severity classification depending on the data source.
  • npm audit counts vulnerabilities by affected package instance (so minimatch across 4 node_modules locations counts differently). DepGra counts unique CVE IDs.
  • npm audit tells you if a fix is available and whether it's a breaking change. DepGra doesn't do remediation — it's a visibility tool.

What the graph adds

The flat list above tells you what's vulnerable. But when I loaded the same scan into DepGra's graph view, two things jumped out:

minimatch is a chokepoint. The flat list shows minimatch has 3 HIGH advisories, same as any other package. But the graph shows that minimatch@3.1.2 has packages like @sentry/node, @typescript-eslint/typescript-estree, and glob all depending on it. If you're prioritizing what to fix, minimatch has a bigger blast radius than its severity alone suggests.

serialize-javascript's risk path is clear. In the flat list, it's one line item. In the graph, you can see the chain: copy-webpack-plugin and terser-webpack-plugin both depend on serialize-javascript@6.0.2. That CRITICAL RCE vulnerability has two separate paths into the project. You can trace each one visually.

None of this is information you can't figure out from npm ls and some digging. But having it laid out as a graph makes the topology obvious instead of something you have to reconstruct in your head.

How DepGra works

The tech stack is pretty simple:

  • Parsers for package-lock.json, Cargo.lock, poetry.lock, requirements.txt, and go.mod
  • OSV.dev batch API for vulnerability data — sends all packages in one request, then fetches full details for any hits
  • SQLite for storage, NetworkX for graph analysis (centrality scoring, path finding)
  • Flask serves the REST API, Svelte + Cytoscape.js renders the graph
  • Topological sort for the DAG layout — O(V+E), handles 1,300+ nodes without choking

For Python requirements.txt specifically, it resolves transitive dependencies by querying the PyPI API, since requirements.txt doesn't include the dependency tree like a lockfile does.

Try it

git clone https://github.com/KPCOFGS/depgra
cd depgra

# Install
cd backend && uv venv .venv && source .venv/bin/activate && uv pip install -r requirements.txt && cd ..
cd frontend && npm install && npm run build && cd ..

# Run
python run.py
# Open http://127.0.0.1:5000
Enter fullscreen mode Exit fullscreen mode

Or use the CLI:

python run.py scan path/to/package-lock.json
python run.py scan requirements.txt --fail-on HIGH
Enter fullscreen mode Exit fullscreen mode

What DepGra doesn't do

I want to be upfront about the limitations:

  • No auto-remediation. It won't suggest version upgrades or create fix PRs. npm audit fix does this and DepGra doesn't.
  • No container scanning, no license compliance, no secrets detection. It's specifically a dependency vulnerability visualizer.
  • The severity classifications come from OSV.dev and can differ from what npm audit or Snyk reports for the same CVE.
  • For very large graphs (1,000+ packages), the visualization gets dense. It's still functional but not as clean as a 50-package graph.

What's next

  • SBOM export (CycloneDX/SPDX)
  • Remediation suggestions (which minimum version upgrade resolves a CVE)
  • GitHub Action for CI/CD integration

The repo is at github.com/KPCOFGS/depgra. MIT licensed. Feedback welcome.

Top comments (0)