Self-Hosting GitLab: What the Alpine Attack Teaches Small Teams
By Arash Latifi — Founder, The DevArt
This week's attack on Alpine's GitLab showed that updating the tool isn't always enough. If you self-host GitLab or similar, take this checklist seriously.
TL;DR — Alpine Linux just survived a serious attack on its GitLab instance — and still had to rebuild everything from scratch. Lesson: with self-hosted tools, updating the app isn't always the fix.
What happened
On October 28, Alpine Linux disclosed that an attacker tried to exploit a critical GitLab bug (CVE-2026-97229) on October 20–21. The bug let an unauthenticated user run arbitrary code via a crafted regex in CI configuration — CVSS 10.0.
Details worth noting:
- The attacker used a freshly registered account, sent crafted CI configs, and crashed GitLab workers 8 times — getting partway through the exploit 4 of those times.
- They also downloaded Alpine's GitLab container image, apparently tuning the exploit to that exact build.
- Alpine found no evidence of success but couldn't rule it out, so they rebuilt the instance from scratch: all passwords reset, secret keys replaced.
The bitter part: upgrading GitLab didn't fix it
Alpine upgraded to GitLab 19.3.6 on October 22 — and the bug was still there.
Why? The fix wasn't in GitLab's code. It was a patch to Ruby's regex engine (Onigmo), which GitLab only applies in its own packages and official images. The real Ruby fix shipped October 23 in 3.3.13, 3.4.12, and 4.0.9.
So if you run GitLab with your own Ruby (from source or a custom image), upgrading GitLab alone does nothing. Alpine also flagged any alpinelinux/gitlab:19.3.6 image pulled before October 27 as vulnerable.
Why this matters for your business
Plenty of small shops and teams self-host GitLab — it's cheaper and the data stays in-house. The hidden cost:
| Responsibility | Vendor-managed SaaS | Self-hosted | |---|---|---| | Applying underlying-layer fixes (like the Ruby patch) | The vendor | You | | Spotting "two-layer" fixes | The vendor | Usually nobody | | Rebuilding after a suspected breach | Vendor team | You, overnight | | Rotating passwords and secrets post-incident | The vendor | You |
The attacker struck one week after the fix was published — the window between "patch released" and "I updated" is now measured in days. And this was an automated, scripted attack, not a targeted one.
Checklist for your own GitLab
- [ ] Check your GitLab version; if it's below 19.2.8 / 19.3.5 / 19.4.2, upgrade now.
- [ ] Find out where your Ruby comes from: official package, official image, or your own build? If it's your own, you need at least
3.3.13/3.4.12/4.0.9. - [ ] If you pulled
alpinelinux/gitlab:19.3.6before October 27, pull it again. - [ ] Put internal GitLab behind a VPN or allowlist — the Alpine attack came from a brand-new account.
- [ ] Write a one-page incident plan: "if we suspect compromise, what do we rotate?" (passwords, secret keys, CI tokens).
FAQ
Q: We don't use GitLab — does this matter to us?
Yes, twice over. First, the bug was in Ruby's regex engine, not GitLab — any Ruby app compiling regexes from user input was exposed. Second, the pattern "the fix lives in a lower layer, not the tool" repeats across self-hosted stacks; we saw the same in recent Node and PHP incidents.
Q: Should we just move to SaaS?
Depends. SaaS means people whose full-time job is patching these bugs carry the responsibility — but your CI data and source code live on someone else's servers. For small teams without a dedicated DevOps person, SaaS is usually the safer call than a half-patched self-hosted GitLab.
Q: How do I know if my server was targeted?
Alpine couldn't be sure either — logs showed the attempt, but success was unprovable. Practical test: check your GitLab and Ruby versions; if you were in the vulnerable range and the server was public, assume someone tried and rotate passwords and secrets at minimum.