The Whistle: Special Bulletin - GitLab's CI/CD regex RCE (CVE-2026-97229) joins CISA's KEV catalog

The Whistle: Special Bulletin - GitLab's CI/CD regex RCE (CVE-2026-97229) joins CISA's KEV catalog

Two Mondays ago this bug led our patch notes. This week CISA put it in the KEV catalog, Alpine disclosed how close the attackers got, and the fix turned out to be a Ruby build change a GitLab version string cannot prove.

A KEV listing, and the patch that hides in packaging

CISA added CVE-2026-97229 to the KEV catalog on October 29, citing evidence of active exploitation, with a federal patch deadline of November 1, three days from listing. The same batch added Cisco’s ASA/FTD CVE-2026-76418. The bug itself ran as our Week 42 headline (CVE-2026-97229, /post/2026-10-19-whistle-week-42/): a CVSS 10.0 integer overflow in GitLab CE/EE’s CI/CD regular-expression validation, reachable by an unauthenticated attacker who sends a crafted regex in CI configuration. The fixes landed October 12 in 19.2.8, 19.3.5, and 19.4.2.

The fix, though, is not a change to GitLab’s own code: it patches the Ruby GitLab bundles into its official packages and container images. Alpine proved it: upgrading their self-built instance from 19.3.4 to 19.3.6 on October 22 did not close the hole, because the image runs standard upstream Ruby rather than the bundled build. A version string like “19.3.6” tells you nothing about this CVE’s patch state. Self-managed from source, or under your own container image: confirm the Ruby underneath is 3.3.13, 3.4.12, or 4.0.9. Official packages or images: patch level rides on being at or past 19.4.2.

Alpine’s near-miss is the exploitation evidence

Alpine published the timeline October 28. A newly registered account sent crafted CI configurations on October 20 and 21 to an instance still running 19.3.4, because the October 13 patch attempt had grabbed 19.3.4, one release short of the fix. The payloads crashed worker processes 8 times; in four of those crashes “the attacker got partway through the exploit and failed at the next step.” The attacker also downloaded Alpine’s container image, which reads as exploit-tuning to their exact build, and was blocked when they returned October 25-26. Alpine’s verdict: “The attack came close to working. We have found no evidence that it succeeded, but we cannot rule it out, so we treated the instance as compromised and rebuilt it from scratch.” They reset every password, replaced the instance’s secret keys, and verified aports, packages, and the October 21 releases untampered; the package signing keys never lived on that server.

The detection cue: worker processes crashing around regex compilation. GitLab’s patch release page includes exploitation-attempt detection guidance, and open-registration instances hand strangers the vulnerable path, where Alpine’s attacker started.

Four GitLab CVEs, one regex engine

Ruby 4.0.9, 3.4.12, and 3.3.13 (October 23) fix the Onigmo engine bugs behind four GitLab CVEs: CVE-2026-89078 and CVE-2026-93577 (fixed in 19.4.1), CVE-2026-97229 (19.4.2), and CVE-2026-110264 (19.5.1). None carry Ruby CVE identifiers of their own, so scanners will keep tracking the family under GitLab’s numbers. The exposure applies past GitLab: the bugs fire wherever Ruby compiles a pattern an attacker controls (Regexp.new, Regexp.union, interpolation), Regexp.timeout does not protect, and length caps do not either, since some triggers are short.

Your upgrade order: self-managed instances to a patched train, the October 27 alpinelinux/gitlab:19.3.6 re-pull if that image is yours, a Ruby check on your own builds, worker-log searches for the crash pattern, then a sweep of other Ruby services that compile untrusted input. This one does not wait for your next maintenance window. Something wrong here, or a stronger opinion? info@stackref.com always works.

This post was created with a Hermes AI agent (hermesagent.ai) from a weekly news gathering workflow, then reviewed and approved by Keith before publication.