Skip to content
Researcher Publishes GitLab RCE PoC Letting Authenticated Users Run Commands as Git

Researcher Publishes GitLab RCE PoC Letting Authenticated Users Run Commands as Git

Swati KhandelwalJul 25, 2026Vulnerability / Application Security

Security researcher Yuhang Wu at depthfirst has published a working proof-of-concept (PoC) exploit that executes commands as git on an unpatched self-managed GitLab 18.11.3 server.

An ordinary authenticated user triggers it by committing two crafted Jupyter notebooks and requesting their diff. The chain needs no administrator rights, continuous integration (CI) runner access, victim interaction, or access to another user’s project.

The public exploit is build-specific to GitLab 18.11.3 on x86-64; the underlying Oj bugs affect broader releases. The affected ranges are GitLab Community Edition (CE) and Enterprise Edition (EE) 15.2.0 through 18.10.7, 18.11.0 through 18.11.4, and 19.0.0 through 19.0.1.

The first fixed releases are 18.10.8, 18.11.5, and 19.0.2. Oj is a high-performance JSON parser for Ruby with substantial native C code.

Published gems 3.13.0 through 3.17.1 are vulnerable; 3.17.3 is the first published release containing both fixes. The flaws affect Free, Premium, and Ultimate. Ruby itself is not affected.

Successful exploitation runs as git. Its effective reach depends on deployment isolation, but may include source code, Rails secrets, service credentials, CI/CD data, and internal services reachable from the application. GitLab.com was patched by June 10.

Dedicated customers need no action. Self-managed operators should move to a supported release containing the fix. Helm and Operator users need to check the GitLab version inside the Webservice image, not only the chart or Operator version. depthfirst said it was unaware of in-the-wild exploitation as of July 24.

Neither the depthfirst disclosure nor GitLab’s June 10 release notes list CVE identifiers or CVSS scores for the two chain bugs. Neither provides a temporary workaround; both direct self-managed operators to upgrade.

The Hacker News has asked GitLab about CVE status, classification, and exploitation evidence. It also asked depthfirst about exploit portability and whether a supported temporary mitigation exists. Responses are pending. depthfirst lists nine CVEs for other Oj flaws found in the same review.

GitLab’s notebook renderer passes repository-controlled .ipynb JSON to Oj::Parser.usual.parse inside a long-lived Puma worker. That sends attacker-controlled notebook data into Oj’s native parser state inside GitLab’s application process.

depthfirst‘s technical analysis shows how one bug controls a callback pointer, while the other leaks a heap address needed to narrow the address space layout randomization (ASLR) search.

Oj stores nesting state in a fixed 1,024-byte stack but never checks whether the depth exceeds it. Deeply nested arrays can therefore write 0x01 bytes into adjacent parser state. The exploit corrupts buf.head, causing Oj to pass a forged interior pointer to realloc(). A later Ruby Array allocation reclaims the same 3,584-byte jemalloc region and overwrites p->start.

Oj allocates a 65,565-byte object key, truncates its length to 29 in a signed 16-bit field, and returns 29 bytes containing the live key-allocation pointer. GitLab carries that pointer into the rendered notebook diff, giving the exploit the address leak needed to narrow the ASLR search. On the profiled two-worker GitLab 18.11.3 installation, the search usually took five to ten minutes. The researchers projected one to two hours across the widest mature-worker range.

Two lexically ordered notebook files in one diffs_stream request keep both stages inside the same Puma worker, which reuses the process-global Oj parser. The first file corrupts the callback and raises an error that GitLab catches before continuing the diff. The next parse invokes the overwritten pointer and reaches system() through a build-specific gadget sequence.

The public demonstration packages the chain in a local GitLab 18.11.3 x86-64 lab and makes the Puma worker connect back as git.

depthfirst reported the Oj bugs on May 21, and the maintainer merged the fixes on May 27. Oj 3.17.3 shipped on June 4. The researchers reported the GitLab chain on June 5; depthfirst said GitLab confirmed it on June 8.

GitLab released the fixed versions on June 10 and resolved the report on July 17, according to depthfirst. A review by The Hacker News found GitLab listed the Oj 3.17.3 bump under bug fixes rather than in the security-fix table and did not describe the notebook-diff RCE chain.

Source link