npm-dep-risk
v0.2.3
Published
Explain the observable risk profile of npm packages used by a project.
Readme
npm-dep-risk
npm-dep-risk is a Node.js CLI for explaining the observable risk profile of npm packages used by a project. It combines local dependency declarations and lockfiles with public npm registry metadata to produce a transparent, heuristic score.
It is developed with Bun and distributed as a Node.js 22+ command-line tool.
npm-dep-risknever installs, downloads, or executes the package it analyzes. It reads local metadata and the public npm registry only.
What it does
- Scan every dependency declaration in the current
package.json. - Resolve the version actually installed through a lockfile whenever possible.
- Highlight a newer version allowed by the manifest when it changes the risk score.
- Explain the score with npm metadata: package and release age, maintainer count, publication cadence, lifecycle scripts, and deprecation notices.
- Produce a readable terminal report or stable JSON (
schemaVersion: 1).
Quick start
npm install --global npm-dep-risk
npm-dep-riskUsage
npm-dep-risk [package-spec] [options]Project scan
Calling npm-dep-risk without an argument scans every declaration in the current project's package.json:
dependenciesdevDependenciesoptionalDependenciespeerDependencies
Each declaration receives its own row. A package declared in more than one section therefore appears more than once. The terminal table is ordered by descending risk score, so packages needing attention appear first.
npm-dep-risk- npm-dep-risk 0.2.3 -
Project dependencies · 3 analyzed · 0 unavailable
Package Type Installed Update Risk
esbuild prod 0.25.4 0.25.8 23 → 8
commander prod 15.0.0 — 0 LOW
typescript dev 5.9.3 — 0 LOW
For details:
- npm-dep-risk [email protected]An unavailable registry entry does not prevent the remaining packages from being analyzed. It remains visible in the table and causes the overall command to exit with code 1.
Single-package analysis
Pass a package name to inspect it in detail:
npm-dep-risk esbuildWhen no version is supplied, npm-dep-risk looks for that package as a direct declaration in the current package.json, then resolves its installed version from a lockfile. If the package is not declared or cannot be found in a lockfile, the CLI analyzes npm's latest version and states that the package is not installed in the project.
An explicit selector bypasses project-version resolution:
| Command | Resolves |
| --- | --- |
| npm-dep-risk [email protected] | An exact npm version |
| npm-dep-risk esbuild@latest | A dist-tag |
| npm-dep-risk esbuild@next | Any existing dist-tag |
| npm-dep-risk esbuild@^0.25.0 | The highest npm version satisfying the SemVer range |
| npm-dep-risk @scope/[email protected] | A scoped package and exact version |
npm aliases, Git and tarball URLs, local paths, multiple specs, and unsatisfied ranges are rejected.
Options
| Option | Description |
| --- | --- |
| --json | Write one machine-readable JSON document to standard output. |
| --verbose | Add signal diagnostics for a single-package analysis. In a terminal project scan, add diagnostics for HIGH and CRITICAL packages. |
| --color <mode> | Control terminal colors: auto (default), always, or none. |
| -h, --help | Display command help. |
| -V, --version | Display the CLI version. |
Colors are enabled automatically for interactive terminals. JSON output is never colorized.
Version resolution and updates
For an implicitly selected package, the following lockfiles are supported:
| Package manager | Lockfiles |
| --- | --- |
| npm | package-lock.json, npm-shrinkwrap.json |
| pnpm | pnpm-lock.yaml |
| Yarn | yarn.lock |
| Bun | bun.lock |
If the installed version is older than the newest version allowed by its declaration range, the CLI shows a compact comparison automatically:
Update
1.11.0 → 1.12.0
23 → 8
✓ Lower risk candidate
For details: npm-dep-risk [email protected]The update candidate remains within the range declared in package.json; it is not necessarily npm's latest version. No update section is shown when the installed version is already the newest compatible version.
Scoring model
Scores are heuristic indicators, not vulnerability findings or a security guarantee. The package and release dimensions are each capped at 100; the overall score is round(35% package + 65% release).
| Dimension | Signal | Maximum impact |
| --- | --- | ---: |
| Package | Young package at the target release | +40 |
| Package | One or two observable maintainers | +20 |
| Package | Rapid publication cadence in the preceding 48 hours | +30 |
| Package | Global deprecation notice | +20 |
| Release | Newly published release | +40 |
| Release | preinstall, install, or postinstall script | +25 |
| Release | Lifecycle script added since the preceding release | +15 |
| Release | Version-specific deprecation notice | +20 |
| Overall score | Level |
| ---: | --- |
| 0–24 | LOW |
| 25–49 | MODERATE |
| 50–74 | HIGH |
| 75–100 | CRITICAL |
Lifecycle scripts are detected from the package's published scripts metadata. They are never run.
JSON output
Successful --json analyses always write a single document to standard output. Both project scans and single-package analyses use the same top-level shape:
{
"schemaVersion": 1,
"analyzedAt": "2026-08-11T17:29:36.616Z",
"project": {
"path": "/path/to/project",
"summary": { "total": 1, "analyzed": 1, "failed": 0 }
},
"analyses": [
{
"status": "success",
"target": { "name": "esbuild", "source": "argument" },
"report": { "resolution": {}, "score": {}, "signals": [] }
}
]
}Project-scan targets additionally include their section and declaredRange. A failed package remains in analyses with status: "error" and a structured error object. With --verbose, JSON signals add a diagnostics object containing their source and applied rule.
Exit codes
| Code | Meaning |
| ---: | --- |
| 0 | Analysis completed successfully. The risk level never changes this code. |
| 1 | Technical error, or at least one package failed during a project scan. |
| 2 | Invalid command-line input or an invalid/unresolvable package selector. |
For human-readable errors, messages are written to standard error. With --json, errors are emitted as one JSON document on standard output.
Scope and limitations
npm-dep-risk currently evaluates public npm metadata and direct project declarations only. It does not yet analyze transitive dependency graphs, lockfile-wide package occurrences, vulnerabilities, provenance, historical maintainer changes, CI policies, or package contents.
Treat its output as one input to a dependency-review workflow, not as a decision engine on its own.
