Zum Inhalt springen

Services, Wiki-Artikel und Blog-Beiträge durchsuchen

↑↓NavigierenEnterÖffnenESCSchließen
CI/CD Pipeline Sicherheit: DevSecOps in der Praxis - Illustration zu DevSecOps und sicherer Softwareentwicklung
Security Operations

CI/CD Pipeline Sicherheit: DevSecOps in der Praxis

CI/CD-Sicherheit: SAST, SCA, Secrets-Scanning in GitHub Actions, GitLab CI und Jenkins - Least-Privilege-Tokens und Supply-Chain-Schutz.

Vincent Heinen Abteilungsleiter Offensive Services
11 Min. Lesezeit
OSCP+ OSCP OSWP OSWA

TL;DR

Supply-Chain-Angriffe wie SolarWinds und XZ Utils beweisen: Wer die CI/CD-Pipeline kompromittiert, kontrolliert den gesamten ausgelieferten Code. Dieser Artikel zeigt, wie Sie GitHub Actions, GitLab CI und Jenkins absichern - konkret mit commit-hash-gepinnten Actions statt mutierbaren Tags, OIDC-basierter AWS-Authentifizierung ohne langlebige Access Keys sowie integrierten Scan-Stufen: Semgrep für SAST, Trivy für Container-Images und Dependabot für Dependency-Updates. Statische Credentials in Pipeline-Konfigurationen gehören eliminiert; stattdessen holen laufzeitgebundene Vault-Integrationen Secrets erst beim Ausführen.

Diese Zusammenfassung wurde KI-gestützt erstellt (EU AI Act Art. 50).

Inhaltsverzeichnis (5 Abschnitte)

Die CI/CD-Pipeline ist das Herzstück moderner Softwareentwicklung - und ein attraktives Ziel für Angreifer. Wer die Pipeline kontrolliert, kontrolliert den Code der in Produktion geht. SolarWinds, 3CX, XZ Utils - Supply-Chain-Angriffe über Build-Systeme sind keine Ausnahme mehr, sondern eine etablierte Angriffskategorie.

Warum CI/CD ein Sicherheitsrisiko ist

Angriffsszenarien auf CI/CD-Systeme:

  1. Geheimnisdiebstahl aus Pipeline-Logs:

    • Entwickler printed versehentlich: echo $PROD_API_KEY
    • CI-Log ist 90 Tage öffentlich sichtbar (bei Public Repos!)
    • Oder: Secrets in Umgebungsvariablen landen in Core Dumps
  2. Dependency Confusion / Typosquatting:

    • npm install firma-internal-lib
    • Angreifer registriert "firma-internal-lib" auf npm.org mit höherer Version
    • npm bevorzugt öffentliches Registry → Malware-Paket installiert
    • SolarWinds-Prinzip: über Lieferant einschleusen
  3. Kompromittierter Third-Party Action:

    • GitHub Actions: uses: actions/checkout@v4
    • Wenn "actions/checkout" Repository kompromittiert wird...
    • ODER: @v4 Tag zeigt auf beliebigen Commit (Tags sind mutable!)
    • Schutz: uses: actions/checkout@SHA (commit hash, immutable!)
  4. CI/CD-Server selbst kompromittiert:

    • Jenkins ohne Authentifizierung: öffentlich erreichbar
    • Angreifer baut bösartige Pipeline → Credentials aus Vault gestohlen
    • Code-Injection in Build-Artifacts
  5. Überprivilegierte Service Accounts:

    • CI-Token hat Schreibrechte auf ALLE Repositories
    • Oder: Deployment-Account hat Production-Admin-Rechte
    • Least-Privilege verletzt → Blast Radius riesig

Secrets Management in Pipelines

Anti-Pattern - was NIEMALS tun:

# FALSCH: Direktes Einchecken in Pipeline-Config
env:
  DATABASE_URL: "postgresql://user:password123@db.firma.de/prod"
  AWS_ACCESS_KEY: "AKIA..."
# FALSCH: Hartcoded in Script
aws s3 cp output/ s3://bucket/ --profile myprofile
# (Credentials im ~/.aws/credentials im Build-Agent)
// FALSCH: In Test-Config-Datei committed
// test/config.js
const apiKey = "sk-prod-12345...";

Richtig: GitHub Actions Secrets

GitHub Repository - Settings - Secrets and variables - Actions

.github/workflows/deploy.yml:

jobs:
  deploy:
    runs-on: ubuntu-latest
    steps:
      - name: Deploy to AWS
        env:
          AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }}
          AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
        run: |
          aws s3 sync ./dist s3://my-bucket

OIDC statt statische Credentials (Best Practice!)

  • AWS OIDC Identity Provider: kein AWS Access Key mehr nötig!
  • GitHub Actions beweist Identität via OIDC Token
  • AWS gibt temporäre Credentials aus (für 1 Stunde)

.github/workflows/deploy-oidc.yml:

jobs:
  deploy:
    permissions:
      id-token: write  # OIDC Token anfordern
      contents: read
    steps:
      - name: Configure AWS Credentials via OIDC
        uses: aws-actions/configure-aws-credentials@v4
        with:
          role-to-assume: arn:aws:iam::123456789:role/GitHubActionsRole
          aws-region: eu-central-1
      - name: Deploy
        run: aws s3 sync ./dist s3://my-bucket

Vorteil: kein langlebiger AWS-Key, automatisch rotierend, GitHub-Repository-gebunden

HashiCorp Vault Integration:

# Pipeline holt Secrets zur Laufzeit:
- name: Get Secrets from Vault
  id: secrets
  uses: hashicorp/vault-action@v3
  with:
    url: https://vault.firma.de
    method: jwt
    role: ci-deploy-role
    secrets: |
      secret/data/production/db password | DB_PASSWORD ;
      secret/data/production/api key | API_KEY

- name: Deploy
  env:
    DB_PASSWORD: ${{ steps.secrets.outputs.DB_PASSWORD }}
  run: ./deploy.sh

Security Scanning in der Pipeline

SAST (Static Application Security Testing)

Semgrep - schnell, open source:

# GitHub Actions:
- name: Run Semgrep
  uses: semgrep/semgrep-action@v1
  with:
    config: >
      p/owasp-top-ten
      p/secrets
      p/dockerfile
  env:
    SEMGREP_APP_TOKEN: ${{ secrets.SEMGREP_APP_TOKEN }}
# Lokal testen:
semgrep --config "p/owasp-top-ten" src/

Bandit (Python):

pip install bandit
bandit -r src/ -ll -ii  # Nur HIGH Confidence, HIGH Severity

ESLint Security Plugin (JavaScript/TypeScript):

npm install --save-dev eslint-plugin-security
{
  "plugins": ["security"],
  "extends": ["plugin:security/recommended"]
}

SCA (Software Composition Analysis) - Dependency Scanning

Dependabot (GitHub native, kostenlos):

# .github/dependabot.yml:
version: 2
updates:
  - package-ecosystem: "npm"
    directory: "/"
    schedule:
      interval: "weekly"
    ignore:
      - dependency-name: "lodash"  # Falls bekannte Breaking Changes
        versions: ["4.x"]
  - package-ecosystem: "docker"
    directory: "/"
    schedule:
      interval: "weekly"

Trivy (Aqua Security, open source):

# Container Image scannen:
trivy image --severity CRITICAL,HIGH --exit-code 1 \
  --ignore-unfixed my-app:latest

# Filesystem scannen (vor Build):
trivy fs --severity CRITICAL,HIGH --exit-code 1 .
# GitHub Actions Integration:
- name: Scan Image with Trivy
  uses: aquasecurity/trivy-action@master
  with:
    image-ref: 'my-app:${{ github.sha }}'
    format: 'sarif'
    output: 'trivy-results.sarif'
    exit-code: '1'
    severity: 'CRITICAL,HIGH'
    ignore-unfixed: true

- name: Upload Trivy Results to GitHub Security
  uses: github/codeql-action/upload-sarif@v3
  with:
    sarif_file: 'trivy-results.sarif'

Secrets Scanning

GitLeaks (lokal + CI):

# In GitHub Actions:
- name: Gitleaks
  uses: gitleaks/gitleaks-action@v2
  env:
    GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
    GITLEAKS_LICENSE: ${{ secrets.GITLEAKS_LICENSE }}
# Lokal (pre-commit Hook), .pre-commit-config.yaml:
repos:
  - repo: https://github.com/gitleaks/gitleaks
    rev: v8.18.0
    hooks:
      - id: gitleaks

truffleHog:

# Scannt git-History auf Secrets:
trufflehog git file://. --only-verified --json

GitHub Secret Scanning (automatisch für Public Repos):

  • Erkennt > 100 Secret-Typen (AWS Keys, Stripe, GitHub PATs)
  • Bei Enterprise: auch für Private Repos aktivierbar
  • Push Protection: Blockiert Push wenn Secret erkannt
  • Settings → Code security → Secret scanning → Push protection: Enable

Sichere GitHub Actions Konfiguration

Sicherheitsregeln für GitHub Actions

  1. Commit-Hash statt Tags (immutable references):

    # UNSICHER - Tag kann überschrieben werden:
    uses: actions/checkout@v4
    
    # SICHER - SHA ist immutable:
    uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11  # v4.1.1

    Tool: pin-github-action (automatisches Pinnen)

  2. Minimale Permissions:

    jobs:
      test:
        runs-on: ubuntu-latest
        permissions:
          contents: read      # Nur lesen, nicht schreiben
          # packages: NICHT angeben wenn nicht nötig
          # id-token: NICHT angeben wenn kein OIDC
        steps: ...

    Globale Default einschränken - .github/workflows/*.yml oder Repository Settings:

    permissions:
      contents: read
  3. Third-Party Actions minimieren:

    • Eigene Actions in .github/actions/ (kein Third-Party-Vertrauen)
    • Wenn Third-Party: nur verifizierte, etablierte Actions
    • Allowlist in Organization-Settings: nur erlaubte Actions
  4. Selbst-gehostete Runner absichern:

    • Kein Shared Runner für privilegierte Deployment-Pipelines
    • Ephemeral Runner (pro Job eine neue VM → keine Persistence)
    • Netzwerkisolation: Runner hat nur Zugriff auf benötigte Systeme
    • KEINE self-hosted Runner für Public Repositories (RCE-Risiko!)
  5. Workflow-Schutz:

    # .github/workflows/protected-deploy.yml:
    on:
      workflow_dispatch:       # Nur manuell auslösbar
        inputs:
          environment:
            type: choice
            options: [staging, production]
            required: true
    environment:
      name: production          # Requires approval!
      url: https://a7.de

    Environment: Settings → Environments → production:

    • "Required reviewers": Senior DevOps, CTO
    • "Wait timer": 5 Minuten (Review-Zeit)
    • "Restrict to protected branches": main

GitLab CI Sicherheit

# .gitlab-ci.yml

# Variable Protection:
variables:
  DEPLOY_TOKEN: $CI_DEPLOY_TOKEN  # Aus Protected CI/CD Variables

deploy_production:
  stage: deploy
  only:
    - main             # Nur aus main-Branch
  when: manual         # Manuelle Bestätigung
  environment:
    name: production
  script:
    - echo "Deploying to production..."
    # Secrets aus GitLab CI/CD Variables (Protected + Masked!)
    - aws s3 sync dist/ s3://prod-bucket

# Masked + Protected Variables in GitLab:
# Settings → CI/CD → Variables → Add Variable
# Protected: nur auf protected branches verfügbar
# Masked: nicht in Logs sichtbar

Supply Chain Security

SLSA Framework (Supply Chain Levels for Software Artifacts)

Level 1 (Grundlegende Reproduzierbarkeit):

  • Build-Prozess dokumentiert, automatisiert
  • Provenance-Metadaten verfügbar

Level 2 (Versionierter Build-Service):

  • Build läuft auf verwaltetem CI-System (nicht lokal!)
  • Provenance authentifiziert

Level 3 (Sichere Build-Platform):

  • Isolation: Build hat keinen Einfluss auf Build-Script
  • Alle Builds über CI (kein manueller Build möglich!)

Level 4 (Maximale Sicherheit):

  • Zweiäugige Reviews für alle Code-Änderungen
  • Hermetischer, reproduzierbarer Build

Software Bill of Materials (SBOM)

Was ist ein SBOM?

  • Vollständige Liste aller Komponenten in einer Software
  • Inklusive: direkte + transitive Dependencies, Versionen, Lizenzen
  • Standard-Formate: CycloneDX (JSON), SPDX (SPDX-JSON)

SBOM generieren:

# syft (Anchore):
syft my-app:latest -o cyclonedx-json > sbom.json

# grype (Schwachstellenabgleich mit SBOM):
grype sbom:./sbom.json

# npm:
npm sbom --sbom-format cyclonedx > sbom.json

GitHub: automatisches SBOM für Releases aktivieren - Repository Settings → Code security → Dependency graph → SBOM

Warum SBOM wichtig ist:

Log4Shell 2021: Unternehmen hatten keine Ahnung, ob Log4j in ihrer Software enthalten war.

  • Mit SBOM: in 5 Minuten prüfbar, ob betroffen
  • Ohne SBOM: 3-5 Arbeitstage manuelle Suche

Sicherheits-Gates in der Pipeline (fail fast!)

Empfohlene Pipeline-Struktur:

Stage 1 - Code Quality (< 2 Minuten):

  • Linting, Formatierung
  • Unit Tests
  • Secrets Scanning (gitleaks)

Stage 2 - Security Scanning (< 10 Minuten):

  • SAST (Semgrep, CodeQL)
  • SCA (trivy fs, npm audit)
  • License Check (FOSSA, SPDX)

Stage 3 - Build & Image Scan (< 15 Minuten):

  • Docker Image Build
  • Image Scan (trivy image)
  • SBOM Generierung
  • Image Signing (Cosign)

Stage 4 - Deploy Staging (automatisch):

  • DAST (OWASP ZAP, Nuclei)
  • Integration Tests

Stage 5 - Deploy Production (manuell + Approval):

  • Nur nach Stage-4-Erfolg
  • Required Reviewer Approval
  • Canary-Deployment optional

Pipeline-Regel: JEDER Security-Gate-Fehler → Pipeline fehlgeschlagen → KEIN Deployment!


DevSecOps ist keine Verlangsamung der Entwicklung - es ist die Vermeidung teurer Sicherheitsvorfälle in Produktion. AWARE7 analysiert CI/CD-Pipelines auf Schwachstellen, implementiert Security-Gates und schult Entwicklungsteams in sicherer Softwareentwicklung.

DevSecOps-Beratung anfragen | Penetrationstest Web-Applikationen

Nächster Schritt

Unsere zertifizierten Sicherheitsexperten beraten Sie zu den Themen aus diesem Artikel, unverbindlich und kostenlos.

Kostenlos · 30 Minuten · Unverbindlich

Artikel teilen

Über den Autor

Vincent Heinen
Vincent Heinen

Abteilungsleiter Offensive Services

E-Mail

M.Sc. IT-Sicherheit mit über 5 Jahren Erfahrung in offensiver Sicherheitsanalyse. Leitet die Durchführung von Penetrationstests mit Spezialisierung auf Web-Applikationen, Netzwerk-Infrastruktur, Reverse Engineering und Hardware-Sicherheit. Verantwortlich für mehrere Responsible Disclosures.

OSCP+ OSCP OSWP OSWA
Zertifiziert ISO 27001ISO 9001AZAV

Rufen Sie uns an

Mo-Fr, 8:00-17:00 Uhr - persönlich und unverbindlich.

0209 8830 6764
Jetzt anrufen