On October 20, 2026, someone registered an account on Alpine Linux's public GitLab instance and started sending it crafted CI configurations. The instance crashed eight times over two days. Four of those crashes were the attacker getting partway through an exploit and failing at the next step. Alpine's maintainers later wrote, with unusual honesty, "The attack came close to working."
The vulnerability is CVE-2026-97229, a CVSS 10.0 unauthenticated remote code execution flaw in GitLab CE and EE. On October 29, CISA added it to the Known Exploited Vulnerabilities catalog, giving US federal agencies until November 1 to patch. This post is about the part of the story that should worry anyone running a self-managed GitLab: Alpine upgraded GitLab, and the vulnerability did not go away.
What CVE-2026-97229 actually is
Per the CVE record and GitLab's October 12 critical patch release (19.4.2, 19.3.5, 19.2.8), the flaw is an integer overflow or wraparound in how GitLab evaluates regular expressions inside CI/CD configuration. An unauthenticated user can send a specially crafted regex in a CI config and execute arbitrary code on the server, because the regex validation is insufficient.
The crucial detail: the underlying bug is not in GitLab's code. It is in Onigmo, the regular expression engine built into Ruby. GitLab's fix is a set of patches to the Ruby interpreter that GitLab bundles in its own packages and container images. Upstream Ruby shipped the same fix on October 23, in Ruby 3.3.13, 3.4.12 and 4.0.9.
That single fact drives everything that followed.
The Alpine Linux timeline, and the upgrade that wasn't
Alpine's post-mortem is one of the most transparent incident write-ups a distribution has published, and the timeline is the lesson:
- October 12 - GitLab releases the fix.
- October 13 - CVE-2026-97229 is published. Alpine upgrades its instance, but to 19.3.4 instead of 19.3.5, the version carrying the fix. A human error, the kind that happens in every operations team.
- October 20-21 - The attacker probes and then launches the main attack: eight worker crashes, four partial exploit progressions. They also download Alpine's GitLab container image, which the maintainers read as the attacker tuning the exploit to their exact build.
- October 22 - Alpine upgrades to GitLab 19.3.6. The instance is still vulnerable, because that image uses standard, unpatched Ruby. The app was current; the interpreter was not.
- October 23 - Ruby releases the upstream fix. The attacker's account is blocked.
- October 25-26 - The attacker returns and tries to get back in. The attempts fail.
- October 26 - Alpine discovers its instance is still vulnerable despite the upgrade.
- October 27-28 - The instance is closed and rebuilt from scratch. All passwords are reset, GitLab's secret keys replaced. Alpine verifies that the aports repository, all packages built October 20-24, and the October 21 stable releases were not tampered with, by checking commits against records the attacker could not reach: a developer's clone and all 45 builders.
- October 29 - GitLab reopens on 19.3.7 with a patched Ruby.
Alpine found no evidence that the attacker's code ever ran: no unexpected files, keys, hooks or processes, and timing probes showed no delays. But a successful exploit of this class would leave no crash and no web-log trace, some logs from the attack day were gone, and they had no outbound connection logging. So they treated the instance as compromised and rebuilt it. That is the correct call, and it is worth saying plainly: "we can't prove a negative" is a reason to rebuild, not a reason to relax.
Why this bug class is bigger than GitLab
The bug is in Ruby's regex engine. Any program that compiles regular expressions from untrusted input is exposed, not only GitLab. Alpine's own ruby package shipped the fix in 3.4.12 (releases 3.22, 3.23, 3.24 and edge) and 3.3.13 (release 3.21); apk upgrade gets it. Other distributions shipped their own Ruby updates around October 23.
This is the uncomfortable pattern of 2026's dependency incidents: the CVE gets a product name, so operators patch the product, while the vulnerable code sits one layer below in a runtime the product merely embeds. Your inventory says "GitLab 19.3.6: patched." Your interpreter says otherwise.
What to check on your own instance
- If you installed GitLab from the official packages or official container images, upgrading to 19.4.2 / 19.3.5 / 19.2.8 or later is enough: those bundles carry the patched Ruby. Verify you are actually on the fixed version, not the one below it. Alpine's 19.3.4-instead-of-19.3.5 slip is the most relatable mistake in the whole report.
- If you run GitLab with your own Ruby - built from source, or in a custom container image on a distribution Ruby - upgrading GitLab is not enough. You need Ruby 3.3.13, 3.4.12, 4.0.9 or later. Check the interpreter, not the app version string.
-
If you use Alpine's
alpinelinux/gitlabimage, pullalpinelinux/gitlab:19.3.6again: the image published on October 27 contains Ruby 3.3.13. Any 19.3.6 image pulled before that date, and all older tags, are vulnerable. - Check for probing. Alpine's tell was repeated worker crashes under crafted CI configs and a newly registered account pulling the container image. Crashes of regex-heavy workers are not noise this month.
- Log outbound connections. Alpine's single biggest evidence gap was having no record of what the GitLab host connected to. Without it, "no evidence of compromise" collapses into "no evidence at all."
The honest ending
There is a detail in Alpine's report that deserves more attention than the CVE itself: they rebuilt a production service serving one of the most widely used Linux distributions on Earth not because they found a breach, but because they could not rule one out. No stolen data, no defaced releases, no smoking gun. Just eight crashes, a missing log window, and the discipline to act as if the worst case were true.
Patching CVE-2026-97229 is the easy part. Knowing whether you patched the thing that was actually vulnerable - and being able to prove what happened before you did - is the real work.
Sources: Alpine Linux, "GitLab security incident: attempted exploitation of CVE-2026-97229" (Oct 28, 2026); GitLab Critical Patch Release 19.4.2 / 19.3.5 / 19.2.8 (Oct 12, 2026); CISA Known Exploited Vulnerabilities catalog, entries CVE-2026-97229 and CVE-2026-76418 (Oct 29, 2026); The Hacker News (Oct 30, 2026).
Top comments (0)