npm-scanner

Design Decisions

Zero npm Dependencies

npm-scanner has no npm dependencies. This is intentional.

The tool audits npm packages for supply chain attacks. If it depended on npm packages, it would be vulnerable to the same attacks it detects. An attacker could compromise a dependency of npm-scanner to disable or subvert its detection.

This constraint means:

The tradeoff is slower development (no libraries) for stronger security guarantees.

Defense in Depth

npm-scanner uses multiple detection mechanisms because no single check catches all attacks:

Each mechanism has blind spots. Together, they provide broader coverage.

Risk Scoring Over Binary Decisions

npm-scanner assigns risk scores rather than pass/fail verdicts because:

  1. Context matters - A lifecycle script in puppeteer is legitimate; in an unknown package it’s suspicious
  2. False positives are costly - Blocking legitimate packages frustrates users
  3. Humans make final decisions - Security tools inform; humans decide

The scoring weights were chosen based on:

Caching Strategy

The cache exists because:

The 3-day default expiration balances freshness with performance. Security-critical data (IOCs) is not cached—it’s bundled with the tool.

Shared Library Pattern

Common functionality lives in npm-audit-lib.sh because:

Scripts source the library rather than copying code.

Report Output Format

Reports are Markdown because:

Structured data (TSV) is generated for programmatic analysis.