123% mehr gemeldete CVEs pro Tag in 2026 als im Vorjahr.

CI/CD

GitHub-Actions-Cache: Wie er funktioniert und was er verbirgt

Der GitHub-Actions-Cache speichert Dateien zwischen Workflow-Läufen, sodass Jobs bereits erledigte Downloads überspringen. Das macht Builds schneller. Es bedeutet aber auch, dass Pakete in Ihren Build gelangen, ohne geladen zu werden, und das sehen die meisten Aufzeichnungen eines Builds nie.

Aktualisiert am

Wie der Cache funktioniert

Die Action actions/cache speichert am Ende eines Jobs eine Reihe von Pfaden unter einem Key und stellt sie zu Beginn eines späteren Jobs wieder her. Ein typisches npm-Setup legt den Download-Cache des Paketmanagers im Cache ab und bildet den Key aus dem Lockfile:

- uses: actions/cache@v4
  with:
    path: ~/.npm
    key: npm-${{ runner.os }}-${{ hashFiles('package-lock.json') }}
    restore-keys: |
      npm-${{ runner.os }}-
- run: npm ci

Beim Wiederherstellen sucht die Action zuerst nach einem exakten Treffer für key, dann nach einem Teiltreffer und dann der Reihe nach nach jedem restore-keys-Präfix. Passen mehrere Caches zu einem Präfix, stellt sie den zuletzt erstellten wieder her. Dieser Fallback hält Builds schnell, nachdem sich das Lockfile geändert hat, und bedeutet zugleich, dass ein Job mit einem Cache starten kann, der für ein älteres Lockfile gebaut wurde.

Oft brauchen Sie die Action gar nicht. setup-node, setup-python, setup-java, setup-go, setup-ruby und setup-dotnet haben Caching eingebaut. Bei Node.js cacht setup-node die globalen Paketdaten von npm, Yarn und pnpm, nicht node_modules, und schaltet das npm-Caching automatisch ein, wenn package.json npm als packageManager deklariert.

Scope und Limits

Regel Was GitHub tut
Welche Caches ein Lauf wiederherstellen kann Die seines eigenen Branches und des Default-Branches; Pull Requests auch die ihres Base-Branches
Was ein Pull Request schreiben kann Nur Caches im Scope seiner Merge-Ref, nicht im Scope des Default-Branches
Speicher Standardmäßig 10 GB pro Repository; Organisations- und Enterprise-Inhaber können das erhöhen
Verdrängung Einträge, auf die über 7 Tage nicht zugegriffen wurde, und die am längsten ungenutzten, wenn der Speicher voll ist
Secrets Nicht cachen: Jeder mit Pull-Request-Zugriff kann Cache-Inhalte lesen

Was der Cache vor Ihrer SBOM verbirgt

Ein Cache ist eine Abkürzung an der Paket-Registry vorbei. Das ist sein Zweck, und genau deshalb verwirrt er jede Aufzeichnung dessen, was ein Build verwendet hat:

  • Kein Download, keine Spur. Aus einem Cache wiederhergestellte Pakete werden ohne Anfrage an die Registry installiert. Eine Aufzeichnung, die auf dem Netzwerkverkehr des Builds beruht, übersieht sie, sofern sie dem Cache nicht folgt.
  • Alter Inhalt unter neuem Key. Ein partieller restore-keys-Treffer stellt einen Cache wieder her, der für ein früheres Lockfile gebaut wurde. Die Installation ergänzt oder ersetzt dann, was sich geändert hat, aber das, womit der Job begonnen hat, ist nicht das, was das aktuelle Lockfile beschreibt.
  • Mehr als Ihre Abhängigkeiten. Caches enthalten auch Build-Tools, Compiler und generierte Dateien, die in keinem Anwendungsmanifest stehen.
  • Ein Scan kann es nicht erkennen. Eine Lockfile-basierte SBOM beschreibt, was im Lockfile steht, ob der Job genau das aus seinem Cache installiert hat oder nicht.

Wie sich das ins größere Problem einfügt, lesen Sie unter warum ein Lockfile keine Aufzeichnung des Ausgelieferten ist und transitive Abhängigkeiten.

Cache Poisoning

Caches werden von den Workflows eines Repositorys gemeinsam genutzt und sind damit ein Weg zwischen ihnen. Im Mai 2024 zeigte der Sicherheitsforscher Adnan Khan, dass jeder, der Code im Kontext des Default-Branches ausführen kann, über einen verwundbaren pull_request_target-Workflow oder eine kompromittierte Abhängigkeit Dateien in Workflows überschreiben kann, die Caches wiederherstellen. Mit dem Cache-Token eines laufenden Jobs kann ein Angreifer den Cache des Repositorys so füllen, dass GitHub legitime Einträge verdrängt, und dann vergiftete Einträge unter denselben Keys schreiben. Ein Release-Workflow, der sie wiederherstellt, führt die Dateien des Angreifers mit seinen eigenen Secrets aus.

So verringern Sie das Risiko:

  • Bauen Sie Releases aus einem sauberen Zustand oder aus Caches, die nur der Release-Workflow schreibt.
  • Führen Sie Pull-Request-Code, dem Sie nicht vertrauen, nie im Kontext des Default-Branches aus.
  • Halten Sie Secrets und Tokens aus gecachten Pfaden heraus.
  • Behandeln Sie das, was ein Cache wiederhergestellt hat, als Build-Input, der dieselbe Prüfung braucht wie ein Download.

Wie CRACI mit Caches umgeht

CRACI ist ein GitHub-Actions-Runner, daher funktionieren actions/cache und die setup-*-Caches wie bisher, zusammen mit Container-Layer-Caching. Caching ist auch ein Grund dafür, dass CRACI Builds etwa doppelt so schnell ausführt wie GitHub-gehostete Runner, mit schnellerer Hardware und kürzeren Wartezeiten.

Was sich ändert, ist die Aufzeichnung. Der paketbewusste Proxy von CRACI zeichnet die Pakete auf, die ein Job lädt, und die Nachweise wandern mit den Caches mit: Wenn ein Job einen Cache wiederherstellt, übernimmt CRACI die ihm bekannten Abhängigkeiten in die SBOM dieses Jobs.

  • Vollständigkeit pro Cache. Jeder Cache hat einen Vollständigkeitsstatus, genau wie jeder Job. Ein Job, der einen unvollständigen Cache wiederherstellt, erhält eine unvollständige SBOM, und ein von ihm erzeugter Cache trägt diesen Status weiter, sodass eine Lücke nie stillschweigend zu einer vollständigen Aufzeichnung wird.
  • Kein Raten aus dem Archiv. CRACI liest keine Paketmanifeste im Cache-Archiv. Es weiß, was in einem Cache steckt, weil es den Job aufgezeichnet hat, der ihn erzeugt hat.
  • Ein Cache pro erzeugendem Job hält diese Nachweise zuverlässig, zusammen mit einer Egress-Richtlinie, die im erzeugenden Job auf default: deny gesetzt ist. Details stehen im Leitfaden zu Cache und SBOM-Vollständigkeit.

Wie die Aufzeichnung funktioniert, lesen Sie unter Build-Time-SBOMs, oder buchen Sie eine Demo, um einen Ihrer gecachten Workflows auf CRACI auszuführen.

GitHub-Actions-Cache: häufig gestellte Fragen

Wie lange bewahrt GitHub einen Actions-Cache auf?

GitHub entfernt Cache-Einträge, auf die über 7 Tage nicht zugegriffen wurde. Überschreitet ein Repository sein Speicherlimit, standardmäßig 10 GB, verdrängt GitHub außerdem Caches nach dem letzten Zugriff, die ältesten zuerst.

Cacht setup-node node_modules?

Nein. Der cache-Input von actions/setup-node cacht die globalen Paketdaten des Paketmanagers für npm, Yarn oder pnpm, nicht node_modules. Der Installationsschritt läuft trotzdem, liest die Pakete aber aus dem wiederhergestellten Cache, statt sie herunterzuladen.

Kann ein Pull Request Caches aus dem Main-Branch lesen?

Ja. Ein Workflow-Lauf kann Caches seines eigenen Branches und des Default-Branches wiederherstellen, und ein Pull Request auch Caches seines Base-Branches. In einem Pull Request erstellte Caches gelten nur für dessen Merge-Ref und lassen sich daher nicht in den Scope des Default-Branches schreiben.

Ist der Actions-Cache in Release-Workflows sicher?

Das ist eine Abwägung. 2024 veröffentlichte Forschung zeigte, dass jeder, der Code in einem Workflow des Default-Branches ausführen kann, Caches vergiften kann, die andere Workflows wiederherstellen, auch Release-Workflows. Workflows, die Releases veröffentlichen oder Deployment-Secrets enthalten, sind sicherer, wenn sie aus einem sauberen Zustand bauen oder aus Caches, die nur sie selbst schreiben.

Verändert ein wiederhergestellter Cache meine SBOM?

Das kann er. Aus einem Cache wiederhergestellte Pakete werden installiert, ohne heruntergeladen zu werden, sodass eine Aufzeichnung auf Basis des Netzwerkverkehrs sie übersieht, sofern sie den Cache nicht verfolgt. Und ein Scan des Lockfiles sagt Ihnen nicht, ob der Cache genau diese Versionen enthielt.

Behalten Sie Ihre Caches und eine vollständige SBOM

Lassen Sie Ihren Workflow auf CRACI laufen: Caches beschleunigen den Build weiterhin, und ihre Abhängigkeiten bleiben in der aufgezeichneten SBOM jedes Jobs.

Demo buchen