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
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.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 withyum update gitlab-ee-19.3.2. Verify the version after restart:sudo gitlab-rake gitlab:env:info | grep GitLab.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.Verify post-update integrity
Run the built-in health checks:
sudo gitlab-rake gitlab:check SANITIZE=trueandsudo 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
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.
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.
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 migratecommand-line tool allows bulk import automation.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
| Criterion | GitLab CE 19.x | Gitea 1.22.x |
|---|---|---|
| Language / architecture | Ruby on Rails + Go (hybrid) | Go — single binary |
| Minimum memory footprint | ~2–4 GB RAM | ~150–300 MB RAM |
| Critical CVEs (CVSS ≥ 9) over 18 months | 4 including CVE-2026-85706 | 0 |
| Built-in 2FA authentication | Yes | Yes |
| Control over patch schedule | You (self-hosted) | You (self-hosted) |
| Already-patched SaaS available | GitLab.com (free tier) | Gitea Cloud (beta) |
| Native CI/CD integration | GitLab CI (full-featured) | Gitea Actions / Forgejo Actions |
| Migration from GitLab | N/A | Built-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.