Verbirgt Ihre Lockfile Schwachstellen?
Eine Lockfile ist das ehrlichste Dokument in Ihrem Repository: Sie listet die genaue Version jedes Pakets auf, das Ihr Build tatsächlich installiert — keine Bereiche, kein „latest“, keine Überraschungen. Sie ist außerdem, leise, eine Liste der Angriffsfläche — jede gepinnte Version ist eine Version, in der jemand seit dem Pinnen ein Loch gefunden haben könnte. Dieser Artikel erklärt, wie ein Scanner diese Liste in Antworten verwandelt: wie die OSV-Datenbank Versionen mit bekannten Schwachstellen abgleicht, warum eine CISA-KEV-Kennzeichnung mehr zählt als ein CVSS-Score und warum „keine Schwachstellen gefunden“ eine Aussage über eine Datenbank ist, nicht über Ihren Code. Sie können die Prüfung selbst im SBOM Vulnerability Scanner ausführen, der Ihre Lockfile im Browser parst und sie niemals hochlädt.
Was eine Lockfile pinnt — und warum sie die Angriffsfläche ist
Moderne Software besteht größtenteils aus dem Code anderer Leute. Eine typische Webanwendung zieht Hunderte von Paketen heran, und jedes davon zieht weitere nach sich: Eine direkte Abhängigkeit von einem Web-Framework kann leicht zu zweihundert transitiven Paketen werden, die Sie nie gewählt und nie geprüft haben. Die Lockfile ist der Nachweis dieses Baums — package-lock.json für npm, eine vollständig gepinnte requirements.txt für Python, go.mod und go.sum für Go — niedergeschrieben, damit jede Installation, auf jeder Maschine, denselben Baum erzeugt. Ohne sie ist „funktioniert auf meiner Maschine“ eine Hoffnung, keine Tatsache.
Dieselbe Exaktheit macht die Lockfile zum richtigen Ort, um nach bekannten Schwachstellen zu suchen. Eine Schwachstellendatenbank ist nach Paketname, Ökosystem und exakter Version indiziert: lodash 4.17.20 ist verwundbar, lodash 4.17.21 ist es nicht, und der Unterschied ist eine einzige Abfrage. Ein schwebender Bereich lässt sich so nicht beurteilen — der Scanner müsste raten, welche Version Sie tatsächlich installiert haben, und Raten ist keine Sicherheitspraxis. Die erste Regel der Lockfile-Hygiene ist also unspektakulär und nicht verhandelbar: Committen Sie die Lockfile, halten Sie sie gepinnt und scannen Sie den gepinnten Baum, nicht die Wunschliste in Ihrem Manifest.
Wie OSV Versionen mit bekannten Schwachstellen abgleicht
OSV.dev ist eine öffentliche Schwachstellendatenbank, die Advisories von GitHub, der NVD und den Sprach-Ökosystemen in einem abfragbaren Index zusammenführt. Ein Scanner sendet ihr einen Stapel von Tripeln aus Name, Ökosystem und Version — lodash, npm, 4.17.20 — und erhält die Schwachstellen-IDs zurück, die genau diese Version betreffen. Die IDs werden dann vollständig abgerufen: eine Zusammenfassung, die betroffenen Bereiche mit ihren behobenen Versionen, die Schwere als CVSS-Vektor und die CVE-Aliase. Nichts über Ihr Projekt reist mit der Abfrage mit — nur die öffentlichen Koordinaten öffentlicher Pakete.
Der Abgleich ist bewusst dumm, und das ist seine Stärke. Er liest Ihren Code nicht, beurteilt nicht, ob Sie die verwundbare Funktion aufrufen, und kümmert sich nicht darum, wie das Paket verwendet wird. Wenn das Advisory sagt, dass Versionen vor 4.17.21 betroffen sind und Sie 4.17.20 pinnen, treffen Sie zu — auch wenn Ihr Code die verwundbare Funktion nie berührt. Diese Übermeldung ist ein Feature: Erreichbarkeitsanalyse ist eine schwierigere, langsamere Frage, und die billige Frage („Ist diese Version bekanntermaßen schlecht?“) erwischt bereits die Abhängigkeit, die Sie vor drei Jahren zu aktualisieren vergessen haben.
Was der Scanner nicht sehen kann
Eine Prüfung per Versionsabgleich hat eine harte Grenze, und es lohnt sich, sie offen auszusprechen: Sie kann nur Schwachstellen finden, die jemand bereits gemeldet hat, für eine Version, die die Datenbank kennt. Eine Schwachstelle, die gestern entdeckt und noch nicht veröffentlicht wurde, ist unsichtbar. Ein Paket, das nie verwundbar, aber bösartig war — ein Typosquat eines beliebten Namens, ein kompromittiertes Release, eine Abhängigkeit, die nach Hause telefoniert — hat überhaupt keine CVE, und kein Scanner dieser Art wird es melden. Dasselbe gilt für Ihren eigenen Code: Der Scanner beurteilt die Pakete, die Sie installieren, nicht den Code, den Sie schreiben.
Die Grenze ist der Grund, warum das Ergebnis „keine Schwachstellen gefunden“ sorgfältig gelesen werden muss. Es bedeutet: Für diese genauen Versionen, in dieser Datenbank, in diesem Moment, ist nichts verzeichnet. Es ist ein nützliches Negativ — ein sauberer Scan einer frischen Lockfile ist wirklich eine gute Nachricht — aber es ist kein Zertifikat. Die Verteidigungen gegen das, was der Scanner nicht sehen kann, sind andere Werkzeuge: neue Abhängigkeiten zu pinnen und zu prüfen, bevor sie in den Baum gelangen, kontinuierlich auf neue Advisories zu achten statt vierteljährlich, und ein plötzliches neues Release eines ruhigen Pakets mit Misstrauen zu betrachten. Der Scanner ist der Rauchmelder, nicht die Feuerwehr.
Warum eine KEV-Kennzeichnung mehr zählt als ein hoher CVSS-Score
Ein CVSS-Score beantwortet eine hypothetische Frage: Wie schlimm wäre diese Schwachstelle, wenn jemand sie ausnutzte? Der Katalog bekannter ausgenutzter Schwachstellen (Known Exploited Vulnerabilities) der CISA beantwortet eine Tatsache: Wird sie gerade jetzt, in freier Wildbahn, von jemandem ausgenutzt? Die beiden Antworten stimmen routinemäßig nicht überein. Eine Schwachstelle mit 9,8 Punkten, die niemand weaponisiert hat, kann bis zum nächsten geplanten Upgrade warten; eine Schwachstelle mit 5,3 Punkten, die auf der KEV-Liste steht — mit einem von der CISA gesetzten Fälligkeitsdatum für die Behebung — verdient einen Patch noch diese Woche, weil der Exploit bereits existiert und bereits im Einsatz ist.
Diese Umkehrung ist der Grund, warum der Scanner KEV-Zeilen separat kennzeichnet, statt sie in die Schwere-Sortierung einzufalten. Die Sortierreihenfolge sagt Ihnen, was schlimm ist; die KEV-Kennzeichnung sagt Ihnen, was dringend ist. In der Praxis ist die Triage kurz: Patchen Sie zuerst die KEV-Einträge, dann die kritischen mit einer veröffentlichten behobenen Version, und planen Sie den Rest mit dem nächsten Upgrade-Zyklus. Das Bulk CVE Triage-Desk auf dieser Website setzt dieselben CVEs in den Ausnutzungskontext — KEV-Status, EPSS-Wahrscheinlichkeit und CVSS zusammen — wenn eine einzelne Kennzeichnung nicht ausreicht, um die Arbeit gegenüber einem Team zu begründen.
Committen Sie die Lockfile, scannen Sie sie in der CI — nicht einmal im Quartal
Eine Lockfile, die nicht committet ist, ist eine Lockfile, die nicht existiert. Wenn sie nur auf der Maschine eines Entwicklers lebt, installiert jede andere Maschine, was „latest“ an diesem Tag gerade auflöst, und der Baum, den Sie gescannt haben, ist nicht der Baum, den Sie ausliefern. Sie zu committen ist die billigste Supply-Chain-Kontrolle, die es gibt: Sie macht Installationen reproduzierbar, macht die Antworten des Scanners für alle wahr und verwandelt ein Abhängigkeits-Upgrade in einen prüfbaren Diff statt in eine stille Drift.
Die zweite Hälfte ist die Kadenz. Schwachstellen werden jeden Tag veröffentlicht, also ist ein Scan, der einmal im Quartal läuft, eine Momentaufnahme, die in Tagen altert. Die nützliche Form ist ein Scan bei jedem Pull Request, der die Lockfile berührt, plus ein geplanter Scan des Main-Branches — dieselbe Schleife wie eine Test-Suite, mit derselben Eigenschaft: Ein neues Advisory macht einen grünen Build an dem Tag rot, an dem es veröffentlicht wird, wenn die Behebung ein Versions-Bump ist, nicht eine Post-Incident-Review. Der Browser-Scanner auf dieser Website ist die manuelle Version dieser Schleife: Fügen Sie die Lockfile nach einem Dependabot-Bump oder vor einem Release ein und bestätigen Sie den Baum, den Sie gleich ausliefern.
Behobene Versionen, Breaking Changes und wann man patcht statt pinnt
Jeder Treffer in einem Scan trägt eine behobene Version — das erste Release, in dem die Schwachstelle verschwunden ist — oder ein ehrliches „keine veröffentlicht“. Der übliche Fall ist ein Patch- oder Minor-Release, und das Upgrade ist eine einzeilige Änderung in der Lockfile. Aber eine behobene Version ist nicht immer eine sichere Version zum Übernehmen: Ein Major-Versionssprung kann Verhalten ändern, von dem Ihr Code abhängt, und eine Behebung, die gestern veröffentlicht wurde, hatte einen Tag Praxistest. Die Abwägung ist dieselbe wie bei jedem Abhängigkeits-Upgrade: Lesen Sie das Changelog, lassen Sie die Tests laufen und aktualisieren Sie zuerst die Pakete, die Sie tatsächlich importieren.
Wenn es keine behobene Version gibt, verengen sich die Optionen auf drei: Entfernen Sie die Abhängigkeit, wenn nichts sie braucht, ersetzen Sie sie durch eine gepflegte Alternative oder entschärfen Sie den verwundbaren Codepfad — übergeben Sie keine nicht vertrauenswürdigen Eingaben mehr an die betroffene Funktion oder stellen Sie den Aufruf hinter eine Prüfung, die das Advisory beschreibt — und beobachten Sie das Advisory auf ein Update. Was Sie nicht tun sollten, ist, die verwundbare Version zu pinnen und sie zu vergessen: Ein Pin ist eine Entscheidung, und er verdient einen Kommentar in der Lockfile oder im Issue-Tracker, der sagt, warum, und ein Datum, um ihn erneut zu prüfen. Scannen Sie nach jeder Änderung erneut; der Scanner braucht Sekunden, und ein zweiter Scan ist der einzige Beweis dafür, dass die Befunde des ersten Scans verschwunden sind.