slsa-pulse
Live SLSA provenance health dashboard for the npm ecosystem.
After the May 11, 2026 TanStack / Mini Shai-Hulud worm — the first
documented malicious npm package carrying a valid SLSA provenance
attestation — the value of "this package is signed" stopped being a
binary trust signal. slsa-pulse tracks the provenance posture of the
most-installed npm packages over time so you can see who publishes with
SLSA, who just lost their attestations, and how the ecosystem is
trending.
- Free, public, no auth, no API key required from you.
- Real data only. Every numeric or status field is fetched live from
- npm's public APIs. There is no seed data, no mock data, no
-
Math.random()jitter anywhere in this codebase.
Endpoints (all public)
Base path: /slsa-pulse (set via BASE_PATH).
| Method | Path | What it does |
| --- | --- | --- |
| GET | /health | {status, ts, tracked} — orchestrator smoke probe |
| GET | / | Dashboard SPA |
| GET | /api/stats | Tracked total, provenance %, 7-day delta, avg trust score, 24h slips/uplifts |
| GET | /api/packages?sort=&order=&filter=&limit=&offset= | Sortable, filterable list |
| GET | /api/package/:name | One package with score breakdown + history |
| GET | /api/slips | Recent slip events (lost provenance) |
| GET | /api/uplifts | Recent uplift events (gained provenance) |
| GET | /api/feed.json | All recent events |
| GET | /api/audit/:name | Live, non-cached audit of any npm package |
| POST | /api/audit-batch | Body {packages: ["react", "lodash", …]} — up to 50 |
| POST | /api/track | Body {name: "foo"} — add to watchlist |
| GET | /api/export.csv | CSV dump of current tracked set |
Real public data sources
| Source | URL | Cadence | What we extract |
| --- | --- | --- | --- |
| npm packument | https://registry.npmjs.org/<pkg> | every hour | latest version, maintainers, last publish, dist.attestations.provenance.predicateType |
| npm attestations | https://registry.npmjs.org/-/npm/v1/attestations/<pkg>@<version> | on demand | full attestation bundle, all predicateType values |
| npm weekly downloads | https://api.npmjs.org/downloads/point/last-week/<pkg> | every hour | downloads |
| npm 30-day downloads | https://api.npmjs.org/downloads/range/last-month/<pkg> | daily (future) | trend sparkline |
Every fetch sets a polite User-Agent (NPM_USER_AGENT),
times out at 10 s, retries 4× with exponential backoff on 429/5xx, and
runs at most 5-concurrent.
Trust score (0–100)
Computed in lib/score.js:
| Signal | Points |
| --- | --- |
| has_provenance (any) | 40 |
| Predicate is slsa.dev/provenance/v1 or /v0.2 | 15 |
| ≥ 3 maintainers (bus factor) | 10 |
| HTTPS repo URL on a major forge | 10 |
| Last publish within 180 days | 10 |
| Weekly downloads ≥ 10,000 | 10 |
| Has a homepage URL | 5 |
Bands: ≥80 high, ≥55 med, ≥30 low, otherwise risk.
Watchlist
lib/watchlist.txt ships with ~320 npm package names hand-picked from
the widely-known "most-depended-upon" set (react, axios, vite, every@tanstack/ package after the May 11 incident, the full @aws-sdk/
core, the Sigstore client libraries, etc.). Only the names are bundled
— every numeric field for these packages is fetched live from npm.
Users can extend the watchlist at runtime with POST /api/track.
Cron schedule
| Cron | Job |
| --- | --- |
| 0 | refreshWatchlist — packument + downloads for every tracked package |
| /15 | processDeltas — write slip/uplift/level_drop events |
| 5 0 | pruneOldSnapshots — keep last 30 snapshots per package |
On boot, INITIAL_REFRESH_ON_BOOT=true triggers an immediate refresh so
the dashboard is populated within ~30 s. The refresh runs async and
does not block server startup.
Local development
cp .env.example .env
npm install
node server.js
# open http://127.0.0.1:4857/slsa-pulse/
better-sqlite3 builds native bindings; on a Linux/Mac arm64 host with
a working C++ toolchain npm install succeeds with a prebuilt binary.
Deploy (RNDLAB orchestrator)
DEPLOY_MANIFEST.json pins port 4857 and base path /slsa-pulse. The
RNDLAB watcher rsyncs the directory to the target host, installs a
systemd unit named slsa-pulse, wires the nginx upstreamhttp://127.0.0.1:4857, runs an /slsa-pulse/health smoke check, then
posts to the showcase. No basic-auth, no admin pages, no secret
required for read paths.
License
MIT.