It’s an Open Source World
Modern software is built on open source - and the numbers are staggering. Today, around 98% of applications rely on open-source dependencies. It’s not just a few libraries sprinkled in for convenience; open source forms the backbone of nearly every software product in existence.
The ecosystem is immense. There are millions of active projects across platforms like GitHub, npm, Maven Central, and PyPI. Popular libraries like Lodash have over a thousand versions. That means a thousand different states of security, performance, and compatibility - and that’s just one project. Vulnerabilities are an inevitable byproduct of this scale. The OSV.dev vulnerability database now tracks over 200,000 vulnerabilities and is growing daily. Hundreds of new vulnerabilities are disclosed each month, feeding a relentless stream of alerts into developer pipelines.
Each application service, even something relatively simple, typically includes between hundreds to thousands of dependencies when accounting for both direct and transitive libraries. Most of them are not explicitly chosen by the developer. They’re pulled in indirectly, nested several layers deep. This is the reality of modern software development - and it’s where the trouble starts.
The Reality: You Are Drowning in Volume
Each time you add a dependency to a project, you’re importing code - and risk - that you don’t control. That new library might rely on a dozen others, each maintained by different people, with different standards and release cadences. As those dependencies stack up, so does your attack surface.
Vulnerabilities don’t announce themselves clearly. They hide in nested packages, sometimes several levels deep, and often in components you’re not even aware you’re using. And even if you fix one today, there's no guarantee you won’t be dealing with a different one tomorrow. Security isn’t a milestone - it’s an ongoing process. New vulnerabilities are discovered constantly, which means the work of securing software is never finished. There is no clean slate - only a moving target.
Patching Fatigue
This nonstop stream of alerts and updates quickly becomes overwhelming. Every vulnerability, no matter how minor, demands investigation. Each fix requires validation, testing, and deployment - and possibly rollback if something breaks. Multiply this effort across hundreds of dependencies and dozens of services, and it’s no wonder developers feel burned out.
“Handling open source risks was a constant uphill battle - no matter our efforts, we couldn’t get ahead.” Jacob Avidar, VP R&D and CISO, Plaxidity
There’s a specific kind of emotional exhaustion that sets in: “Didn’t I just fix this yesterday?” The pace of updates makes it feel like you’re trapped in a loop - just as you clear one set of issues, another appears. The process is repetitive, high-stakes, and rarely rewarded. Over time, it wears teams down, leaving them less responsive, less motivated, and more likely to ignore the next alert that rolls in.
Vulnerability Backlogs
Eventually, the issues start to pile up. What begins as a steady trickle turns into a backlog of vulnerabilities that grows faster than your team can keep up. Each new entry in the list adds pressure to prioritize - and with limited time and people, choices must be made. But choosing is harder than it sounds.
- Which five vulnerabilities should be addressed out of the 50 flagged this week?
- Are they real risks or theoretical ones?
- Can they be exploited?
- Should they delay a release?
These are hard questions to answer under time constraints. And so, many teams end up defaulting to inaction - not because they’re reckless, but because they’re overloaded. It’s a quiet, unintentional acceptance of risk, born out of necessity.
Prioritization is Not Remediation
The problem isn’t just volume - it’s ambiguity. Not all vulnerabilities are critical. Some might affect features you don’t use or require conditions that don’t apply to your environment. But distinguishing signal from noise requires context and time, both of which are in short supply.
Even when a vulnerability seems low risk, ignoring it feels uncomfortable. Teams worry about what might happen if they get it wrong. The result is decision paralysis: spending more time debating than acting. The sheer number of decisions to be made, combined with the fear of missing something important, turns every triage session into a stressful guessing game.
Upgrades: The Only Available Solution
In the end, fixing most vulnerabilities means doing one thing: upgrading. For deeply embedded issues, there’s no patch to apply and no easy workaround. You have to wait for the upstream maintainers to release a new version, and then you have to adopt it.
This is the only reliable path forward - but it’s rarely easy.
But Upgrading is Scary
Upgrading a library is not like flipping a switch. It comes with real risks: breaking changes, regressions, incompatibilities. A new version might require rewriting parts of your codebase or pulling in new versions of other dependencies - which, in turn, might conflict with others. That upgrade ripple effect makes even small changes dangerous.
Major version upgrades often require painful migrations, with updated APIs, deprecated functionality, and uncertain behavior. And when libraries don’t maintain backward compatibility - which is common - teams are forced to choose between staying secure and staying stable. It's no surprise that many avoid upgrades as long as they can. But this only compounds the risk over time.
For a deeper dive into why upgrades are hard, this breakdown [link to why upgrades are so hard] explains the many hidden costs and complexities involved.
Does it Have to Feel like Mopping an Ocean?
The scale of open source is what makes it powerful - and what makes it hard to manage. There’s no end to the vulnerabilities, and no pause in the flow of new ones. Trying to “upgrade everything” is like trying to mop an ocean. You can’t win by brute force.
But that doesn’t mean it’s hopeless. The way forward is through better tooling, smarter automation, and security practices that are built to last. These elements reinforce each other: strong automation handles the bulk of issues automatically, leaving fewer, more manageable decisions that require human prioritization. This balance is what makes the entire process sustainable over time.
Perfection is off the table. But progress - continuous, steady progress - is not only possible, it’s necessary.