GitLab CVE-2026-97229 can survive an application upgrade
GitLab’s Ruby patch gap left Alpine exposed after an upgrade; check runtime ownership, fixed releases and migration costs before calling the server patched.

Upgrading self-managed GitLab, the repository and CI/CD platform, does not necessarily close CVE-2026-97229. Otherwise, the vulnerability can survive the application upgrade—the gap Alpine Linux found after attempted exploitation led it to rebuild its server.
Can a fixed GitLab version still run vulnerable Ruby?
The CVSS 10.0 remote-code-execution flaw sits in Onigmo, Ruby’s regular-expression engine, which GitLab invokes when processing crafted CI/CD configurations.
The exposure extends beyond the GitLab server. Alpine’s GitLab hosts aports, the build recipes used to produce its packages, and Alpine supplies widely used container base images. Repositories, pipeline secrets and deployment credentials all sit in build infrastructure. Those assets make the infrastructure valuable to attackers, and potential exposure can extend to the downstream software built from it.
Censys’s October 13 advisory identified 25,766 vulnerable hosts and 79,224 vulnerable web properties, according to Tech Insider. Read those numbers as historical exposure measurements—not a current inventory, and certainly not a count of confirmed victims. The counts measure different things: a host can serve multiple web properties, which explains why the property count is higher than the host count.
How CI configuration reaches Onigmo—and what access the exploit needs
GitLab compiles regular expressions in CI configurations with Ruby’s Onigmo engine. CVE-2026-97229 is an integer overflow in the calculation of the compiled program’s size.
Crafted UTF-8 repository paths force recompilation after validation checks have passed, according to Tech Insider’s reporting of Rapid7. The invalid instructions produced by that recompilation corrupt control flow in Ruby. The failure is in the size calculation: getting the bytecode program’s size wrong can cause writes beyond the allocated buffer. This is memory corruption with possible code execution. It is not ordinary regex resource exhaustion, and setting Ruby’s Regexp.timeout does not protect against it.
The tested route used the following repository preparation and final request. The exploit payload is omitted:
- A malicious
.gitlab-ci.ymlcommitted to a public-project branch. - A file path containing UTF-8 characters committed to that branch.
- A final CI lint request.
The publishers distinguish access an attacker must already hold from access the instance lets an attacker obtain publicly:
| Publisher | Reported access conditions |
|---|---|
| The Hacker News | Only the final CI lint request is unauthenticated; preparatory repository operations require write access. |
| Tech Insider | Rapid7 describes the chain as fully unauthenticated on instances permitting open self-registration and public project creation. |
Public registration can let an attacker obtain an account and create a project without any pre-existing repository privileges. The preparatory writes still use that account.
Rapid7’s lab tests against official GitLab images produced these results, as reported by The Hacker News:
| Official GitLab image | Result |
|---|---|
| 19.4.1 | Commands executed as git. |
| 19.4.2 | The same input did not execute commands. |
GitLab’s detection guidance also describes preparing file paths through repository APIs.
Inspect the Ruby running inside your GitLab deployment
Inspect the interpreter inside the GitLab installation or running container.
| Deployment | Where the Ruby fix comes from |
|---|---|
| Official GitLab Linux packages and official container images | GitLab’s fixed releases carry a patched bundled Ruby. |
| Self-compiled installations and custom images that install Ruby independently | Operators must update both GitLab and Ruby; upgrading GitLab does not update their independently installed interpreter. |
Upstream Ruby released fixes on October 22–23 in 3.3.13, 3.4.12 and 4.0.9. Custom runtimes need one of those fixed versions or later. Ruby 3.2 reached end of life in April and will not receive the fix. If GitLab is running on that interpreter, there is no patch to wait for on that branch: move it to a fixed Ruby version.
Use these checks to display the bundled Ruby version, inspect GitLab’s environment summary and query the interpreter inside a running container.
# Omnibus install: show the bundled Ruby
/opt/gitlab/embedded/bin/ruby -v
# Summary of GitLab and Ruby versions
sudo gitlab-rake gitlab:env:info
# Container: query the runtime in the running image
docker exec <container> ruby -v
A version string alone cannot establish official-package exposure. Vendors can backport the fix while retaining Ruby’s upstream version number. A version below 3.3.13 therefore does not, by itself, prove that an official GitLab package is vulnerable. Check the release documentation for the exact package running on the instance.
Users of alpinelinux/gitlab must pull alpinelinux/gitlab:19.3.6 again. The October 27 image includes Ruby 3.3.13; earlier downloads bearing that same tag remain vulnerable. Every older tag is vulnerable too.
Alpine provides the fixed Ruby packages on these branches; check the branch as well as the package version:
| Alpine branch | Fixed Ruby package |
|---|---|
| 3.22, 3.23, 3.24 and edge | 3.4.12 |
| 3.21 | 3.3.13 |
This command upgrades installed Alpine packages, including the fixed Ruby package on the branches where that package is available.
apk upgrade
Choose the latest branch patch, not just CVE-2026-97229’s minimum fix
I’d install the latest branch patch listed for October 21 rather than stop at the minimum fix for CVE-2026-97229. The newer releases also fix CVE-2026-110264, another CVSS 10.0 regex vulnerability.
For CVE-2026-97229, Tech Insider lists these affected release ranges and the corresponding fixed releases:
| Branch | Vulnerable releases | Fixed release |
|---|---|---|
| 19.2 | 19.2.0 through 19.2.7 | 19.2.8 |
| 19.3 | 19.3.0 through 19.3.4 | 19.3.5 |
| 19.4 | 19.4.0 through 19.4.1 | 19.4.2 |
GitLab’s October 12 advisory initially named 19.3.4 as fixed, The Hacker News reports. That version was wrong. GitLab corrected the fixed version to 19.3.5 and listed 19.3.4 as affected. Its branch guidance distinguishes the minimum releases that fix this CVE from the newer releases issued on October 21:
| Branch | Fixes CVE-2026-97229, per GitLab's advisory | Newest release (21 October) |
|---|---|---|
| 19.5 | Not listed as affected | 19.5.1 |
| 19.4 | 19.4.2 | 19.4.3 |
| 19.3 | 19.3.5 | 19.3.6 |
| 19.2 | 19.2.8 | 19.2.9 |
| 19.1, 19.0 and 18.11 | Not listed as affected | 19.1.9, 19.0.10 and 18.11.13 |
All seven newer releases fix CVE-2026-110264, as GitLab’s primary October 21 release notes confirm. That flaw is an integer overflow during compilation of a crafted regular expression; under certain conditions, it could allow unauthenticated code execution. GitLab explicitly names backports to 18.11.13, 19.0.10, 19.1.9 and 19.2.9. Receiving the second fix does not establish that those older branches were affected by CVE-2026-97229, so do not use that patch list to infer exposure to the first flaw.
Budget for database migrations, not just package replacement. GitLab lists regular migrations for upgrades to 19.4.3 and 19.3.6, plus post-deploy migrations in 19.4.3 that can run afterward. A single-node installation must finish migrations before GitLab starts. That means downtime. A multi-node installation can potentially avoid it, but only if the upgrade follows the proper zero-downtime procedure rather than treating the package update as the entire job.
Alpine’s eight crashes exposed a two-layer patching failure
Alpine first selected GitLab 19.3.4, one patch short of the fixed 19.3.5. Its later upgrade to 19.3.6 left independently supplied Ruby unpatched. Eight worker crashes showed attempted exploitation and operational disruption—not a cleanly patched service. They also did not confirm remote code execution.
The timeline reported by Tech Insider includes the October 29 KEV addition and the November 1 federal remediation deadline under BOD 26-04:
| Date (2026) | Event |
|---|---|
| October 12 | GitLab ships 19.2.8, 19.3.5 and 19.4.2 |
| October 13 | Rapid7 publishes analysis and reproduces RCE on 19.4.1 CE, Censys issues advisory |
| October 13 | Alpine upgrades its instance to 19.3.4, one patch short of the fixed 19.3.5 |
| October 20 to 21 | Attacker crashes Alpine’s GitLab workers eight times |
| October 22 | Alpine moves to 19.3.6, still on an unpatched Ruby |
| October 22 to 23 | Upstream Ruby releases 3.3.13, 3.4.12 and 4.0.9 |
| October 27 to 28 | Alpine closes and rebuilds the instance from scratch |
| October 29 | CISA adds CVE-2026-97229 to the KEV catalog |
| November 1 | Federal remediation date under BOD 26-04 |
A newly registered account submitted the crafted CI configurations. Four attempts progressed partway and failed at the next step. The October 21 attack caused 502 errors and failing CI jobs. The attacker also downloaded Alpine’s GitLab container image, suggesting an effort to tune the exploit for that build. That download does not establish supply-chain tampering; it is evidence of a different, narrower activity.
Alpine blocked the account on October 23, and attempts to return on October 25–26 failed. The project discovered the still-vulnerable runtime on October 26. On October 27 it restricted access to developers and build servers, then finished rebuilding the instance on October 28.
What Alpine verified—and what the missing evidence leaves open
Alpine found no evidence that the attacker executed code, according to The Hacker News. Evidence needed to rule out execution was missing, so the project rebuilt its GitLab server, replaced its secret keys and reset every account’s password.
Timing probes showed no delays. Investigators found no unexpected files, keys, hooks or processes, and visible web and API requests returned no private data. Background-job logs were missing. The old container filesystem had been discarded, and neither Alpine nor its hosting provider had recorded outbound connections. Alpine stated the problem plainly: “A successful exploit would leave no crash and no trace in the web logs.”
For the integrity checks, Alpine verified that every aports change added October 20–22 matched a recorded push from a known developer. The comparison used records outside the attacker’s reach: a developer’s repository copy and all 45 build servers.
| Publisher | Reported verification cutoff and scope |
|---|---|
| The Hacker News | Every package built October 20–24 verified; checks being extended to October 27. Verified scope included October 21 releases and their minirootfs files used to build official Alpine Docker images. |
| Tech Insider | Packages built October 20–24 verified; no confirmed package tampering. |
| BleepingComputer | No tampering in repository commits, packages or releases through October 27. |
Package and release signing keys were never stored on GitLab.
If the attacker did execute code, the instance held the following assets that could potentially have been exposed:
- All users’ names, email addresses and IP addresses;
- Password hashes and 2FA secrets;
- CI/CD variables and runner tokens;
- Integration, webhook and push-mirror credentials;
- Personal access tokens, stored as hashes;
- Private repositories, confidential issues and confidential merge requests.
Temporary restrictions reduce exposure but do not repair the regex compiler
If patching cannot happen immediately, these containment options address specific parts of the exposed route, with a limited scope:
- Restrict anonymous access to public projects.
- Prevent untrusted users from creating or writing to public projects. Rapid7 recommends these controls, according to The Hacker News and Tech Insider.
- Block the CI lint route, another Rapid7 mitigation reported by The Hacker News.
- Where feasible, restrict inbound access to GitLab’s web interface—Censys’s advice, as reported by Tech Insider.
I’d treat these controls as temporary barriers, not proof of remediation. They have concrete usability costs. Removing public access gives up anonymous browsing; removing contributor self-service limits who can start projects or contribute without approval. Blocking CI lint removes that validation route.
I’d avoid adopting or continuing an independently maintained Ruby/custom-image deployment without more operational capacity if the team cannot inventory its runtime, track dependency advisories and verify patched builds.
Hunt for execution before treating an upgrade as incident closure
For CVE-2026-97229 on self-managed instances, The Hacker News reports six GitLab Sigma-format detection rules. Four carry an experimental label. The rules look for hostile patterns in CI regexp warnings and GraphQL ciLint requests, unusually long paths containing non-ASCII characters, and Ruby crash reports pointing to Onigmo. These are not the two detections in GitLab’s October 21 primary release notes. Those detections address CVE-2026-110264, the other regex vulnerability; do not substitute one rule set for the other.
- Investigate files owned by
gitin/tmp, unexpected Puma or Sidekiq child processes, outbound connections, and modified crontabs or SSH keys belonging to thegituser. - If signs of code execution appear, treat the instance as compromised. The guidance reported by The Hacker News calls for rotating secrets in
gitlab-secrets.json, all CI/CD variables, all runner tokens and all access tokens.
Exposure alone triggers broader advice from Tech Insider: treat CI variables, runner tokens and deploy keys as potentially compromised if the instance was exposed and unpatched after October 12. That threshold differs from the code-execution evidence described by The Hacker News.
Verify the runtime, follow up on credentials and check the dated deadlines
GitLab’s October 21 release notes confirm that GitLab.com is patched. Dedicated tenants on 19.3.5-internal0 and 19.4.2-internal0 or later already include those fixes and need no action for them.
Alpine account holders must use “Forgot your password?” when the service reopens. Passwords reused elsewhere need changing too. Alpine observed credential-stuffing attempts using passwords leaked from other sites, so resetting the Alpine password does not complete the password work for an account holder who reused it elsewhere.
Frequently asked questions
Do GitLab.com and GitLab Dedicated customers need to perform these upgrades?
GitLab.com and GitLab Dedicated are already patched. The runtime inspection and upgrade work described here applies to self-managed installations.
Does Ruby’s Regexp.timeout setting prevent exploitation?
No. Ruby’s maintainers say Regexp.timeout does not protect against this bug. They say the vulnerability matters for programs that compile regular expressions from attacker-controlled text.
Can an independently supplied Ruby 3.2 installation receive this fix?
Ruby 3.2 reached end of life and will not receive the fix. Independently maintained runtimes need to move to Ruby 3.3.13, 3.4.12, 4.0.9 or later; verify compatibility with the GitLab deployment before making that change.
Sources: Attacker Tried to Exploit Alpine Linux’s GitLab via CVSS 10.0 Flaw Its Ruby Left Open, Alpine Linux rebuilds GitLab after attempted RCE attack, GitLab CVE-2026-97229: CVSS 10.0 Joins CISA KEV [2026], GitLab Critical Patch Release: 19.5.1, 19.4.3, 19.3.6, 19.2.9, 19.1.9, 19.0.10, 18.11.13 | GitLab Docs



