Was Ihre Pipeline tatsächlich prüfen kann (mehr als nur Sicherheitsscans)
Wenn die meisten Teams beginnen, Prüfungen in ihre Deployment-Pipeline einzubauen, denken sie zuerst an das Security-Scanning des Anwendungscodes. Ein SAST-Tool ausführen, ein paar Schwachstellen finden, fertig. Aber wenn man sich ansieht, was tatsächlich durch Ihre Pipeline fließt, gibt es viele weitere Dinge, die eine Prüfung wert sind – und einige davon bewahren Sie vor Problemen, die ein reiner Code-Scan nicht erkennen kann.
Moderne Softwareauslieferung bewegt mehr als nur Quellcode. Sie bewegt Abhängigkeitslisten, Container-Images, Infrastrukturdefinitionen, Konfigurationsdateien und Zugangsdaten. Jedes dieser Artefakte birgt eigene Risiken. Eine Pipeline, die nur den Anwendungscode scannt, lässt den Großteil der Angriffsfläche ungeprüft.
Hier sind die Arten von Prüfungen, die Sie in Ihrer Pipeline ausführen können, was sie erkennen und wann sie sinnvoll sind.
Dependency-Scanning
Kaum eine Anwendung wird heute noch komplett neu geschrieben. Ihr Projekt bezieht Bibliotheken von npm, PyPI, Go Modules, NuGet oder Maven. Jede dieser Abhängigkeiten ist Code, den jemand anderes geschrieben hat, und dieser Code kann öffentlich bekannte Schwachstellen enthalten.
Dependency-Scanning gleicht Ihre Abhängigkeitsliste mit Schwachstellendatenbanken ab. Es zeigt Ihnen, ob eine Ihrer Bibliotheken bekannte Sicherheitsprobleme in der von Ihnen verwendeten Version aufweist. Dabei geht es nicht um die Suche nach Zero-Days, sondern darum, die bereits dokumentierten Schwachstellen zu erkennen, für die es oft schon Patches gibt.
Führen Sie diesen Scan immer dann aus, wenn sich Ihre Abhängigkeitsdatei ändert – package.json, go.mod, requirements.txt oder was auch immer Ihr Ökosystem verwendet. Führen Sie ihn mindestens einmal während der Build-Phase aus. Wenn Sie ihn nur bei Pull Requests ausführen, übersehen Sie möglicherweise eine Schwachstelle, die durch das direkte Mergen eines Dependency-Updates in den Hauptbranch eingeschleppt wurde.
Hier ist ein minimales YAML-Snippet für einen GitHub Actions-Job, der npm audit ausführt und die Pipeline abbricht, wenn eine Schwachstelle mit hohem Schweregrad gefunden wird:
name: dependency-scan
on:
pull_request:
paths:
- 'package.json'
- 'package-lock.json'
jobs:
audit:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: '20'
- run: npm audit --audit-level=high
Container-Image-Scanning
Wenn Sie Ihre Anwendung als Container-Image ausliefern, enthält dieses Image mehr als nur Ihren Code. Es enthält ein Basis-Image, eine Betriebssystemschicht, Systembibliotheken und Binärdateien, die Sie nicht geschrieben haben. Eine Schwachstelle im Basis-Image wirkt sich genauso auf Ihre Anwendung aus wie eine Schwachstelle in Ihrem eigenen Code.
Container-Image-Scanning untersucht den gesamten Image-Inhalt, einschließlich der Betriebssystempakete und installierten Bibliotheken. Es erkennt Dinge wie eine verwundbare Version von OpenSSL im Basis-Image oder einen bekannten Exploit in einem Systemdienstprogramm, das Ihre Anwendung nie direkt aufruft, aber dennoch in der Laufzeitumgebung vorhanden ist.
Der richtige Zeitpunkt für diesen Scan ist direkt nach dem Bau des Images, bevor es in die Registry gepusht oder irgendwo deployed wird. Sobald das Image in der Produktion ist, ist ein Scan zwar noch für die Transparenz nützlich, aber der Schaden ist bereits möglich.
Infrastructure-as-Code-Scanning
Wenn Sie Infrastructure as Code mit Terraform, CloudFormation oder Pulumi schreiben, definieren Sie Cloud-Ressourcen in Textdateien. Diese Dateien können Fehlkonfigurationen enthalten, die Sicherheitslücken öffnen: öffentlich zugängliche Storage-Buckets, Datenbanken, die dem Internet ausgesetzt sind, deaktivierte Verschlüsselung oder übermäßig permissive IAM-Rollen.
IaC-Scanning prüft Ihre Infrastrukturdefinitionen auf Sicherheitsbest Practices, bevor Sie sie anwenden. Es ist kein Ersatz für Cloud-Sicherheitsmanagement-Tools, die laufende Umgebungen scannen. Es ist eine präventive Prüfung, die Probleme erkennt, bevor sie zu deployed Ressourcen werden.
Führen Sie diesen Scan aus, wenn jemand einen Pull Request eröffnet, der Infrastrukturcode ändert. Das ist der Punkt, an dem Sie die Konfiguration noch korrigieren können, ohne eine fehlkonfigurierte Ressource bereinigen zu müssen, die bereits läuft.
Secret-Scanning
Entwickler committen versehentlich häufiger Secrets in Repositories, als Teams zugeben möchten. API-Schlüssel, Datenbankpasswörter, SSH-Private-Keys und Service-Account-Tokens landen in Code, Konfigurationsdateien oder Commit-Nachrichten. Einmal in der Repository-Historie, ist das Entfernen schwierig, da es im Git-Verlauf lebt.
Secret-Scanning erkennt Muster, die wie Zugangsdaten aussehen: Zeichenfolgen, die dem Format von AWS Access Keys, GitHub-Tokens, Slack-Webhooks oder generischen Passwörtern entsprechen. Es markiert sie, bevor der Commit den Hauptbranch erreicht.
Dieser Scan ist am effektivsten, wenn er bei jedem Commit oder zumindest bei jedem Pull Request ausgeführt wird. Je früher Sie ein durchgesickertes Secret erkennen, desto geringer ist die Gefährdung. Wenn Sie erst nach dem Merge scannen, war das Secret bereits im Repository und jeder mit Zugriff hätte es abrufen können.
Lizenz-Scanning
Jede von Ihnen verwendete Abhängigkeit hat eine Lizenz. Einige Lizenzen verlangen, dass Sie eine Namensnennung angeben. Andere schränken die kommerzielle Nutzung ein oder verlangen, dass Sie Ihren eigenen Code Open Source stellen, wenn Sie sie verwenden. Lizenz-Scanning prüft die Lizenzen aller Ihrer Abhängigkeiten gegen die Richtlinien, die Ihr Team oder Ihre Organisation definiert hat.
Dies ist keine Sicherheitsprüfung, aber eine rechtliche und Compliance-Prüfung, die eine Veröffentlichung blockieren kann, wenn sie ignoriert wird. Viele Teams führen Lizenz-Scanning zusammen mit Dependency-Scanning durch, da beide dieselben Quelldaten verwenden – Ihre Liste der Abhängigkeiten.
Policy as Code
Policy as Code ist keine einzelne Scan-Art. Es ist eine Methode, Regeln zu kodieren und programmatisch in Ihrer Pipeline durchzusetzen. Anstatt sich auf einen vorgefertigten Scanner zu verlassen, definieren Sie Ihre eigenen Prüfungen: „Jede Datenbankänderung muss von einem DBA überprüft werden“, „Jedes Container-Image muss aus einer genehmigten Registry stammen“, „Jedes Deployment in die Produktion muss einen bestandenen Lasttest haben.“
Diese Regeln werden als Code geschrieben und automatisch in der Pipeline ausgeführt. Policy as Code gibt Ihnen die Flexibilität, das durchzusetzen, was in Ihrem Kontext relevant ist, ohne darauf warten zu müssen, dass ein Anbieter eine Funktion hinzufügt.
Auswahl, was und wann ausgeführt werden soll
Nicht jede Prüfung muss in jeder Phase laufen. Einige sind günstig genug, um bei jedem Commit ausgeführt zu werden. Andere sind langsamer und machen bei Pull Requests oder vor dem Deployment mehr Sinn. Der Schlüssel liegt nicht darin, alles überall auszuführen, sondern jede Prüfung an dem Punkt zu platzieren, an dem sie den größten Nutzen bei geringster Reibung bietet.
Hier ist ein praktischer Ausgangspunkt:
- Jeder Commit: Secret-Scanning, Dependency-Scanning (wenn sich die Abhängigkeitsdatei geändert hat)
- Pull Request: IaC-Scanning, Lizenz-Scanning, Container-Image-Scanning (wenn das Image neu gebaut wurde)
- Vor dem Deployment: Container-Image-Scanning (falls noch nicht geschehen), Policy-as-Code-Prüfungen
Eine kurze Checkliste für Ihre Pipeline
- Dependency-Scanning läuft, wenn sich Abhängigkeitsdateien ändern
- Container-Images werden gescannt, bevor sie die Registry erreichen
- Infrastrukturcode wird gescannt, bevor er angewendet wird
- Secrets werden erkannt, bevor sie den Hauptbranch erreichen
- Die Lizenzkonformität wird für jede Abhängigkeit geprüft
- Benutzerdefinierte Richtlinien werden als Code durchgesetzt, nicht als manuelle Tore
Die konkrete Erkenntnis
Eine Pipeline, die nur den Anwendungscode scannt, prüft eine Schicht eines mehrschichtigen Auslieferungsprozesses. Ihre Abhängigkeiten, Container, Infrastrukturdefinitionen und Zugangsdaten bergen alle Risiken. Fügen Sie Prüfungen für jeden Artefakttyp am richtigen Punkt in der Pipeline hinzu. Das Ziel ist nicht, jede Änderung zu blockieren, sondern Probleme früh genug zu erkennen, sodass die Behebung noch günstig ist.