Direct answer: Self-managed GitLab has 2 flaws with a CVSS score of 10.0: CVE-2026-97229 and CVE-2026-110264. Both can run code on the server without a login. CVE-2026-97229 is already used in attacks and entered CISA KEV on 29 October 2026. Update GitLab to the 29 October release today: 19.5.3, 19.4.5, 19.3.7, 19.2.10, 19.1.10, 19.0.11, or 18.11.14.

The flaws exist only in the GitLab that you install yourself. GitLab patched GitLab.com and GitLab Dedicated.

Main condition: Omnibus packages, the official Docker image, and the official Helm chart need only a GitLab update. Source installs and self-built images also need Ruby 3.3.13, 3.4.12, or 4.0.9. Limit: The temporary steps in this article only reduce exposure. This article contains no exploit code.

We read the GitLab patch release of 12 October, the GitLab patch release of 21 October, the GitLab release of 29 October, the Ruby advisory of 23 October, the Alpine Linux incident report, and CISA KEV on 30 October 2026, at about 10:00 UTC. We ran the commands in steps 1, 2, 4, and 5 in podman containers with the official GitLab 19.3.4, GitLab 19.5.3, Ruby 3.3.12, and Ruby 3.3.13 images on the same date. The test server holds no customer data.

The problem: the first patch does not close every flaw, and a GitLab update alone can fail

A server patched on 12 October is still vulnerable to CVE-2026-110264. A server with its own Ruby can stay vulnerable after a GitLab update.

GitLab released the fix for CVE-2026-97229 on 12 October 2026. 9 days later, the GitLab patch release of 21 October closed a second flaw, CVE-2026-110264, which exists in every version since 7.0. So an admin who patched on 12 October must update again.

The second problem is harder to see. According to the Alpine Linux incident report, a new account probed the Alpine Linux GitLab on 20 October, then attacked on 21 October. GitLab workers crashed 8 times. Alpine had moved to GitLab 19.3.6, but its image used standard Ruby, so the flaw stayed open.

Alpine closed GitLab, rebuilt the server from scratch, reset every password, and replaced the GitLab secrets on 27 to 28 October. Alpine found no proof that attacker code ran, but wrote that it cannot rule it out. One day later, CISA KEV added CVE-2026-97229 to its list of exploited flaws.

Timeline from 12 October to 1 November 2026: first patch, attack on the Alpine Linux GitLab, second patch, Ruby release, Alpine rebuild, CISA KEV, and the CISA deadline.
Grey dots: patch releases and analysis. Red dots: the attack, the Alpine response, and the CISA decision. The first reported attack came 8 days after the first patch. Source: GitLab, Rapid7, Alpine Linux, ruby-lang.org, and CISA KEV.

This month we also covered the PHP2Shell flaws and the PwnEscape kernel flaw. The same pattern came back: the gap from patch to attack was only a few days. For GitLab, BleepingComputer noted on 22 October that CISA had flagged 5 GitLab flaws as exploited since November 2021.

How it works: a crafted regex triggers an integer overflow

Both flaws use the same pattern: a crafted regex pushes a number in the regex compiler past its limit. An update to the 29 October release closes both.

This section uses the summary from the official advisories. Its purpose is to help you pick the right step, not to explain an attack.

CVE-2026-97229: the CI/CD regex compiler

According to the GitLab patch release of 12 October, regex validation in the CI/CD configuration was not strict enough. A crafted regex triggers an integer overflow (CWE-190), and code can then run on the GitLab server. Affected versions: 19.2 before 19.2.8, 19.3 before 19.3.5, and 19.4 before 19.4.2.

Rapid7 reproduced code execution on an unpatched GitLab CE image. Rapid7 also notes the condition: the attacker must be able to plant a CI/CD configuration. An instance with open public sign-up removes that condition.

CVE-2026-110264: the regex compiler, every version since 7.0

According to the GitLab patch release of 21 October, under certain conditions, a user without a login could run code on the server with a regex that triggers an integer overflow when it is compiled. GitLab has not disclosed the exact conditions. The flaw exists in every version since 7.0, so GitLab patched 7 branches.

As of 22 October, eSecurityPlanet quoted Censys: no confirmed exploitation and no verified PoC for CVE-2026-110264. This status can change fast, because its root cause is the same as the flaw already under attack.

Two cards: the exploited CVE-2026-97229 and CVE-2026-110264 since version 7.0, the Onigmo root in Ruby, then a teal box: update to the 29 October release.
(1) Red card: CVE-2026-97229, already in CISA KEV. (2) Amber card: CVE-2026-110264, the 12 October fix does not close it. (3) Amber box: the root cause is in Ruby. (4) Teal box: the 29 October release carries both fixes. Source: GitLab, ruby-lang.org, and CISA KEV.

Root cause: Onigmo inside Ruby

According to the Ruby advisory of 23 October, both flaws come from bugs in Onigmo, the regex engine inside Ruby. GitLab patches Ruby in its official packages and images. Ruby released 3.3.13, 3.4.12, and 4.0.9 with the same fixes on 23 October 2026.

The Ruby advisory says that other Ruby applications are also affected when they compile a regex from user input, for example Regexp.new(input). Regexp.timeout and pattern length limits do not protect. The KEV entry also notes that other products can be affected by the same Ruby bug.

What the patch changes

The Ruby patch fixes 3 bugs: a double free when parsing fails, an integer overflow in the pattern size, and an overflow of internal IDs in patterns with many repeats. The GitLab release of 29 October carries all of those fixes, plus the removal of trust for 8 eMudhra CA certificates with leaked keys (CVE-2026-111943).

Who is at the highest risk

A GitLab instance on the internet with open sign-up has the highest risk. Installs with their own Ruby need 2 updates.

How GitLab is installed decides what you must update. This table summarises GitLab, the Ruby advisory of 23 October, and the Alpine Linux incident report.

Install typeWhat you updateProof of safety
Omnibus package (.deb, .rpm)GitLabGitLab version in step 1
Docker image gitlab/gitlab-ce or gitlab-eeImage tag, then recreate the containerGitLab version in step 1
Official Helm chartChart version and GitLab imagesGitLab version on the Help page
Source installGitLab and RubyStep 1 and step 2
Self-built or distro imageGitLab and the Ruby in the imageStep 1 and step 2
GitLab.com and GitLab DedicatedNothingGitLab applied the fix
Six GitLab install cards: Omnibus, the official Docker image, and the Helm chart need a GitLab update, while source installs and self-built images also need a Ruby update.
Teal cards: official packages and images ship the Ruby that GitLab patched. Red cards: you control your own Ruby, so a GitLab update alone is not enough. Amber card: GitLab.com and Dedicated need no action. Source: GitLab, ruby-lang.org, and Alpine Linux.

The exposure is large. eSecurityPlanet quoted Censys: 81,820 GitLab hosts were visible from the internet on 21 October. BleepingComputer quoted Shadowserver: more than 2,700 GitLab CE instances are exposed. The 2 numbers measure different things, so do not add them up.

Versions that carry the fix

GitLab released fixes for 7 branches. The middle column closes both CVEs. The right column is the target today, because it also carries the 29 October fixes.

BranchMinimum for both CVEs (21 Oct)Latest release (29 Oct)
19.519.5.119.5.3
19.419.4.319.4.5
19.319.3.619.3.7
19.219.2.919.2.10
19.119.1.919.1.10
19.019.0.1019.0.11
18.1118.11.1318.11.14
18.10 and olderNo fix in this branchUpgrade to a supported branch
Table of GitLab versions per branch: the minimum for both CVEs and the 29 October release, a box of Ruby 3.3.13, 3.4.12, 4.0.9, and a GitLab.com box with no action.
Amber column: the minimum version that closes both CVEs. Teal column: the target version today. Top right: Ruby versions for installs with their own Ruby. Bottom right: GitLab.com and Dedicated are patched. Source: GitLab patch releases of 12, 21, and 29 October 2026.

Branches 18.10 and older get no fix. Use the GitLab Upgrade Path tool to see the upgrade order to a supported branch. A large jump across branches needs several stages and migration time.

The 29 October release also asks you to update a self-hosted GitLab Runner to 19.5.1. Runner checks certificates on its own, so a GitLab update does not change it.

Prerequisites

  • SSH access with sudo rights to the GitLab server, or docker exec access to the GitLab container.
  • A GitLab admin account for the Admin area.
  • A list of every GitLab instance: production, staging, mirrors, and GitLab inside vendor products.
  • Disk space for a backup, and a short downtime window for a single-node server.
  • A list of the tokens and secrets stored in GitLab: CI/CD variables, deploy keys, and Runner tokens.

Step 1: Check the GitLab version on each server

Save this script as check-gitlab.sh. The script reads the GitLab version, then compares it with the minimum and the latest version for its branch.

v=$(cat /opt/gitlab/embedded/service/gitlab-rails/VERSION); v=${v%%-*}
case ${v%.*} in
  19.5) min=19.5.1 new=19.5.3;;  19.4) min=19.4.3 new=19.4.5;;
  19.3) min=19.3.6 new=19.3.7;;  19.2) min=19.2.9 new=19.2.10;;
  19.1) min=19.1.9 new=19.1.10;; 19.0) min=19.0.10 new=19.0.11;;
  18.11) min=18.11.13 new=18.11.14;;
  *) echo "$v: branch without a fix. Upgrade to 18.11 or newer."; exit;;
esac
lt() { [ "$1" != "$2" ] && [ "$(printf '%s\n' "$1" "$2" | sort -V | head -1)" = "$1" ]; }
if lt "$v" "$min"; then echo "$v: VULNERABLE to 2 CVSS 10 CVEs. Update to $new."
elif lt "$v" "$new"; then echo "$v: safe from the 2 CVEs. Update to $new for the 29 Oct release."
else echo "$v: latest version as of 29 Oct 2026."; fi

Run the script on an Omnibus server, or send it into a Docker container.

sudo bash check-gitlab.sh                 # Omnibus package
docker exec -i gitlab bash < check-gitlab.sh   # Docker container
Terminal: the check script in a GitLab 19.3.4 container prints VULNERABLE to 2 CVSS 10 CVEs, update to 19.3.7, and in a 19.5.3 container prints latest version as of 29 Oct 2026.
Lines 2 and 4 are the results you look for. The test used the official gitlab/gitlab-ce 19.3.4 and 19.5.3 images in podman on 30 October 2026. Source: Rama Digital test in podman, 30 October 2026.

For a source install, change the path on the first line to /home/git/gitlab/VERSION. You can also open the GitLab Help page, which shows the version to signed-in users.

Check the result: The output says "latest version as of 29 Oct 2026". A "VULNERABLE" result means the server must update today. A "safe from the 2 CVEs" result means both flaws are closed, but the 29 October release is not installed yet.

Step 2: Check Ruby when GitLab uses its own Ruby

This step is only for source installs and self-built images. Save this script as check-ruby.sh, then run it with the Ruby that runs GitLab.

ruby -e 'fix = { "3.3" => "3.3.13", "3.4" => "3.4.12", "4.0" => "4.0.9" }
  v = RUBY_VERSION; f = fix[v[/\A\d+\.\d+/]]
  if f.nil? then puts "#{v}: branch outside the Ruby advisory. Upgrade Ruby."
  elsif Gem::Version.new(v) < Gem::Version.new(f) then puts "#{v}: VULNERABLE. Update Ruby to #{f}."
  else puts "#{v}: has the Onigmo fix." end'
Terminal: the Ruby check on the ruby 3.3.12 image prints VULNERABLE, on 3.3.13 prints has the Onigmo fix, and Ruby inside the official GitLab 19.5.3 still prints 3.3.12.
The last line shows why step 2 is only for your own Ruby. The official package prints 3.3.12, but GitLab already patched that Ruby. For official packages, the GitLab version is the proof. Source: Rama Digital test in podman, 30 October 2026.

In our test, the Ruby inside the official GitLab 19.3.4 and 19.5.3 images both print 3.3.12. The libruby files in the 2 images differ, which matches the Alpine note that GitLab patches Ruby at build time. So do not run step 2 on official packages. It would print VULNERABLE, although the GitLab version is safe.

Check the result: For your own Ruby, the output says "has the Onigmo fix". When you use the alpinelinux/gitlab image, the Alpine Linux incident report asks you to pull the 19.3.6 tag again. Images pulled before 27 October are still vulnerable.

Step 3: Back up, then update GitLab

Back up the configuration and data first, then install the patch version in the same branch. A patch version in the same branch needs no special upgrade order.

sudo tar -czf /root/gitlab-config-$(date +%F).tgz /etc/gitlab
sudo gitlab-backup create
sudo apt update
sudo apt install gitlab-ce=19.3.7-ce.0   # use your branch version, gitlab-ee for EE

On the RHEL family, use this command.

sudo dnf install 'gitlab-ce-19.3.7*'

For Docker Compose, change the image tag, then recreate the container.

# docker-compose.yml: image: gitlab/gitlab-ce:19.3.7-ce.0
docker compose pull
docker compose up -d
A 6-step ladder: a GitLab update and a Ruby update as fixes, then 4 temporary steps with a not-a-fix label: close sign-up, restrict public, take off the internet, check signs.
(1) and (2) Teal boxes: fixes that close the flaws. (3) to (6): temporary steps. The red labels remind you that those steps do not make the server safe. Source: GitLab, Rapid7, and ruby-lang.org.

The /etc/gitlab archive keeps gitlab.rb and gitlab-secrets.json, which the data backup does not include. The GitLab backup guide has the details. This release carries database migrations, so a single-node server has downtime until the migrations finish.

For a source install, update Ruby first to the version in step 2, then update GitLab. For a self-built image, rebuild the image with a patched Ruby.

Check the result: Repeat step 1. The output must say "latest version as of 29 Oct 2026". Then run sudo gitlab-ctl status and confirm that every service runs.

Step 4 (optional): Lock down access when you cannot update yet

This step is only for a short gap until the update is done. Rapid7 says that access limits only close the path that was demonstrated, not the bug.

Turn off new account sign-up and restrict the Public level. In the UI, open Admin area > Settings > General, then change Sign-up restrictions and Visibility and access controls. In a terminal, use this command.

sudo gitlab-rails runner '
  Gitlab::CurrentSettings.update!(signup_enabled: false,
    restricted_visibility_levels: [Gitlab::VisibilityLevel::PUBLIC])
  s = Gitlab::CurrentSettings.current_application_settings
  puts "signup_enabled=#{s.signup_enabled} restricted=#{s.restricted_visibility_levels}"
  puts "public projects: #{Project.where(visibility_level: Gitlab::VisibilityLevel::PUBLIC).count}"'
Terminal: gitlab-rails runner turns off sign-up and restricts the Public level, then prints signup_enabled=false, restricted=[20], and the count of public projects.
The number 20 is the GitLab code for the Public level. The test ran in a GitLab 19.5.3 container with no customer data on 30 October 2026. Source: Rama Digital test in podman, 30 October 2026.

A restricted Public level only blocks new public projects. Existing public projects stay public, so change projects that do not need to be public to Internal or Private. The sign-up restrictions docs and the visibility docs explain the effect of each setting.

When GitLab does not need internet access, close it with a VPN or an IP allowlist until the update is done. This is the strongest of the temporary steps.

Check the result: The output says signup_enabled=false and restricted=[20]. The sign-in page no longer shows a link to register.

Step 5: Look for signs that the server was touched

A failed attack leaves crashes. A successful attack can leave no trace in the web logs, as the Alpine Linux incident report says. Run these commands for the period since 12 October 2026.

sudo zgrep -cE '\[BUG\]|Segmentation fault' /var/log/gitlab/puma/puma_stderr.log*
sudo zcat -f /var/log/gitlab/nginx/gitlab_access.log* | awk '$9 == 502' | wc -l
sudo gitlab-rails runner '
  t = Time.utc(2026, 10, 12)
  fresh = User.where("created_at > ?", t)
  fresh.find_each { |u| puts "account #{u.username} #{u.created_at.to_date} #{u.state}" }
  Ci::Pipeline.where("created_at > ?", t).where(user_id: fresh.select(:id))
    .find_each { |p| puts "pipeline #{p.id} #{p.project.full_path} #{p.user.username}" }'
Terminal: zgrep counts 0 crashes in the Puma log, awk counts 0 responses with 502, and the runner prints 1 new account, the root user from the test install.
The test server is clean, so every count is 0. On your server, check each account you do not know and each pipeline from that account one by one. Source: Rama Digital test in podman, 30 October 2026.
Two columns of GitLab attack signs: in the server logs and in accounts and pipelines, then a red box with the action to take when you see a sign.
Amber column: worker crashes, 502 bursts, and failed CI jobs. Red column: new accounts, pipelines from new accounts, and logins with leaked passwords. Bottom box: isolate, rebuild, replace every secret. Source: GitLab and Alpine Linux.

Look for 4 patterns. First, native Puma worker crashes, which Ruby writes as [BUG] or Segmentation fault. Second, bursts of HTTP 502 and CI jobs that fail without cause. The location of each log is in the GitLab log docs.

Third, new accounts that you do not know. Fourth, pipelines from those new accounts. GitLab also released official detections for both CVEs, for example "Onigmo native worker crash" and "Org mode render error burst".

Check the result: The crash count is 0, there is no 502 burst, and you know every new account. When you see a sign, isolate the server and keep the logs. Then follow the Alpine steps: rebuild the server, reset every password, replace the GitLab secrets, and rotate tokens, CI/CD variables, deploy keys, and Runner tokens.

Example: 1 afternoon of response for 3 GitLab servers

This simulation uses dummy data. The server names, times, and results are not customer data.

Time (UTC)Dummy serverCheckResultAction
08:00git-office (Omnibus 19.3.4)Step 1VULNERABLE to 2 CVEsBack up, then apt install 19.3.7
08:40git-officeRepeat step 1Latest as of 29 OctGo to step 5
09:00git-client (Docker 19.4.2)Step 1VULNERABLE, open sign-upStep 4, then change the tag to 19.4.5
09:30git-lab (source, Ruby 3.3.12)Steps 1 and 2GitLab 19.3.6, Ruby VULNERABLEUpdate Ruby to 3.3.13, then GitLab 19.3.7
10:30git-clientStep 52 unknown accounts, 1 pipeline from an unknown accountIsolate, keep logs, start incident response

The lesson from the simulation: servers with official packages finish fastest. A server with open sign-up needs an account review, not only an update.

Who installs the patch

The patch duty depends on the hosting type. This table helps you see who must act today.

Hosting typePatch ownerWhat you do
Own VM or serverYour IT teamSteps 1 to 5
Container or KubernetesThe team that owns the image and chartChange the tag or chart, then steps 1 and 5
GitLab run by a vendor or consultantThe vendorAsk for written proof of the version, then the step 5 results
GitLab.comGitLabNothing for these 2 CVEs

Rama Digital recommendation: when your GitLab holds product code and production secrets, treat every sign in step 5 as an incident. Leaked source code opens a path to other servers. Read about access rights, approval, and audit logs for a server tool for further checks.

Checklist for today

  1. List every GitLab instance. Owner: server admin. Evidence: a host list with the install type.
  2. Check the version with step 1. Owner: server admin. Evidence: script output per host.
  3. Check Ruby with step 2 for source installs and own images. Owner: server admin. Evidence: script output.
  4. Back up, then update to the 29 October release. Owner: server admin. Evidence: step 1 output after the update.
  5. Update self-hosted GitLab Runner to 19.5.1. Owner: DevOps team. Evidence: the Runner version in the Admin area.
  6. Apply step 4 on servers that cannot update yet. Owner: GitLab admin. Evidence: runner output.
  7. Look for signs with step 5. Owner: server admin. Evidence: command output, kept with the logs.
  8. Stop when every server says "latest version" and step 5 is clean. When you see a sign, stop the patch work and start incident response.

Frequently asked questions

Do GitLab.com users need to do anything? Not for these 2 CVEs. GitLab patched GitLab.com and GitLab Dedicated. The steps in this article are for the GitLab that you install yourself.

I updated on 12 October. Is my server safe? Not yet. The 12 October fix closes only CVE-2026-97229. Update again to the 21 October or 29 October release to close CVE-2026-110264.

Why does the Ruby in official GitLab still print 3.3.12? GitLab patches Ruby at build time without a change to its version number. For official packages, the GitLab version is the proof. Check Ruby only for source installs and self-built images.

Is turning off sign-up enough to close the flaws? No. That step closes 1 demonstrated path. GitLab has not disclosed the conditions for CVE-2026-110264, so only an update closes the flaws.

Is my Ruby on Rails application also affected? It can be, when the application compiles a regex from user input. The Ruby advisory asks for an update to 3.3.13, 3.4.12, or 4.0.9. Applications that use only developer-written regexes are not affected.

How do I know whether the server was broken into? Look for worker crashes, bursts of HTTP 502, new accounts, and pipelines from new accounts, as in step 5. Clean logs do not prove that the server is safe.

Next step

The limit that still applies: an update closes these 2 flaws, but it does not remove access that an attacker may have planted before the patch. When your server shows a sign in step 5, or you need help to check pipelines and secrets after an incident, use Vibe Code Rescue for an audit and stabilisation. For 1 urgent issue today, Book a 30-minute session.

Sources