REC ACTIVE--:--:-- LOCAL
PROGOFFPRG-0112
RecordPRG-0112
Captured
StatusOPEN · UNSEALED
Content hashsha256:d936…d804

the technology desk, on a true attestation

The Provenance Was Valid And The Package Was A Worm

On October 8 a poisoned version of the tensorlake npm package shipped through the project's own release pipeline with valid build provenance attached. Every supply chain record about it was accurate. None of them described what the code did once it was installed.

A build provenance attestation does one thing. It states, under signature, which pipeline turned which source into which package.

On October 8 that statement was true about a worm. Endor Labs reports that at 01:20 UTC on October 7 a malicious commit landed on the main branch of tensorlake, the SDK for a service that gives AI agents sandboxes to run code in. About a day later, at 01:12 UTC on October 8, the project's ordinary GitHub Actions release job published tensorlake 0.5.144 to npm, along with six platform packages at the same version. The release, in Endor's words, "carried valid build provenance." The likeliest cause is a compromised maintainer account, which the researchers are careful to call an inference. Aikido puts the package past 100,000 lifetime installs.

This desk asks of every tool who ends up holding the record. Here the record was held by all the right parties, was signed, was correct, and answered a question nobody installing the package was asking.

what each paper says

Three documents travel with a modern package, and each one is a narrow sentence.

The bill of materials says what the package is made of. For 0.5.144 that list would have read almost exactly like the list for 0.5.143, plus two files in lib and one line in the manifest.

The provenance says where it was built. It was built where tensorlake is always built, by the job that always builds it, from the branch that job always reads.

The signature says the bytes you received are the bytes that were published. They were.

A fourth sentence is missing from the set. Nothing shipped with the package says what it does when it runs. What this one did, per Endor and GBHackers: a preinstall hook ran node lib/setup.mjs before any application code, the loader checked whether it was inside a CI system, pulled down a second runtime, and started an 856 kilobyte payload that collects npm tokens, GitHub tokens, SSH keys, cloud credentials and .env files, then republishes itself into every other package the victim is allowed to publish. One reported component wipes the machine if the stolen token is revoked.

Provenance is a birth certificate. It tells you the hospital.

the sandbox

Notice what tensorlake is for. It exists so that an agent's code can run inside a boundary, with a declared set of things it may touch. The installer for the boundary ran on developer laptops and CI runners with no boundary at all, in the one moment of a package's life when it holds the full permissions of the person typing npm install and has stated no limits of its own. An install script is a stranger handed your keys so that he can deliver a lock.

What a package is permitted to do at install is, for most of the registry, whatever the account running it is permitted to do. That default is written down nowhere, which is why no document could be checked against it.

the missing paper

Adjective, which publishes this press, argued for the fourth document last year. Rob Murtha called it a Software Bill of Function: a signed behavioral inventory listing the functions a piece of software executes, the data it touches, the system calls it makes, and the envelope it promises to stay inside. It is a framework, and tensorlake was under no obligation to have one. The value is in what the comparison would have looked like. A declaration for 0.5.143 lists no network fetch at install and no reads of ~/.ssh. The behavior of 0.5.144 includes both. The difference between a declared behavior and an observed one is a short document, and a machine can refuse on it. The same company's writing on a provable software pipeline makes the companion claim, that the build record and the behavior record belong under one seal so that one cannot be true while the other is silent.

Every signature on this package verified. I would trade two of them for one sentence about behavior, signed by the same hand, that the next version could be caught breaking.

The papers were in order. They were about the building.

The same record an agent receives. No scraping, no guessing — the dossier chrome humans read as dread is the metadata machines read as structure. One source of truth.

GET /records/the-provenance-was-valid-and-the-package-was-a-worm/rawopen ↗
---
id: PRG-0112
title: The Provenance Was Valid And The Package Was A Worm
kicker: the technology desk, on a true attestation
captured: 2026-10-13T17:10:00Z
status: open
author: Aldous Renn
source: https://www.endorlabs.com/learn/tensorlake-npm-package-compromised-by-shai-hulud-in-latest-software-supply-chain-attack
summary: On October 8 a poisoned version of the tensorlake npm package shipped through the project's own release pipeline with valid build provenance attached. Every supply chain record about it was accurate. None of them described what the code did once it was installed.
tags: [provenance, the record, custody, supply chain, capability-vs-permission]
---

A build provenance attestation does one thing. It states, under signature, which pipeline turned which source into which package.

On October 8 that statement was true about a worm. [Endor Labs reports](https://www.endorlabs.com/learn/tensorlake-npm-package-compromised-by-shai-hulud-in-latest-software-supply-chain-attack) that at 01:20 UTC on October 7 a malicious commit landed on the main branch of tensorlake, the SDK for a service that gives AI agents sandboxes to run code in. About a day later, at 01:12 UTC on October 8, the project's ordinary GitHub Actions release job published tensorlake 0.5.144 to npm, along with six platform packages at the same version. The release, in Endor's words, "carried valid build provenance." The likeliest cause is a compromised maintainer account, which the researchers are careful to call an inference. [Aikido](https://www.aikido.dev/blog/tensorlake-npm-package-compromised) puts the package past 100,000 lifetime installs.

This desk asks of every tool who ends up holding the record. Here the record was held by all the right parties, was signed, was correct, and <Highlight>answered a question nobody installing the package was asking</Highlight>.

## what each paper says

Three documents travel with a modern package, and each one is a narrow sentence.

The bill of materials says what the package is made of. For 0.5.144 that list would have read almost exactly like the list for 0.5.143, plus two files in `lib` and one line in the manifest.

The provenance says where it was built. It was built where tensorlake is always built, by the job that always builds it, from the branch that job always reads.

The signature says the bytes you received are the bytes that were published. They were.

A fourth sentence is missing from the set. Nothing shipped with the package says what it does when it runs. What this one did, per Endor and [GBHackers](https://gbhackers.com/tensorlake-package-hijacked): a `preinstall` hook ran `node lib/setup.mjs` before any application code, the loader checked whether it was inside a CI system, pulled down a second runtime, and started an 856 kilobyte payload that collects npm tokens, GitHub tokens, SSH keys, cloud credentials and `.env` files, then republishes itself into every other package the victim is allowed to publish. One reported component wipes the machine if the stolen token is revoked.

> Provenance is a birth certificate. It tells you the hospital.

## the sandbox

Notice what tensorlake is for. It exists so that an agent's code can run inside a boundary, with a declared set of things it may touch. The installer for the boundary ran on developer laptops and CI runners with no boundary at all, in the one moment of a package's life when it holds the full permissions of the person typing `npm install` and has stated no limits of its own. An install script is a stranger handed your keys so that he can deliver a lock.

What a package is permitted to do at install is, for most of the registry, <Redacted reason="never declared">whatever the account running it is permitted to do</Redacted>. That default is written down nowhere, which is why no document could be checked against it.

## the missing paper

Adjective, which publishes this press, argued for the fourth document last year. [Rob Murtha](https://www.linkedin.com/in/robmurthagrowth/) called it a [Software Bill of Function](https://www.adjective.us/blog/software-bill-of-function): a signed behavioral inventory listing the functions a piece of software executes, the data it touches, the system calls it makes, and the envelope it promises to stay inside. It is a framework, and tensorlake was under no obligation to have one. The value is in what the comparison would have looked like. A declaration for 0.5.143 lists no network fetch at install and no reads of `~/.ssh`. The behavior of 0.5.144 includes both. The difference between a declared behavior and an observed one is a short document, and a machine can refuse on it. The same company's writing on a [provable software pipeline](https://www.adjective.us/blog/provable-software-zephyr-glitchlab) makes the companion claim, that the build record and the behavior record belong under one seal so that one cannot be true while the other is silent.

<Marginalia label="On the clean version">Endor reports 0.5.143 as clean and 0.5.144 as removed from npm. Anyone who installed the bad version in that window should treat every credential on the machine as already copied.</Marginalia>

Every signature on this package verified. I would trade two of them for one sentence about behavior, signed by the same hand, that the next version could be caught breaking.

The papers were in order. They were about the building.
<script type="application/ld+json">
{
  "@context": "https://schema.org",
  "@type": "Article",
  "headline": "The Provenance Was Valid And The Package Was A Worm",
  "description": "On October 8 a poisoned version of the tensorlake npm package shipped through the project's own release pipeline with valid build provenance attached. Every supply chain record about it was accurate. None of them described what the code did once it was installed.",
  "identifier": "PRG-0112",
  "datePublished": "2026-10-13T17:10:00.000Z",
  "dateModified": "2026-10-13T17:10:00.000Z",
  "author": {
    "@type": "Person",
    "name": "Aldous Renn",
    "url": "https://progoff.com/authors/aldous-renn"
  },
  "publisher": {
    "@type": "Organization",
    "name": "Progoff",
    "url": "https://progoff.com"
  },
  "image": "https://progoff.com/records/the-provenance-was-valid-and-the-package-was-a-worm/opengraph-image",
  "keywords": "provenance, the record, custody, supply chain, capability-vs-permission",
  "articleSection": "Technology",
  "url": "https://progoff.com/records/the-provenance-was-valid-and-the-package-was-a-worm",
  "mainEntityOfPage": "https://progoff.com/records/the-provenance-was-valid-and-the-package-was-a-worm",
  "sha256": "d936364d9fc7b077d460b632da572470dd50986300c7403f272812930ebdd804",
  "creativeWorkStatus": "open",
  "isAccessibleForFree": true
}