Deployment guide

CVE-2026-85706 GitLab: emergency patch or Gitea migration

Deploy on a VPS Cloud →

Tutorial

CVE-2026-85706 GitLab: emergency patch or Gitea migration

Security & Monitoring9 min read8 steps

CVE-2026-85706 is an unauthenticated path traversal vulnerability rated CVSS 10.0 affecting all self-hosted GitLab CE/EE instances between versions 18.7 and 19.3.1. An attacker with basic HTTP access can read secrets.yml, runner SSH keys, and CI/CD tokens without any authentication. CISA added this vulnerability to its KEV catalog on September 10, 2026, confirming active exploitation in the wild. Patch to 19.3.2 immediately or migrate to Gitea to permanently reduce your attack surface.

Contents· CVE-2026-85706 — CVSS 10.0, unauthenticated path traversal1/10
  1. 01CVE-2026-85706 — CVSS 10.0, unauthenticated path traversal
  2. 02What an attacker can read via path traversal
  3. 03Who is affected — and who is not
  4. 04Patching GitLab CE/EE to 19.3.2
  5. 05Secret rotation after potential exposure
  6. 06Post-patch checklist
  7. 07Alternative: migrate to Gitea on VPS to reduce attack surface
  8. 08Deploy Gitea on a ServOrbit VPS in 4 steps
  9. 09Self-hosted GitLab CE vs Gitea — security and operational criteria
  10. 10Security lesson: managing your Git forge on a root-access VPS

CVE-2026-85706 — CVSS 10.0, unauthenticated path traversal

CVE-2026-85706 is a path traversal vulnerability in the repository management component of GitLab CE and EE. The CVSS vector is AV:N/AC:L/PR:N/UI:N/S:C/C:H/I:H/A:H — no authentication required, no user interaction, full impact on confidentiality, integrity, and availability. In practice, a malformed HTTP request against the repository archives API endpoint allows an attacker to traverse the GitLab instance filesystem and reach sensitive configuration files outside the repository root. The watchTowr researcher published a working proof-of-concept shortly after disclosure, and Rapid7 teams confirmed active exploitation attempts in their ETR telemetry. CISA listed CVE-2026-85706 in its Known Exploited Vulnerabilities catalog on September 10, 2026, imposing a 72-hour remediation deadline on US federal agencies — a strong signal of the real severity of the threat.

What an attacker can read via path traversal

  • secrets.yml — contains the active_record_encryption key and internal token seeds; once compromised, it allows decrypting the entire GitLab database
  • Private SSH keys of GitLab CI/CD runners — allow command execution on build agents and pivoting to deployment environments
  • CI/CD tokens and environment variables stored in configuration — cloud keys, API keys, deployment secrets injected into pipelines
  • Database configuration files (database.yml) — host, port, database name, PostgreSQL connection credentials
  • Redis session data if the configuration points to an accessible Unix socket
  • Content of any file readable by the git system user in the instance tree

Who is affected — and who is not

GitLab CE and EE versions from 18.7.0 to 19.3.1 inclusive are vulnerable, whether installed via omnibus packages, deployed as a Docker container, or deployed via Helm on Kubernetes. GitLab.com (the SaaS service hosted by GitLab Inc.) was patched upstream by the GitLab team before public disclosure — GitLab.com users are not affected and have no action to take. Only self-hosted instances are exposed. GitLab versions prior to 18.7 are not affected by this specific vector, but they are end-of-life and exposed to other unpatched vulnerabilities; upgrading to 19.3.2 is recommended in all cases. Instances isolated behind a firewall or VPN are not protected: the vector is standard HTTP on ports 80 and 443, internal network access or prior VPN compromise is sufficient to trigger exploitation.

Patching GitLab CE/EE to 19.3.2

  1. Back up the instance before any operation

    Run a full backup: sudo gitlab-backup create STRATEGY=copy. Verify the archive is present in /var/opt/gitlab/backups/ and copy it to external storage. Do not skip this step even in an emergency — the patch modifies the database schema and a pre-patch backup is irreplaceable.

  2. Stop GitLab and update the omnibus package

    On Debian/Ubuntu: sudo gitlab-ctl stop && sudo apt-get update && sudo apt-get install --only-upgrade gitlab-ee=19.3.2-ee.0 && sudo gitlab-ctl reconfigure && sudo gitlab-ctl start. On RHEL/CentOS: replace apt-get with yum update gitlab-ee-19.3.2. Verify the version after restart: sudo gitlab-rake gitlab:env:info | grep GitLab.

  3. Update a Docker instance

    Pull the new image: docker pull gitlab/gitlab-ee:19.3.2-ee.0. Stop the existing container: docker stop gitlab. Restart with the new image keeping mounted volumes: docker run --detach --name gitlab --restart always -v /srv/gitlab/config:/etc/gitlab -v /srv/gitlab/logs:/var/log/gitlab -v /srv/gitlab/data:/var/opt/gitlab gitlab/gitlab-ee:19.3.2-ee.0. Wait for the automatic reconfiguration to complete before testing access.

  4. Verify post-update integrity

    Run the built-in health checks: sudo gitlab-rake gitlab:check SANITIZE=true and sudo gitlab-rake gitlab:doctor:secrets. If either check reports an anomaly on secrets.yml, immediately perform the secret rotation described in the next section.

Secret rotation after potential exposure

If your instance was exposed on the internet between the release of version 18.7 and the application of the patch — or if you have any doubt — secret rotation is mandatory. Patching stops future exploitation but does not revoke already exfiltrated credentials. Start by regenerating the database encryption key: sudo gitlab-rake gitlab:encrypted_secrets:rotate_key. Then revoke and regenerate all CI/CD runner tokens from the administration interface (Admin > CI/CD > Runners), then reconfigure each runner agent with the new token via gitlab-runner register. Replace SSH keys deployed on runners. Audit the CI/CD variables of each project (Settings > CI/CD > Variables) and change all deployment secrets — cloud API keys, Docker registry credentials, third-party service access tokens. Notify teams using CI/CD pipelines on the instance that their deployment secrets should be considered compromised until proven otherwise.

Post-patch checklist

  • Confirm installed version: sudo gitlab-rake gitlab:env:info | grep 'GitLab version' must show 19.3.2
  • Search for indicators of compromise in Nginx logs: request patterns containing ../ repeated or encoded (%2e%2e%2f) in /var/log/gitlab/nginx/gitlab_access.log
  • Check for unexpected SSH connections in /var/log/auth.log since the first 18.7 version was installed
  • Scan the instance with the detection tool published by watchTowr to confirm the vector is closed
  • Enable mandatory two-factor authentication for all administrator accounts if not already done
  • Verify HTTP security headers (HSTS, CSP) are correctly emitted after the update via curl -I https://your-instance.example.com
  • Schedule a security audit of repository permissions — successful exploitation may have created ghost administrator accounts

Alternative: migrate to Gitea on VPS to reduce attack surface

GitLab CE is a complete Git forge but its monolithic architecture and large Ruby on Rails codebase mechanically expand the attack surface. CVE-2026-85706 is not an isolated incident: GitLab has had four critical CVEs (CVSS ≥ 9.0) over the past eighteen months. Gitea is a Go-based, single-binary alternative with a memory footprint roughly ten times smaller and a significantly shorter history of critical CVEs. For teams whose needs are limited to Git hosting, pull requests, webhooks, and lightweight CI integration, Gitea covers the essentials with a much smaller exposed surface. Migration involves exporting repositories, issues, wikis, and members from GitLab via the API, then importing them into Gitea — a process documented in the dedicated GitLab-to-Gitea migration article. On a VPS with root access, you retain full control over the update schedule, backups, and secret rotation, without depending on a third-party vendor to decide when your instance is patched.

Deploy Gitea on a ServOrbit VPS in 4 steps

  1. Provision a VPS and select the Gitea template

    From the ServOrbit client portal, create a new VPS (minimum 2 vCPU, 2 GB RAM for a team of up to 20 developers) and select the Gitea application template. The template preconfigures Gitea with systemd, an Nginx reverse proxy with automatic TLS via Let's Encrypt, and daily backups to the object storage of your choice.

  2. Configure the domain and TLS

    Point your subdomain (e.g. git.your-domain.com) to the VPS IP via an A record in your DNS zone. The post-installation script detects the domain, requests a Let's Encrypt certificate via DNS-01 if you use Cloudflare, or HTTP-01 otherwise, and configures Nginx as HTTPS-only with HSTS.

  3. Import repositories from GitLab

    Gitea includes a migration wizard (Administration > Import repositories) that accepts your GitLab instance URL and a personal access token. It imports repositories, branches, tags, open issues, and wikis. For organizations with many projects, the gitea-cli migrate command-line tool allows bulk import automation.

  4. Configure CI/CD runners and revoke the old instance

    Deploy Forgejo Actions or connect a Gitea Act runner on the same VPS or on a dedicated agent. Update deployment secrets in each migrated repository. Once pipelines are validated on Gitea, revoke the tokens on the old GitLab instance, disable runners, and schedule the uninstallation of GitLab to free up resources.

For GitLab instances behind a VPN or internal network: do not defer the patch by assuming network isolation is sufficient. The CVE-2026-85706 vector is HTTP on ports 80 and 443 — any user with VPN access, any compromised workstation on the internal network, or any service that calls the GitLab API can trigger exploitation without any GitLab credentials. The CISA KEV confirms that malicious actors are actively targeting this vector, including in enterprise environments. The patch remains the only reliable remediation.

Self-hosted GitLab CE vs Gitea — security and operational criteria

Scroll the table

CriterionGitLab CE 19.xGitea 1.22.x
Language / architectureRuby on Rails + Go (hybrid)Go — single binary
Minimum memory footprint~2–4 GB RAM~150–300 MB RAM
Critical CVEs (CVSS ≥ 9) over 18 months4 including CVE-2026-857060
Built-in 2FA authenticationYesYes
Control over patch scheduleYou (self-hosted)You (self-hosted)
Already-patched SaaS availableGitLab.com (free tier)Gitea Cloud (beta)
Native CI/CD integrationGitLab CI (full-featured)Gitea Actions / Forgejo Actions
Migration from GitLabN/ABuilt-in wizard + API

Security lesson: managing your Git forge on a root-access VPS

CVE-2026-85706 illustrates a fundamental principle of self-hosted software security: the exposure window between the disclosure of a critical CVE and the application of the patch is the most dangerous period in an instance's life. On GitLab.com, this window was zero — the GitLab team patched silently before disclosure. On a self-hosted instance, the window depends entirely on your ability to be alerted, test, and deploy quickly. A VPS with root access gives you full control over this cycle: you can automate security updates with unattended-upgrades for system packages, set up CVE alerts via GitLab's security program RSS feeds, and test the patch on a staging environment before production. This control is also a responsibility: no cloud provider will patch your GitLab or Gitea instance for you. Best practice is to treat CVSS ≥ 9 CVEs as production incidents — remediation plan within 24 hours, secret rotation within 48 hours. On a ServOrbit VPS, automatic backups and direct root access allow you to meet this schedule without depending on a managed service whose timelines and procedures you do not control.

Deploy Gitea or GitLab on a root-access VPS

On a VPS with root access, patch GitLab or deploy Gitea via the ServOrbit template — secret rotation and updates remain under your control. No intermediary between you and your Git forge.

Need help?

Browse our help center and FAQ, or reach our team — callback, WhatsApp or email. Support in French, English and Arabic.

Message us on WhatsAppopens in a new tab