> A while ago, I collaborated on angulartics2, a shared repository where multiple people still had admin rights. That repo still contained a GitHub Actions secret — a npm token with broad publish rights. This collaborator had access to projects with other people which I believe explains some of the other 40 initial packages that were affected.

> A new Shai-Hulud branch was force pushed to angulartics2 with a malicious github action workflow by a collaborator. The workflow ran immediately on push (did not need review since the collaborator is an admin) and stole the npm token. With the stolen token, the attacker published malicious versions of 20 packages. Many of which are not widely used, however the @ctrl/tinycolor package is downloaded about 2 million times a week.

I still don't get it. An admin on angulartics2 gets hacked, his Github access is used to push a malicious workflow that extracts an npm token. But why would an npm token in angulartics2 have publication rights to tinycolor?

I have admin rights on someone else’s npm repo and I’ve done most of the recent releases. Becoming admin lit a fire under me to fix all of the annoying things and shitty design decisions that have been stuck in the backlog for years so most of the commits are also mine. I don’t want my name on broken code that “works”.

I had just about convinced myself that we should be using a GitHub action to publish packages because there was always the possibility that publishing directly via 2FA, that one (or specifically I) could fuck up and publish something that wasn’t a snapshot of trunk.

But I worried about stuff like this and procrastinated on forcing the issue with the other admins. And it looks like the universe has again rewarded my procrastination. I don’t know what the answer is but giving your credentials to a third party clearly isn’t it.

npm has had support for package-scoped publish tokens (with optional 2FA enforcement) for a few years by now. So in case of compromise, the blast radius would be a single package.

The OP gave the GH repo too broad permissions. There is no good reason for the repo CI workflow to have full access to everything under their account.

I’m using the 2FA tokens, my complaint is that “npm publish” from my own machine has no guarantees of being an exact snapshot of trunk. And a worm could inject code into my system to do the Kernighan exploit.

I think over the last few weeks I have at least talked myself into going back to maintaining multiple user accounts on my laptop to separate personal, open source, and entertainment into separate accounts to reduce the last radius, but the fact is sometimes I like to do two things at once and that will be a pain.

You can get pretty close to guarantees.

Fresh git checkout on prod publish. Run all npm/node commands in ephemeral rootless containers. Only have publish token exposed and injected when you are actually publishing (not on install/build just prior). Separating users like you mentioned doesn't hurt bt doesn't sound like your lower-hanging fruit nor something that would likely save your bacon on its own without other workflow adjustments.

None of this is relatively difficult per se, just a bit extra friction which should be worth it to avoid these kinds of events.

Npm supports one time passwords, and iPhone has builtin support for the protocols that npm uses. Someone’s going to have to pickpocket me to hijack that repo. Hacking my machine with supply chain attacks would be much much easier.

> But why would an npm token in angulartics2 have publication rights to tinycolor?

Imo, this is one of the most classical ways organizations get pwned: That one sin from your youth years ago comes to bite you in the butt.

We also had one of these years ago. It wasn't the modern stack everyone was working to scan and optimize and keep us secure that allowed someone to upload stuff to our servers. It was the editor that had been replaced years and years ago, and it's replacement had also been replaced, the way it was packaged wasn't seen by the build-time security scans, but eventually someone found it with a URL scan. Whoopsie.

Thinking of biology, the reason often given for the disappearance of "unused" genes/base-pairs is that there's a metabolic cost to keeping them around and copying them on every cell division, so they vanish from a form of passive attrition.

I wonder if someday we'll find there's also a more active process, which resembles "remove old shit because it may contain security vulnerabilities."

Sorry if that wasn't clear. This was a token with global publish rights to my npm packages.

I was confused too. Was it your npm token stored in angulartics2 as a Github Actions secret, so it could publish new angulartics2 versions?

Yes, exactly.

[deleted]