npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

lockfile-sentinel

v0.1.1

Published

Security scanner for package-lock.json and pnpm-lock.yaml to detect malicious dependency changes

Readme

lockfile-sentinel 🛡️

A security scanner for package-lock.json and pnpm-lock.yaml that detects suspicious dependency changes before they land in production.

Inspired by the March 2026 Axios vulnerability, lockfile-sentinel analyzes package changes with three powerful detection layers:

  • Blast Radius Report - Track exactly how many transitive dependencies changed
  • New Maintainer Alert - Cross-reference npm metadata to flag suspicious account access
  • Entropy Check - Detect obfuscated or unusually compressed code in dependencies

The Problem

In late March 2026, malicious versions of Axios were pushed to npm, bypassing standard CI checks because they looked like legitimate updates. Developers had no visibility into:

  • How many transitive dependencies were pulled in
  • Whether the maintainer was newly added
  • Whether code was suspiciously obfuscated

lockfile-sentinel solves this by analyzing behavioral anomalies in your lockfile changes.

Installation

npm install -g lockfile-sentinel

Or in your project:

npm install --save-dev lockfile-sentinel

Quick Start

CLI Usage

Scan your current lockfile against the previous commit:

lockfile-sentinel scan

With custom thresholds:

lockfile-sentinel scan \
  --threshold 75 \
  --blast-radius 40 \
  --entropy 6.5 \
  --fail-on-findings

Specify custom base and head files:

lockfile-sentinel scan package-lock.json.old package-lock.json

Output as JSON for CI/CD integration:

lockfile-sentinel scan --json

Analyze Entropy of a File

lockfile-sentinel analyze-entropy src/suspicion.js

Initialize GitHub Actions

lockfile-sentinel init

This creates .github/workflows/lockfile-sentinel.yml to automatically check lockfile changes on every PR.

Architecture

Phase A: Drift Analysis

The tool builds a dependency graph from both lockfile versions and compares tree structure.

Blast Radius Metric: If updating 1 package changes 45+ transitive dependencies, that's high-risk.

Phase B: Metadata Verification

For every new/updated package, the tool:

  1. Queries registry.npmjs.org/<package>
  2. Checks maintainer history and publish timestamps
  3. Flags if the publisher was recently added to the project

Phase C: Entropy Analysis

High-entropy files (>6.5) often indicate:

  • Compression/minification hiding malicious code
  • Encrypted payloads
  • Binary data where text code should be

Shannon Entropy Formula: $$H(X) = -\sum_{i=1}^{n} P(x_i) \log_2 P(x_i)$$

Configuration

Command Line Options

--threshold <number>        Risk threshold (0-100, default: 80)
--blast-radius <number>     Blast radius threshold (default: 45)
--entropy <number>          Entropy threshold (default: 6.5)
--json                      Output as JSON
--fail-on-findings          Exit with code 1 if findings detected

Risk Score Calculation

The tool calculates a risk score (0-100) based on:

  • Base score (0-30): Number of packages changed
  • Critical findings (+35 each): Likely malicious patterns
  • High findings (+15 each): Suspicious behavior
  • Medium findings (+5 each): Worth investigating

Programmatic Usage

const { LockfileSentinel } = require('lockfile-sentinel');

const sentinel = new LockfileSentinel();
const result = await sentinel.scan(
  'package-lock.json.old',
  'package-lock.json',
  {
    blastRadius: 45,
    entropyThreshold: 6.5,
    maintainerAgeHours: 24
  }
);

console.log(result);
// {
//   timestamp: Date,
//   baseFile: string,
//   headFile: string,
//   totalChanges: number,
//   findings: SecurityFinding[],
//   riskScore: number,
//   blastRadius: Map<string, number>,
//   summary: {...}
// }

Security Finding Types

1. Blast Radius

Type: blast_radius
When: A single package update triggers 45+ transitive dependency changes

{
  "type": "blast_radius",
  "severity": "high|critical",
  "package": "axios",
  "message": "Large blast radius: 67 transitive dependencies affected",
  "evidence": {
    "packageName": "axios",
    "oldVersion": "1.5.0",
    "newVersion": "1.6.2",
    "transitiveDepsChanged": 67
  }
}

2. New Maintainer Alert

Type: new_maintainer
When: Package published by user who recently gained access

{
  "type": "new_maintainer",
  "severity": "high",
  "package": "follow-redirects",
  "message": "Suspicious activity detected: Published only 5 minutes ago",
  "evidence": {
    "packageName": "follow-redirects",
    "version": "1.14.9",
    "reasons": ["Published only 5 minutes ago"],
    "maintainers": [{"name": "newuser123", "email": "..."}]
  }
}

3. Entropy Detection

Type: entropy
When: File entropy > 6.5 (indicates compression/obfuscation)

{
  "type": "entropy",
  "severity": "high",
  "package": "malicious-lib",
  "message": "High entropy detected in minified files (7.2)",
  "evidence": {
    "filename": "lib/index.js",
    "entropy": 7.2,
    "fileSize": 45000
  }
}

GitHub Actions Integration

Create .github/workflows/lockfile-sentinel.yml:

name: Security - Lock File Sentinel

on:
  pull_request:
    paths:
      - 'package-lock.json'
      - 'pnpm-lock.yaml'

jobs:
  security-check:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v3
        with:
          fetch-depth: 0
      
      - name: Setup Node.js
        uses: actions/setup-node@v3
        with:
          node-version: '18'
      
      - name: Install lockfile-sentinel
        run: npm install -g lockfile-sentinel
      
      - name: Run security scan
        run: |
          git show HEAD:package-lock.json > /tmp/base-lock.json || true
          lockfile-sentinel scan /tmp/base-lock.json package-lock.json \
            --fail-on-findings \
            --threshold 75

The action will:

  1. Fetch the base lockfile from the previous commit
  2. Compare it against the PR's lockfile
  3. Fail the check if findings are detected or risk score exceeds threshold

Implementation Details

Lockfile Parsers

  • package-lock.json: Native JSON parsing
  • pnpm-lock.yaml: YAML-like structure parsing
  • yarn.lock: Yarn format parsing

Dependency Graph Algorithm

Uses Depth-First Search (DFS) to:

  1. Build transitive dependency tree
  2. Calculate the "blast radius" of changes
  3. Track each package's entire dependency chain

Registry API Integration

Queries https://registry.npmjs.org/<package> to:

  • Fetch maintainer lists
  • Check publish timestamps
  • Verify package metadata integrity

Entropy Calculation

Implements Shannon Entropy:

  • Counts character frequencies
  • Calculates probability distribution
  • Returns entropy score (0-8)

Typical Ranges:

  • 3.5 - 5.0: Normal JavaScript
  • 5.0 - 6.5: Minified code
  • 6.5+: Compressed/obfuscated/binary

Testing

npm test

Run tests with coverage:

npm test -- --coverage

Performance

  • Parsing: <100ms for typical lockfiles
  • Diffing: <50ms for <1000 packages
  • Registry Queries: ~100-500ms depending on package count (rate-limited to avoid npm abuse)
  • Total Scan: ~2-5 seconds for typical PRs

Limitations

  1. Historical Maintainer Data: npm API doesn't provide exact timestamps for when maintainers were added. We infer from version publish times.

  2. Tarball Analysis: Full tarball extraction and analysis is slow. Current implementation samples the beginning of tarballs.

  3. Rate Limiting: npm registry has rate limits (~100 requests/minute). Large updates may hit these limits.

  4. Obfuscation Detection: Entropy-based detection has false positives (legitimate minification can look suspicious).

FAQ

Q: Will this slow down my CI pipeline?
A: No. Typical scans complete in 2-5 seconds with network latency being the primary factor.

Q: Can I use this for private npm registries?
A: Yes! Modify the registry URL in registry-scout.ts.

Q: What if I get false positives?
A: You can:

  • Whitelist packages: --ignore axios,lodash
  • Adjust thresholds: --entropy 7.0
  • Review findings and add to .lockfile-sentinel-ignore

Q: Does this replace vulnerability scanners like Snyk?
A: No! This is complementary. Snyk checks for known vulnerabilities. Lockfile Sentinel detects behavioral anomalies that might be zero-day attacks.

Contributing

Issues and PRs welcome!

License

MIT - See LICENSE file

Security Notice

This tool is designed to enhance supply chain security, but it's not a silver bullet. Always:

  • Review dependency changes manually
  • Keep up with security advisories
  • Use multiple layers of security validation