14 min to read
GitLab CVSS 10 Regex RCE Hits CISA KEV: What Self-Managed Admins Must Do
Two max-severity bugs, one shared root cause in Ruby, and a near miss at Alpine Linux
Your GitLab server is probably the most valuable machine you own. It holds your source code, your CI/CD secrets, your deploy keys and the runner tokens that push builds into production. On 29 October 2026, CISA added CVE-2026-97229, a CVSS 10.0 code-execution flaw in self-managed GitLab, to its Known Exploited Vulnerabilities (KEV) catalogue. A day earlier, the Alpine Linux project published a frank account of an attacker spending a week trying to break into its GitLab server with this bug. The attacker got close.
The story has a twist that matters for anyone who runs GitLab outside the official packages. The real bug lives in Onigmo, Ruby’s regular-expression engine. GitLab’s official packages carry a patched Ruby. A self-built install or a custom container image may not, so upgrading GitLab alone can leave the hole open. That is exactly what happened at Alpine.
TL;DR / Key takeaways
- What: CVE-2026-97229 (CVSS 10.0) lets an unauthenticated attacker run code on a self-managed GitLab server through a crafted regular expression in a CI/CD configuration. CISA added it to KEV on 29 October 2026.
- There’s a second one: CVE-2026-110264 (also CVSS 10.0), fixed on 21 October, is a separate regex-compiler overflow that reaches back to GitLab 7.0. Being patched for the first bug does not fix the second.
- Target versions: 19.5.1, 19.4.3, 19.3.6, 19.2.9, 19.1.9, 19.0.10 or 18.11.13 (or later) fix both.
- The Ruby catch: If your GitLab runs on its own Ruby (source install, or a custom image), you also need Ruby 3.3.13, 3.4.12, 4.0.9 or later.
- Do today: Upgrade, lock down self-registration and public project creation, check worker crash logs from 13 October onwards, and rotate secrets if you find anything suspicious.
Timeline
| When | What happened |
|---|---|
| Late Sep 2026 | GitLab fixes two authenticated critical RCEs, CVE-2026-93577 and CVE-2026-89078, which Ruby later traced to the same regex engine. |
| 12 Oct | GitLab releases 19.4.2, 19.3.5 and 19.2.8, fixing CVE-2026-97229. GitLab.com and Dedicated are already patched. |
| 13 Oct | CVE published. Rapid7 reproduces code execution on an unpatched official 19.4.1 image and publishes proof-of-concept code. Alpine upgrades to 19.3.4 “instead of 19.3.5 (which had the fix) by mistake”. |
| 20–21 Oct | A newly registered account sends crafted CI configurations to Alpine’s GitLab, crashing workers eight times and causing 502 errors. |
| 21 Oct | GitLab releases 19.5.1, 19.4.3 and 19.3.6, plus backports down to 18.11.13, fixing CVE-2026-110264. |
| 22 Oct | Alpine upgrades to 19.3.6. Public PoC repositories claiming CVE-2026-110264 begin to appear. |
| 23 Oct | Ruby releases 4.0.9, 3.4.12 and 3.3.13 with regex compilation fixes for all four GitLab CVEs. Alpine blocks the attacker’s account. |
| 25–26 Oct | The attacker returns. The attempts fail, but Alpine finds its server is still vulnerable because its image used standard, unpatched Ruby. |
| 27–28 Oct | Alpine closes GitLab to outsiders, rebuilds the server, replaces secret keys, resets passwords and publishes its incident report. |
| 29 Oct | CISA adds CVE-2026-97229 to KEV. Reported federal remediation deadline: 1 November 2026. |
What the vulnerabilities are
GitLab compiles regular expressions found in CI/CD configuration files using Ruby. Ruby’s regex engine, Onigmo, had several memory-safety bugs that appear when it compiles a pattern built from text an attacker controls. Ruby’s own advisory describes the scope plainly: “These bugs are reached only when an application compiles a regular expression from a string that an attacker controls.”
GitLab is exactly that kind of application. It takes regexes from user-supplied .gitlab-ci.yml files (for example in rules: conditions) and compiles them on the server.
- CVE-2026-97229 – GitLab describes it as an issue 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, due to insufficient regular expression validation.” Ruby attributes it to an integer overflow in the size of a compiled pattern. Affected: 19.2 before 19.2.8, 19.3 before 19.3.5, 19.4 before 19.4.2.
- CVE-2026-110264 – An “integer overflow when compiling a specially crafted regular expression”, which Ruby ties to an overflow of internal IDs in patterns with many repeats. Affected: every version from 7.0 before 18.11.13, plus 19.0 before 19.0.10, 19.1 before 19.1.9, 19.2 before 19.2.9, 19.3 before 19.3.6, 19.4 before 19.4.3 and 19.5 before 19.5.1. GitLab’s detection guidance points to an Org-mode rendering path as one trigger.
Both carry the vector CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:C/C:H/I:H/A:H. Both were reported by researcher joaxcar (Johan Carlsson) through GitLab’s HackerOne programme.
Why “unauthenticated” deserves a footnote
Rapid7’s testing found that CVE-2026-97229 needs a way to place a malicious CI/CD configuration into a repository. That means committing a crafted .gitlab-ci.yml and a path containing non-ASCII characters to a branch in a public project. That sounds like a barrier, but Rapid7 adds: “On GitLab instances where new users can self register and create projects, this constraint is removed.”
Many self-managed GitLab servers, especially at open source projects, universities and smaller software houses, leave sign-up open. Alpine’s attacker simply registered a fresh account.
Why upgrading GitLab wasn’t enough at Alpine
GitLab’s fix ships as patches to Ruby inside its official Linux packages and container images (the release notes list “Add Ruby regexp … patch” changes in omnibus-gitlab and CNG). Alpine’s report explains the failure in one line: “The fix isn’t in GitLab’s own code but in a patch to Ruby, which GitLab applies only in its official packages. Our image used standard Ruby.”
Alpine’s own GitLab image used the distribution’s Ruby. So even on 19.3.6, the server stayed exploitable until Ruby itself was upgraded. Ruby also warns that Regexp.timeout “does not protect against these bugs”. The crash happens during compilation, not matching.
What happened at Alpine Linux
Alpine’s write-up is one of the most useful incident reports of the year because it is honest about uncertainty:
- The attacker crashed GitLab workers eight times. In four of those crashes they “got partway through and failed at the next step”.
- They downloaded Alpine’s GitLab container image, which Alpine says “suggests they were tuning the exploit to our exact build.”
- Alpine found “no evidence that the attacker ran code on the server, but we cannot rule it out.” It warned that “a successful exploit would leave no crash and no trace in the web logs.” Some logs were missing, and outbound connections were not logged.
- Alpine therefore treated the server as compromised. It rebuilt it, replaced secret keys and reset all passwords. It also verified that packages, releases and signing keys were untouched. The signing keys were never on the GitLab server.
The data Alpine listed as potentially exposed is a good inventory for any GitLab owner: user emails, names and IPs, password hashes, 2FA secrets, CI/CD variables, runner tokens, webhook, integration and mirror credentials, and private repositories and confidential issues.
Am I affected?
| Your setup | Affected? | What you need |
|---|---|---|
| GitLab.com | No | Nothing. GitLab patched it before disclosure. |
| GitLab Dedicated | No | Tenants on 19.3.5-internal0 / 19.4.2-internal0 or later already have the fixes. |
| Self-managed, official Omnibus package or official Docker image | Yes, unless upgraded | GitLab 19.5.1 / 19.4.3 / 19.3.6 / 19.2.9 / 19.1.9 / 19.0.10 / 18.11.13 or later. |
| Self-compiled (source) install, or an image that installs its own Ruby | Yes, even after upgrading GitLab | Fixed GitLab version and Ruby 3.3.13, 3.4.12, 4.0.9 or later. |
| Older than 18.11 | Yes (CVE-2026-110264 reaches back to 7.0) | Upgrade to a supported release line. No backport exists for older branches. |
Two traps to avoid. First, some early coverage listed 19.3.4 as the fix for CVE-2026-97229. GitLab’s advisory says 19.3.5, and Alpine fell into exactly this gap. Second, a server on 19.4.2, 19.3.5 or 19.2.8 is patched for the first CVE but not for CVE-2026-110264.
Check what you are running:
~|#| Omnibus (Linux package): GitLab and Ruby versions
sudo gitlab~|-|rake gitlab:env:info | grep ~|-|Ei 'GitLab information|^Version|Ruby Version'
cat /opt/gitlab/version~|-|manifest.txt | head ~|-|1
~|#| Official Docker image
docker exec ~|-|it ~|<|gitlab~|-|container> cat /opt/gitlab/version~|-|manifest.txt | head ~|-|1
~|#| Source install or custom image: the Ruby that actually runs GitLab
sudo ~|-|u git ~|-|H bash ~|-|lc 'cd /home/git/gitlab && bundle exec ruby ~|-|v'
On official packages, the Ruby version string may not show 3.3.13 or later because GitLab backports its own patch. There, the GitLab version is what counts. On source installs and custom images, check both.
Detection and hunting
GitLab has not published attack-specific IOCs. It has released named threat detections. For CVE-2026-97229 there are six: Onigmo native worker crash, Graphql cilint hostile regexp, ci regexp oversized non ascii path, ci regexp guard rejection, ci lint workhorse worker crash and ci lint scripted client error burst. For CVE-2026-110264 there are two: Onigmo native worker crash and Org mode render error burst. Start there if your SIEM can consume them.
1. Look for worker crashes since 13 October
Failed attempts crash Puma or Sidekiq workers. Successful ones may not. Alpine’s crashes were its main clue. On Omnibus installs:
~|#| Native crashes inside Ruby (regex engine segfaults print a [BUG] banner)
sudo zgrep ~|-|E '\[BUG\]|Segmentation fault|onig|regcomp' \
/var/log/gitlab/puma/puma_stderr.log* /var/log/gitlab/sidekiq/current* 2>/dev/null
~|#| Bursts of errors from CI lint / Org rendering in Rails exceptions
sudo zgrep ~|-|hE 'ci/lint|ciConfig|Org|RegexpError' \
/var/log/gitlab/gitlab~|-|rails/exceptions_json.log* | head ~|-|50
Konfirmity notes that many instances do not ship puma_stderr.log to a SIEM by default. If yours doesn’t, check it on the host now.
2. Review new accounts and CI changes
- New user registrations since 12 October, especially accounts that created a public project within minutes of signing up. Use Admin Area → Users, sorted by creation date, or
audit_json.log. - Recent
.gitlab-ci.ymlcommits with unusually long or deeply nested regexes, or repository paths containing non-ASCII characters. - Unusually heavy use of the CI lint API or the GraphQL
ciConfigquery from a single client.
3. Hunt for post-exploitation on the host
If code runs, it runs as the account GitLab uses (normally git). The Hacker News, summarising GitLab’s guidance, recommends looking for files owned by git in /tmp, unexpected child processes of Puma or Sidekiq, outbound connections, and changed crontabs or SSH keys for the git user.
sudo find /tmp /var/tmp /dev/shm ~|-|user git ~|-|newermt 2026~|-|10~|-|12 ~|-|ls
sudo crontab ~|-|l ~|-|u git
sudo ls ~|-|la ~|-|~|-|time~|-|style~|=|full~|-|iso ~git/.ssh/
sudo ps ~|-|o pid,ppid,user,etime,cmd ~|-|~|-|forest ~|-|u git | grep ~|-|vE 'puma|sidekiq|gitaly|workhorse|postgres|redis|nginx'
For EDR or auditd telemetry, here is a simple behavioural rule written by OffensioX (not a GitLab-published rule) that you can adapt:
title: Shell or Interpreter Spawned by GitLab Puma/Sidekiq
status: experimental
logsource:
product: linux
category: process_creation
detection:
parent:
ParentImage|endswith: '/ruby'
ParentCommandLine|contains:
~|-| 'puma'
~|-| 'sidekiq'
child:
Image|endswith:
~|-| '/sh'
~|-| '/bash'
~|-| '/dash'
~|-| '/curl'
~|-| '/wget'
~|-| '/python3'
~|-| '/perl'
~|-| '/nc'
condition: parent and child
falsepositives:
~|-| Legitimate git hooks or maintenance tasks; baseline first
level: high
Response checklist
Immediately (today)
- Upgrade to 19.5.1, 19.4.3 or 19.3.6 (or the 19.2.9 / 19.1.9 / 19.0.10 / 18.11.13 backports). Note that 19.4.3 and 19.3.6 include database migrations, and single-node installs will have downtime.
- Source installs and custom images: upgrade Ruby to 3.3.13, 3.4.12 or 4.0.9 or later, and confirm the running process uses it. Users of the
alpinelinux/gitlabimage must re-pull 19.3.6. Only the image published on 27 October contains Ruby 3.3.13. - If you cannot patch tonight: disable open sign-up (Admin Area → Settings → General → Sign-up restrictions), restrict who can create projects, block anonymous access to public projects, and put the web UI behind a VPN or IP allowlist. Rapid7 is clear that these steps “do not remediate the vulnerable regular expression compiler”. They only shrink the attack surface.
- Check the logs above for crashes and suspicious new accounts going back to 13 October.
This week
- If you find crash bursts, unexplained accounts or host anomalies, treat the server as compromised, as Alpine did. Rotate
gitlab-secrets.jsonkeys, all CI/CD variables, runner registration and authentication tokens, deploy keys, personal and project access tokens, and webhook and integration credentials. Then reset user passwords and 2FA. - Assume secrets in CI variables are exposed and rotate the cloud, registry and production credentials they grant access to.
- Verify the integrity of artefacts built since 12 October. Alpine checked its package repository against developer copies and its build servers. Do the equivalent for your releases and container images.
- Tell users to change reused passwords. Alpine saw automated logins using leaked passwords.
Longer term
- Close self-registration by default on internal GitLab instances, or require admin approval and an email domain allowlist.
- Track GitLab patch releases (every second and fourth Wednesday, plus ad-hoc criticals). Patch internet-facing instances within days.
- Prefer official packages and images. If you must build your own, track the language runtime as carefully as the application.
- Ship
puma_stderr.log, Sidekiq and audit logs to your SIEM, and log egress from the GitLab host. Alpine could not rule out compromise partly because outbound connections were never logged. - Keep signing keys and production credentials off the GitLab server. This is why Alpine could say its packages were safe.
OffensioX perspective
This incident is a reminder that “patched” is a claim about a dependency graph, not a version number. GitLab did everything right: it shipped fixes fast, patched SaaS before disclosure and published detections. Yet a well-run open source project still ended up exposed for two weeks. A wrong point release, a second CVE and a runtime outside the vendor package each opened a fresh gap. Four critical GitLab RCEs in roughly a month, all traced to one regex engine, show that attackers and researchers are mining the same seam. More will likely follow.
The bigger trend is that CI/CD platforms are now crown-jewel targets. Whoever controls your GitLab controls what you ship, which turns one server into a supply-chain foothold against your customers. We see many Pakistani software houses, fintechs and agencies running self-managed GitLab on a VPS with open sign-up, an old version and production secrets in CI variables. If that sounds familiar, today is the day to fix it. OffensioX offers penetration testing and DevSecOps security assessments covering your GitLab, runners and pipeline secrets, if you would like an independent check.
References
- GitLab – Patch Release: 19.4.2, 19.3.5, 19.2.8 (CVE-2026-97229)
- GitLab – Patch Release: 19.5.1, 19.4.3, 19.3.6 (CVE-2026-110264)
- Alpine Linux – GitLab security incident: attempted exploitation of CVE-2026-97229
- Ruby – Regexp compilation fixes related to GitLab’s CVE-2026-89078, CVE-2026-93577, CVE-2026-97229 and CVE-2026-110264
- Rapid7 – CVE-2026-97229: Critical unauthenticated remote code execution in GitLab
- The Hacker News – Attacker Tried to Exploit Alpine Linux’s GitLab via CVSS 10.0 Flaw Its Ruby Left Open
- GBHackers – CISA Confirms Active Exploitation of GitLab Vulnerability CVE-2026-97229
- Cyber Security News – CISA Warns of GitLab Integer Overflow Vulnerability Exploited in Attacks
- Help Net Security – GitLab admins urged to patch critical RCE flaw (CVE-2026-97229)
- Konfirmity – GitLab CVE-2026-110264 RCE: Fixed Versions
- Astra Security – CVE-2026-110264: GitLab’s Critical CVSS 10.0 Regex RCE Explained
- cvefeed – CVE-2026-97229 record and KEV change log
- CISA – Known Exploited Vulnerabilities Catalog