Was sind die 10 größten CI/CD-Sicherheitsrisiken?

In den OWASP Top 10 CI/CD-Sicherheitsrisiken werden die wichtigsten Sicherheitsrisiken in Continuous Integration- und Continuous Delivery-Pipelines identifiziert. CI/CD-Pipelines sind hochwertige Ziele, da sie direkten Zugang zu Quellcode, Geheimnissen und Produktionsumgebungen haben. Dieser Leitfaden befasst sich mit Flusskontrolle, Identitätsmanagement, Angriffen auf Abhängigkeiten, Pipeline Poisoning und mehr.

1️⃣ CICD-SEC-1 - Unzureichende Mechanismen zur Flusskontrolle

Critical

Übersicht

Unzureichende Flusskontrollmechanismen ermöglichen es Angreifern, bösartigen Code durch CI/CD-Pipelines zu schleusen, ohne ihn ordnungsgemäß zu überprüfen oder zu genehmigen. Dazu gehören die Umgehung von Verzweigungsschutzregeln, das Fehlen erforderlicher Genehmigungen und die fehlende Durchsetzung der Frage, wer Bereitstellungen für die Produktion auslösen kann.

Risiko

Ohne ordnungsgemäße Flusskontrolle kann ein einziges kompromittiertes Entwicklerkonto oder ein böswilliger Insider Code direkt in die Produktion einspeisen und dabei Codeprüfung, Sicherheitsscans und Genehmigungsprozesse umgehen. Dies kann zur Bereitstellung von Hintertüren, Code zur Datenexfiltration oder zerstörerischen Nutzdaten führen.

Beispiel für anfälligen Code

YAML (GitHub Actions) ❌ Bad
# No branch protection — anyone can push directly to main
name: Deploy
on:
  push:
    branches: [main]  # Triggers on any push to main
jobs:
  deploy:
    runs-on: ubuntu-latest
    steps:
    - uses: actions/checkout@v4
    - run: |
        # Deploys immediately — no approval gate!
        kubectl apply -f deploy.yaml
        kubectl rollout status deployment/myapp

Beispiel für sicheren Code

YAML (GitHub Actions) ✅ Good
name: Deploy
on:
  push:
    branches: [main]
jobs:
  test:
    runs-on: ubuntu-latest
    steps:
    - uses: actions/checkout@v4
    - run: npm test
  deploy:
    needs: test
    runs-on: ubuntu-latest
    environment: production  # Requires manual approval
    steps:
    - uses: actions/checkout@v4
    - run: |
        kubectl apply -f deploy.yaml
        kubectl rollout status deployment/myapp

Checkliste zur Schadensbegrenzung

2️⃣ CICD-SEC-2 - Unzureichendes Identitäts- und Zugangsmanagement

Critical

Übersicht

CI/CD-Systeme umfassen mehrere Identitäten: menschliche Benutzer, Dienstkonten, Bot-Tokens und Maschinenidentitäten. Unzureichendes IAM ermöglicht einen zu weitreichenden Zugriff auf Repositorys, Pipelines und Bereitstellungsziele. Gemeinsam genutzte Anmeldedaten, veraltete Konten und fehlende MFA erhöhen das Risiko.

Risiko

Kompromittierte CI/CD-Identitäten mit übermäßigen Berechtigungen können Pipelines ändern, auf Geheimnisse zugreifen, Build-Artefakte verändern und in der Produktion einsetzen. Gemeinsame Dienstkonten machen es unmöglich zu überprüfen, wer eine Aktion durchgeführt hat.

Beispiel für anfälligen Code

YAML (GitHub Actions) ❌ Bad
# Over-permissive workflow with admin token
name: CI
on: push
permissions: write-all  # Full permissions to everything!
jobs:
  build:
    runs-on: ubuntu-latest
    steps:
    - uses: actions/checkout@v4
    - run: |
        # Using org-wide PAT with admin access
        curl -H "Authorization: token ${{ secrets.ADMIN_PAT }}" \
          https://api.github.com/repos/org/other-repo/contents/

Beispiel für sicheren Code

YAML (GitHub Actions) ✅ Good
name: CI
on: push
permissions:
  contents: read    # Minimum required permissions
  packages: write   # Only what's needed
jobs:
  build:
    runs-on: ubuntu-latest
    steps:
    - uses: actions/checkout@v4
    - uses: actions/create-github-app-token@v1  # Scoped app token
      id: app-token
      with:
        app-id: ${{ vars.APP_ID }}
        private-key: ${{ secrets.APP_PRIVATE_KEY }}
        repositories: other-repo  # Scoped to specific repo

Checkliste zur Schadensbegrenzung

3️⃣ CICD-SEC-3 - Missbrauch der Abhängigkeitskette

Critical

Übersicht

CI/CD-Pipelines ziehen Abhängigkeiten von externen Paketregistrierungen (npm, PyPI, Maven, Docker Hub). Angreifer nutzen dies durch Abhängigkeitsverwirrung, Typosquatting, kompromittierte Betreuer-Konten und bösartige Pakete aus. Eine einzige vergiftete Abhängigkeit kann während des Builds beliebigen Code ausführen.

Risiko

Bösartige Abhängigkeiten führen während der Installation Code aus (Postinstall-Skripte, setup.py), stehlen Geheimnisse, injizieren Hintertüren in Build-Artefakte oder stellen Persistenz her. Angriffe auf die Lieferkette wie SolarWinds und Codecov zeigen die katastrophalen Auswirkungen.

Beispiel für anfälligen Code

Jenkinsfile ❌ Bad
pipeline {
  agent any
  stages {
    stage('Build') {
      steps {
        // No lockfile verification, no integrity checks
        sh 'npm install'           // Fetches latest — could be compromised!
        sh 'pip install -r requirements.txt'  // No hash verification
      }
    }
  }
}

Beispiel für sicheren Code

Jenkinsfile ✅ Good
pipeline {
  agent any
  stages {
    stage('Build') {
      steps {
        // Use lockfile with integrity verification
        sh 'npm ci'                   // Uses package-lock.json
        sh 'npm audit --audit-level=high'
        // Python: verify hashes from lockfile
        sh 'pip install --require-hashes -r requirements.lock'
      }
    }
    stage('SCA Scan') {
      steps {
        // Software Composition Analysis
        sh 'trivy fs --scanners vuln,secret .'
      }
    }
  }
}

Checkliste zur Schadensbegrenzung

4️⃣ CICD-SEC-4 - Vergiftete Pipeline-Ausführung (PPE)

Critical

Übersicht

Poisoned Pipeline Execution (PPE) tritt auf, wenn Angreifer CI/CD-Pipeline-Definitionen ändern oder bösartigen Code einschleusen können, der im Pipeline-Kontext ausgeführt wird. Dies kann durch die Manipulation von Pipeline-Konfigurationsdateien in Zweigen, Pull-Requests von Forks oder die Änderung gemeinsam genutzter Pipeline-Vorlagen geschehen.

Risiko

Ein Angreifer, der die Konfiguration der Pipeline ändern kann, erhält Zugriff auf alle Geheimnisse, Anmeldedaten und Berechtigungen, die für die Pipeline verfügbar sind. Er kann Geheimnisse exfiltrieren, Build-Ausgaben manipulieren oder bösartigen Code bereitstellen - alles in einem vertrauenswürdigen Ausführungskontext.

Beispiel für anfälligen Code

YAML (GitHub Actions) ❌ Bad
# Runs pipeline from fork PRs with access to secrets
name: CI
on:
  pull_request_target:  # Runs in base repo context with secrets!
    branches: [main]
jobs:
  build:
    runs-on: ubuntu-latest
    steps:
    - uses: actions/checkout@v4
      with:
        ref: ${{ github.event.pull_request.head.sha }}  # Checks out fork code!
    - run: make build  # Fork's Makefile executes with secrets access
      env:
        DEPLOY_KEY: ${{ secrets.DEPLOY_KEY }}

Beispiel für sicheren Code

YAML (GitHub Actions) ✅ Good
# Separate workflows: untrusted build + trusted deploy
name: CI
on:
  pull_request:  # No secret access for PR builds
    branches: [main]
permissions:
  contents: read
jobs:
  build:
    runs-on: ubuntu-latest
    steps:
    - uses: actions/checkout@v4  # Checks out merge commit (safe)
    - run: npm ci && npm test   # No secrets needed for build/test
    - uses: actions/upload-artifact@v4
      with:
        name: build-output
        path: dist/

Checkliste zur Schadensbegrenzung

5️⃣ CICD-SEC-5 - Unzureichende leitungsgebundene Zugangskontrollen (PBAC)

High

Übersicht

Pipeline-basierte Zugriffskontrollen (PBAC) regeln, auf welche Ressourcen eine Pipeline zugreifen kann: Cloud-Konten, Kubernetes-Cluster, Datenbanken und interne Dienste. Eine unzureichende PBAC bedeutet, dass Pipelines einen breiteren Zugriff als nötig haben, was gegen das Prinzip der geringsten Privilegien verstößt.

Risiko

Überprivilegierte Pipelines können ausgenutzt werden, um auf Ressourcen zuzugreifen, die weit über den vorgesehenen Umfang hinausgehen. Eine kompromittierte Build-Pipeline für einen unbedeutenden Dienst könnte verwendet werden, um auf Produktionsdatenbanken zuzugreifen, die Infrastruktur zu ändern oder auf andere Umgebungen zu wechseln.

Beispiel für anfälligen Code

YAML (GitLab CI) ❌ Bad
# Pipeline with admin-level cloud credentials
deploy:
  stage: deploy
  script:
    - aws configure set aws_access_key_id $AWS_ACCESS_KEY
    - aws configure set aws_secret_access_key $AWS_SECRET_KEY
    # This key has AdministratorAccess policy!
    - aws s3 sync dist/ s3://my-bucket/
    - aws ecs update-service --cluster prod --service myapp
    # Same credentials could access ANY AWS resource

Beispiel für sicheren Code

YAML (GitHub Actions) ✅ Good
name: Deploy
on:
  push:
    branches: [main]
permissions:
  id-token: write  # For OIDC
  contents: read
jobs:
  deploy:
    runs-on: ubuntu-latest
    steps:
    - uses: aws-actions/configure-aws-credentials@v4
      with:
        role-to-assume: arn:aws:iam::123456:role/deploy-s3-only
        # Scoped role: only s3:PutObject on specific bucket
        aws-region: us-east-1
    - run: aws s3 sync dist/ s3://my-bucket/

Checkliste zur Schadensbegrenzung

6️⃣ CICD-SEC-6 - Unzureichende Zeugnishygiene

Critical

Übersicht

CI/CD-Pipelines verarbeiten zahlreiche Anmeldeinformationen: API-Schlüssel, Cloud-Tokens, Registrierungspasswörter, SSH-Schlüssel und Signierzertifikate. Zu einer schlechten Anmeldeinformationshygiene gehören das Festcodieren von Geheimnissen in Pipelinedateien, das Drucken von Geheimnissen in Protokollen, die Verwendung unverschlüsselter Geheimnisspeicher und das ständige Rotieren von Anmeldeinformationen.

Risiko

Durchgesickerte CI/CD-Anmeldeinformationen sind einer der häufigsten Vektoren für den Erstzugriff. Geheimnisse, die in Build-Protokollen offengelegt, an Repositories übergeben oder unverschlüsselt gespeichert werden, ermöglichen Angreifern den direkten Zugriff auf Produktionssysteme, Cloud-Konten und Artefaktregistrierungen.

Beispiel für anfälligen Code

Bash (CI Script) ❌ Bad
#!/bin/bash
# Secrets hardcoded and leaked in logs
export DOCKER_PASSWORD="MyS3cret!"         # Hardcoded!
echo "Logging in with $DOCKER_PASSWORD"  # Printed to logs!

docker login -u admin -p "$DOCKER_PASSWORD" registry.example.com
docker push registry.example.com/myapp:latest

# AWS credentials in environment — visible in process listing
export AWS_SECRET_ACCESS_KEY="wJalrXUtnFEMI/K7MDENG/bPxRfiCY"
aws s3 cp artifact.zip s3://releases/

Beispiel für sicheren Code

YAML (GitHub Actions) ✅ Good
name: Publish
on:
  push:
    tags: ['v*']
jobs:
  publish:
    runs-on: ubuntu-latest
    steps:
    - uses: actions/checkout@v4
    - uses: docker/login-action@v3  # Handles credentials securely
      with:
        registry: registry.example.com
        username: ${{ secrets.DOCKER_USER }}   # Masked in logs
        password: ${{ secrets.DOCKER_TOKEN }}  # Short-lived token
    - run: |
        docker build -t registry.example.com/myapp:${{ github.ref_name }} .
        docker push registry.example.com/myapp:${{ github.ref_name }}

Checkliste zur Schadensbegrenzung

7️⃣ CICD-SEC-7 - Unsichere Systemkonfiguration

High

Übersicht

CI/CD-Systeme (Jenkins, GitLab, GitHub Actions runners) werden häufig mit unsicheren Standardkonfigurationen betrieben. Dazu gehören veraltete Softwareversionen, ungeschützte Verwaltungsschnittstellen, deaktivierte Sicherheitsfunktionen, ein zu freizügiger Netzwerkzugriff und selbst gehostete, projektübergreifende Runner.

Risiko

Eine falsch konfigurierte CI/CD-Infrastruktur kann ausgenutzt werden, um unbefugten Zugriff auf Build-Umgebungen zu erhalten, Geheimnisse abzufangen oder auf interne Netzwerke zuzugreifen. Gemeinsam genutzte, selbst gehostete Läufer ermöglichen projektübergreifende Angriffe, bei denen ein kompromittierter Workflow andere beeinträchtigt.

Beispiel für anfälligen Code

Groovy (Jenkins) ❌ Bad
// Jenkins with insecure configuration
// - Script console enabled without auth
// - Agent-to-controller access unrestricted
// - Outdated plugins with known CVEs

pipeline {
  agent any  // Runs on any available agent — no isolation
  stages {
    stage('Build') {
      steps {
        // Running as root on shared agent
        sh 'whoami'  // root
        sh 'docker build -t myapp .'
      }
    }
  }
}

Beispiel für sicheren Code

Groovy (Jenkins) ✅ Good
pipeline {
  agent {
    kubernetes {  // Ephemeral, isolated pod per build
      yaml """
        apiVersion: v1
        kind: Pod
        spec:
          securityContext:
            runAsNonRoot: true
            runAsUser: 1000
          containers:
          - name: builder
            image: builder:1.2.3
            securityContext:
              allowPrivilegeEscalation: false
              readOnlyRootFilesystem: true
      """
    }
  }
  stages {
    stage('Build') {
      steps {
        container('builder') {
          sh 'make build'
        }
      }
    }
  }
}

Checkliste zur Schadensbegrenzung

8️⃣ CICD-SEC-8 - Unkontrollierte Nutzung von Drittanbieterdiensten

High

Übersicht

CI/CD-Pipelines werden häufig mit Diensten von Drittanbietern integriert: Codequalitäts-Tools, Sicherheitsscanner, Benachrichtigungssysteme und Bereitstellungsplattformen. Für diese Integrationen werden Zugriffstoken und Berechtigungen vergeben, wodurch eine Vertrauenskette entsteht. Eine unkontrollierte Nutzung bedeutet, dass man nicht weiß, worauf Drittanbieterdienste zugreifen oder was sie tun können.

Risiko

Ein kompromittierter Drittanbieterdienst (wie die Codecov-Panne) kann auf Quellcode, Geheimnisse und Build-Artefakte zugreifen. Ohne Governance können Teams unbekannten Diensten übermäßig viele Berechtigungen gewähren und so unsichtbare Angriffsvektoren in der Lieferkette schaffen.

Beispiel für anfälligen Code

YAML (GitHub Actions) ❌ Bad
name: CI
on: push
jobs:
  build:
    runs-on: ubuntu-latest
    steps:
    - uses: actions/checkout@v4
    - run: npm test
    # Unknown third-party action with full repo access
    - uses: random-org/code-analysis@main  # Unpinned, unvetted!
      with:
        token: ${{ secrets.GITHUB_TOKEN }}   # Full token access!
    # Uploading coverage to external service with repo token
    - run: |
        bash <(curl -s https://example.com/uploader.sh)  # Remote script!

Beispiel für sicheren Code

YAML (GitHub Actions) ✅ Good
name: CI
on: push
permissions:
  contents: read
jobs:
  build:
    runs-on: ubuntu-latest
    steps:
    - uses: actions/checkout@v4
    - run: npm test
    # Vetted action pinned to SHA
    - uses: github/codeql-action/analyze@8a470fddafa5cbc14  # Pinned SHA
    # Upload via official CLI tool, not remote scripts
    - uses: codecov/codecov-action@e28ff129e5465c2c0dcc6f003fc735cb6ae0c673
      with:
        token: ${{ secrets.CODECOV_TOKEN }}  # Scoped token
        fail_ci_if_error: true

Checkliste zur Schadensbegrenzung

9️⃣ CICD-SEC-9 - Unsachgemäße Überprüfung der Integrität von Artefakten

High

Übersicht

Build-Artefakte (Container-Images, Binärdateien, Pakete) fließen durch CI/CD-Pipelines in die Produktion. Ohne Integritätsprüfung können Artefakte zu jedem Zeitpunkt manipuliert werden: während der Erstellung, während der Übertragung, in der Artefaktregistrierung oder zum Zeitpunkt der Bereitstellung. Dadurch wird die Vertrauenskette vom Code bis zur Produktion unterbrochen.

Risiko

Manipulierte Artefakte können Backdoors, Malware oder modifizierte Logik enthalten. Ohne Signierung und Verifizierung gibt es keine Möglichkeit zu erkennen, ob ein Artefakt nach der Erstellung verändert wurde. Angreifer können legitime Images in Registern ersetzen oder Artefakte während der Übertragung abfangen.

Beispiel für anfälligen Code

Bash ❌ Bad
#!/bin/bash
# Build and deploy without any integrity checks
docker build -t myregistry.com/app:latest .
docker push myregistry.com/app:latest

# On deployment side — no verification
docker pull myregistry.com/app:latest  # Could be tampered!
docker run myregistry.com/app:latest   # Tag is mutable!

Beispiel für sicheren Code

YAML (GitHub Actions) ✅ Good
name: Build and Sign
on:
  push:
    tags: ['v*']
permissions:
  id-token: write
  packages: write
jobs:
  build:
    runs-on: ubuntu-latest
    steps:
    - uses: actions/checkout@v4
    - run: |
        # Build with immutable tag (SHA)
        docker build -t myregistry.com/app:${{ github.sha }} .
        docker push myregistry.com/app:${{ github.sha }}
    - uses: sigstore/cosign-installer@v3
    - run: |
        # Sign image with keyless signing (Sigstore)
        cosign sign myregistry.com/app:${{ github.sha }}
        # Generate and attach SBOM
        syft myregistry.com/app:${{ github.sha }} -o spdx-json > sbom.json
        cosign attest --predicate sbom.json myregistry.com/app:${{ github.sha }}

Checkliste zur Schadensbegrenzung

🔟 CICD-SEC-10 - Unzureichende Protokollierung und Sichtbarkeit

Medium

Übersicht

CI/CD-Umgebungen erzeugen kritische Sicherheitsereignisse: Pipeline-Ausführungen, Konfigurationsänderungen, geheime Zugriffe und Bereitstellungsaktivitäten. Ohne umfassende Protokollierung und Überwachung bleiben böswillige Aktivitäten in der Pipeline unentdeckt, und die Reaktion auf Vorfälle wird erheblich erschwert.

Risiko

Ohne Einblick in die CI/CD-Aktivitäten können Angreifer Pipelines verändern, Geheimnisse exfiltrieren und Artefakte manipulieren, ohne dass dies zu Warnmeldungen führt. Das Fehlen von Prüfprotokollen macht es unmöglich, den Umfang und die Auswirkungen eines Verstoßes zu bestimmen.

Beispiel für anfälligen Code

Bash ❌ Bad
#!/bin/bash
# Pipeline with no logging or audit trail
echo "Starting deployment..."
kubectl apply -f deploy.yaml
echo "Done."

# No record of: who triggered this, what changed,
# which image was deployed, what secrets were accessed
# Build logs expire after 30 days with no archival

Beispiel für sicheren Code

YAML (GitHub Actions) ✅ Good
name: Audited Deploy
on:
  push:
    branches: [main]
jobs:
  deploy:
    runs-on: ubuntu-latest
    steps:
    - uses: actions/checkout@v4
    - name: Log deployment metadata
      run: |
        echo "=== Deployment Audit Log ==="
        echo "Triggered by: ${{ github.actor }}"
        echo "Commit: ${{ github.sha }}"
        echo "Ref: ${{ github.ref }}"
        echo "Workflow: ${{ github.workflow }}"
        echo "Run ID: ${{ github.run_id }}"
    - name: Deploy with audit
      run: |
        kubectl apply -f deploy.yaml 2>&1 | tee deploy.log
        # Send audit event to SIEM
        curl -X POST "${{ secrets.SIEM_WEBHOOK }}" \
          -d '{"event":"deploy","actor":"${{ github.actor }}","sha":"${{ github.sha }}"}'

Checkliste zur Schadensbegrenzung

📊 Zusammenfassende Tabelle

ID Schwachstelle Schweregrad Schlüssel Abschwächung
CICD-SEC-1Unzureichende Mechanismen zur FlusskontrolleCriticalBranchenschutz, erforderliche Zulassungen, Umwelttore
CICD-SEC-2Unzureichendes Identitäts- und ZugangsmanagementCriticalToken mit geringsten Rechten, OIDC, MFA, Rotation von Anmeldedaten
CICD-SEC-3Missbrauch der AbhängigkeitsketteCriticalSperrdateien, Hash-Verifizierung, private Registraturen, SCA
CICD-SEC-4Vergiftete Pipeline-Ausführung (PPE)CriticalGetrennte Erstellung/Entwicklung, unveränderliche Pipeline-Definitionen, Fork-Kontrollen
CICD-SEC-5Unzureichende PBACHighOIDC-Verbund, skalierte IAM-Rollen, Umgebungstrennung
CICD-SEC-6Unzureichende ZeugnishygieneCriticalGeheimnisverwaltung, Protokollmaskierung, Rotation, geheimes Scannen
CICD-SEC-7Unsichere SystemkonfigurationHighKurzlebige Läufer, Nicht-Root, Plugin-Updates, Netzwerkisolierung
CICD-SEC-8Unkontrollierte Nutzung von DrittanbieterdienstenHighDienstinventar, SHA-Pinning, keine entfernten Skripte
CICD-SEC-9Unsachgemäße Validierung der ArtefaktintegritätHighMitsignieren, Zulassungskontrolle, SLSA-Provenienz
CICD-SEC-10Unzureichende Protokollierung und SichtbarkeitMediumAudit-Protokollierung, SIEM-Integration, Alarmierung, Protokollspeicherung