Some Extra Steps to Not Get Got by a Bad Package
- 2 days ago
- 5 min read

Hey kids!
These supply chain breaches are happening a little too often, so these aren't just theoretical security concerns anymore. Two recent incidents are a big part of why I put this post together.
In May 2026, a poisoned VS Code extension called Nx Console was used to breach GitHub's own internal repositories, exposing roughly 3,800 repos and stealing credentials from developer machines ... including npm tokens, AWS keys, and Claude Code configs. The malicious version was live for only 18 minutes. That was enough. The Hacker News has the full breakdown.
That breach was actually downstream of an even wilder attack ... the TanStack npm supply chain compromise, where a worm hit 42 widely-used JavaScript packages with over 12 million weekly downloads combined. The attackers published malicious versions through TanStack’s own legitimate release pipeline, so the packages came with valid security certificates. They looked completely clean. Snyk wrote a really thorough technical breakdown of how the whole thing worked if you want to go deep on it.
The cooling-off period settings discussed in this post would have blocked the TanStack attack entirely ... those malicious versions were only live for about three hours before they were caught. A seven-day wait and you never would have seen them.

The four-step npm/bun setup we are going to go over came from BOOTOSHI 👑 (@KingBootoshi) on Twitter, who posted it as a prompt you can run directly in Claude Code or Codex. I thought it was a smart, practical starting point, and expanded from there. Go give them a follow and say thanks for the deets. Feel free to copy the exact prompt directly from the tweet too.

So, let's get into it!! Supply chain attacks are a thing now. Not a new thing, but they’re getting more common, and the idea is kind of horrifying when you think about it. Someone sneaks malicious code into a package you already trust, you run 'npm install' like you normally do, and now you’ve got a problem.
This post is written to help you shore up your personal machine, things you can do for yourself to slow down the blast radius if something sketchy makes it into your ecosystem. Your company's security folks should be all over this and have a plan in place for their hardware, so please follow their instructions for their property. This also is not a complete guide to supply chain security because that would be a book. This is just a place to start to hopefully help keep you from having a bad day.

The big idea behind all of this is a cooling-off period. Most malicious packages get caught within days of publishing. If you’re not installing things the minute they drop, you’re in much better shape. You'll see this is pattern in the way I work - I am rarely on the bleeding edge of adoption and never installing beta anything. This kind of situation is partially the reason why I have been more cautious in my approach to jumping into anything too fast. Malicious code, bad actors, and impossible bugs are stressors no one needs.
npm / bun (JavaScript)
Not super comfortable with editing config files directly? If you have access to a coding AI assistant like Claude Code, you can grab the prompt from BOOTOSHI 👑 (@KingBootoshi) on Twitter and prompt it to your AI assistant as-is to do it for you!
These first 4 steps are direct from The King B .... but I added a little more context for folks that haven't worked with these files before -
1. Edit (or create) your ~/.npmrc
Add these three lines:
min-release-age=7
minimum-release-age=10080
save-exact=true
This file can be found or created at your ~/Users/<username> root. The same folder you see your Downloads folder.
'save-exact=true' means when you 'npm install' something, it writes the exact version to your ~'package.json' instead of adding a ^ that lets npm drift to newer versions automatically. Your version will effectively lock. The 'minimum-release-age' setting (in minutes) tells npm to refuse packages that haven’t been published for at least 7 days.

2. Edit (or create) your ~/.bunfig.toml
[install]
minimumReleaseAge = 604800
Same folder, same idea, same 7-day window, just for bun. 604800 is seconds.

3. Pin your dependencies in ~package.json (project specific)
Strip the ^ and ~ off every version in your dependencies, devDependencies, and peerDependencies. Exact versions only. This step needs to happen for all existing solutions you are working on and/or have on your machine that you may open, no exceptions.
"@angular/core": "^21.2.14"
// becomes
"@angular/core": "21.2.14" The caret and tilde exist to let npm automatically pull in compatible newer versions, which sounds nice until a newer version is the one with the hacker attached.
4. Commit your lockfile (project specific)
Whatever you’re using, ~bun.lock, ~package-lock.json, ~pnpm-lock.yaml - commit it to source. The lockfile records the exact resolved tree of everything that gets installed. Without it checked in, nothing stops a fresh install from pulling something different than what you tested with. Again, this step needs to happen for all existing solutions you are working on and/or have on your machine that you may open, no exceptions.
Here is where we are leaving KingBootoshi, and adding more security steps to increase the liklihood that we can sleep at night. All of these steps can be completed by an AI assistant like Claude, if you have access to one. Feel free to do that, or manually follow the steps that you are comfortable with.
Remember, if you don't really understand something listed, don't make changes to it until you understand the implications of the change, and then evaluate if it is the correct change for you. these are all suggestions, not requirements. Read through and make changes at your discretion.
NuGet (.NET)
NuGet doesn’t have a built-in release-age filter, so you can stack a few things:
Lock files
add → <RestorePackagesWithLockFile>true</RestorePackagesWithLockFile>
to → ~.csproj or ~Directory.Build.props
commit → ~packages.lock.jsonUpdates then require an explicit 'dotnet restore --force-evaluate' in a terminal window, so silent drift is impossible.
Central Package Management
add → <ManagePackageVersionsCentrally>true</ManagePackageVersionsCentral>
to → ~Directory.Packages.props
commit → ~packages.lock.jsonThis gives you one place to pin everything instead of hunting across projects.
Audit on restore
Run 'dotnet nuget audit' before any 'dotnet add package' in a terminal window. It’s available in the .NET 8+ SDK and flags known-vulnerable packages. If you have access to tools like Snyk, there are extension for IDE's that will catch vulnerabilities too.
Manual cooling off
Subscribe to the package’s GitHub releases RSS feed. When a new version drops on nuget.org, note the date .... wait 7-10 days, then check for any CVEs (Common Vulnerabilities and Exposures) or community noise before pulling
Renovate / Dependabot
If you use Renovate, set 'minimumReleaseAge: "7 days"' in your ~renovate.json Renovate enforces this natively. Dependabot doesn’t support it yet, but you can set 'open-pull-requests-limit' low to slow the pace. Using these automated dependency update tools can be "set it and forget it", but it can get you in hot water if you can't slow them down.
VS Code Extensions (and other IDE plugins)
This one surprises people because it doesn’t feel like a “package” situation, but extensions run in your editor with a lot of access.
Turn off auto-update
Set "extensions.autoUpdate": false in your ~settings.json
Review release notes manually before updating anything
Export your current extension list with versions and keep it in source control
That way you’re making intentional changes and keeping track
in terminal → --list-extensions --show-versionsCheck the publisher verified badge (blue checkmark ) before installing anything new. Unverified publishers are higher risk

The Manual Workflow That Works Everywhere
For anything that doesn’t have tooling support, this process covers you:
Subscribe to release notifications (GitHub “Watch → Releases only”, RSS, or registry email alerts)
When a new version drops, note the date. Don’t act for 7-10 days
After the window, check:
any CVEs (Common Vulnerabilities and Exposures) filed?
Any noise on GitHub issues / Reddit / Hacker News?
Any unexpected new dependencies in the diff?
Then update
Boring? Yes. Effective? Also yes.
None of this is a guarantee. But it raises the bar and keeps you pretty darn safe, and that matters. Drop any tips you use in the comments below!! 💜

Comments