dependency-auditor
Dependency & supply-chain audit pack for JavaScript/Node package.json manifests: parse dependencies/devDependencies/peer/optional into a normalized list, flag semver-range risk from outdated/loose...
dependency-auditor — heuristic software-composition analysis
Static audit of a Node/JS package.json: parse dependencies, score semver-range risk, bucket licenses, raise severity flags, count by type, and advise deduping. Pure ESM, Node built-ins only, zero npm deps. No live npm registry or CVE feed — every signal is a deterministic heuristic over the manifest text, so it works fully offline.
Tools
| Tool | Input | Output |
|---|---|---|
parse | { packageJson } or { deps } | Normalized dep list { name, range, type, scope, specifier, preMajor, version } + counts by type. |
outdatedHeuristic | { packageJson } / { deps } | Range-tightness risk per dep (wildcard/tag/git → high, caret/tilde → low), a health score/grade. |
licenseSummary | { licenses } or { packageJson } | Licenses bucketed permissive / weak-copyleft / copyleft / network-copyleft / proprietary / unknown, strongest obligation, risky packages. |
severityFlags | { packageJson } / { deps } | Named flags: unpinned-range, git-dependency, prerelease-lock, caret-pre-1.0, deprecated-name-heuristic, too-many-deps. |
countByType | { packageJson } / { deps } | Counts by type, specifier kind, and scope. |
dedupeAdvice | { packageJson } / { deps } | Duplicate declarations, @types in prod, and overlapping-library clusters (moment vs dayjs, request vs axios…). |
Usage
import pack from './index.js';
const pkg = { dependencies: { react: '^18.2.0', moment: '*', 'left-pad': '1.0.0' }, devDependencies: { jest: '^29' } };
const risk = await pack.adapters.outdatedHeuristic({ packageJson: pkg });
// risk.highRisk -> ['moment'] ; risk.grade -> e.g. 'C'
const lic = pack.adapters.licenseSummary({ licenses: { react: 'MIT', ffmpeg: 'GPL-3.0', srv: 'AGPL-3.0' } });
// lic.strongestObligation -> 'network-copyleft'
AI mode
outdatedHeuristic accepts options.ai: true; when a model is reachable (../_shared/llm.js) it adds a plain-English narrative and is tagged mode: 'llm'. Otherwise you get the deterministic analysis tagged mode: 'heuristic'. A down model never throws.
DRY boundary
Audits JS package.json manifest text with heuristics. It does not hit the npm registry, resolve a full lockfile tree, or fetch real CVEs. Dockerfile/container analysis lives in dockerfile; webhook signing/verification lives in webhook-forge.