Programming code on a computer screen representing software supply chain security
Programming code on a computer screen. Image: Bloxgros via Wikimedia Commons (CC BY-SA 4.0)

I almost ignored the email.

It was from GitHub’s Dependabot — the fifth one that week — and I was three sprints deep into a government digital transformation project. You know how it goes. The alerts pile up. You tell yourself you’ll get to them next sprint. And then next sprint becomes next month.

But something made me click this one. Maybe it was the critical label. Maybe it was the fact that the vulnerability had a CVSS score of 9.8 and an active exploit in the wild. Or maybe — and this is the part that still gets me — it was in a package we didn’t even know we were using. A transitive dependency buried four layers deep in our node_modules, quietly opening a backdoor into our production environment for the past eight months.

That audit turned up 47 vulnerabilities across our stack. Not 47 theoretical “maybe someone could exploit this” findings. Forty-seven documented CVEs, 12 of them critical, sitting in dependencies we had pulled in without a second thought.

And here’s the thing — we’re not an outlier. We’re the norm.

The Numbers Are Worse Than You Think

Software supply chain attacks aren’t a new threat, but the scale we’re seeing in 2026 is something else entirely. Earlier this month, researchers uncovered the Megalodon campaign — a coordinated poisoning of over 5,500 GitHub repositories with malicious code designed to steal credentials and environment variables. That’s not a typo. Five thousand five hundred repos. (The Register covered the details.)

The same week, a lone attacker published 14 malicious npm packages disguised as popular OpenSearch and Elasticsearch libraries. If you were building a search feature and ran npm install @opensearch-project/dashboards-helpers — a name that looks disturbingly legitimate — you were pulling in code designed to exfiltrate your AWS credentials.

And a critical remote code execution bug in Gogs, the open-source Git service used by thousands of teams, has been sitting unpatched with a public exploit module circulating for days. No fix yet. No workaround that fully closes the hole.

Sonatype’s latest State of the Software Supply Chain report found that supply chain attacks grew an average of 742% annually over the past three years. In 2025 alone, 91% of organizations reported at least one software supply chain incident. The average cost per incident? North of $4.6 million, according to IBM’s data breach report — and that’s just the direct financial hit, not counting the regulatory fallout or the trust you lose with your users.

Let that sink in. We’re pulling in thousands of dependencies, many of them maintained by unpaid volunteers, and the attackers have figured out that’s where the soft underbelly is.

Why Your Dependencies Are the New Perimeter

For decades, we thought about security in terms of perimeters. Firewalls. VPNs. Network segmentation. Build a wall, keep the bad guys out. That model was already crumbling before the pandemic, but the shift to remote work and cloud-native development finished it off.

Today, your real perimeter isn’t your network boundary. It’s your dependency tree.

Every pip install, every npm i, every go get, every cargo add is a trust decision you’re making in milliseconds. You’re saying: “I trust this package. I trust everyone who maintains it. I trust every dependency it pulls in. I trust that no one has compromised the maintainer’s credentials. I trust that the package on the registry is the same code in the public repo. I trust that this won’t change tomorrow.”

That’s a lot of trust for something you didn’t even read the source code of.

The attack surface has shifted, and it shifted fast. Here are the three vectors hitting teams hardest right now:

1. Typosquatting and Brandjacking

Attackers register package names that are one typo away from legitimate ones. requets instead of requests. elemetree instead of elementtree. The 14 malicious npm packages mimicking OpenSearch libraries? Pure brandjacking — names designed to look official. Developers in a hurry don’t double-check. And honestly, who hasn’t typed a package name wrong at least once?

2. Dependency Confusion

This one is insidious. If your organization uses private packages hosted internally, an attacker can publish a package with the same name on a public registry with a higher version number. Your build system, when resolving dependencies, grabs the higher version from the public registry instead of your internal one. Boom — attacker code in your pipeline. This technique alone compromised dozens of Fortune 500 companies in a single security researcher’s test run.

3. Compromised Maintainer Accounts

Open source maintainers are the unsung heroes of our industry — and they’re exhausted, under-resourced, and increasingly targeted. An attacker compromises a maintainer’s npm or PyPI account (often through a simple phishing email), pushes a malicious patch version, and every project that auto-updates to the latest minor version gets infected. The Megalodon campaign targeting 5,500+ GitHub repos? Many of those started with compromised personal access tokens.

What We Did After That Audit

After the initial panic subsided (there’s always a moment of “should we just rewrite everything in Rust?” — the answer is no), we built a practical, repeatable process. Not a 50-page policy document that nobody reads. An actual workflow that we run every sprint.

Here’s what it looks like:

Phase 1: Know What You Have

You can’t secure what you can’t see. We generated a full software bill of materials (SBOM) for every project. If you’re in the Node.js ecosystem, npm ls --all --json is your starting point. For Python, pip freeze plus a tool like pip-audit. For Go, go mod graph. The output is massive — our main project’s SBOM was 4,000+ lines — but it’s the baseline.

Practical step: Use Syft or CycloneDX to generate SBOMs in a standard format. Store them with your builds. When a new CVE drops, you can grep your SBOMs instead of panicking.

Phase 2: Automate the Triage

Manual auditing doesn’t scale. You need tooling that runs on every pull request. We integrated:

  • Dependabot (native GitHub) for automated version bump PRs with security labels
  • npm audit / pip-audit in CI — fail the build on critical CVEs with known exploits
  • Trivy for container image scanning (yes, your Docker base images are also dependencies)
  • Socket.dev for analyzing package behavior — does this new dependency open network connections? Write to the filesystem? Execute shell commands? If it does and the package description says “string left-padding utility,” that’s a red flag.

The key: fail the build on critical findings. Not “log a warning and move on.” Warnings become noise. No one reads warnings. But if the CI pipeline turns red, someone will fix it.

Phase 3: Pin and Lock

Semantic versioning is a social contract, not a security guarantee. A maintainer can publish a malicious patch version under a legitimate minor release. We moved from caret ranges (^2.3.0) to exact versions with lockfiles that get checked into the repo. Yes, it means more Dependabot PRs. Yes, it’s tedious. But the alternative — automatically pulling in unknown code on every build — is how the Megalodon campaign spread so effectively.

Phase 4: Verify Provenance

This is the part most teams skip, and it’s the part I’m most bullish about. Sigstore and the SLSA framework (Supply-chain Levels for Software Artifacts) let you verify that the package you’re downloading was actually built from the source code it claims to come from. npm is rolling out package provenance. PyPI is following. It’s not perfect yet, but it’s the right direction — cryptographically proving that what you see on GitHub is what you get from the registry.

The Mindset Shift: Dependencies Are Code You Own

Here’s the uncomfortable truth I had to accept after that audit: every dependency you add to your project becomes your responsibility. Not the maintainer’s. Not the registry’s. Yours.

If a critical vulnerability drops at 2 a.m. and the maintainer is asleep (or worse, has abandoned the project), it’s your production environment that’s exposed. It’s your users’ data at risk. It’s your incident response team getting paged.

This doesn’t mean you should stop using open source — that would be absurd. But it does mean treating dependencies with the same scrutiny you’d apply to code your junior developer wrote at 4:55 p.m. on a Friday. Ask yourself before adding any dependency:

  • Do I actually need this, or can I write 20 lines of code instead?
  • Is this package actively maintained? When was the last release? How many open issues?
  • How many transitive dependencies does it pull? (Use npmgraph or cargo tree to visualize this)
  • Who maintains it — a known organization or a single person with 47 other packages they also maintain alone?

I’m not saying every dependency needs a full security audit. But the ones that handle authentication, process user data, or touch your file system? Yeah, those deserve at least a cursory read-through.

The Government IT Perspective

Working in government IT gives you a particular appreciation for supply chain security — because the stakes are different. When a private company gets breached, they lose money and reputation. When a government system gets breached, the impact cascades into citizen services, public trust, and sometimes national security.

I’ve seen procurement processes that spend six months evaluating a vendor’s financial stability but zero minutes checking whether their software dependencies have known vulnerabilities. The contract says “vendor is responsible for security,” and everyone nods and moves on. But when the incident happens — when a compromised npm package opens a backdoor in a citizen-facing portal — the vendor points to the open-source maintainer, the maintainer is a volunteer in another country, and our team is the one explaining to agency leadership why PII was exposed.

That’s why I’ve been pushing for SBOM requirements in every procurement contract — not as a checkbox, but as a living document that gets updated with every release. It’s not radical. The U.S. government mandated SBOMs for federal software suppliers back in 2024. If you’re building or buying software for any organization that handles sensitive data, this should be non-negotiable by now.

Building a Security Habit, Not a Security Sprint

One thing boxing taught me — and I’ve written about this before in my piece on Shadow AI security — is that you don’t get strong by doing one intense workout and then sitting on the couch for a month. You get strong through consistent, daily habits.

Security is the same. You don’t fix your supply chain by doing one massive audit and declaring victory. You fix it by building small, repeatable habits into your development workflow:

  • Run npm audit (or your ecosystem’s equivalent) as part of your pre-commit or CI pipeline — every single time.
  • Review Dependabot PRs the same week they arrive, not next quarter.
  • Spend 15 minutes a week checking your dependency health dashboard. No dashboard? Build one. The data’s all in the tools I mentioned above.
  • When onboarding new developers, include “how we manage dependencies” in the first week — not buried in a wiki page, but as a conversation.

These aren’t exciting. They won’t make a good conference talk. But they’re the difference between catching a critical vulnerability in development and discovering it through an incident report.

Where We Go From Here

The software supply chain security landscape is maturing fast. Sigstore is gaining traction. npm and PyPI are implementing mandatory 2FA for maintainers. The SLSA framework gives teams a clear maturity model to work toward. AI tools are starting to help — AI coding assistants like the ones I’ve been exploring can flag suspicious dependency patterns during code review in ways that static analysis alone can’t.

But the tools are only half the equation. The other half is cultural. It’s about developers — especially senior ones like us — taking ownership of the entire chain, from our code editor to production.

That Dependabot email I almost ignored? It led to six weeks of cleanup work, several uncomfortable conversations with vendors, and a complete overhaul of how we evaluate dependencies. It was painful. It was necessary.

And here’s what I keep coming back to: the only reason we caught it before it became an incident was that someone on the team had configured automated scanning months earlier, on a slow Friday afternoon, when there was no fire to put out. That’s the habit I’m talking about.

Don’t wait for the email you can’t ignore.

Filed under Tech & Gadgets
Last Update: May 31, 2026 by Felix AlterEgo
0 0 votes
Article Rating
Subscribe
Notify of
guest

This site uses Akismet to reduce spam. Learn how your comment data is processed.

0 Comments
Newest
Oldest Most Voted