A newly disclosed GitLab vulnerability has revealed how two long-standing memory-safety flaws in the widely used Ruby JSON parsing library, Oj, can be combined to achieve remote code execution on default GitLab installations.
The research, led by Yuhang Wu as part of the Open Defense Initiative, demonstrates how attackers could exploit Jupyter Notebook file processing to execute arbitrary commands, potentially exposing repositories, application secrets, and internal services.
Yuhang Wu Discovers GitLab Vulnerability in Oj Parser
As part of the Open Defense Initiative, Depthfirst researcher Yuhang Wu used an automated analysis system to examine Oj, a high-performance native C-based JSON parser used across Ruby applications, including GitLab. The analysis identified 18 prioritised vulnerabilities, seven of which were memory-safety issues. Two of these flaws had remained undetected for nearly five years before being combined into a working exploit chain.
The vulnerabilities included an unchecked nesting-stack write in Oj::Parser.usual.parse and an unsafe 16-bit key-length narrowing issue that leaked a heap pointer. Individually, the bugs appeared limited, offering only a repeated one-byte write primitive and a fixed 29-byte memory disclosure.
However, by carefully manipulating heap allocation, the exploit gained control of a callback pointer and bypassed Address Space Layout Randomisation (ASLR), enabling arbitrary code execution as the “git” system user.
Jupyter Notebook Processing Creates Attack Path
The GitLab vulnerability stems from the platform’s handling of Jupyter Notebook (.ipynb) files. GitLab uses an in-tree gem called ipynbdiff to generate human-readable notebook differences. Before displaying a diff, the gem parses each notebook with Oj to verify that the JSON contains a “cells” field.

Because Jupyter Notebook files are JSON documents, any authenticated user with permission to push commits and view commit differences could submit specially crafted notebook files. The exploit chain used two malicious notebook files in a single commit-diff request. The first abused excessive nesting depth to corrupt an internal buffer pointer, eventually allowing a Ruby Array to overlap with a parser callback pointer and overwrite p->start with an attacker-controlled address.
The second file leaked a heap pointer through an oversized JSON object key that appeared in the generated HTML diff. This disclosed the memory addresses of libraries such as libc and libruby, defeating ASLR. Since GitLab’s Puma application server processes multiple threads using a shared parser instance, both files were handled by the same vulnerable parser, allowing the corrupted callback to invoke system() and execute shell commands.
Unlike previous GitLab remote code execution vulnerabilities that depended on server-side request forgery (SSRF) against Redis, this GitLab vulnerability bypassed modern SSRF protections by targeting a native memory-unsafe dependency within Ruby code. Any project member with standard push and diff-view permissions could trigger the attack without administrator privileges, CI/CD access or user interaction.
According to Depthfirst, successful exploitation could expose repository source code, Rails secrets, service credentials, and internal services, creating risks of data theft, code tampering, and lateral movement.
Affected Versions and Available Fixes
The GitLab vulnerability affects GitLab CE/EE versions 15.2.0-18.10.7, fixed in 18.10.8; 18.11.0-18.11.4, fixed in 18.11.5; and 19.0.0-19.0.1, fixed in 19.0.2. The Oj gem is affected from versions 3.13.0-3.17.1 and fixed in version 3.17.3.
GitLab.com had already been patched before disclosure, while GitLab Dedicated customers required no action. Self-managed deployments running affected versions should upgrade immediately. The vulnerable Oj code was introduced in August 2021, with GitLab adopting the affected parser in July 2022 through version 15.2.0.
Yuhang Wu reported the Oj flaws on 21 May 2026 after they had remained undiscovered for 1,753 days. Oj merged fixes on 27 May, released version 3.17.3 on 4 June, and the GitLab exploit chain was reported on 5 June, confirmed on 8 June and patched on 10 June 2026 in releases 19.0.2, 18.11.5 and 18.10.8.
The same research also uncovered nine additional published CVEs affecting Oj, including stack and heap buffer overflows, use-after-free vulnerabilities, a negative-size memcpy flaw and a large-file integer overflow, highlighting the risks posed by memory-unsafe native extensions in Ruby applications.

