Zum Inhalt springen

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

↑↓NavigierenEnterÖffnenESCSchließen
DevSecOps Security Gates: SAST, DAST und SCA in CI/CD-Pipelines - Illustration zu DevSecOps und sicherer Softwareentwicklung
Security Operations

DevSecOps Security Gates: SAST, DAST und SCA in CI/CD-Pipelines

Security Gates in CI/CD-Pipelines automatisch durchsetzen: SAST mit Semgrep und SonarQube, SCA mit Dependency-Check und Snyk, Container-Scanning mit Trivy, Secret-Detection mit detect-secrets und trufflehog, DAST mit OWASP ZAP im Stage-Deployment. Inklusive Pipeline-Konfigurationen für GitHub Actions, GitLab CI und Jenkins sowie Threshold-Management.

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

TL;DR

Schwachstellen die im Produktionsbetrieb entdeckt werden, kosten 10- bis 100-mal mehr als solche, die ein Security Gate im Pull-Request abfängt. Der Guide erklärt das vierstufige Pipeline-Modell: SAST mit Semgrep oder SonarQube prüft neuen Code auf SQL-Injection und OWASP Top 10; SCA mit OWASP Dependency-Check oder Snyk findet CVEs in Bibliotheken; Secret-Detection mit TruffleHog oder gitleaks blockiert versehentlich eingecheckte API-Keys; DAST mit OWASP ZAP testet die laufende Anwendung im Staging. Hard Gates bei CVSS ≥ 9,0 stoppen den Build automatisch. Inklusive vollständiger GitHub-Actions-Pipeline-Konfiguration.

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

Inhaltsverzeichnis (8 Abschnitte)

“Shift Left Security” bedeutet: Sicherheitsprüfungen so früh wie möglich in den Entwicklungsprozess integrieren. CI/CD-Security-Gates sind der Mechanismus dafür - automatisierte Prüfungen die bei kritischen Befunden den Build stoppen. Dieser Guide zeigt die praktische Umsetzung mit konkreten Pipeline-Konfigurationen.

Security Gate Konzept

Was Security Gates sind:

Ohne Security Gates:
  Code commit → Build → Deploy → (Pentest in 3 Monaten)
  → Schwachstelle in Produktion! Kosten: 10-100x höher

Mit Security Gates:
  Code commit → SAST → SCA → Secret-Scan → Build
                → Container-Scan → DAST → Deploy
  → Schwachstelle im PR abgefangen! Kosten: minimal

Gate-Typen:
  Hard Gate (Blocker):
  → Kritische Schwachstellen (CVSS ≥ 9.0): Build FAILS
  → Secrets im Code: Build FAILS (sofort!)
  → Lizenz-Violations (GPL in proprietary): Build FAILS

  Soft Gate (Warning):
  → Hohe Schwachstellen (CVSS 7.0-8.9): Warning + Team-Notification
  → Mittlere Schwachstellen: Alert im PR-Kommentar
  → Informational: Report, kein Block

Threshold-Management:
  → Neue Repo: strenge Thresholds von Anfang an
  → Legacy-Repo: baselining (current state = baseline, keine neuen Vuln)
  → Ratcheting: regelmäßig Threshold verschärfen

SAST - Statische Code-Analyse

SAST-Tools in der Pipeline:

Semgrep (Open Source, schnell):
  # .github/workflows/sast.yml:
  name: SAST with Semgrep
  on: [push, pull_request]
  jobs:
    semgrep:
      runs-on: ubuntu-latest
      steps:
        - uses: actions/checkout@v4
        - uses: semgrep/semgrep-action@v1
          with:
            config: >
              p/security-audit
              p/owasp-top-ten
              p/nodejs
              p/java
            auditOn: push

  # Eigene Regeln (rules/sql-injection.yaml):
  rules:
    - id: raw-sql-concatenation
      languages: [javascript]
      message: "Possible SQL injection via string concatenation"
      severity: ERROR
      pattern: |
        const query = "SELECT * FROM " + $USER_INPUT
      fix: "Use parameterized queries: db.query('SELECT * FROM ?', [input])"

  # GitHub PR-Kommentar mit Findings (automatisch bei semgrep-action)

SonarQube (Enterprise, vollständig):
  # .github/workflows/sonar.yml:
  - name: SonarQube Scan
    uses: SonarSource/sonarqube-scan-action@master
    env:
      SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }}
      SONAR_HOST_URL: ${{ secrets.SONAR_HOST_URL }}
    with:
      args: >
        -Dsonar.qualitygate.wait=true
        -Dsonar.sources=src
        -Dsonar.tests=tests
        -Dsonar.coverage.exclusions=**/tests/**

  # sonar-project.properties:
  sonar.projectKey=myapp
  sonar.qualitygate.wait=true  # Pipeline blockiert bei Gate-Fail!

  # Quality Gate Definition in SonarQube:
  # Security: New Critical Issues = 0 → FAIL
  # Security: New Blockers = 0 → FAIL
  # Coverage: New Code < 80% → WARN

Bandit (Python-spezifisch):
  # Für Python-Projekte:
  - name: Bandit Security Scan
    run: |
      pip install bandit
      bandit -r src/ -ll -f json -o bandit-report.json
      # -ll: nur Medium und höher
      # Exit code ≠ 0 wenn Findings → Pipeline-Fail!
    continue-on-error: false

  - name: Upload Bandit Report
    uses: github/codeql-action/upload-sarif@v2
    with:
      sarif_file: bandit-report.json

SCA - Software Composition Analysis

Dependency-Schwachstellen erkennen:

Dependency-Check (OWASP, kostenlos):
  # .github/workflows/sca.yml:
  - name: OWASP Dependency Check
    uses: dependency-check/Dependency-Check_Action@main
    with:
      project: 'myapp'
      path: '.'
      format: 'HTML,JSON,SARIF'
      failBuildOnCVSS: 9  # Hard Gate: CVSS ≥ 9 → FAIL
      additionalArguments: >
        --enableRetired
        --enableExperimental
        --nodeAuditSkipDevDependencies

  - name: Upload results
    uses: actions/upload-artifact@v4
    with:
      name: dependency-check-report
      path: ${{github.workspace}}/reports

Snyk (kommerziell, sehr genau):
  # .github/workflows/snyk.yml:
  - name: Snyk Security Scan
    uses: snyk/actions/node@master
    env:
      SNYK_TOKEN: ${{ secrets.SNYK_TOKEN }}
    with:
      args: |
        --severity-threshold=high
        --fail-on=all
        --sarif-file-output=snyk.sarif

  # snyk test → kritische CVEs in node_modules
  # snyk monitor → kontinuierliches Monitoring in Snyk-Dashboard
  # Snyk PR-Status: automatischer Check bei jedem PR

npm audit (built-in, Node.js):
  # Immer als Teil jedes Node-Builds:
  - name: NPM Audit
    run: |
      npm audit --audit-level=high --production
      # --production: ignoriert devDependencies
      # Exit 1 wenn high/critical → Pipeline-Fail

Renovate / Dependabot (automatische Dependency-Updates):
  # .github/dependabot.yml:
  version: 2
  updates:
    - package-ecosystem: npm
      directory: /
      schedule:
        interval: weekly
      ignore:
        - dependency-name: "*"
          update-types: ["version-update:semver-major"]
  # → Automatische PRs für Dependency-Updates
  # → Mit SAST/SCA in jedem PR → sofortige Überprüfung

Secret Detection

Secrets im Code verhindern:

detect-secrets (Yelp, pre-commit):
  # .pre-commit-config.yaml:
  repos:
    - repo: https://github.com/Yelp/detect-secrets
      rev: v1.4.0
      hooks:
        - id: detect-secrets
          args: ['--baseline', '.secrets.baseline']
          exclude: .secrets.baseline

  # Baseline erstellen (initiale, bekannte Secrets ausschließen):
  detect-secrets scan > .secrets.baseline
  # → Nur NEUE Secrets werden geblockt

truffleHog v3 (GitHub Actions):
  # .github/workflows/secret-scan.yml:
  - name: TruffleHog Secret Scan
    uses: trufflesecurity/trufflehog@main
    with:
      path: ./
      base: main  # Nur Änderungen seit main
      head: HEAD
      extra_args: >
        --only-verified    # Nur verifizierte Secrets
        --json

gitleaks (CI/CD native):
  # .gitlab-ci.yml:
  gitleaks:
    image: zricethezav/gitleaks:latest
    script:
      - gitleaks detect --source . --config .gitleaks.toml
    allow_failure: false  # Hard Gate!

  # .gitleaks.toml:
  [[rules]]
    id = "aws-access-key"
    description = "AWS Access Key"
    regex = '(?i)AKIA[0-9A-Z]{16}'
    tags = ["key", "AWS"]

  [[rules]]
    id = "generic-api-key"
    description = "Generic API Key"
    regex = '(?i)(api[_-]?key|apikey)\s*[=:]\s*["\']?[a-z0-9]{32,45}'

Pre-Commit Hook (lokal, vor dem Push):
  # .pre-commit-config.yaml:
  - repo: https://github.com/zricethezav/gitleaks
    rev: v8.18.0
    hooks:
      - id: gitleaks

  # Für alle Entwickler aktivieren:
  pip install pre-commit
  pre-commit install  # im Repo-Root
  # → Jeder Commit: geleaks prüft automatisch

Container-Security-Scanning

Docker-Images auf Schwachstellen prüfen:

Trivy (kostenlos, umfassend):
  # .github/workflows/container-scan.yml:
  - name: Build Docker Image
    run: docker build -t myapp:${{ github.sha }} .

  - name: Trivy Container Scan
    uses: aquasecurity/trivy-action@master
    with:
      image-ref: myapp:${{ github.sha }}
      format: 'sarif'
      output: 'trivy-results.sarif'
      severity: 'CRITICAL,HIGH'
      exit-code: '1'  # Hard Gate bei CRITICAL/HIGH!
      ignore-unfixed: true  # Nur behebbare Schwachstellen

  # Trivy scannt:
  # → OS-Pakete (Alpine, Debian, Ubuntu)
  # → Application-Dependencies (pip, npm, go.sum)
  # → Dockerfile: Misconfigurations (COPY --chown fehlend, etc.)
  # → Kubernetes YAML: Security Context fehlt

Dockerfile-Hardening (Trivy Misconfiguration):
  # Schlecht:
  FROM ubuntu:latest          # Tags ≠ Hashes → Mutability
  USER root                   # Läuft als root
  COPY . /app                 # Kein --chown

  # Gut:
  FROM ubuntu:22.04@sha256:abc123  # Pinned Hash
  RUN groupadd -g 1001 appuser && useradd -u 1001 -g appuser appuser
  COPY --chown=appuser:appuser . /app
  USER appuser
  HEALTHCHECK --interval=30s CMD curl -f http://localhost/health || exit 1

Grype (Anchore):
  # GitLab CI:
  container-scan:
    image: anchore/grype:latest
    script:
      - grype myapp:latest -o json > grype-report.json
      - grype myapp:latest --fail-on critical
    artifacts:
      reports:
        container_scanning: grype-report.json

DAST - Dynamische Anwendungsanalyse

DAST in der Pipeline (gegen Staging):

OWASP ZAP (kostenlos):
  # .github/workflows/dast.yml:
  dast:
    name: DAST with OWASP ZAP
    runs-on: ubuntu-latest
    needs: deploy-staging  # Erst nach Staging-Deploy!

    steps:
      - name: Start Application
        run: |
          docker run -d -p 8080:8080 myapp:staging
          sleep 10  # Warten bis App startet

      - name: OWASP ZAP Baseline Scan
        uses: zaproxy/action-baseline@v0.10.0
        with:
          target: 'http://localhost:8080'
          rules_file_name: '.zap/rules.tsv'
          cmd_options: '-a'  # Ajax Spider (für SPAs)

      # Oder: Full Scan (langsamer, umfassender):
      - name: OWASP ZAP Full Scan
        uses: zaproxy/action-full-scan@v0.10.0
        with:
          target: 'http://localhost:8080'
          docker_name: 'ghcr.io/zaproxy/zaproxy:stable'

  # .zap/rules.tsv (False-Positive-Management):
  10202	IGNORE	(Cookie Without SameSite Attribute)  # Intern OK
  10038	IGNORE	(Content Security Policy Header Not Set)  # Separat konfiguriert

Nuclei (Template-basiert, präzise):
  # Für spezifische Schwachstellen-Templates:
  - name: Nuclei Scan
    run: |
      nuclei -u http://localhost:8080 \
        -t cves/ \
        -t exposures/ \
        -severity critical,high \
        -json -o nuclei-results.json

GitLab DAST (Enterprise):
  # .gitlab-ci.yml:
  include:
    - template: DAST.gitlab-ci.yml
  dast:
    variables:
      DAST_WEBSITE: https://staging.example.com
      DAST_FULL_SCAN_ENABLED: "false"  # Baseline für schnellere Pipeline
      DAST_ZAP_USE_AJAX_SPIDER: "true"

Vollständige Pipeline (GitHub Actions)

Komplette DevSecOps-Pipeline:

# .github/workflows/devsecops.yml:
name: DevSecOps Pipeline
on:
  push:
    branches: [main, develop]
  pull_request:
    branches: [main]

jobs:
  # Stage 1: Sofort-Checks (< 2 Min)
  secret-scan:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
        with:
          fetch-depth: 0  # Vollständige Historie für gitleaks
      - uses: trufflesecurity/trufflehog@main
        with:
          path: ./
          base: ${{ github.event.repository.default_branch }}

  sast:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: semgrep/semgrep-action@v1
        with:
          config: p/security-audit p/owasp-top-ten

  # Stage 2: Dependency-Checks (2-5 Min)
  sca:
    runs-on: ubuntu-latest
    needs: [secret-scan]
    steps:
      - uses: actions/checkout@v4
      - run: npm ci
      - run: npm audit --audit-level=high --production

  # Stage 3: Build + Container-Scan (5-10 Min)
  container-scan:
    runs-on: ubuntu-latest
    needs: [sast, sca]
    steps:
      - uses: actions/checkout@v4
      - run: docker build -t myapp:${{ github.sha }} .
      - uses: aquasecurity/trivy-action@master
        with:
          image-ref: myapp:${{ github.sha }}
          severity: CRITICAL,HIGH
          exit-code: 1

  # Stage 4: Deploy Staging + DAST (15-30 Min, nur main)
  deploy-staging:
    if: github.ref == 'refs/heads/main'
    needs: [container-scan]
    runs-on: ubuntu-latest
    steps:
      - run: echo "Deploy to staging..."

  dast:
    if: github.ref == 'refs/heads/main'
    needs: [deploy-staging]
    runs-on: ubuntu-latest
    steps:
      - uses: zaproxy/action-baseline@v0.10.0
        with:
          target: 'https://staging.example.com'

Metriken und Reporting

Security Gate KPIs:

Metriken die zählen:
  □ Mean Time to Remediate (MTTR): wie schnell werden Schwachstellen gefixt?
  □ Vulnerability Debt: wie viele offene Findings, wie alt?
  □ Pipeline-Failure-Rate durch Security Gates: normal 5-15%
  □ False Positive Rate: >30% → Tool-Konfiguration überprüfen!

Security Dashboard (Grafana + InfluxDB):
  # Pipeline-Ergebnisse in InfluxDB schreiben:
  curl -i -XPOST http://influxdb:8086/write \
    --data-binary "pipeline_security,project=myapp \
      sast_findings=3,sca_critical=0,secrets_found=0"

SARIF-Upload (GitHub Security Tab):
  # Alle Tools die SARIF-Output unterstützen:
  # Semgrep, Trivy, SonarQube → GitHub Security → Code Scanning Alerts
  - uses: github/codeql-action/upload-sarif@v2
    if: always()  # Auch bei Pipeline-Fail!
    with:
      sarif_file: trivy-results.sarif
      category: container-scan

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

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 9001AZAVBSI

Cookielose Analyse via Matomo (selbst gehostet, kein Tracking-Cookie). Datenschutzerklärung