Open your lock file and count the packages. For a typical web project it's somewhere between a few hundred and a few thousand. You chose perhaps twenty of them. The rest came along as dependencies of dependencies, written by people you'll never meet. Every one of them runs with the same permissions as your own code.

That's the software supply chain, and in the last couple of years it has become one of the most effective ways to attack applications.

Two wake-up calls

In March 2024, a Microsoft engineer noticed that SSH logins on a test machine were taking about half a second longer than usual. Digging in, he found a backdoor hidden in xz Utils, a compression library present on a huge number of Linux systems. The attacker had spent around two years earning the trust of the project as a helpful contributor before slipping it in. It was caught before reaching most stable distributions, largely by luck and curiosity.

In June 2024, the polyfill.io domain — used by many websites to load a JavaScript compatibility script — came under new ownership and began serving malicious code to some visitors. Sites that had added a single <script> tag years earlier were suddenly sending their users elsewhere.

Neither attack needed to break into the victims' own servers. They simply waited for the victims to load code they trusted.

What you can actually do

You can't audit every package. You can make attacks harder and catch problems sooner.

Commit your lock files. composer.lock, package-lock.json, poetry.lock or a pinned requirements.txt make sure production installs exactly what you tested, not whatever was published this morning.

Run audits in CI. composer audit, npm audit and pip-audit check your dependencies against known vulnerability databases. Fail the build on serious findings.

Automate updates — with review. Tools like Renovate or Dependabot open small, regular pull requests. Small updates are easy to review and easy to roll back. Huge, rare updates are neither.

Self-host critical front-end scripts. Instead of loading JavaScript from a third-party domain at runtime, download a pinned version and serve it yourself. If you must use a CDN, add Subresource Integrity (integrity="sha384-...") so the browser refuses a file that has changed.

Watch for typosquatting. Attackers publish packages with names one letter away from popular ones. Double-check names when adding a dependency, especially when copying from a blog post or an AI suggestion.

Know what you ship. Generating an SBOM (software bill of materials) during the build means that when the next big vulnerability is announced, you can answer "are we affected?" in minutes rather than days.

The mindset shift

Dependencies aren't free. Each one is a small, ongoing relationship with another team. Before adding a package, ask whether it's maintained, how many people maintain it, and whether a few lines of your own code would do. Fewer, healthier dependencies are the cheapest security improvement most teams can make.