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

soloshield

v0.2.0

Published

Fast, local, no-cloud security scanner for secrets, vulnerable dependencies, and AI-hallucinated (slopsquatted) packages. Runs as a CLI, pre-commit hook, or CI step.

Readme

soloshield

The zero-account, single-binary security check for solo devs and small teams who don't want to run three tools or sign up for a platform.

Secrets scanning and supply-chain scanning are both well-served by mature tools — but they're separate tools, and the best ones increasingly assume you're a team with a dashboard budget. soloshield is different on purpose:

  • One binary, two checks. Secrets and dependency supply-chain risk (hallucinated/typosquatted packages, known CVEs) in a single tool instead of running Gitleaks plus a separate supply-chain scanner.
  • No account, ever. Not "free tier" — there is no signup, no dashboard, no org to create. Point it at a directory and read the output.
  • Genuinely offline-capable. --no-deps gives you secrets-only scanning with zero network calls. Full mode makes only explicit, visible calls to public registries (npm/PyPI) and OSV.dev.
  • Actually tested on real, messy repos, not just clean examples — see the hardening notes below for the specific monorepo bugs this found and fixed before publishing.

Where this fits (and where it doesn't)

This is not trying to out-feature Socket.dev (behavioral analysis, npm-registry integration, built by a team with 1B+ monthly downloads of their own tools) or Gitleaks/TruffleHog (the mature, high-star standards for secrets alone). If you're a security team at a funded company, those are probably the better call, and running more than one layer is normal practice in this space.

soloshield is for the gap underneath that: a solo developer or a two-person team who wants a real check before shipping AI-assisted code, without creating an account or reading a pricing page first. If that's not you, the bigger tools above are worth your time instead.

What it catches

  1. Hardcoded secrets — AWS keys, GitHub tokens, Stripe keys, Slack tokens/webhooks, private key blocks, JWTs, and high-entropy generic API key assignments. Placeholder-aware (won't flag "your_api_key_here" or SECRET_KEY = "dev").
  2. AI-hallucinated / nonexistent packages — checks every package.json, requirements.txt, and pyproject.toml (PEP 621 + Poetry) dependency against the real npm/PyPI registries. Catches "slopsquatting": AI coding assistants sometimes invent plausible-looking package names that don't exist, which attackers then pre-register to serve malware.
  3. Typosquat risk — flags dependency names suspiciously close (edit distance ≤2) to a well-known package (e.g. expres vs express), while correctly treating PyPI/npm separator variants (charset_normalizer vs charset-normalizer) as the same package, not a typosquat.
  4. Known vulnerabilities — cross-references pinned versions against the OSV.dev open vulnerability database.

v1 hardening (this pass)

Real-world testing against live repos (express, flask, requests) surfaced and fixed two real bugs before they'd have hit a user:

  • Critical false-positive storm fixed: the original pyproject.toml parser read every TOML key as if it were a package name, flagging things like build-backend, testpaths, and quote-style as "hallucinated packages." Replaced with a proper TOML parser (smol-toml) that only reads actual PEP 621 / Poetry dependency fields.
  • Typosquat false positive fixed: PyPI/npm treat -, _, . as equivalent separators in package names (charset_normalizer == charset-normalizer). Names are now normalized before comparison.
  • .gitignore awareness added: the file walker now reads and respects the repo's own .gitignore, on top of built-in ignores (node_modules, .git, dist, etc).
  • Config-based allowlisting added (.aegisrc.json): teams can suppress specific known-safe findings without disabling the scanner entirely.
  • Standalone binary packaging: built with Node's Single Executable Application (SEA) feature. The output is a real, self-contained ELF/Mach-O/PE binary with the Node runtime embedded — verified to run with zero PATH and no Node/npm installed on the host at all. This matters for adoption: no "install Node first" friction for CI runners, locked-down machines, or non-technical users.

Verified clean (0 false positives) against express.js, flask, and requests source trees; verified it still catches all planted issues in the test fixture (real secret pattern, hallucinated package, typosquatted package) both from source and from the compiled binary.

v1 hardening — pass 2 (large monorepo stress test)

Tested against a real ~30,000-file, 616-manifest monorepo (Next.js). This surfaced four more real issues, all fixed:

  • Redundant network calls: 3,318 dependency lookups for only 988 unique packages (70% waste) — added an in-memory cache so each unique ecosystem:package is only checked once per scan.
  • Silent false negatives under load: firing hundreds of fully-concurrent requests caused OSV.dev to return a 403 on one request; since lookups fail-open, an unbounded scan could silently miss a real known vulnerability rather than surfacing an error. Fixed with a concurrency limiter (semaphore, 40 in-flight requests) plus a retry-with-backoff on 429/403 responses.
  • Workspace/monorepo false positives: "@next/swc": "workspace:*" was flagged as a critical "hallucinated package" — it's a normal internal workspace reference, never published standalone (confirmed: genuinely 404s on the real npm registry, but that's expected and not a security issue). Fixed two ways: (1) skip workspace:/file:/link:/portal: protocol versions outright, and (2) cross-reference dependency names against every name field declared in the repo's own package.json files, since some monorepos pin siblings with an ordinary-looking version number instead of the explicit workspace protocol.
  • npm alias syntax not parsed: "loader-utils3": "npm:[email protected]" (npm's package-aliasing feature, common in build tooling that runs multiple major versions of a dependency side by side) was checking the local alias name instead of the real target package. Fixed by parsing the npm:name@version syntax.
  • Typosquat cross-domain false positive: cypress was flagged as a typosquat of express (edit distance 2) despite being an entirely unrelated, legitimate package. Real typosquats overwhelmingly preserve the first character of the target name; added a first-character match requirement to the heuristic, which removes this class of false positive while still catching same-prefix typos (expres vs express).

Net effect on the stress-test repo: package findings dropped from an initial 20+ (mostly false positives) down to 2 defensible ones (a test-fixture package inside the target repo's own test suite, and a fair "verify this" caution on a legitimately different, older package). Full scan time: ~53s for the 616-manifest monorepo — acceptable for CI, though noted as a tuning point in the roadmap below for very large repos with a tight CI budget.

Known remaining limitation: dependency manifests found inside the target repo's own test fixtures/snapshots (e.g. a test file that intentionally uses a fake package name to test some other tool's parsing) will still occasionally surface as "hallucinated" — because, from the registry's point of view, they genuinely don't exist. This is inherent to static scanning without semantic understanding of "is this file test data"; documented rather than papered over with path-based heuristics that risk suppressing real findings elsewhere.

Install & run (from source)

npm install
npm run build
node dist/index.js .                  # scan current directory
node dist/index.js . --json           # machine-readable output
node dist/index.js . --no-deps        # fully offline, secrets-only
node dist/index.js . --fail-on medium # stricter CI gate (default: high)

Build the standalone binary

./scripts/build-binary.sh soloshield-linux   # or soloshield-macos / soloshield.exe
./dist-bundle/soloshield-linux .             # no node/npm required to run this

Note: SEA does not cross-compile — run the build script on each target OS. Do not strip the resulting binary; it corrupts the embedded blob (confirmed by testing — this crashes with a segfault).

Once published to npm, source install becomes:

npx soloshield .

Config file (.aegisrc.json)

Drop this in your repo root to suppress specific known findings:

{
  "allow": ["src/config.js:12", "npm:some-package-name"]
}
  • Secrets are keyed as "<file>:<line>".
  • Package findings are keyed as "<ecosystem>:<package-name>".

Integration points

  • Pre-commit: see .pre-commit-config.sample.yaml
  • CI (GitHub Actions): see .github-workflow-sample/soloshield.yml
  • Manual / any other CI: just call the binary, check the exit code (0 = pass, 1 = findings at or above --fail-on threshold)

Design principles

  • No SaaS. No servers to run, no accounts, no telemetry. The only network calls are optional, explicit lookups to public registries (npm/PyPI) and OSV.dev for vulnerability data — skippable entirely with --no-deps.
  • Fail-open on network issues. If a registry is unreachable, soloshield won't falsely flag your dependencies as hallucinated — it reports what it can verify.
  • Low false-positive bias. Placeholder detection, entropy checks, separator normalization, and .gitignore awareness keep noise down so CI gates stay usable rather than becoming background noise engineers learn to ignore.

Roadmap (not yet built)

  • Publish to npm registry (npx soloshield) and set up cross-platform binary releases (GitHub Actions matrix build for Linux/macOS/Windows) — SEA does not cross-compile, so binaries must be built on each target OS
  • Expand popular-package seed list to a live top-N feed instead of the static seed list
  • Additional ecosystems (Go modules, Rust crates)
  • Baseline/diff mode: only fail on new findings vs. a committed baseline
  • Tune concurrency limit (currently 40) with real production data if very large monorepos need it faster or safer
  • Optional: heuristic to de-prioritize (not suppress) findings inside common test-fixture path patterns (**/fixtures/**, **/snapshot*/**, **/test-data/**), surfaced as lower severity rather than filtered out entirely