Rapid7 turns GitLab's perfect-10 bug into working exploit

Published

Rapid7 researchers have built a working exploit for CVE-2026-97229, the CVSS 10.0 GitLab flaw patched on October 12, and their write-up adds an important caveat: the route they demonstrated only works after the attacker has already pushed content to a public project.

In a technical analysis by Jonah Burgess, Rapid7 says its proof of concept reliably runs arbitrary commands as GitLab's git operating-system account on the official gitlab/gitlab-ce:19.4.1-ce.0 Linux amd64 image, with ASLR enabled. The bug, reported to GitLab through HackerOne by joaxcar, is an integer overflow in how GitLab CI/CD handles regular expressions. GitLab described it as allowing code execution by an unauthenticated user. GitLab's release notes do not report exploitation in the wild at the time of disclosure.

The trigger is unauthenticated, the setup is not

In Rapid7's chain, the attacker first commits a malicious CI configuration and a specially named file to a public project. Only the final step, a request to GitLab's CI lint API, needs no login: on a public project that endpoint reads an attacker-chosen commit and evaluates its CI rules without creating a pipeline or contacting a runner. Rapid7 notes that requiring write access conflicts with GitLab's "no privileges required" rating, and because the original report is still private, it does not yet know how the reported attack avoids that step. The prerequisite narrows who can use this particular route. It does not make an unpatched server safe.

How a regex becomes a shell

GitLab already caps the size and repeat counts of CI regular expressions. Rapid7 found two ways past those checks. An inline regex comment, written as {5(?#)7805}, splits a repeat count so GitLab's scanner never sees a number above 1,000, while Ruby's Onigmo regex engine ignores the comment and reads 57,805. Then a repository path containing four-byte UTF-8 characters makes Ruby recompile the pattern for UTF-8, expanding its character classes into large Unicode tables. GitLab never checks the size of that recompiled program, and the recompile happens before the 50-millisecond match timeout starts. The overflow lets the researchers steer Onigmo's own bytecode, recover a pointer inside libruby and redirect execution to system(). The worker then crashes, so the attacker sees an HTTP 502 after the command has already run.

Rapid7 says its offsets are specific to GitLab CE 19.4.1 on Linux amd64, other builds need adjusted values, and the exploit needs a little over 2 GiB of memory in the worker. We covered the original patch release when it shipped. A repeat-range double-free fixed in the same release is not part of this chain.

Upgrade to 19.4.2, 19.3.5 or 19.2.8

Affected releases are GitLab CE and EE 19.2 before 19.2.8, 19.3 before 19.3.5, and 19.4 before 19.4.2. GitLab.com was patched before disclosure and Dedicated customers do not need to act. Self-managed administrators should upgrade. As a temporary measure, Rapid7 suggests restricting credential-free access to public projects that attackers can write to, or blocking the CI lint route, while stressing that route controls do not repair the vulnerable Ruby compiler.

For detection, Rapid7 recommends correlating, in /var/log/gitlab/gitlab-workhorse/current, a several-second GET to /api/v4/projects/<project>/ci/lint?content_ref=<ref> ending in "badgateway: failed to receive response: EOF" and HTTP 502, with a Puma worker crash or restart at the same moment, a saved trace naming regexp_matcher.rb, a shell child process, or a jump of roughly 2 GiB in worker memory. The referenced commit would carry a (?#)-split repeat, repeated POSIX word classes and a path with four-byte UTF-8 characters. Rapid7 cautions that the undisclosed original route may look different.

With the mechanism now laid out step by step by a third party, the window in which an unpatched GitLab server is merely theoretically exposed is closing.

This briefing is provided by IntelFusions for informational and defensive purposes only. It is based on sources assessed to be reliable at the time of writing, and analytic judgments carry the confidence levels indicated. Indicators of compromise are defanged; re-arm them only in controlled environments. IntelFusions is not affiliated with the organizations named and makes no warranty as to completeness or accuracy.

Read the full analysis on IntelFusions