Update or not, that is the question
How to deal with updates in the era of supply chain attacks and low-quality updates

In the good old days, when a new update for a dependency, framework, or language arrived, we were excited to try it out. We fiddled with it, tested it, and looked for ways it could improve our projects.
We still do that today, but the mood has changed. When you look around now, it feels like every major ecosystem eventually gets hit by some kind of supply chain incident.
Writing software was already hard enough. Maintaining a codebase is proof of work on its own, almost like cryptocurrency mining sometimes. Why would you assume malicious intent in the code you depend on?
Malicious code was not easy to do. Now it is easier.
The same applies to attackers. They need to put in a lot of effort to create malicious code, get it into a repository, and make it look legitimate.
There are multiple ways attackers do this, from poisoning GitHub Actions caches, to publishing malicious packages in the dependency tree, to socially engineering maintainers.
With the rise of AI, some parts of that work are getting easier. Attackers can generate convincing code, create fake repositories faster, and even imitate legitimate project communication.
Here are a couple of examples:
- https://posthog.com/blog/nov-24-shai-hulud-attack-post-mortem
- https://tanstack.com/blog/npm-supply-chain-compromise-postmortem
- https://github.com/axios/axios/issues/10636
- https://edera.dev/stories/tarmageddon
I am not saying that all of those attacks or vulnerabilities were caused by AI, but it does lower the cost of doing parts of the work.
All of those had the potential to reach hundreds or thousands of other repositories and their users.
The severity varies from stealing data to gaining control over systems.
The victims are not only the users of the dependencies, but also the maintainers. They can lose their reputation, their users, and even their jobs.
Quality of updates
The quality of updates is also a concern. AI can help maintainers move faster, but it can also make it easier to ship code that is not well-tested, not well-documented, or not fully thought through.
But was it really different before? Not that much. We had plenty of low-quality updates before AI as well. The cadence is just higher now, so the rough edges are more visible.
That usually means more hotfixes, more patch releases, and more hesitation from users. People want the latest version, but they also do not want to become unpaid QA.
This raises the question: should we update our dependencies? Should we trust the maintainers?
What can you do to protect yourself from attacks and low-quality updates?
Wait
You do not need to install the latest version of every dependency, framework, or language the minute it lands. In many cases, waiting a little gives the ecosystem time to surface regressions, suspicious behavior, or supply chain issues.
This is a heuristic, not a law. If an update fixes a critical security issue you are exposed to, waiting may be the wrong move. But when the risk is low, letting the dust settle for a day or two is often reasonable.
If you use npm, I recommend moving to pnpm as they included more security features - as this above. It will not fetch dependency, which is younger than 24 hours. pnpm
Check the repository / Changelog
Before updating, check the changelog, issues, commits, and if possible, who made the change.
Maybe you will find out that the update is not relevant for your project. Or maybe you will find signs that something is off, whether that is a broken release, a suspicious package change, or a maintainer handover you did not know about.
N-1 strategy
I work a lot with Flutter, and I often use an N-1 strategy. I do not rush to the newest version on day one. I usually move to the previous stable line once it has had time to receive its first fixes.
I avoid the freshest release because it often receives a wave of hotfixes. The 3.44 release is already available, but I am only now moving to 3.41.9. That is exactly the pattern I expect: a release lands, reality hits, and then the hotfixes arrive.
We could place bets on how many hotfixes 3.44 will need, and I am confident the number will be higher than 0.
More on that here: shorebird.dev/blog
Pick maintained dependencies
When you are about to add a new dependency, check whether it is maintained. Look at the last commit, the issue tracker, the pull requests, and whether the releases look deliberate or abandoned.
If a dependency is popular, it may be a bigger target, but it is also more likely to be noticed and fixed quickly.
A package with many downloads and occasional, boring updates can actually be a good sign. It may be mature and stable. Abandonware is riskier, because people often notice it only when a long-awaited update finally appears.
Avoid exotic and post-install scripts
This depends on the package manager you are using, but be extra careful with post-install scripts. Allow them only for packages you know and trust. They are a legitimate feature, but they are also a convenient way to execute code during installation.
Pin your dependencies
Pinning your dependencies is a good practice in general, and it also limits surprise.
An update should be a conscious decision, not ambient background noise. Review the diff, the changelog, and the lockfile changes before updating.
Also, when you are using CI/CD, the builder should use the pinned version, not whatever became latest five minutes ago. That alone can save you from both broken builds and bad releases.
This also applies to your plugins in IDEs. If you have a plugin that is not pinned, it can update itself without you noticing, and it can cause issues or even be malicious.
Update the dependencies and test the code
You are supposed to update your dependencies.
They bring CVE fixes, performance improvements, and new features. If you never update, you are not being safe. You are just letting risk age in place.
Always take calculated risks, not fear-driven ones. Think about what helps your development cycle and what helps your users. Audit the update, check the changelog, and test your code after upgrading.
By not updating or patching your dependencies, you create more surface for attackers. You are basically leaving the door open for them.
Conclusion
So should you update or not?
Yes, you should update. Just do it deliberately.
Check the changelog, the issues, and the commits. Give fresh releases a little time when you can, and move faster when the security risk is immediate.
If an update has been out for a while, it is often more stable, but do not outsource your judgment. Take a quick look at what changed and why.
If you want to know, how I think about dependencies themselves, check out my article on Dependency Management.
It is important to say: By doing some work, you increase chance of breaking something. Do not be spitful of maintainers who ship a broken release. They are not doing it on purpose. They are just human, and they are trying to do their best. Be kind to them, helpful and collaborative.
Socials
Thanks for reading this article!
For more content like this, follow me here or on X or LinkedIn.