Agents run npm install and execute code nobody read.
Sentinel is a transparent auditing proxy in front of registry.npmjs.org: it serves real packages unchanged, but intercepts every tarball, scores it with a deterministic audit engine, and attaches a verdict — so an agent or a human sees the risk before install-time code runs.
npm can't retract bad releases, has no install-time permissions, and lets attackers squat names. The event-stream pattern — a clean package ships a trojaned patch release — still works today, and agents install with zero risk signaling.
The demo
A previously-clean package ships a patch release with a
postinstall that harvests secrets. Sentinel's verdict, and
what npm install sees when it fetches the bad tarball:
$ sentinel audit color-stream 1.4.1
color-stream@1.4.1
────────────────────────────────────────────────────────
install ⚠ runs lifecycle scripts
score ░░░░░░░░░░ 0/100
verdict BLOCK
findings (7)
critical [install-scripts] postinstall reads environment variables,
decodes an encoded blob
critical [secret-exfil] reads sensitive material (~/.npmrc, AWS
credentials) with a network egress sink
high [network-egress] connects to a hardcoded IP address
high [obfuscation] uses eval()
$ npm install --registry http://localhost:4873 color-stream
HTTP 403 x-sentinel-verdict: block x-sentinel-score: 0
# and a clean package passes untouched
$ sentinel audit is-odd 3.0.1
is-odd@3.0.1 → score 100/100 ALLOW (signed, no install scripts) How it works
- Transparent proxy: resolves and serves real npm packages unchanged;
the verdict rides response headers, and
blockpolicy turns a bad tarball into a 403 at install time - Deterministic scoring — start at 100, weighted penalties per finding, any critical forces block — fully reproducible in CI; an LLM adapter only adds context, never the score
- Policy and approval gate: signed per-enterprise policy — with a lint and a dry-run impact preview against real audit history before signing — capability manifests, and a hard privilege boundary: the agent can request an approval, only a human can grant it, enforced by signed Ed25519 role tokens on the control plane
- Deny-by-default sandbox (macOS Seatbelt, Linux bubblewrap):
lifecycle scripts get no network, no credential env vars, no writes
outside a fixed floor, and no
$HOMEreads unless a capability is approved; detected violations quarantine that exact tarball fleet-wide - Agent-native surfaces: a stdio MCP server for agent hosts and a
CLI whose exit codes make
sentinel audita CI gate;sentinel explainturns a verdict into per-finding remediation and a suggested last-known-good version — advisory only, it never rewrites a lockfile - Whole-tree gates: audit every package in an npm/yarn/pnpm lockfile, write a CycloneDX SBOM, post the verdict to the PR via a GitHub Action
- Signed audit attestations (DSSE/in-toto, Ed25519) verified offline as a deploy-time gate, plus known-malicious advisory and CVE-range (SCA) detection
- Identity and history signals: typosquat and dependency-confusion detection, and release-anomaly findings — maintainer takeover, dormancy resurrection, new capabilities in a patch release
- Durable history and observability (opt-in, zero-dependency
SQLite): verdict trends, top-flagged packages, and a violation
timeline on the dashboard, the CLI, and
/-/metrics - Hardened trust boundary: tarball fetches pinned to allowlisted origins (no SSRF), Host-header spoofing refused, byte caps and opt-in rate limits on expensive routes
Status
What started as the audit-proxy wedge has grown into the full layer (July 2026): signed per-enterprise policy and install-time permission manifests, a deny-by-default capability sandbox, offline signature and Sigstore-provenance verification, known-malicious (GHSA) and CVE-range detection, supply-chain identity and release-anomaly heuristics, whole-tree lockfile auditing with SBOMs and signed attestations, a CI-native GitHub Action, an agent-native MCP server, durable observability, and a hardened network trust boundary. Current work is open-source launch prep; the long arc is policy and install-time permissions for the whole ecosystem.
Docs: README · Architecture · ADRs