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

pnpm-audit-hook

v1.4.3

Published

pnpm hook that blocks vulnerable packages before download. Uses GitHub Advisory Database with offline static DB fallback.

Readme

pnpm-audit-hook

npm version license node

+==============================================================================+
|                            PNPM-AUDIT-HOOK                                    |
|                  PRE-DOWNLOAD DEPENDENCY FIREWALL                             |
+------------------------------------------------------------------------------+
| pnpm install/add/update                                                       |
|        |                                                                     |
|        v                                                                     |
| resolve lockfile -> audit advisories -> enforce policy -> PASS / WARN / BLOCK |
+==============================================================================+

Block vulnerable npm packages before they are downloaded.

pnpm-audit-hook is a pre-download security gate for pnpm. It runs after dependency resolution and before package downloads, checks every resolved package against multiple vulnerability sources, and blocks installation when critical or high-severity issues are found.

Unlike pnpm audit, which runs after dependencies are already installed, pnpm-audit-hook prevents vulnerable code from reaching node_modules in the first place. Once configured, it works automatically with pnpm install, pnpm add, and pnpm update.


Table of Contents


At a Glance

                         +-----------------------------+
                         |     DEPENDENCY FIREWALL     |
                         +-----------------------------+

pnpm install/add/update
          |
          v
+-------------------+     +---------------------+     +----------------------+
| Resolve lockfile  | --> | Audit package list  | --> | Apply project policy |
+-------------------+     +----------+----------+     +----------+-----------+
                                     |                           |
                   +-----------------+-----------------+         |
                   |                                   |         |
                   v                                   v         v
          +----------------+                 +----------------+  +------------+
          | GHSA / OSV    |                 | Static DB      |  | allow/warn |
          | live sources  |                 | offline checks |  | or block   |
          +----------------+                 +----------------+  +------------+

pnpm-audit-hook acts like a dependency firewall: it inspects the resolved package graph, checks live and bundled vulnerability intelligence, applies your policy, and stops risky packages before download.


Why Use pnpm-audit-hook?

Most dependency audit tools detect vulnerable packages after installation. pnpm-audit-hook moves that control earlier in the lifecycle by turning dependency installation into a policy-enforced security checkpoint.

It is designed for teams that need:

  • Pre-download protection — vulnerable packages are blocked before they reach your machine.
  • Zero workflow disruption — audits run automatically during normal pnpm commands.
  • Multiple vulnerability sources — GitHub Advisory Database, OSV.dev, a bundled static database, and NVD enrichment.
  • Secure defaults — critical and high-severity vulnerabilities are blocked by default.
  • CI/CD compatibility — structured output, annotations, and pipeline-friendly exit codes.
  • Offline support — the bundled static database can be used in air-gapped environments.

Key Features

Pre-Download Blocking

  • Hooks into pnpm through afterAllResolved.
  • Runs after dependency resolution but before package downloads.
  • Blocks vulnerable packages before they enter node_modules.
  • Works automatically with pnpm install, pnpm add, and pnpm update.

Multiple Vulnerability Sources

  • GitHub Advisory Database — real-time GHSA data.
  • OSV.dev — aggregated vulnerability data from GHSA, npm, NVD, and other sources.
  • Bundled static database — historical vulnerability data for offline and low-latency checks.
  • NVD enrichment — CVSS and severity enrichment for findings with incomplete severity data.
  • Sources are queried in parallel, then merged and deduplicated.

Performance-Oriented Design

  • Severity-aware file cache.
  • Bloom filter for fast package-existence checks.
  • Gzip-compressed static database shards.
  • Compact static database indexes.
  • Configurable API concurrency.

Fail-Closed Security Model

  • Source failures block installation by default.
  • Invalid semver ranges are treated as potentially affected.
  • Expired allowlist entries are ignored.
  • Static database files are verified with SHA-256 integrity hashes.
  • Cache reads and writes protect against symlink and path traversal attacks.
  • Cache writes are atomic to reduce corruption risk.

Flexible Policy Engine

  • Configure block, warn, and allow behavior by severity.
  • Allowlist vulnerabilities by CVE, GHSA, package, and version range.
  • Add optional expiration dates to allowlist entries.
  • Override blocking severity with environment variables for CI workflows.

CI/CD Native

  • GitHub Actions annotations using ::error:: and ::warning::.
  • Azure DevOps logging commands and task variables.
  • JSON output for custom automation.
  • Human-readable output for local development.
  • Automatic CI detection for verbose pipeline logs.

Offline and Air-Gapped Support

  • Bundled static vulnerability database works without network access.
  • --offline mode disables live API calls.
  • Cached results can be reused until their TTL expires.

Compact Status Banner

  • Clean installs produce a single-line confirmation.
  • Warning and blocked installs show concise CVE/GHSA details before the full report.
  • Output remains readable for local development and CI logs.

Developer Experience

  • Sensible defaults require minimal setup.
  • pnpm-audit-scan supports manual audits without installation.
  • .pnpm-audit.yaml supports project-specific policy customization.
  • Private registries are supported through PNPM_REGISTRY or npm_config_registry.
  • Temporary bypass is available with pnpm install --ignore-pnpmfile.

Quick Start

pnpm add -D pnpm-audit-hook
pnpm exec pnpm-audit-setup

After setup, every pnpm install runs a pre-download vulnerability audit automatically.

Files Created During Setup

| File | Purpose | |------|---------| | .pnpmfile.cjs | pnpm hook entry point loaded automatically by pnpm | | .pnpm-audit.yaml | Optional project security policy configuration | | .pnpm-audit-cache/ | Runtime cache directory created automatically |

Recommended commit commands:

git add .pnpmfile.cjs .pnpm-audit.yaml
echo ".pnpm-audit-cache/" >> .gitignore
git add .gitignore

How It Works

Install Gate Overview

pnpm command
    |
    v
+--------------------+    +----------------------+    +--------------------+
| resolve lockfile   | -> | audit every package  | -> | policy decision    |
+--------------------+    +----------------------+    +---------+----------+
                                                               |
                                  +----------------------------+------------------+
                                  |                                               |
                                  v                                               v
                            [PASS / WARN]                                    [BLOCK]
                                  |                                               |
                                  v                                               v
                         download + install                                abort install
flowchart LR
    A[pnpm install] --> B[Resolve Dependencies]
    B --> C[afterAllResolved Hook]
    C --> D{Audit Resolved Packages}
    D -->|Safe| E[Download and Install]
    D -->|Blocked Finding| F[Abort Install]

When pnpm resolves the dependency graph, pnpm-audit-hook receives the resolved lockfile through .pnpmfile.cjs. It extracts every package and version, checks the configured vulnerability sources, applies policy rules, and either allows pnpm to continue or aborts installation.

Detailed Flow

flowchart TD
    A[pnpm command] --> B[Resolve dependency graph]
    B --> C[afterAllResolved hook]
    C --> D[Extract package list]
    D --> E[Load configuration]
    E --> F{Cache hit?}
    F -->|Yes| G[Use cached result]
    F -->|No| H[Query vulnerability sources]
    H --> I[Merge and deduplicate findings]
    I --> J{Missing severity?}
    J -->|Yes| K[Enrich with NVD]
    J -->|No| L[Apply policy]
    K --> L
    G --> L
    L --> M{Blocked findings?}
    M -->|Yes| N[Abort install]
    M -->|No| O[Warn if needed]
    O --> P[Continue install]

Prerequisites

  • Node.js 18 or later
  • pnpm with .pnpmfile.cjs support, typically pnpm 6 or later

This package is designed for pnpm projects. For npm, use npm audit; for Yarn, use yarn audit.


Installation

Per Project Recommended

pnpm add -D pnpm-audit-hook
pnpm exec pnpm-audit-setup

This installs the package, creates .pnpmfile.cjs, and creates .pnpm-audit.yaml if it does not already exist.

Global Installation

Use global installation when you want to audit every pnpm project on your machine.

pnpm add -g pnpm-audit-hook
mkdir -p ~/.pnpm-hooks
cp $(pnpm root -g)/pnpm-audit-hook/dist ~/.pnpm-hooks/ -r
cp $(pnpm root -g)/pnpm-audit-hook/.pnpmfile.cjs ~/.pnpm-hooks/
pnpm config set global-pnpmfile ~/.pnpm-hooks/.pnpmfile.cjs

From Source

git clone https://github.com/asx8678/pnpm-audit-hook.git
cd pnpm-audit-hook
pnpm install
pnpm run build

cp -r dist /path/to/your/project/
cp .pnpmfile.cjs /path/to/your/project/

Upgrading from v1.1.0

When upgrading from v1.1.0, note the following changes:

  • OSV.dev is enabled by default. Disable it with sources.osv: false or PNPM_AUDIT_DISABLE_OSV=true.
  • Cache keys changed, so a one-time cache rebuild will occur automatically.
  • Additional vulnerabilities may be reported because OSV.dev aggregates data from multiple databases.
  • --update-db requires a source checkout because the update script is not included in a package installed from npm.

Verify Installation

# Expected to succeed
pnpm add lodash

# Expected to be blocked because this version is known to be vulnerable
pnpm add [email protected]

Clean Install Output

🛡️  pnpm-audit ── 142 packages ── github ✓  osv ✓  static-db ✓ ── ✅ clean ── 203ms

Warning Output

Medium, low, and unknown-severity findings warn by default and allow installation to continue.

🛡️  pnpm-audit ── 87 packages ── github ✓  osv ✓  static-db ✓ ── ⚠️  2 warnings (1 medium, 1 low) ── 312ms
  ⚠  CVE-2024-4067 [MEDIUM] [email protected] — ReDoS vulnerability
  ⚠  CVE-2024-4068 [MEDIUM] [email protected] — Uncontrolled resource consumption

Blocked Install Output

Critical and high-severity findings block by default.

🛡️  pnpm-audit ── 1 packages ── github ✓  osv ✓  static-db ✓ ── 🚫 1 BLOCKED ── 245ms
  🚫 GHSA-xxxx-xxxx-xxxx [CRITICAL] [email protected] — Malicious Package (fix: 4.0.0)

+=============================================+
|           PNPM AUDIT SECURITY REPORT         |
+=============================================+

Source Status:
  github: OK (152ms)
  osv: OK (180ms)

Package Summary:
  Total packages scanned: 1
  Safe packages: 0
  Packages with vulnerabilities: 1

Vulnerabilities by Severity:
  CRITICAL: 1

Vulnerability Details:
  [CRITICAL] GHSA-xxxx-xxxx-xxxx
    Package: [email protected]
    Title: Malicious Package in event-stream
    Affected: =3.3.6
    Fixed in: 4.0.0

+=============================================+
| AUDIT FAILED - installation blocked          |
+=============================================+

Usage

Automatic Mode

After setup, audits run automatically.

pnpm install                  # Audit runs automatically
pnpm add express              # New dependency is audited
pnpm add [email protected]       # Safe package installs normally
pnpm add [email protected]   # Vulnerable package is blocked

Manual Scan

Use the CLI to audit the current lockfile without installing packages.

pnpm-audit-scan                       # Human-readable output
pnpm-audit-scan --format json         # JSON output for CI or scripts
pnpm-audit-scan --severity critical   # Only block critical vulnerabilities
pnpm-audit-scan --offline             # Use static DB and cache only

Output Formats

| Format | Use Case | Flag | |--------|----------|------| | human | Local terminal output | --format human | | json | CI parsing and automation | --format json | | github | GitHub Actions annotations | --format github | | azure | Azure DevOps logging commands | --format azure |

Default Finding Behavior

| Severity | Default Action | Result | |----------|----------------|--------| | critical | Block | Installation fails with exit code 1 | | high | Block | Installation fails with exit code 1 | | medium | Warn | Installation continues with exit code 2 for manual scans | | low | Warn | Installation continues with exit code 2 for manual scans | | unknown | Warn | Installation continues after enrichment is attempted |

Policy Decision Map

resolved finding
      |
      v
+--------------+        +----------------+        +---------------------+
| severity     | -----> | project policy | -----> | install decision    |
+--------------+        +----------------+        +----------+----------+
                                                       |        |
                                           +-----------+        +-----------+
                                           v                    v
                                      [allow/warn]          [block]
                                           |                    |
                                           v                    v
                                    continue install       abort before download

Configuration

Create .pnpm-audit.yaml in the project root.

policy:
  block:
    - critical
    - high
  warn:
    - medium
    - low
    - unknown
  allowlist:
    - id: CVE-2024-12345
      reason: "False positive"
    - package: legacy-lib
      expires: "2025-06-01"

sources:
  github: true
  osv: true
  nvd: true

performance:
  timeoutMs: 15000

cache:
  ttlSeconds: 3600

staticBaseline:
  enabled: true
  cutoffDate: "2025-12-31"

failOnNoSources: true
failOnSourceError: true
offline: false

All fields are optional. Secure defaults are applied when fields are omitted.

Configuration Options

| Option | Description | Default | |--------|-------------|---------| | policy.block | Severities that abort installation | ["critical", "high"] | | policy.warn | Severities that log warnings | ["medium", "low", "unknown"] | | policy.allowlist | Exceptions to skip | [] | | sources.github | Enable GitHub Advisory Database | true | | sources.osv | Enable OSV.dev | true | | sources.nvd | Enable NVD severity enrichment | true | | performance.timeoutMs | API timeout in milliseconds | 15000 | | cache.ttlSeconds | Default cache duration | 3600 | | staticBaseline.enabled | Use the bundled static database | true | | staticBaseline.cutoffDate | Static database coverage cutoff | 2025-12-31 | | staticBaseline.dataPath | Custom static database path | Auto-detected | | failOnNoSources | Block when no advisory sources are available | true | | failOnSourceError | Block when an advisory source fails | true | | offline | Skip live API calls | false |

Source Toggles

sources:
  github: true
  osv: true
  nvd: true

Equivalent environment variables:

PNPM_AUDIT_DISABLE_GITHUB=true pnpm install
PNPM_AUDIT_DISABLE_OSV=true pnpm install

Offline Audit

pnpm-audit-scan --offline
PNPM_AUDIT_OFFLINE=true pnpm install

Update the Vulnerability Database

pnpm-audit-scan --update-db
pnpm-audit-scan --update-db=full
GITHUB_TOKEN=your_token pnpm run update-vuln-db:incremental

Allowlist

Allowlist entries suppress specific vulnerabilities or package findings. Use allowlists for documented exceptions, false positives, or temporary accepted risk.

policy:
  allowlist:
    # By CVE or GHSA ID
    - id: CVE-2024-12345
      reason: "False positive for our use case"

    # By package name
    - package: legacy-lib
      reason: "Accepted risk while migration is in progress"
      expires: "2025-06-01"

    # Scoped to a specific vulnerability, package, and version range
    - id: CVE-2024-12345
      package: affected-pkg
      version: ">=1.0.0 <2.0.0"
      reason: "Only affects an unused feature"
      expires: "2025-12-31"

| Field | Required | Description | |-------|----------|-------------| | id | One of id or package | CVE or GHSA identifier, case-insensitive | | package | One of id or package | Package name, case-insensitive | | version | No | Optional semver range constraint | | reason | No | Audit-trail documentation | | expires | No | ISO date when the entry expires |

Expired entries are ignored automatically.


Environment Variables

| Variable | Description | |----------|-------------| | GITHUB_TOKEN / GH_TOKEN | GitHub API token for higher rate limits | | NVD_API_KEY / NIST_NVD_API_KEY | NVD API key for higher rate limits | | PNPM_AUDIT_CONFIG_PATH | Custom configuration file path | | PNPM_AUDIT_DISABLE_GITHUB | Disable GitHub Advisory Database | | PNPM_AUDIT_DISABLE_OSV | Disable OSV.dev | | PNPM_AUDIT_BLOCK_SEVERITY | Override block severities, for example critical,high,medium | | PNPM_AUDIT_QUIET | Suppress non-error output | | PNPM_AUDIT_DEBUG | Enable debug logging | | PNPM_AUDIT_VERBOSE | Enable verbose logging | | PNPM_AUDIT_JSON | Emit JSON output | | PNPM_AUDIT_FORMAT | Output format: human, azure, github, or json | | PNPM_AUDIT_OFFLINE | Use only the static database and cache | | PNPM_AUDIT_FAIL_ON_NO_SOURCES | Fail when no advisory sources are available | | PNPM_AUDIT_FAIL_ON_SOURCE_ERROR | Fail when an advisory source errors | | PNPM_AUDIT_GITHUB_CONCURRENCY | Maximum concurrent GitHub API requests | | PNPM_REGISTRY / npm_config_registry | Custom npm registry URL |

Verbose mode is enabled automatically in common CI environments, including CI, GITHUB_ACTIONS, TF_BUILD, GITLAB_CI, and JENKINS_URL.


CLI Reference

pnpm-audit-scan supports the following flags.

| Flag | Description | |------|-------------| | --format <format> | Output format: human, json, azure, or github | | --severity <list> | Comma-separated severities to block | | --offline | Skip live API calls and use only the static database and cache | | --update-db | Run an incremental vulnerability database update | | --update-db=full | Run a full vulnerability database rebuild | | --quiet | Suppress non-error output | | --verbose | Enable verbose output | | --debug | Enable debug output | | --config <path> | Use a custom configuration file | | --help | Show help text | | --version | Show version |

When --update-db is used, the database update runs and the CLI exits without performing an audit.


Vulnerability Sources

Source Fan-In

[ Static DB ]     [ GitHub Advisory ]     [ OSV.dev ]
      \                  |                  /
       \                 |                 /
        +--------- merge + deduplicate ----+
                          |
                          v
                [ NVD severity enrichment ]
                          |
                          v
                 normalized findings
flowchart TD
    subgraph PRIMARY["Primary Sources"]
        A[Static Database]
        B[GitHub Advisory API]
        C[OSV.dev API]
    end

    A --> D[Merge and Deduplicate]
    B --> D
    C --> D
    D --> E{Unknown Severity?}
    E -->|Yes| F[NVD Enrichment]
    E -->|No| G[Final Findings]
    F --> G

| Source | Type | Purpose | Rate Limits / Notes | |--------|------|---------|---------------------| | Static DB | Bundled | Historical vulnerability checks and offline support | No API required | | GitHub Advisory | API | Current GHSA vulnerability data | 60 requests/hour without token; 5,000 requests/hour with token | | OSV.dev | API | Aggregated vulnerability data from GHSA, npm, NVD, and other databases | Free; no key required | | NVD | API | CVSS and severity enrichment | 5 requests/30 seconds without key; 50 requests/30 seconds with key |

Query Strategy

sequenceDiagram
    participant H as Hook
    participant C as Cache
    participant S as Static DB
    participant G as GitHub API
    participant O as OSV.dev API
    participant N as NVD API

    H->>C: Check package@version
    alt Cache hit
        C-->>H: Return cached findings
    else Cache miss
        H->>S: Query bundled database
        par Live sources
            H->>G: Query GitHub Advisory API
        and
            H->>O: Query OSV.dev API
        end
        H->>H: Merge and deduplicate
        opt Unknown severity
            H->>N: Enrich severity
        end
        H->>C: Cache result
    end

Caching

The cache reduces repeated API calls and improves install performance.

Cache Lifecycle Snapshot

package@version
      |
      v
+--------------+       hit + fresh       +----------------+
| cache lookup | ---------------------> | return findings |
+------+-------+                         +----------------+
       |
       | miss or expired
       v
+----------------+     +----------------+     +---------------------+
| query sources  | --> | merge results  | --> | atomic cache write  |
+----------------+     +----------------+     +---------------------+
flowchart LR
    A[Package Query] --> B{Cache Exists?}
    B -->|Yes| C{Expired?}
    C -->|No| D[Return Cached Result]
    C -->|Yes| E[Query Sources]
    B -->|No| E
    E --> F[Write Cache Entry]
    F --> G[Return Result]

Cache Location

.pnpm-audit-cache/
├── ab/
│   └── ab1234...def.json
├── cd/
│   └── cd5678...ghi.json
└── ...

Dynamic TTL

| Severity | TTL | Rationale | |----------|-----|-----------| | Critical | 15 minutes | Refresh quickly for high-risk findings | | High | 30 minutes | Keep significant findings current | | Medium | 1 hour | Standard refresh interval | | Low / Unknown | Configured TTL | Use project default |


CI/CD Integration

GitHub Actions

name: Install with Audit
on: [push, pull_request]

jobs:
  install:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: pnpm/action-setup@v4
      - uses: actions/setup-node@v4
        with:
          node-version: 20
          cache: pnpm
      - run: pnpm install
        env:
          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
          NVD_API_KEY: ${{ secrets.NVD_API_KEY }}

The hook runs during pnpm install and fails the job when blocking vulnerabilities are found.

GitHub Actions output includes annotations and optional outputs for downstream steps.

| Output | Description | |--------|-------------| | audit-blocked | true when installation is blocked | | vulnerability-count | Total vulnerability count | | critical-count | Number of critical vulnerabilities | | high-count | Number of high vulnerabilities |

Azure DevOps

trigger:
  - main

pool:
  vmImage: ubuntu-latest

steps:
  - task: NodeTool@0
    inputs:
      version: 20
  - script: |
      npm install -g pnpm
      pnpm install
    displayName: Install with Audit
    env:
      GITHUB_TOKEN: $(GITHUB_TOKEN)
      NVD_API_KEY: $(NVD_API_KEY)
      PNPM_AUDIT_FORMAT: azure

Azure DevOps output uses pipeline logging commands for grouped output, errors, warnings, and task variables. Azure Pipelines are auto-detected when TF_BUILD=True.

| Variable | Description | |----------|-------------| | AUDIT_BLOCKED | true when installation is blocked | | AUDIT_VULNERABILITY_COUNT | Total vulnerability count | | AUDIT_CRITICAL_COUNT | Number of critical vulnerabilities | | AUDIT_HIGH_COUNT | Number of high vulnerabilities |


Static Vulnerability Database

pnpm-audit-hook includes a bundled vulnerability database for historical findings. This reduces API usage, improves performance, and supports offline audits.

Benefits

  • Faster checks for known historical vulnerabilities.
  • Offline and air-gapped operation.
  • Reduced dependency on external API availability.
  • Fewer rate-limit issues in CI.

Integrity Verification

Static database shard files include SHA-256 hashes generated during the build. At runtime, the reader verifies these hashes before using the data. If a shard is modified or corrupted, the integrity check detects it.

Compression and Optimization

The build process optimizes the static database automatically:

  • Compact index keys reduce index size.
  • Large shard files are gzip-compressed.
  • Small shards remain uncompressed for fast reads.
  • The runtime reader handles both .json and .json.gz files transparently.

Optimization runs through scripts/optimize-static-db.js during pnpm run build.

Updating the Database

The database is built from the GitHub Advisory Database through a GraphQL query. The update script fetches npm ecosystem advisories, normalizes them, groups them by package, deduplicates by advisory ID, and writes one shard per affected package.

pnpm run update-vuln-db:incremental
pnpm run update-vuln-db
pnpm run update-vuln-db:full
pnpm run update-vuln-db -- --sample
pnpm run update-vuln-db -- --cutoff=2024-06-30T23:59:59Z

A GitHub token is recommended for faster updates:

export GITHUB_TOKEN=ghp_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx

After updating, rebuild and commit the generated data.

pnpm run build
git add src/static-db/data/ dist/static-db/data/
git commit -m "chore: update vulnerability database"

Generated File Structure

Source data:

src/static-db/data/
├── index.json
├── lodash.json
├── axios.json
├── @angular/
│   └── core.json
└── ...

Optimized build output:

dist/static-db/data/
├── index.json.gz
├── lodash.json
├── @angular/
│   └── core.json
├── directus.json.gz
└── ...

For packaging alternatives and tradeoffs, see docs/db-packaging-evaluation.md.


Architecture

Component Map

+-------------------+
| .pnpmfile.cjs     |
| afterAllResolved  |
+---------+---------+
          |
          v
+-------------------+        +-------------------+
| Audit Engine      | <----> | File Cache        |
| extract + scan    |        | TTL + integrity   |
+----+---------+----+        +-------------------+
     |         |
     |         v
     |   +-------------------+
     |   | Policy Engine     |
     |   | block / warn / ok |
     |   +-------------------+
     |
     v
+-------------------+
| Advisory Sources  |
| static/GHSA/OSV   |
+-------------------+
classDiagram
    class PnpmHook {
        +afterAllResolved(lockfile, context)
    }

    class AuditEngine {
        +runAudit(lockfile, runtime)
        -extractPackages(lockfile)
        -aggregateVulnerabilities(packages)
        -evaluatePolicies(findings)
    }

    class VulnerabilitySource {
        <<interface>>
        +query(packageName, version)
    }

    class StaticDatabase {
        +query(packageName, version)
        -loadShard(packageName)
        -bloomFilter
    }

    class GitHubAdvisory {
        +query(packageName, version)
        -fetchFromAPI()
        -rateLimiter
    }

    class OsvSource {
        +query(packageName, version)
        -fetchFromAPI()
    }

    class NVDEnricher {
        +enrichSeverity(findings)
        -fetchCVSS(cveId)
    }

    class PolicyEngine {
        +evaluate(findings, config)
        -checkAllowlist(finding)
        -checkSeverity(finding)
    }

    class FileCache {
        +get(key)
        +set(key, value, ttl)
        +prune()
    }

    PnpmHook --> AuditEngine
    AuditEngine --> VulnerabilitySource
    AuditEngine --> PolicyEngine
    AuditEngine --> FileCache
    VulnerabilitySource <|.. StaticDatabase
    VulnerabilitySource <|.. GitHubAdvisory
    VulnerabilitySource <|.. OsvSource
    GitHubAdvisory --> NVDEnricher

Security Model

Defense Boundary

+------------------------------------------------------------------+
| FAIL-CLOSED BOUNDARY                                             |
+------------------------------------------------------------------+
| source unavailable      -> block by default                      |
| no enabled sources      -> block by default                      |
| invalid semver range    -> treat as affected                     |
| expired allowlist item  -> ignore exception                      |
| tampered static shard   -> reject data                           |
+------------------------------------------------------------------+

Fail-Closed Defaults

| Condition | Default Behavior | |-----------|------------------| | Advisory source fails | Block installation | | All sources are disabled | Block installation | | Invalid allowlist entry | Ignore the entry | | Expired allowlist entry | Ignore the entry | | Unknown severity | Warn and attempt enrichment | | Invalid vulnerability semver | Treat as potentially affected |

Security Controls

  • Pre-download blocking prevents vulnerable packages from reaching node_modules.
  • API credentials are read only from environment variables.
  • File paths and package names are validated to reduce path traversal risk.
  • Cache reads and writes detect symlinks.
  • Cache writes use a temporary file and atomic rename.
  • Static database files are protected with SHA-256 integrity checks.
  • Cache key versioning invalidates stale cached data after database updates.

Troubleshooting

AUDIT FAILED — How do I unblock installation?

One-time bypass:

pnpm install --ignore-pnpmfile

Investigate findings:

pnpm-audit-scan --format json | jq '.findings'

Recommended fixes:

  1. Upgrade the vulnerable package to a patched version.
  2. Allowlist the vulnerability if it is a verified false positive.
  3. Adjust policy.block in .pnpm-audit.yaml if your policy requires a different threshold.

OSV.dev or GitHub API is unreachable

Use offline mode:

PNPM_AUDIT_OFFLINE=true pnpm install

Disable a specific source:

PNPM_AUDIT_DISABLE_OSV=true pnpm install
PNPM_AUDIT_DISABLE_GITHUB=true pnpm install

Disable fail-closed behavior for source errors:

failOnSourceError: false

Audits are slow

  • Set GITHUB_TOKEN to increase GitHub API rate limits.
  • Reuse .pnpm-audit-cache/ between CI runs where appropriate.
  • Use offline mode for the fastest audits when live source checks are not required.

Verbose logging appears in CI

Verbose mode is auto-enabled in common CI environments. To suppress it:

PNPM_AUDIT_QUIET=true pnpm install

Static database was updated but old results still appear

Cache keys include database version information, so stale entries should invalidate automatically. To force a refresh:

rm -rf .pnpm-audit-cache/
pnpm install

Uninstall

Per Project

rm .pnpmfile.cjs
pnpm remove pnpm-audit-hook
rm -f .pnpm-audit.yaml
rm -rf .pnpm-audit-cache/

Removing .pnpmfile.cjs is enough to disable the hook. The package can remain installed without affecting pnpm commands.

Global Installation

pnpm config delete global-pnpmfile
rm -rf ~/.pnpm-hooks
pnpm remove -g pnpm-audit-hook

Temporarily Disable

mv .pnpmfile.cjs .pnpmfile.cjs.disabled
mv .pnpmfile.cjs.disabled .pnpmfile.cjs

Bypass once:

pnpm install --ignore-pnpmfile

Local Development

Setup

git clone https://github.com/asx8678/pnpm-audit-hook.git
cd pnpm-audit-hook
pnpm install
pnpm run build

Test Directly

pnpm run build
pnpm add lodash
pnpm add [email protected]

Run Tests

pnpm test

Exit Codes

| Code | Meaning | |------|---------| | 0 | Success; no blocking vulnerabilities | | 1 | Critical or high-severity vulnerability blocked | | 2 | Warning-level vulnerabilities found | | 3 | Source error under fail-closed policy |


+--------------------------------------------------------------+
| Ship faster. Install safer. Block vulnerable packages early. |
+--------------------------------------------------------------+

License

MIT