CI/CD-Runner absichern ist kein Sicherheits-Hack, sondern eine nachhaltige Betriebsaufgabe: Runner ziehen Quellcode, bauen Artefakte und haben häufig Zugriff auf Credentials, Caches und das interne Netzwerk. Für Administratoren und Operatoren ist entscheidend, Angriffsflächen messbar zu reduzieren und klare Prüf- und Rückfallpfade zu haben. Dieser Leitfaden liefert konkrete Maßnahmen, Prüfschritte und Troubleshooting für Credential-Isolation, robustes Workspace-Cleanup und Schutz der Build‑Kette.
Warum Runner ein kritischer Angriffsvektor sind
Runner sind Ausführungsumgebungen für CI/CD-Jobs (Builds, Tests, Packaging). Ein kompromittierter Runner kann:
- Secrets exfiltrieren (Tokens, SSH-Keys, Cloud-Credentials).
- Artefakte verändern oder manipuliert signieren.
- Cache-Poisoning durchführen und dadurch nachfolgende Builds beeinflussen.
- Pivoting ins interne Netzwerk ermöglichen.
Wichtige Unterscheidung: trusted-Builds (z. B. geschützte Branches oder Releases) versus untrusted-Builds (forks, externe PRs, öffentliche Contributions). Für untrusted Builds muss die Betriebsannahme gelten: der Job ist potentiell bösartig.
Grundprinzipien: Minimalrechte, Isolation, Nachvollziehbarkeit
Betreiben Sie Härtung entlang dreier messbarer Ziele:
- Isolationsziel: Kein Job darf State eines anderen Jobs sehen.
- Credential-Ziel: Jobs erhalten nur minimal notwendige, bevorzugt kurzlebige Credentials.
- Integritätsziel: Herkunft und Unveränderbarkeit von Abhängigkeiten und Artefakten sind nachvollziehbar.
Diese Ziele lassen sich operationalisieren, testen und auditieren.
Credential-Isolation: Umsetzung, Gründe und typische Fallen
Credential-Isolation bedeutet: keine statischen Allzweck-Tokens. Teilen Sie Identitäten nach Pipeline-Phase (Build, Package, Release, Deploy) und Kontext. Nutzen Sie kurzlebige Tokens (TTL in Minuten/Stunden) via OIDC, STS (Security Token Service) oder HashiCorp Vault-Leases. Kurzlebige Credentials begrenzen den Blast Radius bei Kompromittierung und vereinfachen Widerruf.
Technische Optionen und ihr Einsatz
OIDC (OpenID Connect) ist ein Protokoll zur Ausgabe von kurzlebigen Tokens; es verbindet CI-Systeme mit Cloud-IAM oder Vault ohne dauerhafte Secrets. KMS/HSM (Key Management Service / Hardware Security Module) speichert private Schlüssel außerhalb der Runner. Vault bietet dynamische Secrets (z. B. Datenbank-Credentials auf Lease-Basis). Jede Option hat Betriebsanforderungen: OIDC benötigt zuverlässige Token-Claims, Vault erfordert Hochverfügbarkeit und Access-Policies.
Beispiel: Vault-Policy für Package-Push
# Vault policy (HCL) - erlaubt Token zum Schreiben in ein internes Artefakt-Repo
path "secret/data/ci/artifacts/*" {
capabilities = ["create", "update", "read"]
}
Warum das funktioniert: Vault vergibt zeitlich begrenzte Tokens, und die Policy schränkt Pfade ein. Wann es scheitert: wenn Runner den Vault-Token persistieren (z. B. in Cache) oder Policies zu breit definiert sind.
Policy-begrenzte Signierung über Signierdienst
Private Signierschlüssel dürfen nicht auf normalen Runnern liegen. Ein Signierdienst (ein interner Service, der über KMS/HSM signiert) nimmt Artefakt-Hashes entgegen, prüft Policies (z. B. dass der Build von einem geschützten Branch stammt) und signiert dann. Die Signaturoperation benötigt separate Audit-Logs und strikte Authentifizierung.
CI/CD-Runner absichern: Isolation auf Infrastrukturebene
Wählen Sie Isolation nach Risiko und Wirtschaftlichkeit:
- Host-Runner: Schnell, aber nur für fully-trusted Jobs.
- Container-Runner: Gute Performance, aber nur mit rootless/strikten Mount-Policies.
- Ephemeral VM/Instance-Runner: Höchste Isolation; pro Job frische VM oder Snapshot. Kosten höher, Sicherheit am höchsten.
Ephemeral-Runner sind besonders empfehlenswert für untrusted Builds: nach Beendigung wird die Instanz zerstört, damit Persistenz nicht möglich ist.
Beispiel: Kubernetes-Runner als Ephemeral-Job
apiVersion: batch/v1
kind: Job
metadata:
name: runner-job-{{ .RunID }}
spec:
template:
spec:
securityContext:
runAsUser: 1000
runAsGroup: 1000
fsGroup: 1000
containers:
- name: builder
image: registry.internal/runner-image:stable
securityContext:
allowPrivilegeEscalation: false
capabilities:
drop: ["ALL"]
restartPolicy: Never
backoffLimit: 0
Warum das hilft: Kubernetes erlaubt Namespaces, NetworkPolicies und Pod-Security-Kontexte zur Einschränkung. Achtung: fehlerhafte RBAC- oder Volume-Einstellungen können Isolation unterwandern.
Sicheres Workspace-Cleanup: Robust und manipulationsresistent
Ein fehlerhaftes Cleanup ermöglicht Persistenz. Probleme entstehen durch offene Handles, gemountete Dateisysteme, Symlink-Tricks und restriktive ACLs. Ein robustes Cleanup implementiert mehrere Schutzschichten: dedizierte Workspaces, Ownership-Normalisierung, –one-file-system beim Löschen und Prüfläufe mit Audit-Logging.
Linux: Erweitertes Cleanup inklusive Handle-Check
#!/usr/bin/env bash
set -euo pipefail
JOB_DIR="$1"
RUNNER_UID=1001
RUNNER_GID=1001
# 1) Prozesse beenden, die in JOB_DIR arbeiten
fuser -k -TERM -m "$JOB_DIR" || true
sleep 1
fuser -k -KILL -m "$JOB_DIR" || true
# 2) Ownership und Rechte normalisieren
chown -R "${RUNNER_UID}:${RUNNER_GID}" "$JOB_DIR" 2>/dev/null || true
chmod -R u+rwX,go-rwx "$JOB_DIR" 2>/dev/null || true
# 3) Prüfen auf Mountpoints im Jobdir
mountpoints=$(findmnt -n -o TARGET --target "$JOB_DIR" || true)
if [ -n "$mountpoints" ]; then
echo "Found mounts: $mountpoints" >&2
# Option: detach mounts safely or warn and abort
fi
# 4) Löschen sicher durchführen
rm -rf --one-file-system "$JOB_DIR"
Weshalb fuser nötig ist: Offene Dateihandles verhindern Löschung; Prozesse müssen sauber beendet werden. Scheitern kann das Skript, wenn ein Job Systemprozesse gestartet hat, die das Skript nicht terminieren darf—deshalb Logging und Warnstufen wichtig.
Windows: Handles, Reboot-Plan und Antivirus-Interaktion
Auf Windows sind Locks durch Dienste und AV üblich. Ergänzen Sie Cleanup mit Handle-Checks (Sysinternals Handle/Process Explorer), Retries und einem geplanten Reboot-Pfad, falls Löschung nicht möglich ist. Bloße Retries reichen bei hartnäckigen Locks nicht immer — dokumentieren Sie einen Rollback-Pfad.
Build-Kettensicherheit: Paketquellen, Caches und Signierung
Schützen Sie die Build-Kette durch Isolation von Paketquellen, Proxys mit Allow-Lists, kontrollierte Caches und unveränderliche Artefakt-Policies.
Interne Mirrors und Egress-Restriktion
Neben Allow‑Lists für Paketendpunkte sollten Runner nur definierten Egress haben: VCS, Mirror, Artefakt-Repo, KMS/Signierdienst. Egress-ACLs reduzieren Chancen für exfiltration/Zeichen zur Command-and-Control-Infrastruktur. Testen Sie Änderungen zunächst im Monitor-Mode (nur Logging) bevor Sie blocken.
Artefakt-Repo-Hardening
Setzen Sie Write-Policies (non-overwrite), Retention-Policies und require-signed-artifact-Flags, wenn Ihr Repo das unterstützt. Audit-Logs müssen zeigen, wer wann ein Artefakt veröffentlichte. Beispielregel: „Releases dürfen nur nach Signatur durch Signierdienst veröffentlicht werden“.
Cache-Strategien gegen Poisoning
Trennen Sie Caches nach Vertrauenszonen und Projekten. Vermeiden Sie shared writable caches für untrusted Jobs. Nutzen Sie TTL-Invalidierung und verzeichnete Cache-Hashes, um Poisoning zu erkennen.
Netzwerk- und Host-Härtung: konkrete Maßnahmen
Behandeln Sie Runner wie kritische Infrastruktur-Komponenten:
- eigene Netzwerksegmente oder VLANs
- definierte Egress-ACLs
- Host-Firewall und Patchprozess
- Monitoring und zentralisierte Logs
Beispiel: einfache iptables-Regel für Egress (VM-Runner)
# Erlaube nur DNS, HTTP(S) zu mirror.example und signing.example
iptables -A OUTPUT -m owner --uid-owner runner -p udp --dport 53 -j ACCEPT
iptables -A OUTPUT -m owner --uid-owner runner -p tcp -d mirror.example --dport 443 -j ACCEPT
iptables -A OUTPUT -m owner --uid-owner runner -p tcp -d signing.example --dport 443 -j ACCEPT
iptables -A OUTPUT -m owner --uid-owner runner -j DROP
Warum das hilft: Selbst wenn ein Job versucht, bösartige Kommunikation aufzubauen, bleibt Egress begrenzt. Achtung: DNS-over-HTTPS und andere Umgehungswege können dies unterlaufen—testen und monitoren.
Testing, Audit und Validierung
Sichern Sie Maßnahmen durch automatisierte Tests und Audits:
- Regelmäßige Audit-Jobs, die versuchen, aus einem Runner heraus nicht erlaubte Aktionen durchzuführen (nur im isolierten Testnetzwerk!).
- Post-Job-Audits: Prüfe Workspace-Verbleib, offene Handles, aktive Prozesse.
- Log-Analyse: Suche nach Token-Exfiltration oder ungewöhnlichen Egress-Verbindungen.
Beispiel-Testskript: Post-Cleanup-Validation
#!/usr/bin/env bash
# Prüft, ob ein Job-Verzeichnis nach Cleanup noch existiert
JOB_DIR="$1"
if [ -e "$JOB_DIR" ]; then
echo "CLEANUP FAILED: $JOB_DIR still exists" >&2
ls -la "$JOB_DIR" >&2
exit 2
fi
# Prüfe auf aktive Prozesse des Runner-User
if pgrep -u runner >/dev/null; then
echo "ACTIVE PROCESSES FOUND" >&2
ps -u runner -o pid,cmd
exit 3
fi
exit 0
Typische Stolperfallen und Troubleshooting
1) Geheimnisse versehentlich ins Build-Log
Ursache: Debug-Prints oder fehlendes Masking. Maßnahmen: CI-Log-Masking aktivieren, Sensible Variablen nicht als Plain-Text ausgeben. Prüfen Sie Logs automatisiert auf Muster (API-Keys, Bearer-Tokens) mit einem scanner-Job.
2) Privileged Container missbraucht
Ursache: Privilegierte Container oder Durchreichen von Docker-Socket. Maßnahme: rootless-Builds, keine Host-Socket-Mounts, Nutzung von Buildkit/remote daemon. Test: Job versucht, neue Container auf Host zu starten (nur in Testumgebung!).
3) Signierschlüssel auf Runner
Ursache: Praktikabilität statt Sicherheit — Teams legen Schlüssel lokal ab. Maßnahme: Signaturdienste zentralisieren, Schlüssel nur im HSM/KMS. Rückfall: Sofort Rotation und Invalidierung aller potentiell kompromittierten Schlüssel.
Rollback- und Notfallstrategie
Führen Sie Änderungen stufenweise ein:
- Monitor-Mode: nur Logging, keine Blockade.
- Schrittweises Schließen von Egress/Policy-Bereichen.
- Parallelbetrieb alter und neuer Runner-Pools; Umschaltung per Feature-Flag/Route.
- Break-Glass-Tokens für Notfälle mit Kurzlebigkeit und Audit.
Wichtig: dokumentieren Sie die Rückrollschritte und testen Sie sie regelmäßig in einem isolierten Testlauf.
Praxis-Checkliste: Umsetzung in 90–180 Minuten
- Aktive Tokens inventarisieren und für jede Pipeline-Phase Rechte prüfen.
- Untrusted Jobs auf separate Runner-Pools oder Ephemeral-VMs migrieren.
- Cleanup-Skripte erweitern: process-kill, chown, chmod, –one-file-system, Post‑Validation.
- Signierprozess auditieren und Schlüsselbewegung in HSM/KMS planen.
- Egress-ACLs in Monitor-Mode anlegen und Traffic beobachten.
- Audit-Job: Versuche, aus Runner unautorisierte Aktionen auszuführen (isoliert).
Fazit
CI/CD-Runner absichern bedeutet, Praktikabilität mit messbarer Sicherheit zu verbinden. Priorisieren Sie Credential-Trennung nach Pipeline-Phase (mit kurzlebigen Tokens), garantiertes Workspace-Cleanup (oder Ephemeral-Runner) und Signierung über Signierdienst bzw. HSM/KMS. Ergänzen Sie das Ganze mit Egress-Restriktionen, Monitoring und regelmäßigen Audit-Tests. Mit schrittweiser Einführung, Monitor-Mode-Phasen und getesteten Rückfallpfaden bleibt Sicherheit handhabbar und betriebssicher.
FAQ
Was ist der größte Fehler beim Absichern von CI/CD-Runnern?
Reicht ein Container als Isolation für untrusted Builds?
Wie stelle ich sicher, dass Workspace-Cleanup wirklich funktioniert?
Warum darf der private Signierschlüssel nicht auf dem Runner liegen?
Wie gehe ich mit Performance-Einbußen durch stärkere Isolation um?
Welche Prüfungen sollten in einem Audit-Job für Runner enthalten sein?
CI/CD-Runner absichern: Betrieb, Monitoring und Integration
Technische Maßnahmen sind nur so gut wie ihr Betrieb. Planen Sie Monitoring, Metriken und Integrationen bereits bei der Einführung von Runner-Härtungen ein, damit Sicherheit wiederholbar und messbar bleibt.
Wichtige Metriken und Alerts:
- Cleanup-Failure-Rate: Anteil Jobs, bei denen Post-Job‑Validation fehlgeschlagen ist. Schwellenwert definieren und Alarm auslösen, bevor Aufräumdefizite zur Persistenz führen.
- Vault-Lease‑Errors und OIDC-Token‑Failures: Signalisiert Probleme bei Kurzzeit‑Credentials oder fehlerhafte Claims.
- Ungewöhnliche Egress-Verbindungen pro Runner-Pool: plötzliche Steigerungen deuten auf Exfiltration oder Umgehungsversuche hin.
- Signatur‑Anfragen pro Stunde und Signier‑Fehler: Abweichungen können auf kompromittierte Pipelines oder Policy‑Fehler hinweisen.
Integrationshinweise:
- IAM/IdP: Binden Sie CI als OAuth/OIDC-Client an bestehende Identity‑Provider (z. B. AD, Okta). So bleiben Audit und Benutzerlebenszyklus zentral steuerbar.
- Secrets-Backends: Nutzen Sie Vault/KMS dynamisch; automatisieren Sie Lease‑Erneuerung und Rotation. Dokumentieren Sie Notfall‑Rotationen und testen Sie den Key‑Revocation‑Pfad.
- Artefakt-Repository: Ergänzen Sie Signing‑Policies um Attestations (Build‑Metadaten, SBOM). Das macht Herkunft prüfbar und erleichtert Incident‑Analysen.
Runbook- und Rückfallpraxis:
- Erstellen Sie ein kurzes Runbook: Schritte zum Isolieren eines Runner‑Pools, Schlüsselrotation, Disable‑Switch für Signierdienst und Rollback auf warm‑standby‑Runner.
- Führen Sie regelmäßige Chaos‑Tests in einer Testzone durch (Cleanup-Fail, Egress-Block) und bewerten Sie Betriebsprozesse anhand konkreter SLAs.
Fazit: Betrieb und Integration sind keine Nachgedanken. Gute Metriken, automatisierte Rotation sowie abgestimmte Runbooks machen CI/CD‑Sicherheit belastbar und im Alltag handhabbar.
Für dieses Thema sind auch Supply-Chain-Security und Build-Kette Schützen wichtig. Der Beitrag ordnet diese Aspekte verständlich ein und zeigt, worauf es im Alltag ankommt.