GitLab Org-mode regex flaw: the October 12 fix is not enough
CVE-2026-110264 (CVSS 10.0) lets a crafted .org file run code on self-managed GitLab back to 7.0. Fixed versions, interim steps and GitLab's own log checks.
By Yaali. October 23, 2026, 6 min read, Vulnerabilities, Patching, DevOps.
GitLab shipped a critical patch release on October 21 for CVE-2026-110264, a CVSS 10.0 integer overflow in the regular expression compiler that GitLab says could let an unauthenticated user run arbitrary code on the server "under certain conditions". Every self-managed Community Edition (CE) and Enterprise Edition (EE) instance from version 7.0 onwards is affected unless it runs 19.5.1, 19.4.3, 19.3.6 or one of the backports: 19.2.9, 19.1.9, 19.0.10 or 18.11.13. GitLab.com is already patched, and GitLab Dedicated tenants on 19.3.5-internal0, 19.4.2-internal0 or later already have the fix.
This is the second maximum-severity regex flaw from GitLab this month, reported by the same researcher, joaxcar, through HackerOne. The October 12 releases (19.4.2, 19.3.5 and 19.2.8) that fixed CVE-2026-97229 are still vulnerable to this one, so an instance patched ten days ago needs patching again. No exploitation had been reported as of October 22, and the flaw was not in CISA's Known Exploited Vulnerabilities (KEV) catalog.

How it works
GitLab's advisory says only that a crafted regular expression triggers an integer overflow during compilation. The detail comes from the detection rules GitLab's security team published on October 20 in its open TLDR repository. GitLab renders .org files (the plain-text Org-mode format) with the org-ruby gem, version 0.9.12, through its markup pipeline. An Org file can declare its own task keywords on a #+TODO: line, and the gem escapes those keywords when it builds its first keyword pattern. It then passes the raw, unescaped keyword into a second pattern, Regexp.new("^#{keyword}\\s*"), so whoever writes the file controls a regex source string.
That string goes to Onigmo, the regex engine inside Ruby. Onigmo gives every repetition in a pattern a numeric ID and stores it in a signed 16-bit field, which holds values up to 32,767. A keyword with more than 32,767 generic repeats pushes the ID past that limit, it wraps to a negative number, and the repeat instruction writes outside its buffer when the pattern is matched. GitLab's notes say that with heap grooming driven by the request body, this becomes a system() call running as the git user, the account the GitLab application runs under.
Two details matter for exposure. GitLab's rule text says the attack "needs no authentication, only one public project that can hold the .org payload": an anonymous visitor viewing the file triggers the render. The file still has to get into a public project first, which on an instance with open sign-up is any new account. The rules also cover a second route through the editor preview (Projects::BlobController#preview), where a logged-in user passes a file_path ending in .org to force the Org renderer onto any content.
The fix is a patch to Ruby itself. GitLab's release notes list "Add Ruby regexp repeat ID overflow patch for 3.3, 3.4 and 4.0" in 19.2.9 and later, and GitLab bundles its own Ruby in the Linux package and its container images. That is why the affected range reaches back to 7.0, released in 2014: the vulnerable code sits in the regex engine that every GitLab release has shipped with.
What attackers are doing
Nothing confirmed yet. GitLab's advisory, BleepingComputer and IT-Connect all report no known exploitation, and CISA had not listed the flaw as of October 22. The history is a reason to move fast anyway. CVE-2026-85706, last month's maximum-severity GitLab file read flaw, was added to the KEV catalog one day after GitLab fixed it.
GitLab's own notes describe what an attempt looks like: noisy and repetitive. Most render attempts either exceed the markup time budget and raise a timeout, or crash the worker outright. A few land on unused memory and complete silently, and that quiet case is the one that can precede success.
What to do

1. Upgrade
Move to 19.5.1, 19.4.3 or 19.3.6. If you are on an older branch, GitLab backported the fix to 19.2.9, 19.1.9, 19.0.10 and 18.11.13, which is unusual for a vendor that normally patches only the three latest minor releases. Anything older than 18.11 has to move to one of these. 19.4.3 and 19.3.6 run database migrations, so a single-node instance stays down until they finish; multi-node deployments can use GitLab's zero-downtime upgrade procedure.
If you build GitLab from source on your own Ruby, the GitLab version alone does not tell you whether you are fixed, because the fix is a patch to Ruby's regex engine. Confirm with GitLab's source installation notes that your Ruby build carries it.
The same release fixes eleven other issues, including CVE-2026-15723 (CVSS 8.2), an authentication flaw in OmniAuth-to-LDAP account auto-linking, and CVE-2026-112212 (CVSS 7.5), cache poisoning in the OAuth and OpenID Connect discovery endpoints.
2. If you cannot upgrade today
GitLab lists no workaround. Its detection notes advise reducing public visibility until you patch, since the unauthenticated route needs a public .org file. In the admin area under Settings > General > Visibility and access controls, add Public to "Restricted visibility levels" so only administrators can create public projects, and under "New user account restrictions" turn off sign-up or require admin approval. Then list existing public projects with GET /api/v4/projects?visibility=public and make private any that do not need to be public.
Restricting who can reach the GitLab web interface, through a firewall rule, VPN or IP allowlist, cuts exposure further. Neither step stops a logged-in user from using the editor preview route, so treat both as a bridge to the upgrade.
3. Check whether someone tried
GitLab published two rules for self-managed instances, and their raw queries work without a security information and event management (SIEM) system. Paths below are for the Linux package.
- Render timeouts: in
/var/log/gitlab/gitlab-rails/exceptions_json.log, look forTimeout::Errorwithextra.class_nameset toOtherMarkupand anextra.file_nameending in.org. GitLab's rule fires at five or more from onemeta.client_idwithin 30 minutes. A client ID of the formip/<address>means the request was anonymous. - Native crashes: in
/var/log/gitlab/puma/puma_stderr.log, a[BUG]crash report whose backtrace mentionsorg-ruby,headline.rbormatch_at. Many log shippers do not collect this file by default. - Preview abuse: requests to
Projects::BlobController#previewinproduction_json.logwhere thefile_pathparameter ends in.orgbut the URL points at a different file. - The payload itself: in each suspect repository,
rg -l --glob '**/*.org' '^\#\+(TODO|SEQ_TODO|TYP_TODO):.{500,}'finds Org files with oversized keyword lines. Note who committed them and when.
GitLab is explicit that a successful exploit can be quiet, so a clean result here proves nothing. Also look for files owned by git in /tmp, unexpected child processes of Puma or Sidekiq, outbound connections from the GitLab host, and changed crontabs or SSH keys for the git user.
4. If you find signs of compromise
Preserve exceptions_json.log, production_json.log, the Workhorse log and the payload files before restarting anything. Remove or make private the project holding the payload, delete the payload commits and block the source address. Rebuild on a fixed version, then rotate the secrets in /etc/gitlab/gitlab-secrets.json, all CI/CD variables, runner tokens and every access token, plus credentials for any cloud or deployment integration the instance connects to.
The wider lesson
Two GitLab fixes in ten days for the same engine is a reason to confirm the running version (Admin > Help, or /api/v4/version) after each upgrade and record it against the advisory. Teams that applied 19.4.2 on October 12 and closed the change are exposed again. File renderers belong on the list of attack surface next to APIs and pipelines, since they also feed user input to code running as the server account.
Our platform and cloud engineering team runs and upgrades self-managed GitLab, including secret rotation after an incident, and our attack surface management service finds GitLab instances exposed to the internet with anonymous access to public projects. Open the chat and Yaali, our AI agent, will pass your question to the engineer who would do the work.
Sources: GitLab critical patch release 19.5.1, GitLab TLDR detection: Org mode render error burst, GitLab TLDR detection: Onigmo native worker crash, BleepingComputer, IT-Connect, Astra Security, HOL Guard.
Read next
- Dell CSM Authorization: two CVSS 10 flaws, upgrade to 1.18
- GitLab file read flaw: older branches now have a fix
- OpenCode on Windows: MCP sign-in could run server code
Back to the blog, or tell us about your system in the chat. Yaali, our AI agent, answers first and brings in an engineer.