PoisonBox: Install-time poisoning sandbox
Run a package's install script inside a throwaway, hardware-isolated micro-VM and watch everything it touches live: every process, file, secret read and outbound connection, traced at the syscall level and diffed against how a package should behave.
npm install is the most trusted command on the planet, and I've never quite understood why. A single install can run arbitrary lifecycle scripts, read your environment, touch tens of thousands of files and open a socket, all before you've written a line of code against the thing. The declared behaviour is a package.json. The actual behaviour is whatever the author felt like on the day.
I've spent enough of my life watching processes do things they weren't supposed to, whether profiling, tracing, or chasing a leak through a system nobody quite remembered building, to be twitchy about how little anyone looks at this one.
So PoisonBox is a recorder for that gap. It runs a package's install script inside a throwaway, hardware-isolated micro-VM and captures everything: child processes, files created and read, the secrets it reaches for, and every outbound connection. Then it renders the run as a live graph and diffs it against how a package is supposed to behave, with a risk score where every point links back to the exact event that earned it.
The panel above is a real capture, not a mock-up. Everything you watch it do, it did, inside a disposable VM that was deleted the moment it finished.
The hard part
Capture's the easy bit. The hard parts are speed, isolation and legibility. A fresh, observable VM per install has to come up in a second or two, or nobody's ever going to run it. A legitimate install can touch forty thousand files, so the graph has to stay readable when even the honest case is noisy. And the judgement that actually matters is a fine one:
Telling "reads ~/.npmrc to authenticate" from "reads ~/.npmrc to exfiltrate" is the whole game. Same file, opposite intent.
That call never comes from a syscall on its own. It comes from the shape of the whole run: what got read, what happened next, and where the bytes went.
Three installs, three fates
The cleanest way to show it is to run three packages through the same sandbox, over the same three decoy credentials, and watch where they diverge.

One behaves: it reads its own manifest, writes a build cache and exits. No secret touched, no socket opened. Risk 0, and the analysis says clean rather than inventing suspicion. One is the grey case that quote above is about: it reads ~/.npmrc, the npm auth token, and runs a shell step, but never opens a connection. That's a 6, not a 19, because nothing left the box while we watched. And one steals the SSH key, the npm token and the AWS credentials, then connects to a host that isn't any registry:
install: evil-analytics@1.0.0
spawn node preinstall.js lifecycle script
read ~/.ssh/id_rsa SSH KEY (!)
read ~/.npmrc NPM TOKEN (!)
read ~/.aws/credentials AWS CRED (!)
spawn sh -> id reconnaissance
connect 45.9.148.99:443 (non-registry) EXFIL risk 19
The score isn't the point. The thread from the three secret reads to the one outbound connection is: that's the difference between a package that authenticates and a package that robs you, and it's drawn from the run, not asserted.
A real one
Synthetic packages are honest enough for a demo, but the interesting test is a real attack. So we rebuilt the October 2021 ua-parser-js payload from the public post-mortems, the one that shipped to millions off a hijacked npm account, and ran it. On Linux it probes the OS, reaches out to the attacker's hardcoded IP to pull down a second stage, a Monero miner, and tries to run it. In the sandbox the download can't complete, but the reach for it is the tell: a connect to a hardcoded, non-registry host during install. Caught, and labelled a reconstruction, because a reconstruction is never dressed up as the original.
TRUST, BUT RECORD EVERY SYSCALL.
Where it goes
The trace is the interesting output for a second reason: it becomes context. Hand the run, the diff and the package's history to an agent and you get a review with its reasoning attached, a risk score you can click into rather than a number you're told to trust. For a while I had the graph down as a nice-to-have rather than the thing that sells this. Watching people's faces when the exfil arc fires, I think I had it backwards.
It feeds the same supply-chain surface OSPulse already watches: detection first, then the evidence that says exactly what happened, and when.