Das Ruby-Team hat die Versionen 4.0.9, 3.4.12 und 3.3.13 veröffentlicht. Sie beheben drei Fehler in der Regex-Engine Onigmo, über die Angreifer Schadcode auf betroffenen Servern ausführen können. Bekanntester Fall sind die kritischen GitLab-Lücken der vergangenen Wochen. Gefährdet ist aber jede Ruby-Anwendung, die reguläre Ausdrücke aus fremden Eingaben baut. Wer nur selbst geschriebene Muster nutzt, ist laut Ruby-Team nicht betroffen.
Wichtig für das Verständnis: Bevor Ruby ein Muster auf einen Text anwendet, übersetzt es das Muster in ein internes Programm. Die Fehler stecken in diesem Kompilierschritt, nicht erst im eigentlichen Abgleich.
Vier GitLab-CVEs, drei Ruby-Fehler
GitLab kompiliert reguläre Ausdrücke aus Nutzereingaben, etwa aus CI/CD-Konfigurationen. Der Sicherheitsforscher Johan Carlsson meldete über das Bug-Bounty-Programm vier Lücken: CVE-2026-89078 und CVE-2026-93577 mit CVSS 9,9 sowie CVE-2026-97229 und CVE-2026-110264 mit dem Höchstwert 10,0, die sich ohne Anmeldung ausnutzen lassen. GitLab hat sie zwischen dem 23. September und dem 21. Oktober geschlossen, indem es das mitgelieferte Ruby selbst gepatcht hat. Das jüngste Update betrifft alle GitLab-Versionen seit 7.0 aus dem Jahr 2014.
Das Ruby-Team ordnet die vier CVEs drei Fehlern zu:
- CVE-2026-89078: doppelte Speicherfreigabe beim Einlesen eines Musters
- CVE-2026-93577 und CVE-2026-97229: Ganzzahlüberlauf bei der Berechnung der Größe des kompilierten Programms
- CVE-2026-110264: Überlauf interner Zähler bei Mustern mit sehr vielen Wiederholungen
Neu sind die Korrekturen nicht. Die doppelte Speicherfreigabe ist seit Mai 2025 im Entwicklungszweig behoben und seit Ruby 4.0.0 in einem Release. Der Fix für die Zähler kam im April 2026, der für die Programmgröße im September 2026. In ein Release schafften es die beiden aber erst jetzt. Ruby 4.0.8 vom 22. Oktober enthielt den Fix für die Programmgröße als Teil eines Routine-Updates, ohne Hinweis auf Sicherheit. Einen Tag später folgte 4.0.9 mit dem letzten fehlenden Fix, und die Zweige 3.4 und 3.3 bekamen alle drei auf einmal. Ruby 3.3 erhält eigentlich nur noch Sicherheitskorrekturen, 3.3.13 ist ausdrücklich eine Ausnahme wegen der GitLab-CVEs. Für Ruby 3.2 und älter gibt es keine Updates mehr.
Wie eine Suchfunktion zum Einfallstor wird
Ein typisches Beispiel ist eine Suche in einem Rails-Controller, die Einträge im Speicher filtert:
regex = Regexp.new(params[:search].to_s)treffer = produkte.select { |name| regex.match?(name) }Der Parameter stammt direkt aus der Webanfrage. Nutzer können damit nach einem Wort suchen oder mit Ankern wie ^ und $ nach Anfang und Ende filtern. Sie bestimmen damit aber auch das Muster, das Ruby kompiliert, und ein Angreifer kann ein präpariertes Muster übergeben. Angewendet werden muss es dafür gar nicht: Der Speicherfehler passiert schon in Regexp.new. Dasselbe gilt für Regexp.union und für interpolierte Literale wie /#{params[:search]}/.
Im schlimmsten Fall läuft dann Code des Angreifers mit den Rechten des Ruby-Prozesses, also mit Zugriff auf Datenbank, Secrets aus der Umgebung und Dateisystem. Bei einem einzelnen Versuch ist ein Absturz des Prozesses wahrscheinlicher. Wiederholt wird daraus ein Denial of Service ohne Anmeldung. Aktive Angriffe melden bisher weder GitLab noch Ruby.
Oft braucht eine solche Suche gar keine Regex-Engine. Wer nur nach dem eingegebenen Text sucht, vergleicht einfach Zeichenketten:
suche = params[:search].to_streffer = produkte.select { |name| name.include?(suche) }Sonderzeichen sind dann ganz normale Zeichen. Muss eine Eingabe in ein festes Muster eingebaut werden, maskierst Du sie mit Regexp.escape. Den Aufbau des Musters bestimmst dann weiter Du:
regex = /\A#{Regexp.escape(params[:search].to_s)}/Timeout hilft nicht, nur das Update
Die Ruby-Dokumentation empfiehlt für fremde Muster bisher ein Timeout, weil sie nur vor Denial of Service warnt. Regexp.timeout bricht aber nur einen zu langen Abgleich ab. Die Fehler passieren vorher beim Kompilieren, dort greift das Timeout nicht. Auch eine Längenbegrenzung hilft laut Ruby-Team nicht zuverlässig, weil manche Fehler schon mit kurzen Mustern auslösbar sind. Wer nicht sofort aktualisieren kann, sollte keine Muster aus fremden Eingaben kompilieren.
Mit einem Versionsmanager ist das Update schnell erledigt: neue Version installieren, im Projekt eintragen, Gems neu bauen. Mit mise reichen für die Reihe 3.4 zwei Befehle:
mise use [email protected] installMit rbenv sind es drei: rbenv install 3.4.12, rbenv local 3.4.12 und bundle install. Steht die Version im Gemfile fest, passt Du dort die ruby-Zeile an. Docker-Images bekommen einen neuen Tag, Distributionspakete folgen mit eigener Verzögerung, und Bundles wie GitLab Omnibus liefern ihr Ruby mit dem Produkt-Update. Ob der Server wirklich die neue Version nutzt, zeigt ruby -v.
Keine Ruby-CVEs, keine Scanner-Warnung
Eigene CVE-Nummern hat das Ruby-Projekt bisher nicht beantragt. Dahinter steckt eine Grundsatzfrage: Ruby hat das Kompilieren fremder Muster immer als unsicher betrachtet. Aus dieser Sicht liegt die Schwachstelle in der Anwendung, nicht im Interpreter. Bei zwei ähnlichen Fehlern, CVE-2022-28738 und CVE-2024-27282, hat Ruby trotzdem CVEs vergeben, und die Dokumentation lässt bis heute offen, ob der Anwendungsfall unterstützt wird. Das Team will das jetzt klären und danach über CVEs entscheiden.
Für Dich als Betreiber hat das eine ganz praktische Folge. Die GitLab-CVEs beschreiben GitLab-Versionen, keine Ruby-Versionen. Schwachstellen-Scanner, die installierte Software mit CVE-Datenbanken abgleichen, finden zu einem alten Ruby 3.4.11 deshalb nichts und schlagen nicht an. Ob Du betroffen bist, erfährst Du nur aus dem Ruby-Advisory. Bis zu einer Entscheidung empfiehlt das Team, die GitLab-Kennungen zur Nachverfolgung zu nutzen.