GitLab Unauthenticated RCE Across 12 Years (CVE-2026-110264)
A regex-compiler integer overflow rated 10.0, CVE-2026-110264 exposes every self-managed GitLab since 7.0 to unauthenticated RCE; fixed October 21, 2026.
TL;DR
- CVE-2026-110264 is an integer overflow in the regular-expression compiler of self-managed GitLab, rated CVSS v3.1 10.0, the maximum, by GitLab. Under conditions GitLab has not disclosed, an unauthenticated attacker can execute arbitrary code on the server by supplying a specially crafted regular expression.
- Every self-managed GitLab CE/EE release from 7.0 (2014) onward is affected, because the flaw sits in Onigmo, the regex engine of Ruby, which GitLab ships and patches inside its own packages. GitLab fixed seven release lines at once on October 21, 2026, backporting further than its normal policy.
- No exploitation has been reported and the flaw is not in the CISA KEV catalog. No proof of concept is public, and GitLab has published no workaround: because the preconditions are undisclosed, no configuration rules an instance out, so the update is the only certain protection.
- Update to 19.5.1, 19.4.3, 19.3.6, 19.2.9, 19.1.9, 19.0.10 or 18.11.13 now. If you patched on October 12 for CVE-2026-97229, you are in range again: those builds sit one patch below the new fixed versions.
Am I affected?
You are affected if both of these hold:
- You run self-managed GitLab Community Edition or Enterprise Edition, in any deployment type: omnibus packages, Docker, Helm charts or source installs. GitLab.com already runs a fixed version, and GitLab Dedicated tenants on 19.3.5-internal0 and 19.4.2-internal0 or later need no action.
- Your version is in an affected range. GitLab has not said which features or settings an attacker needs, so no instance below the fixed versions can be ruled out by configuration.
| Branch | Affected versions | Fixed version |
|---|---|---|
| 19.5 | 19.5.0 | 19.5.1 |
| 19.4 | 19.4.0 to 19.4.2 | 19.4.3 |
| 19.3 | 19.3.0 to 19.3.5 | 19.3.6 |
| 19.2 | 19.2.0 to 19.2.8 | 19.2.9 |
| 19.1 | 19.1.0 to 19.1.8 | 19.1.9 |
| 19.0 | 19.0.0 to 19.0.9 | 19.0.10 |
| 18.11 and every older branch back to 7.0 | 7.0 to 18.11.12 | 18.11.13 |
Check the version on every instance, including staging and CI-only servers. In the web interface, the version appears under Help and in the Admin Area overview. On the host:
cat /opt/gitlab/embedded/service/gitlab-rails/VERSION # omnibus package install
docker exec gitlab cat /opt/gitlab/embedded/service/gitlab-rails/VERSION # Docker: adjust the container name
cat /home/git/gitlab/VERSION # source install
Instances running 19.2.8, 19.3.5 or 19.4.2, the October 12 fix for CVE-2026-97229, are inside the affected ranges and must move one patch higher.
How do I fix it?
Upgrade to the fixed version for your branch, following GitLab's documented upgrade path for old instances. Four of the seven fixed versions, 18.11.13, 19.0.10, 19.1.9 and 19.2.9, are backports GitLab reserves for severe issues; its normal policy covers only the three most recent monthly releases.
Plan the upgrade window. The 19.4.3 and 19.3.6 releases include database migrations that run during the upgrade, so a single-node server is down while they finish; multi-node installations can apply the patch without downtime using GitLab's zero-downtime procedure. The 19.4.3 release also runs post-deploy migrations.
There is no published workaround, and the limits of any improvised one should be stated plainly: GitLab has not disclosed the preconditions, so restricting features, signups or CI usage is not a documented defense. Network-level restriction of who can reach the instance reduces exposure but is not a fix GitLab stands behind. The upgrade is the protection.
The same October 21 release fixes 10 other issues, two of them high severity: CVE-2026-15723, an account takeover through the OmniAuth-to-LDAP auto-linking email lookup when SAML and LDAP auto-linking are both enabled, and CVE-2026-112212, a cache-poisoning flaw in the OAuth and OpenID Connect discovery endpoints. Updating once covers all of them.
What is the root cause?
GitLab compiles regular expressions that its users supply, and the engine it compiles them with, Onigmo, counted two kinds of internal identifiers with unbounded counters, so a pattern carrying enough repeat constructs wrapped the identifiers and corrupted the compiled program.
GitLab is a Ruby on Rails application, and Ruby's built-in regex engine is Onigmo, a C library. GitLab does not use the system Ruby: it bundles its own Ruby, patched in its own packages, which is why an Onigmo weakness travels into every GitLab release since 7.0 and why GitLab ships the fix by patching the Ruby it carries.
Ruby's own advisory names the bug behind CVE-2026-110264 precisely: "overflow of internal IDs in a pattern with many repeats". The fix, merged upstream in ruby/ruby pull request #16801, "Reject overflowed repeat/null-check IDs in huge regexps", shows the mechanics in two lines. When Onigmo compiles a range repeat such as (?:foobar){0,100}, it emits a pair of virtual-machine instructions that need a numeric identifier:
r = add_mem_num(reg, num_repeat); /* OP_REPEAT ID */
reg->num_repeat++;
+ if ((MemNumType)reg->num_repeat <= 0) return ONIGERR_TOO_MANY_RANGE_REPEAT;
The added line is the check that was missing. The ID is stored as a MemNumType, which Onigmo defines as short int, a signed 16-bit integer with a maximum of 32,767. Before the fix, reg->num_repeat incremented forever with no comparison against that limit, so once the counter passed 32,767 the value written as the ID wrapped to a negative number. The new check casts the counter to MemNumType and stops compilation as soon as the cast value is zero or negative, before a wrapped ID reaches the compiled program. The same gap existed for the null-check identifiers that Onigmo assigns when it compiles constructs it must verify for empty matches:
r = add_mem_num(reg, reg->num_null_check); /* NULL CHECK ID */
if (r) return r;
reg->num_null_check++;
+ if ((MemNumType)reg->num_null_check <= 0) return ONIGERR_TOO_MANY_NULL_CHECK;
A crafted pattern with a very large number of these constructs pushes the counters past the identifier range; the stored values wrap and collide inside the compiled program. The regression tests added with the fix show the two trigger shapes, each repeated 100,000 times in a single pattern:
'(?:foobar){0,100}' * 100000 # range repeats
'(?:(?:foo)?|(?:bar)?)*' * 100000 # constructs needing null checks
GitLab's advisory states that this integer overflow, reached while compiling such a pattern, could be turned into arbitrary code execution on the server. Researcher Johan Carlsson, who uses the handle joaxcar, reported the flaw through GitLab's HackerOne bug bounty program, the fourth regex-engine code-execution flaw of his in GitLab in a month, and the first to reach versions before 19.2.
How is it exploited?
No exploit code is public, so the steps below follow the advisory, the upstream patch and Ruby's description of the input path rather than a released proof of concept.
- The attacker supplies a crafted regular expression to a GitLab feature that compiles user-supplied patterns. GitLab compiles patterns its users provide, such as those in CI configuration, though it has not disclosed which features reach this bug.
- The pattern is generated, not typed: it repeats a quantified construct tens of thousands of times, like the two shapes in the regression tests.
- During compilation, the repeat and null-check identifier counters pass the range of
MemNumTypeand wrap, so the compiled program carries colliding identifiers. - The corrupted compilation state yields memory corruption, which GitLab states could be turned into code execution as the GitLab server process.
The observable traces of failed or attempted exploitation are the subjects of the two detection rules GitLab published, both in its open-source TLDR detection framework, written in the Sigma format against GitLab's application logs.
How does the attack flow?
The flow is short: a machine-generated pattern full of repeats reaches the compiler, its identifiers wrap, and the corrupted program either crashes the worker or hands execution to the attacker.
thousands of repeat constructs"] --> B["Submitted to a GitLab feature
that compiles user patterns"] B --> C["Onigmo assigns OP_REPEAT and
null-check IDs from unbounded counters"] C --> D["Counters pass MemNumType range:
no bounds check, IDs wrap"] D --> E["Colliding IDs corrupt the
compiled program"] E --> F["Worker crash, or memory corruption
turned into code execution"]
What can an attacker do?
- Run arbitrary code on the GitLab server as the GitLab process user, without authentication. The CVSS vector carries scope Changed, meaning the score accounts for impact beyond the vulnerable component itself.
- Reach everything the GitLab process can reach: repositories and their history, CI/CD variables and other stored secrets, the container and package registries, and the host running the instance.
- Pivot through CI: runners execute jobs defined in the affected instance, so server-side code execution can influence the workloads and machines that trust it.
Conditions the attacker needs: network access to the GitLab web interface, and the undisclosed preconditions. No authentication is required per the CVSS vector, CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:C/C:H/I:H/A:H, and no user interaction is indicated. Since the preconditions are not published, an internet-reachable self-managed instance should be treated as exposed.
Why does the fix work?
Ruby pull request #16801 closes the overflow at both counters. After each increment, the new code casts the counter to MemNumType and returns a hard error if the value has wrapped:
/* regcomp.c, compile_range_repeat_node() */
if ((MemNumType)reg->num_repeat <= 0) return ONIGERR_TOO_MANY_RANGE_REPEAT;
/* regcomp.c, compile_tree_empty_check() */
if ((MemNumType)reg->num_null_check <= 0) return ONIGERR_TOO_MANY_NULL_CHECK;
Two new error codes, ONIGERR_TOO_MANY_RANGE_REPEAT (-224) and ONIGERR_TOO_MANY_NULL_CHECK (-225), with messages in regerror.c, mean a pattern whose identifiers would overflow is now rejected as a RegexpError before the compiled program exists. Colliding identifiers cannot be produced, so the corruption path is closed. The fix is complete for this flaw, and it carries regression tests for both trigger shapes.
Deployment is the interesting part. The upstream fix was merged into ruby/ruby on April 29, 2026, and no Ruby release carried it until October 23, 2026: Ruby 4.0.9, 3.4.12 and 3.3.13, which the advisory confirms as the first releases of their series containing it, and Ruby 4.0.8 explicitly does not contain this one. GitLab did not wait: its October 21 packages carry its own backport of the patch, which its release notes list as "Add Ruby regexp repeat ID overflow patch for 3.3, 3.4 and 4.0" across the 19.2 through 19.5 builds, alongside the earlier repeat-range fix reaching the older branches. Installing a fixed GitLab version applies the fix through the bundled Ruby.
How do I check if I was compromised?
No exploitation of CVE-2026-110264 has been reported, and no indicators of compromise exist. GitLab and CISA's catalog show no in-the-wild activity as of October 25, 2026.
Until that changes, defenders have two published detection rules and general monitoring:
- GitLab's Sigma rules, Onigmo native worker crash and Org mode render error burst, run against GitLab's own application logs and are the vendor-supported way to look for exploitation attempts.
- In general terms, clusters of Ruby worker crashes tied to pattern compilation, error bursts from Org mode rendering, and unexpected child processes or outbound connections from the GitLab service account are the signals a successful or attempted exploitation would leave behind. Treat any such finding as a code-execution incident: isolate, snapshot, rotate the secrets the instance holds, and rebuild from a clean installation.
Timeline
- 2026-04-29: the fix, ruby/ruby pull request #16801, "Reject overflowed repeat/null-check IDs in huge regexps", is merged upstream.
- 2026-09-23: GitLab fixes the first two joaxcar regex-engine flaws, CVE-2026-89078 and CVE-2026-93577, both rated 9.9 and requiring an account, in 19.4.1.
- 2026-10-12: GitLab fixes CVE-2026-97229, an unauthenticated 10.0 regex-compiler overflow, in 19.2.8, 19.3.5 and 19.4.2.
- 2026-10-21: GitLab fixes CVE-2026-110264 in 19.5.1, 19.4.3, 19.3.6, 19.2.9, 19.1.9, 19.0.10 and 18.11.13, backporting beyond its normal policy.
- 2026-10-22: CVE-2026-110264 published with the CVSS v3.1 10.0 rating.
- 2026-10-23: Ruby releases 4.0.9, 3.4.12 and 3.3.13 with the underlying Onigmo fixes and its advisory naming the bug behind each GitLab CVE.
- 2026-10-25: this post.
FAQ
I patched on October 12 for CVE-2026-97229. Am I safe now?
No. The October 12 builds, 19.2.8, 19.3.5 and 19.4.2, are inside the affected ranges of CVE-2026-110264, whose fixed versions sit one patch higher at 19.2.9, 19.3.6 and 19.4.3. The earlier flaw stopped at 19.2; this one does not, so every self-managed instance needs the October 21 release regardless of what it applied before.
Is GitLab.com or GitLab Dedicated affected?
No. GitLab.com already runs a fixed version, and GitLab Dedicated tenants on internal releases 19.3.5-internal0 and 19.4.2-internal0 or later already include the fix. The exposure is self-managed CE and EE installations of every deployment type.
Which GitLab features does the attacker need?
GitLab has not disclosed the preconditions, so there is no documented way to rule an instance out by configuration. GitLab compiles regular expressions its users supply, such as CI configuration patterns, and the published detection rules watch for Onigmo worker crashes and Org mode render error bursts. Treat any internet-reachable self-managed instance as exposed until it is patched.
Does Regexp.timeout or a pattern length limit protect my own Ruby applications?
No. Ruby's advisory states that Regexp.timeout does not protect against these bugs and that length limits are unreliable because short patterns can trigger some of them. Applications that compile attacker-controlled strings with Regexp.new, Regexp.union, Regexp.compile or interpolation into a regexp literal should upgrade Ruby and stop compiling untrusted patterns.
Will a CVE scanner flag vulnerable Ruby installations?
Not through a Ruby CVE identifier: Ruby has not requested one, at least for now, and directs users to track GitLab's four CVE numbers, whose records name only GitLab as the affected product. Track Ruby by version instead: 4.0.9, 3.4.12 and 3.3.13 are fixed, Ruby 4.0.8 lacks the fix for CVE-2026-110264, and Ruby 3.2 and earlier are end of life without a fix.
What does the upgrade cost on a single-node server?
The 19.4.3 and 19.3.6 releases include database migrations that must finish before GitLab starts, which means downtime on a single-node installation. Multi-node installations can apply the patch with GitLab's zero-downtime procedure, and 19.4.3 additionally runs post-deploy migrations after the upgrade.
Find unpatched GitLab instances before attackers do
Scan your external assets and container images with Ostorlab to surface every self-managed GitLab instance in your estate still running a version from before the October 21, 2026 releases, including staging and CI-only servers that rarely receive attention.
References
- GitLab Critical Patch Release 19.5.1, 19.4.3, 19.3.6, 19.2.9, 19.1.9, 19.0.10 and 18.11.13, October 21, 2026, with the CVE-2026-110264 description, CVSS 10.0 vector, affected ranges, backport note, joaxcar credit, detection links and migration warnings: https://docs.gitlab.com/releases/patches/patch-release-gitlab-19-5-1-released/ (checked October 25, 2026)
- CVE-2026-110264 record with the affected-version ranges and the HackerOne report reference: https://cveawg.mitre.org/api/cve/CVE-2026-110264 (checked October 25, 2026)
- Ruby advisory, "Regexp compilation fixes related to GitLab's CVE-2026-89078, CVE-2026-93577, CVE-2026-97229 and CVE-2026-110264", October 23, 2026, with the bug-per-CVE table, affected-input definition, workaround limits and credits: https://www.ruby-lang.org/en/news/2026/10/23/regexp-fixes-for-gitlab-cves/ (checked October 25, 2026)
- ruby/ruby pull request #16801, "Reject overflowed repeat/null-check IDs in huge regexps", merged April 29, 2026, with the two counter checks, the new error codes and the regression tests: https://github.com/ruby/ruby/pull/16801 (checked October 25, 2026)
- Ruby 4.0.9 release, October 23, 2026, the first 4.0 release carrying the CVE-2026-110264 fix: https://www.ruby-lang.org/en/news/2026/10/23/ruby-4-0-9-released/ (checked October 25, 2026)
- Ruby 3.4.12 and 3.3.13 releases, October 23, 2026: https://www.ruby-lang.org/en/news/2026/10/23/ruby-3-4-12-released/ and https://www.ruby-lang.org/en/news/2026/10/23/ruby-3-3-13-released/ (checked October 25, 2026)
- GitLab omnibus merge request adding the Ruby regexp repeat ID overflow patch to the 19.5 build, from the release's bug-fix list: https://gitlab.com/gitlab-org/omnibus-gitlab/-/merge_requests/9922 (checked October 25, 2026)
- GitLab detection rule "Onigmo native worker crash", Sigma format, in the TLDR framework: https://gitlab.com/gitlab-security-oss/tldr/-/blob/main/Detections/platforms/GitLab/Vulnerability%20Detections/onigmo_native_worker_crash.md (checked October 25, 2026)
- GitLab detection rule "Org mode render error burst", Sigma format, in the TLDR framework: https://gitlab.com/gitlab-security-oss/tldr/-/blob/main/Detections/platforms/GitLab/Vulnerability%20Detections/org_mode_render_error_burst.md (checked October 25, 2026)
- The HackerOne report for CVE-2026-110264, reference 4093475: https://hackerone.com/reports/4093475 (referenced from the CVE record, checked October 25, 2026)
- The Hacker News, "Critical GitLab Flaw (CVSS 10.0) Could Allow Unauthenticated RCE Across 12 Years of Releases", October 21, 2026, with the fixed-version matrix, the re-exposure of October 12 patchees and the upgrade-downtime detail: https://thehackernews.com/2026/10/critical-gitlab-flaw-cvss-100-could.html (checked October 25, 2026)
- The Hacker News, "Ruby Fixes Three Regex Engine Bugs Responsible for Four Critical GitLab RCE Flaws", October 23, 2026: https://thehackernews.com/2026/10/ruby-fixes-three-regex-engine-bugs.html (checked October 25, 2026)
- CVE-2026-97229, the October 12 companion fixed in 19.2.8, 19.3.5 and 19.4.2: https://www.cve.org/CVERecord?id=CVE-2026-97229 (checked October 25, 2026)
- GitLab zero-downtime upgrade documentation: https://docs.gitlab.com/update/zero_downtime/ (checked October 25, 2026)
- GitLab upgrade paths for old versions: https://docs.gitlab.com/update/ (checked October 25, 2026)
- CISA Known Exploited Vulnerabilities catalog, checked for these CVEs on October 25, 2026 (not listed): https://www.cisa.gov/known-exploited-vulnerabilities-catalog