Sitemap
0xK1L

0xK1L

GitLab’s Perfect-10 Bug: How a Regular Expression in a CI File Became Remote Code Execution

CVE-2026–97229 is an integer overflow in GitLab’s CI/CD regex compiler. Patched on October 12, exploited in the wild by the end of the month.

6 min read2 days ago

--

Press enter or click to view image in full size
GitLab’s Perfect-10 Bug: How a Regular Expression in a CI File Became Remote Code Execution

TL;DR: CVE-2026–97229 is a maximum-severity (CVSS 10.0) bug in self-managed GitLab CE and EE. A specially crafted regular expression in a CI/CD configuration triggers an integer overflow in GitLab’s CI/CD regex compiler and runs commands on the GitLab server. GitLab patched it on October 12, 2026. A public proof-of-concept followed, CISA added it to the KEV catalog on October 29 after exploitation was seen, and Shadowserver counted more than 1,000 unpatched, internet-exposed servers under attack.

Press enter or click to view image in full size
How the attacker moved, at a glance (simplified diagram by the author)

Why GitLab servers are such valuable targets

A self-managed GitLab server holds an organization’s source code, its CI/CD secrets (cloud keys, deploy tokens, registry passwords), its runner tokens, and often the keys that push to production. Code execution on that server is close to code execution on everything it deploys. That’s why a 10.0 here deserves the same urgency as a firewall bug.

Background: regular expressions in CI files

GitLab CI files (.gitlab-ci.yml) can contain regular expressions, for example in rules: conditions that decide when a job runs (“only if the branch name matches /^release-.*/”). GitLab has to parse and compile those patterns on the server. A regex engine is a small compiler and virtual machine: it turns a pattern into internal instructions and executes them. Like any compiler, it has to stay within the memory it allocated.

GitLab guards this with validation, including a size check, so oversized or dangerous patterns are rejected.

The bug

GitLab describes it as an integer overflow (CWE-190) in the CI/CD Regular Expression Compiler, caused by insufficient regular expression validation, that “could have allowed an unauthenticated user to execute arbitrary code on the GitLab server via a specially crafted regular expression in a CI/CD configuration.”

The public proof-of-concept adds a little more detail: a particular Unicode path causes Ruby to compile the regular expression again after GitLab’s size check. The recompiled pattern is no longer the one that was checked, and an integer overflow in that process redirects the regex engine’s execution, which the exploit turns into command execution.

Get 0xK1L’s stories in your inbox

Join Medium for free to get updates from this writer.

An integer overflow happens when a number gets too big for its storage and wraps around to a small value. If that number is a size or an offset, the program allocates or checks too little, then writes or jumps outside the bounds it believes are safe.

Press enter or click to view image in full size
How it should work vs. what the attacker makes happen (simplified diagram by the author)

How an attacker uses it

Based on the public PoC by Jonah Burgess:

  1. The attacker needs permission to push a branch to a public project on the instance. On GitLab servers with open sign-up, anyone can create an account and a project, so in practice the barrier is very low.
  2. A request to GitLab’s CI lint endpoint (which validates CI configuration) is then sent without any token, cookie or authorization header.
  3. Commands run as GitLab’s git account, not as root, but that account owns repositories and much of GitLab’s data.
  4. The exploit needs a lot of memory and is tuned to specific builds (tested on CE 19.4.1). A typical attempt ends with an HTTP 502 because the worker crashes after the command runs.
Press enter or click to view image in full size
The attack chain as described by official sources (diagram by the author)

Exploited in the wild

CISA added CVE-2026–97229 to its Known Exploited Vulnerabilities catalog on October 29, giving federal agencies until November 1 to patch. GitLab’s advisory notes that exploitation evidence came from external researchers. No attacker IPs, domains or file hashes had been published as of October 30. Over the following weekend, Shadowserver reported tracking more than 1,000 unpatched, internet-exposed GitLab servers under ongoing attack.

Press enter or click to view image in full size
Incident timeline, compiled from official statements

Affected and fixed versions

  • Affected: GitLab CE and EE 19.2 before 19.2.8, 19.3 before 19.3.5, 19.4 before 19.4.2.
  • Fixed: 19.4.2, 19.3.5, 19.2.8. (Some early reports cited 19.3.4, but GitLab now recommends 19.3.5.)
  • Not affected: GitLab.com is already patched, and GitLab Dedicated customers need no action.

The same patch release fixed 23 other vulnerabilities, including a high-severity XSS (CVE-2026–92883) and a prompt-injection issue in GitLab Duo Agent Platform (CVE-2026–96893). That’s another reason to upgrade rather than look for a workaround.

Press enter or click to view image in full size
GitLab’s official patch release notes for 19.4.2 / 19.3.5 / 19.2.8 (source: docs.gitlab.com)

What to do

  1. Upgrade now to 19.4.2, 19.3.5 or 19.2.8 (or later).
  2. Close open sign-up or require admin approval. Bugs that need “any account” become “anyone” when sign-up is open.
  3. Don’t expose GitLab to the whole internet unless you have to. Put it behind a VPN or SSO proxy where possible.
  4. Hunt: review recent CI configuration changes for strange regular expressions, look for bursts of HTTP 502 on CI lint requests, and check for unexpected processes started by the git user. GitLab also published six threat detections for self-managed instances.
  5. If you find signs of compromise: treat the server as breached. Rotate CI/CD variables, runner registration tokens, deploy keys and personal access tokens, and review recent pushes and pipeline changes.
Press enter or click to view image in full size
Quick action checklist

Lessons

  • Validate what you execute, not what you received. The bug lived in the gap between the pattern GitLab checked and the pattern Ruby finally compiled. Validation must happen on the final form.
  • “Requires an account” is weak protection when accounts are free. Review which features any user can reach.
  • Patch windows keep shrinking. Two weeks from patch to KEV listing is now normal for internet-facing DevOps tools.

Confirmed vs. not confirmed

  • Confirmed: the vulnerability, CVSS 10.0, affected and fixed versions (GitLab), KEV listing (CISA), Shadowserver’s exposure numbers.
  • From the public PoC: the CI lint path, the Unicode recompilation detail and the git execution context.
  • Not disclosed: who is exploiting it, and how many servers were actually compromised.

References

This article is part of “Black October 2026: The Vulnerabilities”, a 5-part follow-up to the Black October series that explains October 2026’s most critical vulnerabilities for awareness purposes. Facts come from the vendor advisories and researcher reports listed above and are current as of November 2, 2026. Some investigations are ongoing, so details may change.

--

--