CVSS 10.0 unauthenticated RCE — CVE-2026-110264, an integer overflow compiling a crafted regular expression in the bundled Onigmo engine. Reaches every self-managed release since 7.0 (2014). Patched October 21.
Verdict: patch lane, urgent tier — and beware the patch trap. The October 12 patch releases (for CVE-2026-97229 and others) do not cover this flaw: anyone who "already patched GitLab this month" before October 21 is still exploitable. No exploitation reported yet, but public PoC code is circulating, preconditions are undisclosed (assume reachable), and GitLab offers no workaround. GitLab.com and Dedicated tenants are already fixed — this is a self-managed problem.
A crafted regex fed to the Onigmo engine overflows during compilation, giving unauthenticated remote code execution on self-managed GitLab — one public write-up demonstrates the path through a crafted Org-mode file render. GitLab patched its vendored copy rather than waiting on upstream, and has not disclosed which endpoints reach the compiler, so treat every unauthenticated surface as in scope. A PoC repository is public on GitHub (unverified — handle in a sandbox, never on infrastructure).
| Line | Upgrade to |
|---|---|
| 19.5 | 19.5.1 |
| 19.4 / 19.3 / 19.2 / 19.1 / 19.0 | 19.4.3 / 19.3.6 / 19.2.9 / 19.1.9 / 19.0.10 |
| 18.11 (and every release back to 7.0) | 18.11.13 — older lines must jump forward |
| Category | Vendor | Status |
|---|---|---|
| Vendor | GitLab | Patched + rules published — fixes across seven version lines Oct 21; no workaround and preconditions undisclosed; two Sigma detections against GitLab application logs: "Onigmo native worker crash" and "Org mode render error burst" — run both back to Oct 20. Release post moved in their docs reorg; patch feed: docs.gitlab.com/releases/patch-releases.xml |
| VM scanners | Qualys / Tenable / Rapid7 | Nothing published found for this CVE as of Oct 23 — version checks will come; verify in each console before relying on scan results |
| SIEM content | SOC Prime | Analysis published; rule content behind their platform |
| Community | GitHub / Nuclei | PoC public (OppositDeer repo and mirrors — unverified, treat as hostile); no Nuclei template found yet |
| KEV | CISA | Not listed as of Oct 23 |
GitLab named two Sigma rules but the rule text is not in public sources, and scanners have nothing. The logic below reconstructs what those rules must look for, inferred from the flaw's shape (crafted regex → Onigmo crash during compile) — tune before trusting. These catch failed attempts; a clean exploit may leave neither.
Worker-crash canary — regex engine overflows crash Ruby workers before they succeed:
# host telemetry on GitLab servers process.name IN (ruby, puma, sidekiq, gitlab-workhorse) termination.signal = SIGSEGV → any occurrence on a GitLab host since Oct 20 is worth a look
Render-endpoint error bursts — the demonstrated path is a crafted Org-mode file render ("Org mode render error burst"):
# GitLab production_json.log / LB logs status = 500 AND (path contains preview_markdown OR render OR blob OR requested file extension = .org) | bucket 10m, count by src_ip → alert on bursts from a single source
Pre-patch inventory sweep — find the instances nobody registered:
# network / asset data HTTP responses with header X-GitLab-* OR title "GitLab" on internal ranges → cross-check each against the fixed-version table above
Splunk (index=*) / Elastic ES|QL (FROM logs-*) — CIM Endpoint / Web field names for Splunk, ECS for Elastic; GitLab's own JSON logs carry status and path; tune to your add-on or integration:
# worker-crash canary on GitLab hosts
index=* earliest=-30d@d (process_name IN ("ruby","puma","sidekiq","gitlab-workhorse") OR "puma" OR "sidekiq") ("SIGSEGV" OR signal="SIGSEGV" OR "segfault")
| stats count min(_time) as first max(_time) as last by host process_name
# render-endpoint error bursts (production_json.log or the load balancer)
index=* earliest=-30d@d status=500 (path="*preview_markdown*" OR uri_path="*preview_markdown*" OR path="*/render*" OR path="*/blob/*" OR path="*.org" OR uri_path="*.org")
| eval src=coalesce(remote_ip, src)
| bin _time span=10m
| stats count by _time src
| where count>10
# pre-patch inventory: GitLab instances answering on internal ranges
index=* earliest=-7d@d ("X-Gitlab-Feature-Category" OR "X-GitLab-Meta" OR server="nginx" "GitLab")
| stats dc(dest) as instances values(dest) as hosts
// worker-crash canary on GitLab hosts
FROM logs-*
| WHERE @timestamp > NOW() - 30 days
| WHERE (process.name IN ("ruby", "puma", "sidekiq", "gitlab-workhorse") OR message LIKE "*puma*" OR message LIKE "*sidekiq*")
AND (message LIKE "*SIGSEGV*" OR message LIKE "*segfault*")
| STATS count = COUNT(*), first = MIN(@timestamp), last = MAX(@timestamp) BY host.name, process.name
// render-endpoint error bursts (production_json.log or the load balancer)
FROM logs-*
| WHERE @timestamp > NOW() - 30 days AND http.response.status_code == 500
| WHERE url.path LIKE "*preview_markdown*" OR url.path LIKE "*/render*" OR url.path LIKE "*/blob/*" OR url.path LIKE "*.org"
| EVAL src = COALESCE(client.ip, source.ip)
| STATS count = COUNT(*) BY t = BUCKET(@timestamp, 10 minute), src
| WHERE count > 10
// pre-patch inventory: GitLab instances answering on internal ranges
FROM logs-*
| WHERE @timestamp > NOW() - 7 days
| WHERE message LIKE "*X-Gitlab-Feature-Category*" OR message LIKE "*X-GitLab-Meta*" OR (message LIKE "*nginx*" AND message LIKE "*GitLab*")
| STATS instances = COUNT_DISTINCT(destination.address), hosts = VALUES(destination.address)
The Hacker News — CVSS 10.0 GitLab flaw · SOC Prime analysis · Astra — technical explainer · Konfirmity — fixed versions · GitLab release notes (vendor — release post moved in their docs reorg; patch feed: docs.gitlab.com/releases/patch-releases.xml)