Back to Intelligence

CVE-2026-97229: Critical GitLab CI/CD RCE (CVSS 10.0) — Detection, Hunting, and Remediation Guide

SA
Security Arsenal Team
October 15, 2026
11 min read

On October 12, 2026, GitLab shipped an emergency patch release for CVE-2026-97229, a critical integer overflow/wraparound (CWE-190) in the CI/CD regular expression compiler affecting both GitLab Community Edition (CE) and Enterprise Edition (EE). The vendor-assigned CVSSv3.1 score is 10.0 — the maximum severity rating — reflecting a remotely exploitable code execution path against the GitLab server itself.

There is one important nuance defenders must understand. While the vendor's CVSS vector characterizes the issue as fully unauthenticated, reproduction work documented by Rapid7 showed that an attacker must first have a mechanism to plant a malicious CI/CD configuration into a repository before triggering the vulnerability. That precondition matters enormously for your risk model: any GitLab instance that allows external user registration, public project contributions, or merge requests from untrusted forks effectively collapses that precondition to zero. If your instance is internet-facing with open sign-up or accepts contributions from outside your organization, treat this as unauthenticated RCE in practice, not just on paper.

Self-managed GitLab is high-value target real estate. A compromised GitLab server hands an attacker source code, CI/CD secrets and tokens, runner infrastructure, and in many environments a springboard into production deployment pipelines. We have seen this movie before with prior GitLab RCEs — mass scanning and opportunistic exploitation follow critical GitLab advisories within days. Patch immediately, then hunt.

Technical Analysis

Affected Products

  • GitLab Community Edition (CE) — self-managed installations
  • GitLab Enterprise Edition (EE) — self-managed installations
  • GitLab.com SaaS is patched by GitLab directly; the exposure here is overwhelmingly self-managed instances, particularly those exposed to the internet

The flaw resides in the CI/CD regular expression compiler — the component that parses and compiles regex patterns found in .gitlab-ci.yml and related pipeline configuration. An integer overflow or wraparound (CWE-190) occurs during compilation of a specially crafted regular expression. Under the right conditions, the miscalculation corrupts memory handling in the compiler, producing a condition the attacker can steer into arbitrary code execution in the context of the GitLab server process.

Attack Chain (Defender's View)

  1. Precondition: The attacker gains the ability to commit a CI/CD configuration to a repository on the target instance. Viable paths include:
    • Open user registration + creating a project and pushing a malicious .gitlab-ci.yml
    • Submitting a merge request from a fork to a project where pipelines run on MRs from untrusted sources
    • Compromising a low-privilege developer account (phishing, credential stuffing, leaked PAT)
  2. Trigger: The malicious configuration is processed — either when a pipeline is created/validated or when the CI/CD regex compiler evaluates the crafted pattern.
  3. Exploitation: The integer wraparound in the regex compiler produces memory corruption, yielding code execution as the git user (or the service account running the Rails/Puma/Sidekiq workload).
  4. Post-exploitation: Attackers typically pivot to harvesting CI/CD variables, Personal Access Tokens, deploy keys, and runner registration tokens — everything needed to poison downstream build and deployment pipelines.

Exploitation Status

  • Vendor advisory: Published October 12, 2026 alongside the patch release
  • CVSSv3.1: 10.0 (Critical)
  • Public technical detail: Rapid7's Emerging Threat Response team reproduced the issue and published analysis the same week, which materially lowers the bar for exploit development by other parties
  • Active exploitation: At the time of writing, no confirmed widespread in-the-wild exploitation has been publicly documented, but given the CVSS 10.0 rating, public reproduction analysis, and GitLab's history of rapid post-advisory scanning, defenders should operate as if exploitation is imminent
  • CISA KEV: Monitor the CISA Known Exploited Vulnerabilities catalog — critical GitLab RCEs are frequently added once exploitation is observed

Detection & Response

The most reliable post-exploitation telemetry on a GitLab server is process lineage: the Ruby-based GitLab web and job processes (Puma, Sidekiq) and Gitaly should essentially never spawn interactive shells, downloaders, or scripting interpreters. Regex-compiler memory corruption payloads typically manifest as a shell or command interpreter child of one of these processes. The detections below focus on that lineage, plus auditing of CI/CD configuration changes for regex-heavy payloads.

YAML
---
title: GitLab Server Process Spawning Shell or Interpreter
description: Detects GitLab Rails/Sidekiq/Gitaly processes spawning shells, scripting interpreters, or download utilities — a strong indicator of post-exploitation following CI/CD-triggered code execution such as CVE-2026-97229.
references:
  - https://www.rapid7.com/blog/post/etr-cve-2026-97229-critical-unauthenticated-remote-code-execution-in-gitlab
  - https://attack.mitre.org/techniques/T1059/
author: Security Arsenal
date: 2026/10/14
status: experimental
id: 8f2c1a94-3b6d-4e5a-9c71-2d4e6f8a0b1c
tags:
  - attack.execution
  - attack.t1059
logsource:
  category: process_creation
  product: linux
detection:
  selection_parent:
    ParentImage|endswith:
      - '/puma'
      - '/sidekiq'
      - '/gitaly'
      - '/gitlab-workhorse'
      - '/ruby'
  selection_parent_user:
    ParentUser|contains:
      - 'git'
  selection_child:
    Image|endswith:
      - '/bash'
      - '/sh'
      - '/dash'
      - '/zsh'
      - '/python'
      - '/python3'
      - '/perl'
      - '/curl'
      - '/wget'
      - '/nc'
      - '/ncat'
  condition: selection_parent and selection_child
falsepositives:
  - GitLab backup or maintenance rake tasks run manually by administrators (these typically run as git but via gitlab-rake, not as children of puma/sidekiq)
  - Custom CI hooks executed locally rather than on runners — rare on the server itself
level: high
---
title: GitLab Shell Fetch-and-Execute Pattern via Web Process
description: Detects curl/wget piped to a shell executed under the git service account, a common payload staging pattern after RCE on a GitLab server.
references:
  - https://www.rapid7.com/blog/post/etr-cve-2026-97229-critical-unauthenticated-remote-code-execution-in-gitlab
  - https://attack.mitre.org/techniques/T1105/
author: Security Arsenal
date: 2026/10/14
status: experimental
id: 3d7e9b12-5a4c-4f68-b812-9e3a7d502c44
tags:
  - attack.command_and_control
  - attack.t1105
  - attack.t1059.004
logsource:
  category: process_creation
  product: linux
detection:
  selection_user:
    User|contains:
      - 'git'
  selection_cmd:
    CommandLine|contains:
      - 'curl'
      - 'wget'
  selection_pipe:
    CommandLine|contains:
      - '| bash'
      - '| sh'
      - '|bash'
      - '|sh'
  condition: selection_user and selection_cmd and selection_pipe
falsepositives:
  - Administrator-run installation or upgrade scripts executed as root rather than git (filter by user to reduce noise)
level: critical
---
title: Outbound Connection from GitLab Service Processes to Uncommon Destination
description: Detects network connections initiated by GitLab Ruby/Sidekiq processes to non-standard destinations, which may indicate C2 or data exfiltration after CI/CD-based compromise.
references:
  - https://www.rapid7.com/blog/post/etr-cve-2026-97229-critical-unauthenticated-remote-code-execution-in-gitlab
  - https://attack.mitre.org/techniques/T1071/
author: Security Arsenal
date: 2026/10/14
status: experimental
id: 5b1e7c30-8d92-4a1f-ae64-7c2b9f104e83
tags:
  - attack.command_and_control
  - attack.t1071
logsource:
  category: network_connection
  product: linux
detection:
  selection_image:
    Image|endswith:
      - '/puma'
      - '/sidekiq'
      - '/ruby'
  selection_ports:
    DestinationPort:
      - 4444
      - 5555
      - 6666
      - 8081
      - 9001
  condition: selection_image and selection_ports
falsepositives:
  - Legitimate outbound integrations (webhooks, package registries, monitoring) — baseline known-good destinations and tune the port list to your environment
level: medium

KQL — Microsoft Sentinel / Defender

GitLab servers emit Syslog and (if instrumented with auditd or a forwarder) process execution telemetry ingestible into Sentinel. The following hunts work against the Syslog and CommonSecurityLog tables for Linux-hosted GitLab, plus DeviceProcessEvents where Defender for Endpoint is deployed on the host.

KQL — Microsoft Sentinel / Defender
// Hunt 1: GitLab service processes spawning shells/interpreters (post-exploitation lineage)
// Works against Syslog-ingested auditd/execve data from GitLab hosts
Syslog
| where TimeGenerated > ago(14d)
| where ProcessName in~ ("bash", "sh", "dash", "python", "python3", "perl", "curl", "wget", "nc", "ncat")
| where SyslogMessage has_any ("puma", "sidekiq", "gitaly", "gitlab-workhorse")
   or SyslogMessage has "auid=" and SyslogMessage has "git"
| project TimeGenerated, Computer, ProcessName, SyslogMessage, SeverityLevel
| order by TimeGenerated desc;

// Hunt 2: Defender for Endpoint on GitLab hosts — suspicious child processes of git user workloads
DeviceProcessEvents
| where TimeGenerated > ago(14d)
| where InitiatingProcessAccountName =~ "git"
   or InitiatingProcessFileName in~ ("puma", "sidekiq", "gitaly", "ruby")
| where FileName in~ ("bash", "sh", "dash", "zsh", "python", "python3", "perl", "curl", "wget", "nc", "ncat")
| project TimeGenerated, DeviceName, InitiatingProcessFileName, InitiatingProcessCommandLine, FileName, ProcessCommandLine, AccountName
| order by TimeGenerated desc;

// Hunt 3: Newly created accounts or tokens touching CI/CD config — precondition activity
// Review Syslog for pushes/MRs modifying .gitlab-ci.yml around the advisory window
Syslog
| where TimeGenerated > ago(30d)
| where SyslogMessage has ".gitlab-ci.yml"
| where SyslogMessage has_any ("commit", "push", "merge_request", "pipeline")
| summarize EventCount = count(), FirstSeen = min(TimeGenerated), LastSeen = max(TimeGenerated) by Computer, SyslogMessage
| order by LastSeen desc;

Velociraptor VQL

For live forensics on a suspected-compromised GitLab host, this artifact enumerates running processes and flags shell/interpreter children under the git user, plus checks for recently modified CI configuration in repositories.

VQL — Velociraptor
-- Artifact: GitLab.Server.PostExploitHunt
-- Identify suspicious process lineage and recent CI config changes on GitLab hosts

-- Suspicious children running under the git service account
SELECT Pid, Ppid, Name, Exe, CommandLine, Username, CreateTime
FROM pslist()
WHERE Username =~ 'git'
  AND Name =~ '(?i)(bash|sh|dash|zsh|python|perl|curl|wget|nc|ncat)'

-- Recently modified .gitlab-ci.yml files across repositories (default omnibus path)
SELECT FullPath, Mtime, Size
FROM glob(globs='/var/opt/gitlab/git-data/repositories/**/.gitlab-ci.yml')
WHERE Mtime > now() - 2592000
ORDER BY Mtime DESC

-- Established outbound connections from Ruby/GitLab processes
SELECT Pid, Name, RemoteIP, RemotePort, Status
FROM netstat()
WHERE Name =~ '(?i)(puma|sidekiq|ruby|gitaly)'
  AND Status =~ 'ESTABLISHED'
  AND NOT RemoteIP =~ '^(127\.|10\.|172\.(1[6-9]|2[0-9]|3[01])\.|192\.168\.)'

Remediation & Verification Script

Use the following on self-managed omnibus or source installations to confirm your current version, check exposure (open registration, public projects), and apply the October 12, 2026 security patch. Verify the exact fixed version numbers against GitLab's official security release notes before and after patching — the patch release post for CVE-2026-97229 lists the fixed versions for each supported release line.

Bash / Shell
#!/bin/bash
# CVE-2026-97229 GitLab verification and remediation helper
# Run as root on the GitLab server. Test in staging first.

echo "=== Current GitLab version ==="
if command -v gitlab-rake >/dev/null 2>&1; then
  gitlab-rake gitlab:env:info 2>/dev/null | head -20
cat /opt/gitlab/version-manifest.txt 2>/dev/null | grep -m1 gitlab-ce
  cat /opt/gitlab/version-manifest.txt 2>/dev/null | grep -m1 gitlab-ee
else
  echo "Omnibus commands not found — check source install or container image tag."
fi

echo ""
echo "=== Exposure check: is this host internet-facing? ==="
ss -tlnp | grep -E ':(80|443)\b' || echo "No web listeners found on 80/443"

echo ""
echo "=== Package upgrade (Omnibus — APT example; use yum/dnf for RHEL-family) ==="
echo "Backup first: gitlab-backup create STRATEGY=copy"
echo "Then: apt update && apt install gitlab-ee   # or gitlab-ce"
echo "Confirm target version matches the Oct 12, 2026 security release notes."

echo ""
echo "=== Post-patch verification ==="
echo "gitlab-rake gitlab:check SANITIZE=true"
echo "gitlab-ctl status"

echo ""
echo "=== Audit recent CI config pushes (last 30 days) ==="
sudo -u git gitlab-rails runner \
  'puts Project.joins(:repository).where("projects.created_at > ?", 30.days.ago).limit(50).pluck(:path_with_namespace)' \
  2>/dev/null || echo "Review audit events via Admin > Monitoring > Audit Events instead."

echo ""
echo "=== Rotate secrets if compromise suspected ==="
echo "- Revoke and reissue Personal Access Tokens for privileged users"
echo "- Rotate CI/CD variables, deploy keys, runner registration/auth tokens"
echo "- Review Admin > Users for accounts created near the advisory window"

Remediation

  1. Patch immediately. Apply the October 12, 2026 GitLab security patch release on all self-managed CE and EE instances. Pull the exact fixed version numbers for your release line from the official GitLab patch release notes at https://about.gitlab.com/releases/categories/releases/ and the advisory itself. Do not assume your release train auto-updates — most omnibus installs require a manual package upgrade.
  2. Take a backup before upgrading. gitlab-backup create STRATEGY=copy, then verify restore integrity. If the upgrade fails mid-flight you need a clean rollback path.
  3. Eliminate the precondition where possible. Disable open user registration on internet-facing instances (Admin Area → Settings → General → Sign-up restrictions). Require admin approval for new accounts. Restrict who can create projects and push CI/CD configuration.
  4. Harden pipeline execution from untrusted sources. Do not run pipelines on merge requests from forks against protected branches without manual review. Gate CI/CD variable exposure so secrets are not available to pipelines triggered by unvetted contributors.
  5. Reduce blast radius. Ensure GitLab is not running as root, segment the host from production networks, and restrict egress from the GitLab server to only required destinations (package registries, webhook targets). The network-level Sigma rule above is far more effective when egress is tightly baselined.
  6. Audit and rotate. Review audit events for new accounts, project creation, and .gitlab-ci.yml modifications in the weeks preceding patching. If there is any indication of compromise, rotate PATs, CI/CD variables, deploy keys, and runner tokens — assume anything readable by the git user was taken.
  7. Monitor for follow-on exploitation. Track CISA KEV for CVE-2026-97229 additions and watch Rapid7 and GitLab channels for updated exploitation intelligence. CVSS 10.0 bugs in internet-facing developer infrastructure do not stay theoretical for long.

Closing Assessment

CVE-2026-97229 is exactly the class of vulnerability that keeps GitLab administrators up at night: a maximum-severity memory corruption flaw reachable through the CI/CD pipeline itself, on infrastructure that by design holds your organization's crown jewels. The "attacker needs to plant a config file" caveat provides cold comfort — for any instance with open registration or untrusted contributors, that precondition is trivially met. Patch this week, hunt for the process-lineage indicators above, and treat your GitLab host with the same defensive rigor you apply to your identity providers. In modern intrusions, the CI/CD server is the identity provider for your software supply chain.

Related Resources

Security Arsenal Penetration Testing Services AlertMonitor Platform Book a SOC Assessment vulnerability-management Intel Hub

Is your security operations ready?

Get a free SOC assessment or see how AlertMonitor cuts through alert noise with automated triage.