Gestern war’s noch sicher, oder?
Security wird oft wie ein Zeitpunkt behandelt: „Wir prüfen beim Release." Doch die meisten Risiken entstehen nicht, weil neuer Code geschrieben wird, sondern weil sich unser Wissen über längst ausgelieferte Abhängigkeiten verändert. Sicherheit ist damit ein Attribut des Betriebs und nicht des Builds, und der wachsende Abstand zwischen Systemzustand und Wissensstand ist genau das, was Security Debt in der Praxis ausmacht.
Security als Zeitpunkt gedacht
Wenn ein Team ein eigenes Produkt betreibt, taucht früher oder später ein bestimmtes Muster auf. Sicherheit wird wie ein Zeitpunkt behandelt, an dem man einmal hinschaut und dann weiterarbeitet. Geprüft wird beim Release, beim Einbau eines neuen Features oder wenn jemand bewusst etwas ändert. Dazwischen gilt das System als sicher, weil sich ja nichts bewegt hat.
Diese Sicht wirkt logisch, weil sich Risiko für uns nach Veränderung anfühlt. Solange niemand Code anfasst, scheint auch nichts passieren zu können. Genau an dieser Stelle führt uns die Intuition in die Irre, denn Sicherheit hängt nicht nur davon ab, was wir zuletzt geändert haben.
Nicht der Code bewegt sich, das Wissen
Ein großer Teil der Risiken entsteht nicht dadurch, dass heute neuer Code geschrieben wird, sondern dadurch, dass sich unser Wissen über längst ausgelieferte Abhängigkeiten verändert. Der Code auf dem Server liegt still, während die Wissenslage über ihn weiterläuft. Was gestern noch unauffällig aussah, ist heute ein dokumentiertes Finding, und was heute niemand kennt, wird irgendwann als CVE, Advisory oder ganze Exploit-Klasse sichtbar.
Damit verschiebt sich die eigentliche Frage. Sie lautet nicht, ob wir seit dem letzten Release etwas geändert haben, sondern ob unser Bild von den eingesetzten Bibliotheken noch dem entspricht, was inzwischen öffentlich über sie bekannt ist. Dieser Abstand wächst von allein, auch wenn niemand am Code arbeitet.
Eine Zeitreise durch drei Lockfiles
Um das greifbar zu machen, habe ich eine kleine Security-Zeitreise für ein Node.js-Projekt gefahren. Ich habe mir die letzte `package-lock.json` aus drei aufeinanderfolgenden Jahren genommen, also die Stände von Ende 2023, Ende 2024 und Ende 2025, und diese Snapshots anschließend im Jahr 2026 mit `npm audit` gegen den heutigen Stand geprüft.
Der Trick dabei ist, dass sich an den alten Lockfiles nichts ändert. `npm audit` gleicht den festgeschriebenen Abhängigkeitsbaum gegen die aktuelle Advisory-Datenbank ab, sodass jede Prüfung dasselbe alte System betrachtet, nur mit dem Wissen von heute. Ich messe also nicht, wie sich der Code verändert hat, sondern wie sich unser Wissen über denselben Code verändert hat. Nebeneinandergestellt ergeben die drei Snapshots das folgende Bild.
Was die Zahlen wirklich sagen
Der interessante Teil ist nicht, dass die Zahlen zum jüngeren Snapshot hin kleiner werden, sondern was sie über unsere Wahrnehmung verraten. Der naheliegende Schluss wäre, dass ein System mit der Zeit unsicherer wird. Präziser ist das Gegenteil, denn die 73 Lücken im 2023er-Stand waren von Anfang an vorhanden. Es hat nur gedauert, bis sie entdeckt, reproduzierbar beschrieben und in einer Datenbank verwertbar gemacht wurden. Ein CVE ist deshalb seltener ein neues Problem als vielmehr eine neue Erkenntnis über eine alte Realität.
Warum der Abstand von allein wächst
Wenn der Code stillliegt und der Abstand trotzdem größer wird, lohnt die Frage, woher dieses Wachstum eigentlich kommt. Drei Kräfte wirken hier zusammen, und keine davon hat etwas damit zu tun, dass jemand am Produkt arbeitet. Die erste ist Aufmerksamkeit, weil ein weit verbreitetes Paket im Lauf der Zeit von immer mehr Augen gelesen, gefuzzt und auseinandergenommen wird, sodass eine lange unbemerkte Lücke irgendwann auffällt. Die zweite ist Reife der Angriffe, weil aus einer abstrakten Schwachstelle mit der Zeit ein fertiger, reproduzierbarer Exploit wird, der auch ohne tiefes Wissen anwendbar ist.
Die dritte Kraft ist die Tiefe des Abhängigkeitsbaums, und sie ist in der Praxis die unangenehmste. Ein modernes Node-Projekt bringt selten nur die paar Pakete mit, die in der `package.json` stehen, sondern mehrere Hundert transitive Abhängigkeiten, die niemand bewusst ausgewählt hat. Genau diese tiefen, nie direkt angefassten Pakete sind es, die am leisesten altern, weil niemand sie im Blick hat und ihr Risiko sich über Jahre ansammeln kann, ohne je sichtbar zu werden.
Daraus folgt eine wichtige Unterscheidung, die aus einer langen Liste von Findings erst eine Rangfolge macht. Nicht jede gemeldete Schwachstelle wiegt gleich schwer, denn es ist ein Unterschied, ob verwundbarer Code tatsächlich auf einem erreichbaren Pfad in Produktion läuft oder ob er in einem Paketteil steckt, den ihr nie aufruft. Eine kritische Lücke in einer Funktion, die euer Produkt gar nicht verwendet, ist in der Praxis weniger dringend als eine mittlere Lücke mitten im heißen Pfad. Wer das trennt, verwandelt die reine Zahl der Findings in eine Liste, die man tatsächlich abarbeiten kann.
Sicherheit ist ein Attribut des Betriebs
Genau hier liegt der Haken an einer Sicherheitsarbeit, die nur beim Release ansetzt. Sie behandelt Sicherheit als Eigenschaft des Builds, obwohl sie mindestens genauso eine Eigenschaft des Betriebs ist. Wer ausschließlich beim Release prüft, misst nicht, ob das System sicher ist, sondern ob es mit dem damaligen Wissensstand unauffällig war. In Produktion läuft dasselbe System aber Tag für Tag gegen den Wissensstand von heute.
Das erklärt auch, warum sich Sicherheitsarbeit manchmal wie ein Fass ohne Boden anfühlt. Der Grund ist nicht, dass ständig neue Fehler entstehen, sondern dass ständig neue Wahrheiten über die vorhandenen sichtbar werden. Wer diesen Mechanismus akzeptiert, hört auf, sich über den nächsten Fund zu wundern, und richtet den Betrieb darauf ein.
Security Debt, das man messen kann
Der wachsende Abstand zwischen dem, was in den eigenen Abhängigkeiten steckt, und dem, was inzwischen darüber bekannt ist, ist das, was Security Debt in der Praxis bedeutet. Solange dieser Begriff nur als Metapher im Raum steht, ändert er nichts. Nützlich wird er erst, wenn man ihn wie eine Kennzahl behandelt, die man regelmäßig abliest, statt sie einmal im Jahr zu erschrecken.
Dafür braucht es keine große Plattform, sondern einen festen Rhythmus und eine Handvoll Fragen, die man bei jeder Prüfung gleich stellt. Wie viele bekannte Lücken stecken gerade im produktiven Abhängigkeitsbaum, und wie viele davon liegen auf einem erreichbaren Pfad? Wie alt ist der älteste direkt genutzte Pflichtbaustein, den noch niemand aktualisiert hat? Und wie viel Zeit vergeht typischerweise zwischen dem Tag, an dem eine Lücke öffentlich wird, und dem Tag, an dem wir sie geschlossen haben? Diese drei Zahlen zusammen beschreiben den Abstand besser als jede einzelne, und ihre Entwicklung über die Monate zeigt, ob die Schuld wächst oder schrumpft.
Ein Gedankenspiel
Man muss keinen konkreten Vorfall bemühen, um zu sehen, wie der Mechanismus wirkt. Es genügt, ihn einmal durchzudenken. Stell dir ein kleines Produktteam vor, das sauber gelauncht hat: frischer Abhängigkeitsbaum, `npm audit` ohne Findings, und seitdem kein Grund, das Lockfile anzufassen. Nach dem Modell der Zeitreise lässt sich vorhersagen, was in einem Jahr passiert, obwohl niemand eine Zeile ändert, denn der Abstand zum Wissensstand wächst still.
Angenommen, in einer transitiven Abhängigkeit tief im Baum wird eine Lücke öffentlich. An dieser Stelle lassen sich zwei Verläufe gegenüberstellen. Ohne eingerichteten Betriebs-Check erführe das Team davon vermutlich eher zufällig, und niemand könnte auf Anhieb sagen, ob das verwundbare Paket überhaupt im eigenen Baum steckt und auf welchem Pfad. Diese Antwort zu beschaffen würde in der Hektik mehr kosten als die eigentliche Behebung.
Mit einem laufenden Check wäre die Ausgangslage eine andere, weil die Frage nach dem eigenen Baum schon beantwortet ist, bevor sie dringend wird. In beiden gedachten Verläufen geht es um dasselbe Produkt, dieselbe Lücke und dieselbe eigentliche Behebung. Der einzige Unterschied ist, ob der Abstand laufend gemessen wurde, und schon dieses eine Gedankenspiel zeigt, dass genau daran hängt, ob aus einer bekannten Lücke ein ruhiger Handgriff oder ein Notfall wird.
Was das konkret heißt
Praktisch bedeutet das, Abhängigkeiten als laufende Betriebsaufgabe zu verstehen und nicht als Projekt, das man einmal abschließt. Dazu gehört, in festem Rhythmus gegen den heutigen Wissensstand zu prüfen, die Findings nach erreichbarem Pfad zu priorisieren statt nach roher Zahl, und für den Ernstfall vorab zu klären, wer entscheidet und wie schnell ein Fix ausgerollt werden kann. Die letzte Zeile der Zeitreise ist dabei kein Beweis, dass man je fertig ist, sondern nur, dass kontinuierliche Pflege den Snapshot nah am aktuellen Wissensstand hält.
Dieser Betriebsblick steht selten allein, sondern verzahnt sich mit den Nachbarthemen. Dass ein Angriff oft schon beim lokalen Installieren eines Pakets beginnt und nicht erst in Produktion, beschreiben wir im Artikel Scannen nach dem Commit reicht nicht, und wie dasselbe laufend gepflegte Betriebswissen bei einer Störung zum Vorteil wird, zeigen wir in Ein Betriebshandbuch, das mitschreibt.
Wenn du für dein eigenes Produkt einmal ehrlich einordnen möchtest, wie groß dieser Abstand gerade ist, hilft ein strukturierter Blick von außen. Genau dafür gibt es unser kostenloses, anonymes Security Self-Assessment auf secure-vibe-coding.de, das dir zeigt, wo du stehst und welche Schritte sich als Nächstes lohnen. Wenn du die Ergebnisse lieber gemeinsam einordnen und daraus einen laufenden Betriebsprozess machen willst, sprechen wir gerne darüber.
Häufige Fragen
Wird ein System mit der Zeit unsicherer?
Nicht der Code verändert sich, sondern die Wissenslage über ihn. Viele Lücken waren längst vorhanden und werden erst später als CVE oder Advisory sichtbar. Sicherheit ist deshalb ein Attribut des Betriebs, nicht nur des Builds.
Reicht es, beim Release zu prüfen?
Nein. Wer nur beim Release prüft, misst gegen den damaligen Wissensstand. In Produktion läuft das System aber gegen den heutigen. Kontinuierliche Pflege hält den Abstand zwischen Systemzustand und Wissensstand klein.
Warum wächst der Abstand, obwohl sich am Code nichts ändert?
Weil drei Kräfte unabhängig vom Code wirken: Ein verbreitetes Paket wird mit der Zeit von mehr Leuten geprüft, aus Schwachstellen werden fertige Exploits, und tiefe transitive Abhängigkeiten altern unbemerkt, weil niemand sie direkt im Blick hat.
Sind alle gemeldeten Schwachstellen gleich dringend?
Nein. Entscheidend ist, ob verwundbarer Code auf einem tatsächlich erreichbaren Pfad in Produktion läuft. Eine kritische Lücke in einer Funktion, die ihr nie aufruft, ist weniger dringend als eine mittlere mitten im heißen Pfad. Diese Trennung macht aus einer langen Finding-Liste eine abarbeitbare Rangfolge.
Was bedeutet Security Debt konkret?
Den wachsenden Abstand zwischen dem, was in deinen Abhängigkeiten steckt, und dem, was inzwischen darüber bekannt ist. Nützlich wird der Begriff, wenn man ihn wie eine Kennzahl behandelt und regelmäßig abliest, statt ihn nur als Metapher zu benutzen.
Wie kann ich diesen Abstand selbst messen?
Richte einen festen, wiederkehrenden Lauf gegen den heutigen Stand ein, etwa wöchentlich `npm audit --omit=dev` plus einen Scanner wie `osv-scanner`, und verfolge drei Zahlen über die Zeit: offene Lücken auf erreichbarem Pfad, Alter des ältesten ungepflegten Pflichtbausteins und die Zeit vom Bekanntwerden bis zum Fix.
Ähnliche Themen
DNS wird massiv unterschätzt
Für Techies ist DNS die Schaltzentrale des Internets, für viele andere nur „dieser Eintrag in der FritzBox". Dabei hängt praktisch alles daran, denn wer den MX-Record umbiegt, fängt E-Mails ab und setzt darüber reihenweise Zugänge zurück, an denen auch MFA nichts ändert. Die eigentliche Sicherheit liegt deshalb nicht am einzelnen Login, sondern in der Kontrolle über DNS und die Zugänge, die daran hängen.
Weiterlesen →Warum „wir scannen nach dem Git Commit" für Supply Chain Security nicht reicht
Ein kompromittiertes npm-Paket wird nicht erst gefährlich, wenn es im Repository landet, sondern in dem Moment, in dem ein Entwickler es lokal installiert. Wer Supply Chain ernst nimmt, muss deshalb nicht fragen „Haben wir gescannt?", sondern „Können wir innerhalb von Minuten unseren Blast Radius bestimmen?", und das ist eine organisatorische Frage, keine reine Tool-Frage.
Weiterlesen →