Skip to content
GitLab Oj Spill

GitLab Oj Spill

Depthfirst July 25, 2026

GitLab RCE · Found autonomously by depthfirst through the Open Defense Initiative

As part of the Open Defense Initiative , the depthfirst system analyzed Oj, a high-performance JSON parser with a substantial native C implementation, and produced a prioritized queue of potentially exploitable findings. The system surfaced 18 prioritized vulnerabilities, including 7 memory-safety bugs. Two of them, an out-of-bounds write and a heap-pointer disclosure, had survived in Oj for nearly five years. Oj is a low-level dependency used by GitLab, and we combined the two bugs to achieve remote code execution on a default GitLab installation.

Any authenticated user who can commit changes can trigger the vulnerability and execute commands. GitLab reaches the vulnerable code through its in-tree ipynbdiff gem, which renders diffs of Jupyter .ipynb notebooks. A crafted notebook, viewed on its commit diff page, feeds attacker-controlled bytes straight into Oj’s C parser inside a Puma worker.

A GitLab installation is affected when its notebook transformer calls Oj::Parser.usual.parse and it bundles Oj 3.13.0 through 3.17.1.

All GitLab tiers are affected, including CE and EE across Free, Premium, and Ultimate. GitLab.com was patched by the June 10 release. Ruby itself is not affected; the vulnerabilities are in Oj’s native C extension.

Upgrade self-managed GitLab to a current supported patch release. The fixes first shipped in GitLab 18.10.8, 18.11.5, and 19.0.2, all of which bundle Oj 3.17.3.

If you manage Oj directly, upgrade to Oj 3.17.3 or later . Version 3.17.3 was the first published release containing both fixes.

For Helm and Operator deployments, check the GitLab application version in the Webservice image rather than the chart or Operator version.

Use depthfirst Supply Chain to identify affected Oj versions across direct and transitive dependencies.

Both bugs live in Oj’s native C parser, and the depthfirst system surfaced both autonomously during an automated review of Oj’s source. Human analysis then chained them into a working exploit.

The first is an out-of-bounds write. The parser tracks array and object nesting in a fixed 1,024-byte stack inside its parser struct and increments the depth with no bounds check. A deeply nested notebook sweeps one-byte selectors forward through the struct, and because each written byte reads back as a valid selector, the sweep sustains itself until it rewrites an interior heap pointer.

The second is a heap-pointer disclosure. An overlong JSON key narrows through a signed 16-bit length field, so the read returns inline bytes that overlap a live external key pointer. GitLab echoes that pointer back through the rendered notebook diff, which leaks a heap address and defeats ASLR.

Chained together, the leak locates libc and libruby, and the write redirects the parser’s start callback into system() , executing an attacker-controlled command as git .

In addition to the two bugs used in this chain, depthfirst’s broader Oj review produced nine additional CVE advisories: CVE-2026-54502, CVE-2026-54896, CVE-2026-54897, CVE-2026-54898, CVE-2026-54899, CVE-2026-54900, CVE-2026-54901, CVE-2026-54902, and CVE-2026-54903.

Read the full technical analysis

These vulnerabilities were discovered autonomously by the depthfirst platform as part of the Open Defense Initiative. We thank the Oj maintainer and the GitLab security team for their responsiveness throughout coordinated disclosure.

Check your GitLab version against the table above and confirm the bundled Oj version is between 3.13.0 and 3.17.1. You are in scope if the GitLab tree contains the Oj::Parser.usual.parse notebook transformer call and bundles an affected Oj release. For Helm and Operator installs, judge the actual Webservice/Puma image’s GitLab version, not the chart number.

depthfirst is not aware of in-the-wild exploitation. This was a coordinated private disclosure through the Open Defense Initiative, and GitLab independently reproduced the RCE.

The vulnerable notebook-diff code path also existed on GitLab.com. GitLab had patched GitLab.com by the June 10 release, so GitLab.com users do not need to take action. Operators of affected self-managed installations must upgrade to a fixed release.

No. The bugs are in Oj, a native C extension that GitLab depends on, not in Ruby core.

Our full root-cause analysis, proof of concept, and patch walkthrough are in the technical research post .