In 2013 I wrote a diploma on elliptic curves. Last night my tool used them to check its own release. A developer built croak, a Claude Code hook that intercepts shell commands before an AI agent runs them, having npm or pnpm plan the install without executing it, then inspecting install scripts, lockfile, registry metadata and unpacked package code in memory to issue an explained verdict. The tool also verifies npm provenance signatures using Node's built-in crypto, confirming its own release as valid and rejecting a mismatched tarball. On its own eval it flagged all 36 attacks but blocked only 27, sending the remaining nine to a human for review. TL;DR : In 2013 I wrote a university diploma on elliptic-curve cryptography, and it went into a drawer. Thirteen years later the same math signs most of what you npm install . I taught croak 🐸, my pre-install gate for AI agents, to check those signatures itself. Last night it checked its own fresh release: verified . Then I gave it the same signature with a different tarball: invalid . Below is what that check actually involves, and why the curve is the easy part. In 2013: a diploma on elliptic curves and key exchange. Points, groups, a lot of modular arithmetic. Defended, filed, forgotten. I went into test automation, and the curves stayed in the drawer. Then AI agents started running npm install on their own. An install doesn't just download code. It runs it: postinstall , native builds, whatever a package wants. An agent does this all day, in your terminal, usually without reading anything. It also invents package names that sound right, and attackers register those names. croak sits between the agent and the install. It's a Claude Code hook: before a shell command runs, croak has npm or pnpm plan the install resolve it, run nothing , then reads that plan as data: install scripts, the lockfile, registry metadata, and the code of every new package, unpacked in memory and never executed. It gives a verdict and explains it to the agent : agent: npm install reactt-domm croak: 🐸 croak blocked this command before it ran. reactt-domm: not on npm; did you mean react-dom ? Do not work around this check another package manager, a different command, or editing files to install it ; tell the user what croak found and let them decide. postinstall that downloads a binary lands here. It also scans an unfamiliar repo before you open it croak repo : VS Code tasks that run on open, code hidden after hundreds of spaces, obfuscation , because "clone this take-home assignment and run it" is a real attack too. It's early, and it misses things. On its own eval it flags all 36 attacks but blocks only 27; the other nine go to a human as 🟡. I'd rather publish that number than a prettier one. Most attacks give themselves away in the code: a postinstall that pipes curl into sh , process.env posted somewhere. And install scripts are losing ground anyway: pnpm 10 and npm 12 no longer run a dependency's scripts unless the project allows them. I checked with a bait package that writes a marker file: npm 11 still runs them; npm 12 doesn't. That pushes attacks into code you import , and that code can look exactly like the real thing. Someone steals a maintainer's token, publishes from a laptop, and the tarball looks like every release before it. That is the question code can't answer: who built this tarball, and from what? npm has an answer. It's called provenance. And it's elliptic curves all the way down. When a package is published from CI with provenance, a few things happen in a couple of seconds: release.yml in repo X, at commit Y" Here's my own release from last night, read straight from the certificate: leaf key: ec { namedCurve: 'prime256v1' } // P-256 valid: Nov 1 23:13:03 2026 GMT - Nov 1 23:23:03 2026 GMT // 10 minutes issuer: O=sigstore.dev, CN=sigstore-intermediate A key that lives for ten minutes and is then thrown away. The trust comes from the log, not from keeping a secret for years. Count the curves. The registry's own signature on every package: P-256 . The build's ten-minute key: P-256 . Rekor's key: P-256 . Fulcio's CA uses its bigger sibling, P-384. My diploma, signing my node modules . Here is the elliptic-curve part of croak's verifier: verify "sha256", message, leaf.publicKey, signature One line. node:crypto does the curve math, and it does it better than I would. No point addition by hand, no hand-rolled anything. In 2026, writing your own ECDSA would be a red flag, not a skill. All the hard parts moved into the plumbing around that line. A signature verifies something . The question is whether it is the thing you think. croak's check, in order: js const logged = readLogEntry entries 0 , trust.rekor ; // 1. Rekor promised it saw this, and when const leaf = leafOf material ; checkCertificate leaf, trust.fulcio, logged.loggedAt ; // 2. Fulcio issued it, valid at that moment // 3. the envelope's signature verifies with the leaf key // 4. the log entry is for this exact signature, certificate and payload checkSubject payload, subject ; // 5. the statement is about THIS tarball return { status: "verified", identity: fulcioIdentity leaf.raw }; A few things I only learned by building it: "DSSEv1