AWS put out a long post on supply chain security after the run of npm attacks this year. It’s worth reading if you’ve got twenty minutes. Most people don’t, so here is what we’d actually pull out of it and act on.
Quick recap of why this matters: Shai-Hulud, Chalk/Debug, the tea.xyz token farming thing, the axios scare. Different packages, same story every time. Someone phishes a maintainer, the attacker pushes a bad version of a package people trust, and anyone who installs it in that window gets hit. Shai-Hulud’s payload ran inside CI pipelines and on developer laptops, grabbed npm tokens, GitHub tokens, AWS keys, whatever it could find, and used them to spread to the next victim.
There’s a maintainer side to this (don’t get your account phished) and a consumer side (don’t let a bad package reach your production systems). We’re going to talk about the second one, because that’s the side most of you reading this can actually do something about today.
Get rid of long-lived credentials
This is what made Shai-Hulud spread as fast as it did. The malware went looking for npm tokens, GitHub tokens, and AWS keys, and it found them, because that’s exactly where long-lived credentials tend to sit: config files, environment variables, the usual places. Once a key like that is stolen, it works until someone notices and revokes it. That could be hours. It could be longer.
Short-lived credentials solve this by expiring on their own, with no one having to remember to revoke anything. If you run GitHub Actions or GitLab CI, set up OIDC so each job pulls a token that’s only good for that run. On AWS, IAM Identity Center does the same job for people logging in by hand, and the newer aws login command makes this painless enough that there’s not much excuse left to keep static keys around.
Sometimes you’re stuck with a third-party service that just doesn’t support temporary credentials. Fine. Put that one credential in a proper secrets manager, lock down who can read it, and rotate it on a schedule. Just don’t let it sit in a .env file that nobody’s looked at since the project started.
If you only change one thing this week, change this one. Find your long-lived credentials and swap them for something that expires.
Don’t rely on one layer
A compromised account is bad. What decides how bad is whether anything else stands in the way once that account is in.
A few things worth having stacked on top of each other:
- MFA everywhere, no exceptions. If you maintain something solo, this matters even more, because there’s no second person around to notice something’s wrong.
- Require a second approver before a release goes out. One compromised account shouldn’t be able to ship anything by itself.
- Put that approval inside the pipeline, not just at the pull request stage. A stolen developer credential can still open a PR. It shouldn’t also be able to push it to production without someone else signing off.
None of this is new. It’s the same separation-of-duties thinking that’s been standard in finance for decades, just pointed at package releases instead of wire transfers.
Sign what you build
Here’s the layer that still catches things after a credential has already been stolen. Signing ties a built package or container image to the specific pipeline that produced it, cryptographically. So if someone breaks into a developer’s laptop but not the CI signing key, they can build whatever they want and your deployment still won’t accept it.
AWS calls their version of this AWS Signer. The part that actually matters is who’s allowed to sign: only the CI pipeline role, never a person’s own credentials. The keys themselves live in hardware modules certified to FIPS 140-3 Level 3, meaning even if someone got into the signing service, pulling the key out would be extremely hard.
For containers specifically, Amazon ECR can trigger signing the moment an image gets pushed, no extra step needed. Then at deploy time, something checks the signature before anything is allowed to run. No signature, no deployment. It’s a blunt rule and that’s exactly why it works.
If you publish to npm, there’s a lighter version of this you can turn on today: npm provenance. It’s been in npm since version 9.5, it ties a published package back to the exact GitHub Actions run that built it using Sigstore underneath, and maintainers enable it with one flag: npm publish --provenance. If you’re on the consuming end, checking whether a package you’re about to add even has a provenance attestation takes ten seconds and tells you something real.
Stop letting every team pull from wherever
If every team in your org is installing straight from the public npm or PyPI registry, nobody has a single place to block a bad package, and nobody can quickly answer “are we affected” when the next incident hits.
A proxy registry, AWS CodeArtifact being one option, fixes both problems at once. You can lock down which upstream sources are even allowed, which kills typosquatting outright (the trick where a malicious package is published under a name one letter off from something real). And when something does go wrong, you’ve got one place to search instead of pinging every team in Slack and hoping someone answers.
Pin your versions too, while you’re at it. Auto-updates are convenient right up until one of them quietly pulls in a compromised release behind your back.
Look for malicious behavior, not just known CVEs
Here’s the thing most vulnerability scanners miss: they’re built to catch CVEs, which by definition are vulnerabilities someone has already found and written up. Shai-Hulud-style attacks aren’t accidental bugs waiting to be discovered. They’re malicious on day one. There’s no CVE for “this package was built to steal your secrets” until someone catches it and files one, and that can take days.
Catching these earlier means watching what a package actually does when it runs, not just reading its code. Amazon Inspector does this kind of behavioral check and feeds what it finds into the OpenSSF Malicious Packages Repository, which is shared across the whole community. During the tea.xyz campaign, packages were going from freshly published to formally flagged in around 30 minutes on average. You need that kind of speed, because these things spread through automated builds faster than any human is going to review a diff.
There’s also a nastier variant worth knowing about: packages that look completely clean when published and only turn malicious after a delay. Reading the code won’t catch this, because the bad part isn’t there yet. Only behavioral or runtime checks have a shot.
And keep a Software Bill of Materials for everything you ship, in SPDX or CycloneDX, whichever your tools support. When something blows up, an SBOM is the difference between answering “do we use this package” in five minutes versus five days.
Watch your logs like someone’s actually going to read them
Logging only helps if someone, or something automated, is actually paying attention to it. At minimum, get your logs centralised and run something that flags weird activity on its own, Amazon GuardDuty being the obvious AWS option.
A handful of specific things worth an alert, because they show up again and again in real incidents:
- A role getting assumed from a country or IP you’ve never seen before
- Secrets getting read from outside your normal CI systems
- Code landing in a container registry straight from a laptop, skipping the pipeline entirely
- A new access key getting created and used within seconds
None of these alone proves much. A few of them together, especially right after you’ve found a leaked credential, is exactly the pattern worth losing sleep over.
The thread running through every one of these recent npm attacks is the same: one phished maintainer, one bad package, and then it spreads to everyone who happened to run npm install that week. You can’t stop the first compromise from your end. What you can do is make sure it never reaches your production systems, and build in a way to find out fast if it already has.
We help teams review their CI/CD pipelines, dependency management, and credential handling, then fix what matters most first.
Get in touch →Source
This post is commentary on Well-architected best practices for software supply chain security by Trevor Schiavone and Desiree Brunner, AWS Security Blog, 26 May 2026.