Skip to content
Beta, invitation only

Limit what a compromised npm package can do.

Scanners flag known-bad packages. Kratex enforces what every package can do at install and at runtime, including the ones nobody has flagged yet.

Install and runtime

Every npm install runs the maintainer's code on your machine, and so does every dependency you import. Kratex enforces rules on both.

01

Stop trusting lifecycle scripts.

Postinstall scripts run with the same access your shell has. kratex install puts them under your rules instead.

$ kratex install
  resolving 412 packages
  ok    react@19.0.0
  ok    react-dom@19.0.0
  block chalk@5.3.0
        reason: postinstall.sh requested network
        policy: acme / web / v17
  ok    vite@7.0.0

install incomplete (1 blocked)
policy.jsonv17 · acme / web
{
  "extends": "kratex/default",
  "filesystem": "audit",
  "network": [
    "registry.npmjs.org",
    "deps.acme.internal"
  ],
  "subprocess": "allow"
}
02

Apply the same rules at runtime.

Every dependency you import is also a dependency you execute. kratex run enforces the same rules every time it does.

03

Every decision goes to the dashboard.

Each decision records the device, the project, what was attempted, and the rule that decided. Triage without filing a ticket.

  1. 14:42:08block install · chalk@5.3.0 postinstall · kira-mbp
  2. 14:41:55allow install · react@19.0.0 · kira-mbp
  3. 14:39:12block process · child_process.spawn left-pad · ci-runner-7
  4. 14:33:01audit fs · write /etc/hosts · owen-linux
  5. 14:29:44allow net · connect registry.npmjs.org · ci-runner-3
Dashboard

Assign a policy to each project. Triage the events your machines send back.

Machine events

  • blocked
    chalk@5.3.0postinstall · net
    2m
  • blocked
    left-pad@1.3.0child_process.spawn
    12m
  • audit
    /etc/hostsfs.write
    18m
  • allowed
    react@19.0.0install
    26m
  • allowed
    registry.npmjs.orgnet.connect
    31m

Policies

  • acme / web
    v17
    enforce
    today
  • acme / payments
    v04
    audit
    today
  • acme / infra
    v22
    enforce
    3d ago
  • acme / data-ingest
    v11
    enforce
    1w ago
  • acme / docs
    v02
    audit
    2w ago
36 compromises since 2017

Each of these ran on machines that never imported it directly.

2026
  1. node-ipc (again)

    Maintainer's email domain expired. An attacker bought the lapsed domain, used a forgotten-password flow to take over the npm account, and published versions that exfiltrated AWS tokens, SSH keys, Kubernetes configs, and CI secrets to an attacker-controlled server. node-ipc carried millions of weekly downloads at the time.

  2. @tanstack/*

    A fork pull request reached a GitHub Actions runner. The worm's successor, Mini Shai-Hulud, poisoned the CI cache, extracted the publishing OIDC token from runner memory, and shipped 84 malicious versions across 42 @tanstack/* packages in six minutes. By end of day the same campaign had reached 170+ packages across npm and PyPI.

  3. @bitwarden/cli

    TeamPCP, pivoting from the Trivy compromise, pushed a malicious release to the Bitwarden npm namespace. Version 2026.4.0 ran a preinstall that downloaded the Bun runtime, executed an obfuscated loader, and exfiltrated npm tokens, GitHub tokens, SSH keys, and AWS, Azure, and GCP credentials. The stolen data was AES-encrypted and pushed as public repositories under each victim's own GitHub account.

  4. axios

    A North Korean operator phished the lead maintainer and planted a RAT on the maintainer's workstation. Versions 1.14.1 and 0.30.4 added a malicious dependency, plain-crypto-js, that dropped a cross-platform RAT on macOS, Windows, and Linux. Roughly six hundred thousand installs occurred during the three-hour window before the versions were pulled.

  5. @aquasecurity/trivy-action, 47+ npm packages

    An autonomous bot exploited a pull_request_target misconfiguration in Trivy's GitHub Actions workflows. The operator stole a personal access token, force-pushed seventy-six of seventy-seven Trivy action tags to malicious commits, and shipped a poisoned Trivy binary through official channels. Stolen credentials cascaded into the CanisterWorm campaign, which infected 47+ npm packages with a postinstall that stole tokens and republished onward.

2025
  1. @crowdstrike/*

    The same Shai-Hulud worm reached the crowdstrike-publisher npm account. Multiple CrowdStrike-namespace packages, including @crowdstrike/commitlint and @crowdstrike/falcon-shoelace, were republished with a loader that ran TruffleHog against the host and uploaded any matching secrets. CrowdStrike rotated keys and confirmed the Falcon sensor was unaffected.

You can't audit every npm package. Don't have to.