It was secure yesterday, wasn’t it?
Security is often treated as a point in time: “We check at release.” Yet most risks do not arise because new code is written, but because what we know about dependencies shipped long ago changes. Security is therefore an attribute of operations, not of the build, and the growing gap between the state of the system and the state of knowledge is exactly what security debt amounts to in practice.
Security thought of as a point in time
When a team runs a product of its own, a certain pattern appears sooner or later. Security is treated like a point in time, when you look once and then carry on working. Checks happen at release, when a new feature is built in or when someone deliberately changes something. In between, the system counts as secure, because nothing has moved.
This view seems logical, because to us risk feels like change. As long as nobody touches the code, nothing seems able to happen. This is exactly where intuition leads us astray, because security does not only depend on what we changed last.
It is not the code that moves, it is the knowledge
A large share of the risks does not arise because new code is written today, but because what we know about dependencies shipped long ago changes. The code on the server sits still, while knowledge about it keeps moving. What looked unremarkable yesterday is a documented finding today, and what nobody knows about today will at some point become visible as a CVE, an advisory or an entire class of exploits.
That shifts the real question. It is not whether we have changed anything since the last release, but whether our picture of the libraries we use still matches what has since become public knowledge about them. This gap grows on its own, even when nobody works on the code.
A journey through three lockfiles
To make this tangible, I took a small security journey through time for a Node.js project. I took the last `package-lock.json` from three consecutive years, that is the states at the end of 2023, the end of 2024 and the end of 2025, and then checked these snapshots in 2026 with `npm audit` against today’s state.
The trick is that nothing changes in the old lockfiles. `npm audit` compares the pinned dependency tree against the current advisory database, so every check looks at the same old system, only with today’s knowledge. So I am not measuring how the code has changed, but how our knowledge about the same code has changed. Side by side, the three snapshots give the following picture.
What the numbers really say
The interesting part is not that the numbers get smaller towards the more recent snapshot, but what they reveal about our perception. The obvious conclusion would be that a system becomes less secure over time. The more precise reading is the opposite: the 73 vulnerabilities in the 2023 state were there from the start. It just took time until they were discovered, described reproducibly and made usable in a database. A CVE is therefore less often a new problem than a new insight into an old reality.
Security is an attribute of operations
This is exactly the catch with security work that only starts at release. It treats security as a property of the build, although it is at least as much a property of operations. Anyone who only checks at release is not measuring whether the system is secure, but whether it looked unremarkable with the knowledge of the time. In production, however, the same system runs day after day against today’s knowledge.
This also explains why security work sometimes feels like a bottomless pit. The reason is not that new bugs keep appearing, but that new truths about the existing ones keep coming to light. Once you accept this mechanism, you stop being surprised by the next finding and set up operations for it.
What this means in practice
In practice this means checking and updating dependencies regularly rather than only at releases, keeping an eye on the versions in use, and seeing updates as an ongoing operational task rather than a project you complete once. The last row of the journey is no proof that you are ever done, only that continuous care keeps the snapshot close to the current state of knowledge.
And exactly this growing gap between what is in your own dependencies and what has since become known about them is what security debt means in practice. It piles up quietly as long as nobody looks, and only shrinks if you pay it down regularly.
If you want to take an honest look at how big this gap is for your own product right now, a structured view from outside helps. That is exactly what our free, anonymous security self-assessment at secure-vibe-coding.de is for: it shows you where you stand and which steps are worth taking next.
Frequently asked questions
Does a system become less secure over time?
It is not the code that changes, but the knowledge about it. Many vulnerabilities were there all along and only become visible later as a CVE or advisory. Security is therefore an attribute of operations, not only of the build.
Is it enough to check at release?
No. Anyone who only checks at release measures against the knowledge of the time. In production, however, the system runs against today’s. Continuous care keeps the gap between the state of the system and the state of knowledge small.
What does security debt mean in concrete terms?
The growing gap between what is in your dependencies and what has since become known about them. Regular updates keep this debt small instead of letting it pile up unnoticed.
How can I measure this gap myself?
A good start is to check old lockfiles with `npm audit` against today’s advisories and to plan updates as an ongoing operational task instead of only looking at releases. That shows you how much knowledge has built up since the last deliberate look.
Related topics
DNS is massively underestimated
For techies, DNS is the control centre of the internet; for many others it is just “that setting in the router”. Yet practically everything depends on it: whoever redirects the MX record intercepts email and can use it to reset one account after another, and MFA does nothing to stop that. Real security therefore does not sit at the individual login, but in control over DNS and the accounts that hang off it.
Read more →Why “we scan after the git commit” is not enough for supply chain security
A compromised npm package does not become dangerous when it lands in the repository, but the moment a developer installs it locally. Anyone who takes the supply chain seriously should therefore not ask “Did we scan?” but “Can we determine our blast radius within minutes?”, and that is an organisational question, not merely a tooling one.
Read more →