SEKurity GmbH Logo
CVE-Forschung

InSEKurity of the Week (CW44/2026): GitLab CI/CD Regex Integer Overflow RCE (CVE-2026-97229)

Ein praeparierter regulaerer Ausdruck in einer CI/CD-Konfiguration bringt einen Integer in Rubys Regex-Engine Onigmo zum Ueberlauf und macht aus einem GitLab-Puma-Worker eine Shell als git-Benutzer. CVSS 10.0, seit 29. Oktober 2026 im CISA-KEV-Katalog, Angriffsversuch auf das GitLab von Alpine Linux.

SEKurity Team

Offensive Security Experten

23 Min. Lesezeit
Teilen:

Diese Woche in unserer Serie InSEKurity of the Week: die Plattform, die Ihren Quellcode, Ihre CI/CD-Secrets und Ihre Deployment-Pipelines verwaltet. Am 12. Oktober 2026 hat GitLab die kritischen Patch-Versionen 19.4.2, 19.3.5 und 19.2.8 für CVE-2026-97229 veröffentlicht — einen Integer Overflow im Compiler für reguläre Ausdrücke in CI/CD, bewertet mit CVSS 10.0. Ein speziell präparierter regulärer Ausdruck in einer CI/CD-Konfiguration erlaubt einem Angreifer, beliebigen Code auf dem GitLab-Server auszuführen — als Betriebssystem-Konto git, dem jedes Repository auf dem System gehört. Am 29. Oktober hat CISA die Schwachstelle in den Katalog der Known Exploited Vulnerabilities aufgenommen.

Der Bug steckt eigentlich nicht in GitLabs Code. Er sitzt in Onigmo, der in Ruby eingebauten Regex-Engine, und GitLab hat ihn behoben, indem es den Ruby-Interpreter patcht, den es in seinen eigenen Paketen und Container-Images ausliefert. Genau dieses Detail wurde relevant: Alpine Linux — dessen GitLab-Instanz mit dem Ruby der eigenen Distribution läuft — hat GitLab aktualisiert, blieb verwundbar und musste zusehen, wie ein Angreifer die GitLab-Worker achtmal zum Absturz brachte, während er genau diese Lücke auszunutzen versuchte. Alpine konnte einen Erfolg nicht ausschließen und hat den Server von Grund auf neu aufgebaut.

Und CVE-2026-97229 hat ein Geschwister. Neun Tage später lieferte GitLab eine weitere Runde kritischer Releases für CVE-2026-110264 aus — einen zweiten Overflow mit CVSS 10.0 in derselben Engine, der bis GitLab 7.0 (2014) zurückreicht. Wer am 12. Oktober gepatcht und dann aufgehört hat, ist noch nicht fertig.

🚨 Zusammenfassung

  • CVE-ID: CVE-2026-97229 — „Integer Overflow issue in CI/CD Regular Expression Compiler impacts GitLab CE/EE”
  • CVSS-3.1-Score: 10.0 Critical (GitLab als CNA), Vektor CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:C/C:H/I:H/A:H
  • CWE: CWE-190: Integer Overflow or Wraparound
  • Hersteller-Advisory: GitLab Critical Patch Release 19.4.2, 19.3.5, 19.2.8, veröffentlicht am 2026-10-12
  • Betroffene Software: Selbst betriebene GitLab Community Edition und Enterprise Edition 19.2 vor 19.2.8, 19.3 vor 19.3.5 und 19.4 vor 19.4.2 — über alle Deployment-Arten hinweg (Linux-Paket, Docker, Helm, Source). GitLab.com und GitLab Dedicated sind bereits gepatcht
  • Ursächliche Komponente: Rubys Regex-Engine Onigmo; upstream behoben in Ruby 3.3.13, 3.4.12 und 4.0.8 (4.0.9 enthält alle zugehörigen Fixes)
  • Angriffsvektor: Netzwerk — ein präparierter regulärer Ausdruck in einer CI/CD-Konfiguration, die GitLab auswertet
  • Authentifizierung erforderlich: Laut GitLab keine. Der öffentliche Exploit-Pfad benötigt einmalig die Möglichkeit, in ein öffentliches Projekt zu pushen, und löst den Bug dann mit einem Request ganz ohne Zugangsdaten aus. Auf Instanzen mit offener Selbstregistrierung ist das keine Hürde
  • Impact: Remote Code Execution als GitLab-Konto git innerhalb eines Puma-Workers — voller Zugriff auf Repositories, CI/CD-Variablen, Runner-Tokens und die Secrets der Anwendung
  • Patch-Status: Verfügbar seit 2026-10-12. Die Folge-Schwachstelle CVE-2026-110264 erfordert die Releases vom 2026-10-21 (19.5.1, 19.4.3, 19.3.6, 19.2.9, 19.1.9, 19.0.10, 18.11.13) oder neuer
  • Selbst kompiliert / eigenes Ruby: Ein GitLab-Upgrade allein reicht nicht — der Ruby-Interpreter muss 3.3.13, 3.4.12, 4.0.9 oder neuer sein
  • Ausnutzungsstatus: Öffentlicher PoC von Rapid7 seit 2026-10-13; Ausnutzungsversuch gegen das GitLab von Alpine Linux am 2026-10-20/21
  • CISA KEV: Gelistet seit 2026-10-29; Frist für US-Bundesbehörden 2026-11-01

🖥️ Was ist GitLab?

GitLab ist eine vollständige DevSecOps-Plattform in einer einzigen Anwendung: Git-Repository-Hosting, Merge Requests und Code Review, Issue Tracking, eine Container- und Package-Registry und — im Kern — GitLab CI/CD, die Pipeline-Engine, die Code baut, testet und deployt. Laut GitLab nutzen mehr als 50 % der Fortune-100-Unternehmen die Plattform, die über 70 Millionen registrierte Benutzer zählt.

Anders als GitHub wird GitLab sehr häufig selbst betrieben: auf einer VM aus dem Linux-Paket („Omnibus”), als offizielles Docker-Image, auf Kubernetes per Helm oder aus dem Quellcode kompiliert. Genau das legt CVE-2026-97229 in die Hände einzelner Admin-Teams — GitLab.com war vor der Veröffentlichung gepatcht, die selbst betriebenen Instanzen nicht.

Typische Einsatzszenarien

  • Quellcodeverwaltung für interne Produkte, Infrastructure-as-Code und Konfigurations-Repositories
  • CI/CD-Pipelines, die Deployment-Zugangsdaten, Cloud-Keys, Signing-Keys und Registry-Tokens als CI/CD-Variablen speichern
  • Container- und Package-Registries, aus denen Produktiv-Deployments gespeist werden
  • Hosting von Open-Source-Projekten — etwa gitlab.alpinelinux.org von Alpine Linux — mit öffentlichen Projekten und offener Registrierung
  • Regulierte Umgebungen, in denen die Plattform aus Compliance-Gründen on-premises bleiben muss

Warum ein GitLab-Server ein Kronjuwel ist

Ein GitLab-Server ist ein Kontrollpunkt der Software-Lieferkette. Codeausführung als git bedeutet Lese- und Schreibzugriff auf jedes Repository der Instanz, auf die verschlüsselten Secrets, die die Anwendung entschlüsseln kann, und auf die Runner-Tokens, die sie mit der Build-Infrastruktur verbinden. Ein Angreifer, der GitLab kontrolliert, muss nicht in die Produktion einbrechen — er kann warten, bis die Produktion seinen Code deployt.

🔍 Technische Analyse

Beschreibung der Schwachstelle

GitLab erlaubt Pipeline-Autoren, reguläre Ausdrücke in der CI/CD-Konfiguration zu verwenden — etwa in rules:exists und rules:changes, die abhängig davon, welche Pfade in einem Commit existieren oder geändert wurden, entscheiden, ob ein Job oder eine eingebundene Datei greift. GitLab kompiliert diese vom Benutzer gelieferten Muster mit Rubys eingebauter Engine Onigmo und prüft sie vorher: eine Längenprüfung der Quelle, eine Prüfung auf Subroutinen-Aufrufe (\g), ein Scanner, der zu große Wiederholungsgrenzen ablehnt, ein Probe-Compile, ein Timeout von 50 ms und eine Obergrenze von 1 MB für das kompilierte Objekt.

CVE-2026-97229 schleust ein Muster an all diesen Prüfungen vorbei. Wenn Onigmo das Muster später für einen UTF-8-Eingabestring kompiliert, läuft eine vorzeichenbehaftete Integer-Multiplikation über, die Engine erzeugt ein riesiges Programm, und ein Sprung innerhalb dieses Programms zeigt an die falsche Stelle. Das Ergebnis ist vom Angreifer beeinflusster Kontrollfluss im Ruby-Prozess — Codeausführung auf dem GitLab-Server.

Root-Cause-Analyse

Die technische Analyse von Rapid7, die den Bug Ende-zu-Ende gegen das offizielle 19.4.1-CE-Image reproduziert hat, beschreibt vier Zutaten:

  1. Ein Validator, der das Muster anders liest als die Engine. GitLabs REPEAT_BOUND-Scanner erkennt nur zusammenhängende Ziffern innerhalb von {...}. Ein Inline-Regex-Kommentar (?#) innerhalb der Quantor-Klammern teilt die Zahl: Onigmo ignoriert den Kommentar und liest die vollständige, große Wiederholungsgrenze, während GitLabs Scanner eine kleine sieht und sie durchlässt.
  2. Eine Größenprüfung an der falschen Kompilierung. Das Muster wird als US-ASCII validiert, wo es klein ist. Ist der Eingabestring ein Dateipfad mit UTF-8-Zeichen, kompiliert Rubys rb_reg_prepare_re() das Muster für die neue Kodierung neu — und POSIX-Wortklassen expandieren zu großen Unicode-Tabellen. Diese Neukompilierung passiert, bevor der zeitlich begrenzte Match startet, und wird nie auf ihre Größe geprüft.
  3. Ein vorzeichenbehafteter Overflow in Onigmos Expansionsentscheidung. In compile_quantifier_node() entscheidet Onigmo, ob ein begrenzter Quantor ausgerollt wird, indem es die Größe des Rumpfs mit der Obergrenze in einem vorzeichenbehafteten Integer multipliziert. In Rapid7s Beispiel ergibt ein Rumpf von 37.151 Bytes mal eine Grenze von 57.805 genau 2.147.513.555 — 29.908 über INT_MAX. Das Produkt wird negativ, der Test „klein genug zum Expandieren” besteht, und Onigmo erzeugt jede einzelne Kopie.
  4. Ein Sprung, berechnet aus einer übergelaufenen Länge. Der OP_JUMP, der eine leere Alternative überspringt, wird aus der bereits übergelaufenen Länge berechnet und landet innerhalb des expandierten Programms statt dahinter. Vom Angreifer geformte Bytes am Ende der Kopien werden dann von Onigmos VM ausgeführt; Rapid7s Kette springt von dort in einen system()-Aufruf in libruby.

GitLabs Backport ersetzt die Multiplikation durch eine divisionsbasierte Prüfung (IS_EXPAND_LIMIT_OK) und lehnt kompilierte Programme über etwa 512 MiB ab (MAX_COMPILED_PROGRAM_SIZE). Das Ruby-Projekt hat denselben Fix upstream als CVE-2026-93577 („Integer Overflow in der Größe eines kompilierten Musters”) ausgeliefert und stellt klar, dass Regexp.timeout nicht vor diesen Bugs schützt und dass auch eine Begrenzung der Musterlänge sie nicht zuverlässig verhindert.

Angriffsvektor

Der demonstrierte Pfad besteht aus zwei Schritten: einem authentifizierten Setup, das den Payload platziert, und einem unauthentifizierten Trigger, der GitLab dazu bringt, ihn auszuwerten.

# NUR ILLUSTRATIV -- Datenfluss der von Rapid7 veroeffentlichten Kette; KEIN funktionsfaehiger Exploit.
# Die echten Payload-Bytes und Offsets sind build-spezifisch und bewusst weggelassen.

 Angreifer-Konto mit Push-Rechten auf IRGENDEIN oeffentliches Projekt
   |   (bei offener Registrierung: Konto anlegen, oeffentliches Projekt erstellen)
   |
   | 1. Branch "payload-ref" pushen mit:
   |      - .gitlab-ci.yml mit rules:exists / rules:changes und einer Regexp,
   |        deren Wiederholungsgrenze durch einen Inline-Kommentar geteilt ist  {NNN(?#)NN}
   |      - wiederholten POSIX-Wortklassen (klein in ASCII, riesig in UTF-8)
   |      - einem eingecheckten Dateipfad aus 4-Byte-UTF-8-Zeichen
   v
 anonymer HTTP-Client (kein Token, kein Cookie)
   |
   | 2. GET /api/v4/projects/<oeffentliches-projekt>/ci/lint?content_ref=payload-ref
   v
 GitLab-Puma-Worker (laeuft als OS-Benutzer "git")
   |  validiert Regexp als US-ASCII ............ besteht
   |  Match gegen UTF-8-Pfad ................... Ruby kompiliert fuer UTF-8 neu
   |  Onigmo: body_size * repeat_bound ......... Signed Overflow -> expandiert trotzdem
   |  falsch platzierter OP_JUMP ............... VM fuehrt Angreifer-Bytes aus
   v
 system("<Angreifer-Befehl>") als git  ->  Worker stuerzt danach ab, HTTP 502

Der Trigger-Request ist laut Rapid7 ein einfaches GET auf den projektbezogenen CI-Lint-Endpunkt:

# NUR ILLUSTRATIV -- Request-Gestalt fuer Log-Auswertung und Detection.
# Aus Rapid7s Analyse uebernommen; ohne den platzierten Payload bewirkt er nichts.
GET /api/v4/projects/attacker%2Fpublic-project/ci/lint?content_ref=payload-ref HTTP/1.1
Host: gitlab.example.com
User-Agent: Mozilla/5.0
Accept: */*

Drei Eigenschaften dieses Requests sind für Verteidiger wichtig. Er enthält keinerlei Authentifizierung — die Leseprüfung des Endpunkts besteht, weil das Projekt öffentlich ist, und die Token-Prüfung weist einen Request ohne Benutzer nicht ab. Die Lint-Route erzeugt keine Pipeline und kontaktiert keinen Runner, in der Pipeline-Liste taucht also nichts auf. Und ein erfolgreicher Durchlauf endet damit, dass der Worker nach der Rückkehr aus system() abstürzt — der Angreifer sieht ein HTTP 502, genau das, was die PoC-README ihren Nutzern als erwartetes Ergebnis ankündigt.

Rapid7 weist offen darauf hin, dass sein Setup-Schritt im Widerspruch zu GitLabs Bewertung PR:N steht: Der ursprüngliche HackerOne-Report von joaxcar (Johan Carlsson) ist nicht öffentlich, und wie er ohne die Schreibvoraussetzung auskommt, ist unbekannt. Die praktische Konsequenz formuliert Rapid7 selbst: Auf Instanzen, auf denen sich neue Benutzer selbst registrieren und Projekte anlegen können, entfällt diese Einschränkung.

Das Geschwister: CVE-2026-110264

Am 21. Oktober lieferte GitLab die kritischen Releases 19.5.1, 19.4.3, 19.3.6, 19.2.9, 19.1.9, 19.0.10 und 18.11.13 für CVE-2026-110264 aus — „Integer Overflow issue in Regular Expression Compiler impacts GitLab CE/EE”, wieder CVSS 10.0, wieder gemeldet von joaxcar. Das Ruby-Projekt beschreibt ihn als Überlauf interner IDs in einem Muster mit vielen Wiederholungen. Betroffen sind alle Versionen ab 7.0, die Releases vom 12. Oktober sind also weiterhin verwundbar. GitLabs veröffentlichte Detection heißt „Org mode render error burst”; laut Konfirmitys Zusammenfassung dieser Regel wird diese Variante über das Org-Mode-Rendering erreicht, bei dem das Gem org-ruby aus einem #+TODO:-Schlüsselwort eine Regex baut, ohne es zu escapen.

Ausnutzung in freier Wildbahn

  • 2026-10-13 — Rapid7 veröffentlicht seine Einschätzung und einen öffentlichen Proof-of-Concept, der Befehle als git auf dem offiziellen Image gitlab/gitlab-ce:19.4.1-ce.0 ausführt.
  • 2026-10-20 bis 21 — Ein neu registriertes Konto sondiert die GitLab-Instanz von Alpine Linux und sendet präparierte CI-Konfigurationen. GitLab-Worker-Prozesse stürzen achtmal ab; bei vier dieser Abstürze kam der Angreifer ein Stück weit durch den Exploit, bevor er am nächsten Schritt scheiterte. Außerdem lädt der Angreifer Alpines GitLab-Container-Image herunter — laut Alpine ein Zeichen dafür, dass er den Exploit auf genau diesen Build zuschnitt.
  • 2026-10-25 bis 26 — Der Angreifer kehrt zurück und versucht, wieder Zugang zu erlangen; die Versuche scheitern.
  • 2026-10-28 — Alpine veröffentlicht seinen Bericht: „The attack came close to working”. Kein Hinweis auf Erfolg, aber man „cannot rule it out” und behandelt die Instanz als kompromittiert.
  • 2026-10-29 — CISA nimmt CVE-2026-97229 in den KEV-Katalog auf. GitLab gibt an, Ausnutzungsversuche erkannt zu haben, und hat Threat Detections für selbst betriebene Instanzen veröffentlicht.

Die Ursache bei Alpine ist lehrreich. Am 13. Oktober wurde versehentlich auf 19.3.4 statt 19.3.5 aktualisiert. Am 22. Oktober folgte das Upgrade auf 19.3.6 — das ebenfalls nicht half, weil Alpines eigenes GitLab-Image das Standard-Ruby der Distribution nutzt, nicht GitLabs gepatchtes. Erst das am 27. Oktober veröffentlichte Image mit Ruby 3.3.13 schloss die Lücke.

Post-Exploitation-Impact

  1. Befehlsausführung als git — das Konto, dem alle Repository-Daten, Uploads und das Arbeitsverzeichnis der Anwendung gehören.
  2. Offenlegung von Secrets — CI/CD-Variablen, Runner-Registrierungs- und Authentifizierungs-Tokens, Webhook- und Integrations-Zugangsdaten, Zugangsdaten für Push-Mirrors und 2FA-Secrets (Alpines eigene Liste potenziell offengelegter Daten).
  3. Diebstahl von Quellcode — private Repositories, vertrauliche Issues und Merge Requests.
  4. Manipulation der Lieferkette — Änderung von Code, CI-Definitionen oder Release-Artefakten, sodass nachgelagerte Builds den Payload des Angreifers ausliefern.
  5. Pivot in die Build-Infrastruktur — Runner-Tokens und als CI/CD-Variablen gespeicherte Cloud-Zugangsdaten öffnen den Weg von GitLab zu den Deployment-Zielen.
  6. Wiederverwendung von Zugangsdaten — Passwort-Hashes der Benutzer; Alpine merkt an, dass der Angreifer auch Passwörter ausprobierte, die von anderen Seiten geleakt waren.

📊 Impact-Bewertung

Unmittelbarer Impact

  • Vollständige Kompromittierung einer selbst betriebenen GitLab-Instanz durch jeden, der in ein öffentliches Projekt pushen — oder eines anlegen — kann.
  • Ein erfolgreicher Exploit hinterlässt kaum Spuren: Laut Alpine erzeugt er keinen Absturz und keinen Eintrag im Web-Log, nur die gescheiterten Versuche sind laut.
  • Eine aktualisierte GitLab-Versionsnummer garantiert bei selbst kompilierten Installationen und eigenen Images keinen Fix.

Betroffene Versionen

KomponenteBetroffenBehoben
GitLab CE/EE 19.4 (CVE-2026-97229)19.4.0 — 19.4.119.4.2
GitLab CE/EE 19.3 (CVE-2026-97229)19.3.0 — 19.3.419.3.5
GitLab CE/EE 19.2 (CVE-2026-97229)19.2.0 — 19.2.719.2.8
GitLab CE/EE (CVE-2026-110264)alle ab 7.019.5.1, 19.4.3, 19.3.6, 19.2.9, 19.1.9, 19.0.10, 18.11.13
GitLab CE/EE 18.10 und älter—Kein Fix; Upgrade auf eine unterstützte Linie
Ruby (selbst kompiliert / eigene Images)3.3 < 3.3.13, 3.4 < 3.4.12, 4.0 < 4.0.93.3.13, 3.4.12, 4.0.9
Ruby 3.2betroffenKein Fix geplant
GitLab.com / GitLab Dedicated—Bereits gepatcht, keine Aktion nötig

Die aktuellen Patch-Releases zum Zeitpunkt der Veröffentlichung sind 19.5.3, 19.4.5, 19.3.7, 19.2.10, 19.1.10, 19.0.11 und 18.11.14 (GitLab hat 19.5.2 und 19.4.4 übersprungen). Sie enthalten beide Regex-Fixes sowie einen davon unabhängigen Fix zum Zertifikatsvertrauen (CVE-2026-111943). Der einfachste Weg, abgedeckt zu sein, ist ein direktes Upgrade auf den neuesten Patch Ihrer Linie.

Betroffene Umgebungen

  • Instanzen mit offener Selbstregistrierung — die Schreibvoraussetzung des öffentlichen Exploit-Pfads kostet den Angreifer eine Registrierung.
  • Open-Source- und Community-Instanzen mit öffentlichen Projekten, wie die von Alpine.
  • Selbst kompiliertes GitLab und eigene Container-Images, die ihr eigenes Ruby mitbringen — das GitLab-Upgrade transportiert den Fix nicht.
  • Aus dem Internet erreichbare Instanzen im Allgemeinen. Shadowserver verfolgt knapp 2.800 aus dem Internet erreichbare Instanzen der GitLab Community Edition.
  • Interne Instanzen sind für jeden Insider, Dienstleister oder kompromittierten Entwickler-Account erreichbar, der in ein öffentliches oder internes Projekt pushen kann.

Angreiferprofile

  • Supply-Chain-Akteure, die Open-Source-Infrastruktur ins Visier nehmen — der Angreifer bei Alpine lud das Container-Image des Ziels herunter, um den Exploit anzupassen.
  • Initial Access Broker und Ransomware-Affiliates, für die ein GitLab-Server ein wertvoller Brückenkopf mit Zugangsdaten zu allem ist, was von dort deployt wird.
  • Spionage-Akteure, die an Quellcode und den in CI/CD hinterlegten Secrets interessiert sind.
  • Opportunistische Angreifer, die den öffentlichen PoC gegen Instanzen mit offener Registrierung einsetzen.

🛡️ Mitigationsstrategien

Sofortmaßnahmen (Priorität 1)

1. Exakte GitLab-Version ermitteln (und bei Source-Installationen auch Ruby).

# Linux-Paket (Omnibus): gibt GitLab-, GitLab-Shell- und Systeminformationen aus.
# Die Zeile "Version:" unter "GitLab information" und die Zeile "Ruby Version:" pruefen.
sudo gitlab-rake gitlab:env:info

# Docker: denselben Rake-Task im Container ausfuehren (<container> durch dessen Namen ersetzen)
docker exec <container> gitlab-rake gitlab:env:info

# Remote ueber die REST-API (erfordert ein Access Token);
# das Feld "version" liefert z. B. "19.4.5-ee"
curl --request GET \
  --header "PRIVATE-TOKEN: <your_access_token>" \
  --url "https://gitlab.example.com/api/v4/metadata"
# Selbst kompilierte Installation: im GitLab-Verzeichnis (z. B. /home/git/gitlab) als git-Benutzer ausfuehren
bundle exec rake gitlab:env:info RAILS_ENV=production

# Selbst kompiliert oder eigenes Image: Das Ruby, mit dem GitLab tatsaechlich laeuft, muss
# 3.3.13, 3.4.12, 4.0.9 oder neuer sein -- die GitLab-Version allein beweist hier nichts
ruby -v

Gleichen Sie das Ergebnis mit der Tabelle oben ab. Beim Linux-Paket und den offiziellen Images ist GitLabs gepatchtes Ruby Teil des Releases — dort zählt die GitLab-Version. Bei selbst kompilierten Installationen und eigenen Images müssen beide Versionen gefixt sein.

2. Auf den neuesten Patch-Release Ihrer Linie aktualisieren.

# Debian/Ubuntu, Linux-Paket -- exakte Version festlegen (Beispiel: neuester 19.4-Patch).
# Fuer die Community Edition gitlab-ce=19.4.5-ce.0 verwenden.
sudo apt update && sudo apt install gitlab-ee=19.4.5-ee.0

# RHEL / AlmaLinux / Oracle Linux 9 -- auf Version 8 .el8 verwenden
sudo dnf install gitlab-ee-19.4.5-ee.0.el9

# Docker: das gefixte Image-Tag ziehen, dann den Container damit neu erstellen
docker pull gitlab/gitlab-ce:19.4.5-ce.0

Single-Node-Instanzen haben während dieses Upgrades eine Downtime, weil die Datenbank-Migrationen abgeschlossen sein müssen, bevor GitLab startet; Multi-Node-Setups können das Zero-Downtime-Verfahren nutzen. Ein GitLab-Upgrade aktualisiert den GitLab Runner nicht — selbst betriebene Runner separat aktualisieren.

3. Wer eigenes Ruby betreibt, muss auch Ruby aktualisieren. Für selbst kompilierte Installationen und eigene Images Ruby 3.3.13, 3.4.12 oder 4.0.9 (oder neuer) aus Distribution oder eigenem Build installieren. Alpine-basierte Images: apk upgrade liefert Ruby 3.3.13 auf Alpine 3.21 und 3.4.12 auf 3.22, 3.23, 3.24 und edge. Nutzer von alpinelinux/gitlab:19.3.6 müssen das Image neu ziehen — nur Images, die am 27. Oktober oder später veröffentlicht wurden, enthalten das gefixte Ruby.

4. Bis zum Patch: den billigen Schreibpfad entfernen. Rapid7 empfiehlt, den anonymen Zugriff auf öffentliche Projekte einzuschränken und nicht vertrauenswürdige Benutzer daran zu hindern, öffentliche Projekte anzulegen oder in sie zu schreiben. Als Administrator:

# Selbstregistrierung deaktivieren und Nicht-Admins die Sichtbarkeitsstufe "public" verbieten.
# Erfordert ein Administrator-Token. Bestehende oeffentliche Projekte behalten ihre Sichtbarkeit --
# diese separat pruefen (Admin-Bereich > Projekte, nach Sichtbarkeit filtern).
curl --request PUT \
  --header "PRIVATE-TOKEN: <admin_access_token>" \
  --url "https://gitlab.example.com/api/v4/application/settings" \
  --data "signup_enabled=false" \
  --data "restricted_visibility_levels[]=public"

Das Blockieren der Route /api/v4/projects/:id/ci/lint an einem Reverse Proxy oder einer WAF unterbricht den demonstrierten Trigger. Rapid7 stellt aber ausdrücklich klar, dass diese Maßnahmen nur den demonstrierten Zustellweg adressieren und den verwundbaren Regex-Compiler nicht beheben. Sie verschaffen Zeit; sie sind kein Fix.

Detection-Maßnahmen

GitLab hat Threat Detections für selbst betriebene Instanzen veröffentlicht — darunter „Onigmo native worker crash” und „Org mode render error burst” — in seinem offenen TLDR-Detection-Repository. Die folgenden Prüfungen setzen die von Rapid7 veröffentlichten Indikatoren auf einer Linux-Paket-Installation um (Standard-Logpfade):

# 1. Anonyme CI-Lint-Requests, die mit HTTP 502 endeten -- das erwartete Ergebnis des PoC.
#    Workhorse schreibt JSON-Access-Logs; Zeitraum an die eigene Aufbewahrung anpassen.
sudo grep -E '/api/v4/projects/[^ "]+/ci/lint' /var/log/gitlab/gitlab-workhorse/current \
  | grep -E '"status":502'

# 2. Der passende Workhorse-Fehler, wenn der Puma-Worker mitten im Request abgestuerzt ist
sudo grep -F 'badgateway: failed to receive response' /var/log/gitlab/gitlab-workhorse/current

# 3. Alle CI-Lint-API-Aufrufe auf Rails-Seite, um Projekt, Ref und Client-IP zu korrelieren
sudo grep -F '/ci/lint' /var/log/gitlab/gitlab-rails/api_json.log

# 4. Ruby-/Onigmo-Abstuerze von Puma-Workern -- ein Trace mit regexp_matcher.rb ist ein starkes Signal
sudo grep -E -i 'onigmo|regexp_matcher\.rb|\[BUG\]|Segmentation fault' /var/log/gitlab/puma/puma_stderr.log

GitLabs Empfehlungen nach einer möglichen Kompromittierung nennen die Stellen, an denen man auf dem Host selbst suchen sollte:

# 5. Dateien des git-Benutzers in Temp-Verzeichnissen, angelegt seit dem Release 19.4.2
sudo find /tmp /var/tmp -user git -newermt '2026-10-12' -ls

# 6. Prozessbaum des git-Benutzers -- eine Shell, curl, wget oder python unterhalb eines
#    Puma-/Sidekiq-Ruby-Prozesses ist der staerkste Indikator fuer eine erfolgreiche Ausnutzung
ps -u git -o pid,ppid,etime,args --forest

# 7. Crontab des git-Benutzers -- auf Eintraege achten, die niemand im Team angelegt hat
sudo crontab -l -u git

# 8. Bestehende TCP-Verbindungen mit zugehoerigem Prozess -- auf Shells oder Download-Tools
#    des git-Benutzers achten, die mit unerwarteten Zielen sprechen
sudo ss -tnp | grep -E 'users:\(\("(sh|bash|dash|curl|wget|python3?|perl)"'

Prüfen Sie außerdem die SSH-Keys des git-Benutzers auf unerwartete Einträge, und denken Sie an Alpines Warnung: Ein erfolgreicher Exploit hinterlässt womöglich keine der oben genannten Absturzspuren.

# Sigma-Regel -- Shell oder Download-Tool, gestartet von GitLabs Ruby-Prozessen (Linux Process Creation).
# Nur ein Ausgangspunkt: legitime Kindprozesse der eigenen Umgebung vor dem Alerting ausfiltern.
title: Shell Spawned by GitLab Ruby Process as git User
id: 2f6d7a4e-3c1b-4b8e-9a51-7e0c2d9f4a10
status: experimental
description: Detects a shell or download tool started by the GitLab embedded Ruby (Puma/Sidekiq) as the git user, as seen in CVE-2026-97229 exploitation.
references:
  - https://www.rapid7.com/blog/post/ra-gitlab-ci-cd-regex-integer-overflow-technical-analysis-cve-2026-97229/
logsource:
  product: linux
  category: process_creation
detection:
  selection_parent:
    ParentImage|endswith: '/opt/gitlab/embedded/bin/ruby'
    User: 'git'
  selection_child:
    Image|endswith:
      - '/sh'
      - '/bash'
      - '/dash'
      - '/curl'
      - '/wget'
      - '/python3'
      - '/perl'
  condition: selection_parent and selection_child
level: high
tags:
  - attack.execution
  - attack.t1059.004
  - cve.2026-97229

Wenn Sie Hinweise auf Codeausführung finden, folgen Sie GitLabs Empfehlung: die Secrets in gitlab-secrets.json, alle CI/CD-Variablen, Runner-Tokens und Access Tokens rotieren — und, wie Alpine, einen Neuaufbau der Instanz statt einer Bereinigung in Betracht ziehen.

Langfristige Sicherheitsverbesserungen

  1. Die mitgelieferte Runtime als Teil des Produkts behandeln. Das Ruby (und andere Interpreter) in Ihrem GitLab-Image in SBOM und Patch-Prozess erfassen — insbesondere bei selbst kompilierten Installationen und eigenen Images.
  2. Kritische GitLab-Releases innerhalb eines Tages einspielen. Alpines eigene Lektion; jede Release Note auf Ruby- oder andere Komponenten-Patches prüfen, die der eigene Build übernehmen muss.
  3. Offene Registrierung schließen oder für neue Registrierungen eine Admin-Freigabe verlangen (require_admin_approval_after_user_signup), und neue Projekte standardmäßig privat anlegen.
  4. Ausgehende Verbindungen protokollieren — vom GitLab-Host und zur Datenbank — und Logs länger als 14 Tage aufbewahren; Alpine fehlten Logs vom Tag des Angriffs.
  5. Secrets in CI/CD-Variablen minimieren: kurzlebige, OIDC-basierte Zugangsdaten statt langlebiger Cloud-Keys bevorzugen.
  6. Release-Tags und Artefakte signieren, damit Releases unabhängig vom GitLab-Server verifiziert werden können.
  7. Den GitLab-Host isolieren von Produktivnetzen; ein kompromittierter GitLab-Server sollte nicht alles erreichen können, wohin er deployt.
  8. Passwörter nie wiederverwenden — der Angreifer bei Alpine probierte auch anderswo geleakte Zugangsdaten aus.

⚠️ Warum ist das kritisch?

  1. Maximaler Schweregrad, bestätigte Ausnutzung — CVSS 10.0 und im CISA-KEV-Katalog mit einer Frist von drei Tagen für US-Bundesbehörden.
  2. Ein öffentlicher, funktionierender PoC — Rapid7s Kette führt auf dem offiziellen 19.4.1-Image zuverlässig Befehle aus.
  3. In der Praxis „unauthentifiziert” auf jeder Instanz mit offener Registrierung und öffentlichen Projekten.
  4. Der Patch kann still ins Leere gehen — eigene Images und selbst kompilierte Installationen brauchen ein Ruby-Upgrade, das die GitLab-Versionsnummer nicht verrät.
  5. Zwei CVSS-10.0-Bugs in derselben Engine innerhalb von neun Tagen — die Patches vom 12. Oktober decken CVE-2026-110264 nicht ab.
  6. Explosionsradius in der Lieferkette — Quellcode, CI/CD-Secrets und der Weg zu jedem Deployment-Ziel liegen auf demselben Server.

📅 Timeline und Disclosure

  • 2026-10-12 — GitLab veröffentlicht 19.4.2, 19.3.5 und 19.2.8 und behebt CVE-2026-97229 (über HackerOne gemeldet von joaxcar) mit einem gepatchten Ruby in Paketen und Images.
  • 2026-10-13 — Rapid7 veröffentlicht seine Einschätzung und einen öffentlichen PoC; Help Net Security ruft Admins zum Patchen auf. Alpine Linux aktualisiert versehentlich auf 19.3.4 statt 19.3.5.
  • 2026-10-16 — Rapid7 veröffentlicht seine vollständige technische Analyse.
  • 2026-10-20 / 21 — Ein Angreifer sendet präparierte CI-Konfigurationen an Alpines GitLab; acht Worker-Abstürze, 502-Fehler und fehlgeschlagene CI-Jobs.
  • 2026-10-21 — GitLab veröffentlicht 19.5.1, 19.4.3, 19.3.6, 19.2.9, 19.1.9, 19.0.10 und 18.11.13 und behebt die Geschwister-Lücke CVE-2026-110264 (alle Versionen ab 7.0).
  • 2026-10-22 — Alpine aktualisiert auf 19.3.6, bleibt aber verwundbar, weil das Image Standard-Ruby nutzt.
  • 2026-10-23 — Ruby veröffentlicht 4.0.9, 3.4.12 und 3.3.13 mit den Regex-Fixes; Alpine sperrt das Konto des Angreifers.
  • 2026-10-25 / 26 — Die Versuche des Angreifers, wieder Zugang zu erlangen, scheitern; Alpine stellt fest, dass die Instanz weiterhin verwundbar ist.
  • 2026-10-27 — Alpine beschränkt GitLab auf Entwickler und Build-Server, baut neu auf und veröffentlicht alpinelinux/gitlab:19.3.6 mit Ruby 3.3.13.
  • 2026-10-28 — Alpine schließt den Neuaufbau ab, rotiert Secrets und veröffentlicht seinen Incident-Bericht.
  • 2026-10-29 — CISA nimmt CVE-2026-97229 in den KEV-Katalog auf; GitLab bestätigt Ausnutzungsversuche und veröffentlicht Detections.
  • 2026-11-01 — Frist zur Behebung für zivile US-Bundesbehörden.

📚 Ressourcen und Referenzen

🤝 SEKurity Unterstützt Sie

Die meisten Organisationen schützen ihr GitLab wie ein internes Werkzeug — und das ist es ganz und gar nicht. Dort liegt Ihr Quellcode, dort sind Ihre Deployment-Zugangsdaten gespeichert, und dort beginnt Ihr Release-Prozess. CVE-2026-97229 zeigt, wie schmal der Grat ist: ein öffentliches Projekt, eine präparierte Regex, und ein anonymer Request macht aus dieser Plattform die des Angreifers.

Die sinnvollen Fragen dieser Woche sind konkret. Kann sich jeder aus dem Internet ein Konto auf Ihrem GitLab anlegen? Welche öffentlichen Projekte gibt es, und wer darf in sie pushen? Nutzt Ihr GitLab-Image GitLabs Ruby oder Ihr eigenes? Welche Secrets liegen in CI/CD-Variablen, und was könnte eine git-Shell damit anfangen? Und hätten Ihre Logs acht Worker-Abstürze in einer Mittwochnacht gezeigt — und hätte jemand hingesehen?

Wir testen DevOps-Plattformen und CI/CD-Pipelines aus der Perspektive des Angreifers — unauthentifiziert von außen, mit einem Entwickler-Account und von einem kompromittierten Runner aus — und zeigen Ihnen, wie weit ein Brückenkopf in Ihrer Toolchain tatsächlich reicht. Wenn Ihr GitLab noch nie Teil eines Penetrationstests war, ist diese Woche der richtige Zeitpunkt, das zu ändern.

Unsere Leistungen

  • Penetration Testing: Web-Anwendungen, mobile Apps (Android & iOS), SAP-Systeme, Active Directory
  • Groß angelegte Angriffe: Perimeter-Tests, IT-Infrastruktur-Tests, Red-Team-Engagements
  • Security Awareness: Phishing-Kampagnen, Hacking-Demonstrationen

Handeln Sie jetzt — bevor es Angreifer tun.


Kontakt:

Website: www.sekurity.de

Anfragen: www.sekurity.de/contact

LinkedIn: SEKurity GmbH


Ihr SEKurity Team — Your Trusted Adversaries

Die Sicherheit Ihrer DevOps-Plattformen und Ihrer Software-Lieferkette ist unser Antrieb.


Quellen

Über den Autor

SEKurity Team

Offensive Security Experten

Das SEKurity GmbH Team besteht aus erfahrenen Penetrationstestern, Security-Forschern und Cybersecurity-Beratern. Unter dem Motto 'Your Trusted Adversaries' unterstützen wir Organisationen dabei, ihre IT-Sicherheit aus der Perspektive eines Angreifers zu bewerten und zu verbessern.

Verwandte Artikel

CVE-Forschung

InSEKurity of the Week (CW37/2026): N-able N-central Pre-Auth RCE ueber Struts-BeanUtils-Race (CVE-2026-86218)

Zwei gleichzeitige Multipart-Requests an eine unauthentifizierte Struts-Action liefern einem Angreifer Jettys laufende Konfiguration -- und damit eine Shell auf dem System, das jeden Endpunkt eines MSP verwaltet. CVSS 10.0, vor der Offenlegung ausgenutzt, seit dem 8. September im CISA-KEV-Katalog -- der vierte N-central-Hotfix in fuenf Wochen.

Von sekurity-teamWeiterlesen →