← Back to Feed CACHED · 2026-09-24 10:20:08 · CACHE_KEY CVE-2026-93577
CVE-2026-93577 · CWE-190 · Disclosed 2026-09-24

GitLab has remediated an issue in GitLab CE/EE affecting all versions from 19.2 before 19.2.7

ASSESSED — NOISGATE
Vendor
Reassessed
Verdict:
Do you agree?
01 · The Real Story

Someone can slip a booby-trapped regex into a merge request and own your entire source code vault

CVE-2026-93577 is an integer overflow (CWE-190) in the regular expression compiler that GitLab CE/EE uses to parse CI/CD pipeline configurations. An authenticated user — anyone who can push a .gitlab-ci.yml file or open a merge request against a repo with CI enabled — can craft a regex pattern that triggers the overflow during compilation. The overflow corrupts memory in a way that yields arbitrary code execution on the GitLab application server process. Affected versions span every release from 19.2 through 19.2.6, 19.3 through 19.3.2, and 19.4.0. It shares the same regex-engine attack surface with companion bug CVE-2026-89078 (a double-free in the same parser). Fixed in 19.2.7, 19.3.3, and 19.4.1, released 2026-09-23.

The vendor CVSS of 9.9 is *justified and, if anything, generous only in the decimal*. The vector — AV:N/AC:L/PR:L/UI:N/S:C — accurately captures the low bar: network-reachable, trivial complexity, low-privilege auth, no user interaction, scope-change to the underlying server. GitLab is not a commodity workstation app; it is the CI/CD platform, the artifact store, the container registry, and the source-code repository for most organizations that deploy it. RCE on this host is tantamount to supply-chain compromise. The only friction is the authentication gate, and GitLab instances routinely allow self-registration, external contributors, or broad internal user bases — making that gate thinner than the CVSS PR:L label implies. No public PoC or wild exploitation is confirmed yet, which shaves a hair off urgency but does not change the blast radius.

"Auth-to-RCE on your source-of-truth CI/CD server via a regex in .gitlab-ci.yml — supply-chain takeover territory."
02 · The Attack Path

5 steps from start to impact.

STEP 01

Obtain authenticated GitLab session

The attacker needs a valid GitLab account on the target instance. Many self-managed GitLab instances allow open registration (/users/sign_up), guest access to public projects, or external contributor accounts. Alternatively, a compromised developer credential (phished, leaked, reused) suffices. The required privilege level is the lowest GitLab role — Guest or Reporter with fork access is enough to create a CI config in a forked repo.
Conditions required:
  • Target runs GitLab CE/EE 19.2–19.4 in a vulnerable version range
  • Attacker can register or already holds any authenticated account
Where this breaks in practice:
  • Instances with registration disabled and strict IdP-gated SSO narrow the attacker pool significantly
  • Guest accounts on private-only instances cannot fork repos without explicit group membership
Detection/coverage: Auth audit logs (AuditEvents API), new-account-creation alerts, IdP sign-in anomaly detection.
STEP 02

Craft malicious .gitlab-ci.yml with overflow regex

The attacker authors a .gitlab-ci.yml file containing a specially constructed regular expression that triggers an integer overflow in the regex compiler during pipeline parsing. The regex pattern is designed to make an internal size computation wrap around, leading to an undersized buffer allocation. No special tooling beyond a text editor is needed — the pattern is a static string. The companion CVE-2026-89078 targets the same parser with a double-free variant, giving the attacker two independent memory corruption primitives.
Conditions required:
  • Knowledge of the overflow trigger pattern (not yet public but trivially reverse-engineerable from the patch diff)
Where this breaks in practice:
  • No public PoC exists yet, so attackers must invest effort in diffing the patch — but this is routine for skilled adversaries and typically takes hours to days after patch release
Detection/coverage: Static analysis of .gitlab-ci.yml diffs for anomalous regex complexity; no vendor-supplied detection signature exists yet.
STEP 03

Push config to trigger pipeline parsing

The attacker pushes the malicious .gitlab-ci.yml to any branch (including in a fork they control). GitLab's pipeline creation subsystem automatically parses the file, invokes the regex compiler, and hits the overflow. In many configurations, even a draft merge request triggers pipeline evaluation. The attacker does not need to wait for a maintainer to approve or merge anything — the parse happens at push time.
Conditions required:
  • Repo has CI/CD enabled (default for most GitLab projects)
  • Pipeline runs are not gated behind manual approval for the attacker's branch/fork
Where this breaks in practice:
  • Organizations using only: protected or CI/CD job approval policies may block automatic pipeline creation from forks
  • GitLab Premium/Ultimate security policies can restrict who triggers pipelines
Detection/coverage: Pipeline creation audit events; anomalous pipeline triggers from new/external users; GitLab Workhorse and Sidekiq logs for parsing errors.
STEP 04

Achieve arbitrary code execution on GitLab server

The integer overflow causes a heap buffer to be allocated smaller than expected. Subsequent writes during regex compilation overflow the buffer, corrupting adjacent heap metadata or objects. The attacker leverages this to hijack control flow and execute arbitrary commands as the git user (or whatever user the GitLab application process runs as — often git or gitlab). This user typically has read access to all repositories, CI/CD secrets, and runner registration tokens.
Conditions required:
  • Heap layout must be somewhat predictable — typical for long-running Ruby/Go processes with stable allocation patterns
Where this breaks in practice:
  • ASLR and heap hardening on modern Linux may require multiple attempts, but the attacker can retry by pushing additional commits
  • SELinux/AppArmor in enforcing mode may limit post-exploitation actions (but most GitLab Omnibus installs do not confine the application process)
Detection/coverage: Host-based detection: EDR/AV on the GitLab server for anomalous process spawning from Puma/Sidekiq workers; crash logs in /var/log/gitlab/; kernel audit for execve from git user.
STEP 05

Pivot to supply-chain compromise

With code execution on the GitLab server, the attacker can read every repository (including private ones), exfiltrate CI/CD variables and secrets (RAILS_CONSOLE or direct database access), inject backdoors into source code, poison container registry images, mint new personal access tokens for persistence, and register rogue CI runners. This is a full supply-chain takeover — every artifact built by this GitLab instance is now suspect.
Conditions required:
  • GitLab server process has access to the PostgreSQL database and Git repository storage (always true in standard Omnibus/Docker installs)
Where this breaks in practice:
  • Network segmentation between GitLab and production deployment targets may slow lateral movement
  • Code review practices may catch injected backdoors in high-value repos, but the attacker can target less-reviewed repos or inject into build scripts rather than source
Detection/coverage: Git audit logs for unexpected commits from service accounts; CI/CD secret access audit; container image signing verification (Cosign/Notary); PAT creation alerts.
03 · Intelligence Metadata

The supporting signals.

In-the-wild exploitationNot confirmed. No active exploitation reported as of 2026-09-24. Not listed in CISA KEV. Disclosed <24 hours ago — window for weaponization is open.
Proof-of-conceptNo public PoC. Reported by *joaxcar* via HackerOne #3995696. Patch diff is available and the regex compiler is a constrained target — expect weaponized PoC within days to low weeks.
EPSS scoreNot yet scored — CVE is <24 hours old. Given the RCE impact, network vector, and GitLab's install base, expect EPSS to settle in the top 5% once scored.
KEV statusNot listed as of 2026-09-24. Monitor CISA KEV catalog — GitLab CVEs with RCE impact have historically been added within weeks of PoC release.
CVSS vectorCVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:C/C:H/I:H/A:H — 9.9. Network-accessible, low complexity, low privilege (any authenticated user), no user interaction, scope change (breaks out of regex context to server). The S:C is the key driver: the vuln is in the CI parser but impact is on the underlying OS.
Affected versionsGitLab CE/EE 19.2.0–19.2.6, 19.3.0–19.3.2, 19.4.0. Versions prior to 19.2 are *not* affected — the vulnerable regex compiler was introduced in 19.2.
Fixed versions19.2.7, 19.3.3, 19.4.1 — released 2026-09-23. GitLab.com (SaaS) is already patched. GitLab Dedicated customers patched automatically.
Internet exposureShodan/Censys show >20,000 self-managed GitLab instances on public internet (per CyCognito footprint data from September 2026). ZoomEye indexes ~1.26M IPv4 matches for the GitLab fingerprint globally.
Companion vulnerabilityCVE-2026-89078 — double-free in the same regex parser/compiler, also CVSS 9.9, fixed in the same patch release. Treat as a pair; patching one patches both.
Researcher / disclosureReported by joaxcar via GitLab's HackerOne bug bounty program. Coordinated disclosure with patch release on 2026-09-23. Hype score 11/100 per CVEMon — low public attention so far, but expected to spike.
04 · The Call

Final Verdict
= UNCHANGED to CRITICAL (9.6/10)

Why this verdict

  • Vendor baseline is fair. The CVSS 9.9 accurately models the network-accessible, low-complexity, auth-to-RCE chain with scope change. The PR:L is correctly assessed — any authenticated GitLab user with push access to any repo (including forks) can trigger the vulnerable code path. No adjustment needed for vector accuracy.
  • Authentication friction is real but thin. The PR:L requirement means the attacker needs an account. However, GitLab self-managed instances commonly allow open self-registration, external contributor access, or have broad internal user populations (hundreds to thousands of developers). This is not the same friction as, say, requiring domain admin. Downward adjustment: −0.2 for the auth gate.
  • No PoC or exploitation yet — but the clock is ticking. The patch shipped <24 hours ago and no public exploit exists. This reduces *immediate* urgency slightly but does not change the structural severity. The patch diff is public and the regex compiler is a well-understood attack surface — weaponization timeline is days, not months. Downward adjustment: −0.1 for current threat maturity.
  • Role multiplier: GitLab is a canonical CI/CD and supply-chain component. Per the high-value role catalog, GitLab occupies the *CI/CD + artifact stores* and *supply-chain registries* categories. Essentially 100% of GitLab installations serve this role by definition — it is not a component that *sometimes* runs in a high-value position; it *always* does. RCE on the GitLab server yields: (a) read/write access to all source code repositories, (b) exfiltration of all CI/CD secrets, deployment tokens, and API keys, (c) ability to inject backdoors into build pipelines and source code (supply-chain attack), (d) poisoning of container registry images, (e) minting of persistent access tokens, (f) pivot to runner infrastructure. The blast radius is supply-chain-scale. This floors the verdict at CRITICAL regardless of authentication friction.
  • Internet exposure compounds the risk. Over 20,000 self-managed GitLab instances are directly internet-facing per Shodan/Censys, and many accept user registrations. The attack does not require internal network access — it is fully remote.

Why not higher?

The CVSS ceiling is 10.0, which would require PR:N (unauthenticated). This vulnerability requires authentication — even if the bar is low, it is nonzero. A CVSS 10.0 or a score above 9.6 would overstate the ease of initial access. The current 9.6 correctly reflects the virtually-guaranteed supply-chain impact gated behind a single, often-thin authentication check.

Why not lower?

Any attempt to downgrade below CRITICAL fails the deployment-role floor test. GitLab is definitionally a CI/CD platform — 100% of installs occupy the high-value role. RCE on this component is supply-chain compromise by definition. The authentication requirement is the only friction point, and it is insufficient to breach the CRITICAL floor: GitLab's self-registration defaults, broad internal user bases, and external contributor models mean the attacker population is large. Downgrading to HIGH would require evidence that <1% of GitLab instances are reachable or that the auth gate is genuinely restrictive — neither is true.

05 · Compensating Control

What to do — in priority order.

  1. CRITICAL 9.6CRITICAL 9.2
    Disable open user registration immediately — Navigate to Admin Area → Settings → General → Sign-up restrictions and uncheck *Sign-up enabled*. This eliminates the easiest path for external attackers to obtain the required authenticated session. Enforce SSO/SAML as the sole authentication method if possible. Deploy within the noisgate mitigation SLA of 3 days for CRITICAL findings — ideally within hours given the low effort required.
  2. CRITICAL 9.6HIGH 8.2
    Restrict CI/CD pipeline creation from forks and unprotected branches — Set Settings → CI/CD → General pipelines → CI/CD configuration fetch strategy to limit pipeline triggers to protected branches only. Enable merge request approval policies that require maintainer approval before CI runs on MR pipelines from forks. This breaks step 3 of the attack path for external contributors and low-privilege users. Deploy within 3 days.
  3. CRITICAL 9.6CRITICAL 9.0
    Deploy host-based monitoring on the GitLab server — Install or verify EDR/agent coverage on the GitLab application server. Alert on: (a) unexpected child processes spawned by Puma or Sidekiq workers, (b) execve calls from the git user that are not standard Git operations, (c) crash dumps or segfaults in /var/log/gitlab/. This does not prevent exploitation but enables rapid detection and response. Deploy within 3 days.
  4. CRITICAL 9.6CRITICAL 9.0
    Place GitLab behind a WAF or reverse proxy with authentication hardening — If GitLab is internet-facing, ensure it sits behind a WAF (Cloudflare, AWS WAF, Imperva) or reverse proxy that can rate-limit and log API/Git push requests. Enforce MFA for all users via the IdP. While a WAF cannot inspect .gitlab-ci.yml content for malicious regexes, MFA and rate-limiting raise the cost of credential abuse. Deploy within 3 days.
  5. CRITICAL 9.6IGNORE 0.0
    Apply the vendor patch (19.2.7, 19.3.3, or 19.4.1) — This is the definitive fix. Upgrade your GitLab self-managed instance to the patched version corresponding to your release train. Single-node instances will experience brief downtime for database migrations; multi-node deployments can use zero-downtime upgrade procedures. This is the only control that fully eliminates the vulnerability. Per the noisgate remediation SLA for CRITICAL, complete within 90 days — but given the supply-chain blast radius and imminent PoC likelihood, aim for <7 days.
All controls applied
CRITICAL 9.6IGNORE 0.0
What doesn't work
  • Network-level IP allowlisting for Git pushes — does not help if the attacker is an authorized internal user or has legitimate VPN access; the attack originates from a valid authenticated session, not a network anomaly.
  • GitLab CI/CD include restrictions — restricting include: directives does not mitigate this because the malicious regex is in the top-level .gitlab-ci.yml rules: or only: blocks, not in an included file.
  • Container-level sandboxing of CI runners — irrelevant because the vulnerability is in the *GitLab server's pipeline parser*, not in the runner execution environment. The RCE happens before any runner is invoked.
  • Disabling GitLab Pages or Container Registry — does not address the vulnerable regex compiler in the CI/CD configuration parser; these are unrelated subsystems.
06 · Verification

Crowdsourced verification payload.

Run this script on the GitLab server itself (or any host that can reach the GitLab API) as any user with curl access. Invoke with: bash check_cve_2026_93577.sh https://gitlab.example.com <PRIVATE_TOKEN>. The private token needs only read_api scope (any user). No root/sudo required.

noisgate-verify.sh
BASHREAD-ONLYSAFE
#!/usr/bin/env bash
# check_cve_2026_93577.sh — Verify GitLab is patched against CVE-2026-93577
# Usage: bash check_cve_2026_93577.sh <GITLAB_URL> <API_TOKEN>
# Exit codes: 0 = PATCHED, 1 = VULNERABLE, 2 = UNKNOWN

set -euo pipefail

GITLAB_URL="${1:-}"
TOKEN="${2:-}"

if [[ -z "$GITLAB_URL" || -z "$TOKEN" ]]; then
  echo "Usage: $0 <GITLAB_URL> <API_TOKEN>"
  echo "UNKNOWN — missing arguments"
  exit 2
fi

# Strip trailing slash
GITLAB_URL="${GITLAB_URL%/}"

# Query GitLab version API
RESPONSE=$(curl -sf --max-time 10 \
  -H "PRIVATE-TOKEN: $TOKEN" \
  "${GITLAB_URL}/api/v4/version" 2>/dev/null) || {
  echo "UNKNOWN — could not reach GitLab API at ${GITLAB_URL}"
  exit 2
}

VERSION=$(echo "$RESPONSE" | grep -oP '"version"\s*:\s*"\K[^"]+' 2>/dev/null) || {
  echo "UNKNOWN — could not parse version from API response"
  exit 2
}

echo "Detected GitLab version: $VERSION"

# Parse major.minor.patch
IFS='.' read -r MAJOR MINOR PATCH <<< "$(echo "$VERSION" | grep -oP '^[0-9]+\.[0-9]+\.[0-9]+')"

if [[ -z "$MAJOR" || -z "$MINOR" || -z "$PATCH" ]]; then
  echo "UNKNOWN — could not parse version components from '$VERSION'"
  exit 2
fi

# Vulnerable ranges:
#   19.2.0 - 19.2.6  (fixed in 19.2.7)
#   19.3.0 - 19.3.2  (fixed in 19.3.3)
#   19.4.0           (fixed in 19.4.1)
# Versions < 19.2 are NOT affected.

if (( MAJOR < 19 )); then
  echo "PATCHED — version $VERSION predates the vulnerable code (introduced in 19.2)"
  exit 0
fi

if (( MAJOR > 19 )); then
  echo "PATCHED — version $VERSION is beyond the affected major release"
  exit 0
fi

# MAJOR == 19
if (( MINOR < 2 )); then
  echo "PATCHED — version $VERSION predates the vulnerable code (introduced in 19.2)"
  exit 0
fi

if (( MINOR == 2 )); then
  if (( PATCH >= 7 )); then
    echo "PATCHED — version $VERSION contains the fix (19.2.7+)"
    exit 0
  else
    echo "VULNERABLE — version $VERSION is in the affected range (19.2.0–19.2.6)"
    exit 1
  fi
fi

if (( MINOR == 3 )); then
  if (( PATCH >= 3 )); then
    echo "PATCHED — version $VERSION contains the fix (19.3.3+)"
    exit 0
  else
    echo "VULNERABLE — version $VERSION is in the affected range (19.3.0–19.3.2)"
    exit 1
  fi
fi

if (( MINOR == 4 )); then
  if (( PATCH >= 1 )); then
    echo "PATCHED — version $VERSION contains the fix (19.4.1+)"
    exit 0
  else
    echo "VULNERABLE — version $VERSION is in the affected range (19.4.0)"
    exit 1
  fi
fi

# MINOR > 4 on major 19 — should be safe
echo "PATCHED — version $VERSION is beyond all known affected minor releases"
exit 0
07 · Sources

Peer Review

What defenders are saying.

Submit a review attribution: handle + country only
0 flags selected · stored anonymously
Validation Results

Crowdsourced verification outputs.

Results submitted by users who ran the verification payload against their environment.