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

pmharden

v0.1.5

Published

Security hardening CLI for npm, pnpm, yarn, and bun — config linter, global package auditor, and .npmrc secret scanner

Readme

pmharden

Audits the environment your npm/pnpm/yarn/bun installs run in — not just the packages.

npx pmharden

CI npm version License: MIT


The problem

I ran this on my own machine and found a plaintext npm token in ~/.npmrc — readable by any postinstall script on any package I'd ever installed.

That's the same attack that hit eslint-scope in 2018. A compromised maintainer account pushed a malicious version. The postinstall script read ~/.npmrc, sent the auth token to an attacker server, then used it to publish more malicious packages. Self-propagating.

The token had been sitting there for years. npm audit never flagged it. Socket.dev never flagged it. Neither tool looks at your config files.


What it does

Three checks, one command:

pmharden audit    — config linter (.npmrc, .pnpmrc, .yarnrc.yml, bunfig.toml)
pmharden secrets  — plaintext tokens, file permissions
pmharden global   — stale or risky globally installed packages
pmharden          — all three

Example output:

Config Audit

✖  CRITICAL  [npm] ~/.npmrc (plaintext-npm-token)
  Plaintext secret: //registry.npmjs.org/:_authToken=npm_***REDACTED***
  Fix: Replace with ${NPM_TOKEN}

✖  HIGH  [npm] ~/.npmrc (allow-git-all)
  allow-git=all permits installs from unreviewed git commits.
  Fix: npm config set allow-git=none

✖  HIGH  [yarn] ~/.yarnrc (yarn-v1-no-script-control)
  yarn v1 has no config-level script blocking. Every postinstall attack
  applies with no mitigation path.
  Fix: yarn set version berry

─── Summary ────────────────────────────────
 1 critical   2 high  1 medium

Action required: Fix critical/high issues before your next install.

⚡ Fix all with one command:

  claude -p 'You are fixing package manager security issues...'
  opencode run '...'

When it finds issues, it generates a single prompt you can paste into Claude or OpenCode to fix everything in one shot.


Why existing tools don't catch this

| Tool | What it checks | What it misses | |------|---------------|----------------| | npm audit | CVEs in installed packages | Your config, your secrets, your globals | | Socket.dev | Per-package behavior analysis | Config files, ~/.npmrc tokens | | npq | Install-time interception | Existing misconfig risks | | Snyk | Dependency CVEs | PM environment audit | | pmharden | Config + secrets + globals | Per-package CVE database |

Use it alongside npm audit, not instead of it.


The attacks this prevents

postinstall execution

Every package you install can run arbitrary code during npm install unless ignore-scripts=true is set.

| Attack | Year | What happened | |--------|------|---------------| | eslint-scope | 2018 | Malicious postinstall read ~/.npmrc tokens, published more malicious packages | | ua-parser-js | 2021 | Hijacked account, preinstall dropped crypto miners on millions of machines | | node-ipc | 2022 | Maintainer added postinstall that wiped files on Russian/Belarusian IPs (CVE-2022-23812) | | Ledger Connect Kit | 2023 | Malicious build scripts drained crypto wallets |

pmharden audit checks that ignore-scripts=true is set.

zero-day window

Malicious packages often get reported and pulled within days. If you install the day they're published, you're in the window.

| Attack | Year | Notes | |--------|------|-------| | crossenv + 36 typosquats | 2017 | 36 packages, all immediately malicious | | IconBurst | 2022 | Typosquat packages scraped form data from live apps | | LofyGang | 2022 | 200+ packages, exfiltrated Discord tokens |

pmharden audit checks that minimum-release-age=7 days is set — blocks packages published in the last 7 days.

plaintext tokens

GitGuardian's annual report consistently puts npm tokens among the top leaked secrets in public repos. Once a postinstall script has your publish token, it can push new versions of any package you own.

pmharden secrets checks for plaintext tokens and overly-permissive file modes.


Config checks

npm

| Setting | Risk | Severity | |---------|------|----------| | ignore-scripts not true | Allows postinstall execution | HIGH | | allow-git=all | Installs from unreviewed git commits | HIGH | | No minimum-release-age | Zero-day window open | MEDIUM | | unsafe-perm=true | Scripts run as root | HIGH | | audit=false | Disables built-in CVE checks | MEDIUM |

pnpm

| Setting | Risk | Severity | |---------|------|----------| | strict-dep-builds not set | Build scripts run without review | HIGH | | No minimumReleaseAge | Zero-day window open | MEDIUM | | blockExoticSubdeps not set | Non-registry sub-dependencies allowed | MEDIUM |

yarn

| Setting | Risk | Severity | |---------|------|----------| | yarn v1 (classic) | No config-level script blocking — architectural gap | HIGH | | enableScripts: false missing (v2+) | Allows postinstall execution | HIGH |

yarn v1 has no ignore-scripts equivalent that works via .yarnrc. See yarnpkg/yarn#5335. Every attack in the table above hit yarn v1 users with no mitigation available.


Install

npm install -g pmharden   # global
npx pmharden              # no install

CI

- name: pmharden self-audit
  run: node dist/cli.js audit   # or: npx pmharden@latest audit

Exit code 1 on CRITICAL/HIGH. Suitable for blocking merges.


Contributing

Good first issues:

  • binding.gyp detection — pure-JS packages with native build files (typosquat signal)
  • Token scope checking — distinguish publish tokens from read-only tokens
  • pnpm onlyBuiltDependencies allowlist enforcement
  • Bun lockfile integrity checks
  • --fix flag — auto-apply safe remediations to config files

See AGENTS.md for the full contribution guide including how to add a new check.


Further reading


MIT