Critical GitLab arbitrary file read flaw leaks server secrets. Learn how to hunt logs, stop admin session forgery, and execute an incident recovery runbook.
CVE-2026-85706 is a CVSS 10.0 unauthenticated arbitrary file read in the repository commits API of self-managed GitLab Community Edition (CE) and Enterprise Edition (EE), versions 18.7 through 19.3. CISA added it to the Known Exploited Vulnerabilities (KEV) catalog on 11 September 2026, a day after GitLab shipped the first fixes. GitLab.com and GitLab Dedicated are already patched. On a vulnerable self-managed server an attacker needs no account to read files the GitLab application can read, and the files that matter most are instance secrets such as gitlab.yml and the keys in gitlab-secrets.json. Stolen keys give an attacker the means for session forgery, database decryption and CI/CD pipeline hijacking, which is why upgrading alone does not close the incident. Arbitrary file-read primitives hit a different vendor's stack in Microsoft Defender's ShieldCrash zero-day exposing arbitrary file read.
Correction (7 October 2026): patch versions and flaw details
Correction (7 October 2026): the version of this article published on 12 September gave a patch table for GitLab 16.11 and 17.0–17.3 and install commands pinned to 17.3.2. None of those are the fix for CVE-2026-85706, and the article did not name the flaw as the exploited one. The fixed versions are listed below. The old table and commands have been removed, and the flaw-mechanics section has been rewritten to what GitLab has published.
- What it is: per GitLab's patch release notice, "an unauthenticated user could have read arbitrary files from the GitLab server due to improper path confinement and missing authentication enforcement in the repository commits API." CVSS 10.0 (
CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:C/C:H/I:H/A:N). - Fixed versions (GitLab CE and EE): 19.3.2, 19.2.6, 19.1.8, 19.0.9 and 18.11.12. Affected range per GitLab: 18.7 through 19.3 before those releases. The notice mentions no workaround.
- Backport dates matter: 19.3.2, 19.2.6 and 19.1.8 shipped on 10 September 2026. GitLab backported the fix to 19.0.9 and 18.11.12 on 23 September 2026, so anyone on 18.11 or 19.0 had no fixed release until then. Treat the exposure window for those lines as running to 23 September when you hunt through logs.
- Exploitation: CISA added it to the KEV catalog on 11 September 2026 as "GitLab Community Edition and Enterprise Edition Path Traversal Vulnerability", with a federal due date of 14 September 2026. The KEV entry marks forensic triage as required ("Forensics Triage Requirements" under BOD 26-04) and lists ransomware campaign use as unknown. See also the NVD record.
- Detections: GitLab says it released three threat detections for customers. Their names refer to an LFI attempt reading
gitlab.yml, LFI via themetadata.pathparameter, and a file-path LFI attempt. - Background: CVE-2023-2825 (May 2023) was a different path-traversal bug that affected only GitLab 16.0.0 and was fixed in 16.0.1 (NVD). GitLab scored it CVSS 10.0 (NVD: 7.5); it is the bug this article originally covered.
Standard binary package upgrades eliminate the traversal vector but do not cycle compromised keys. Secret-storage tooling itself is not immune either, as a HashiCorp Vault flaw allowing root host takeover via blank SSH certificates showed. An instance patched with the latest release remains fully vulnerable to offline session minting and database decryption if secrets were exfiltrated during the exposure window.
Threat Context & Flaw Mechanics
GitLab's description is brief: improper path confinement and missing authentication enforcement in the repository commits API let an unauthenticated user read arbitrary files from the server. GitLab has not published the request format, so this article does not reproduce one.
What an attacker can reach depends on which files the GitLab application user can read. Which of the files below were readable on a given install is inference, not something GitLab or CISA has confirmed. Check your own file permissions and treat anything the application can read as exposed:
gitlab.ymland other application configuration (the target of one of GitLab's detection rules)secrets.ymlanddatabase.ymlunder the Rails config directory/etc/gitlab/gitlab-secrets.json, if the service user can read it (on Omnibus installs it is normally restricted, but containerized deployments can differ)- Raw Git repositories under
/var/opt/gitlab/git-data/repositories
A fast scan-to-exploit window hit another Git hosting platform in the Gitea RCE flaw enabled by default settings. For GitLab, CISA's KEV listing one day after the first fixes is the sourced evidence that exploitation began quickly.
The True Blast Radius: Anatomy of Compromised Server Secrets
When an attacker reads instance secrets, they obtain cryptographic material governing identity authentication, session encryption, and data-at-rest protection. A different Git platform saw SAML itself become the forgery vector in the critical SAML signature-wrapping flaw exposing GitHub Enterprise Server.
| Key / Attribute | Cryptographic Purpose | Exploitation Mechanism | Blast Radius Impact |
|---|---|---|---|
secret_key_base | Encrypts and signs Rails session cookies (_gitlab_session). | Mints encrypted cookies with administrative user IDs via ActiveSupport::MessageEncryptor. | Full administrative web access bypassing passwords, MFA, and SAML assertions. |
db_key_base | AES-256 symmetric key encrypting sensitive PostgreSQL columns via attr_encrypted. | Decrypts database dumps or SQL query results offline. | Direct exposure of plaintext CI/CD variables, private SSH deploy keys, and cloud credentials. |
otp_key_base | Encrypts TOTP two-factor authentication seeds. | Decrypts stored TOTP seeds to generate valid rolling six-digit MFA codes. | Complete neutralization of account-level multi-factor protection. |
ci_jwt_signing_key | RSA private key signing CI_JOB_JWT tokens for pipelines. | Forges valid OIDC identity tokens without triggering a pipeline. | Unauthorized role assumption in AWS IAM, GCP Workload Identity, or HashiCorp Vault. |
openid_connect_signing_key | Signs OpenID Connect assertions for enterprise SSO. | Forges JWT claims for downstream applications federated to GitLab. | Lateral movement into internal wikis, dashboards, and enterprise tooling. |
gitlab_shell.secret_token | Authorizes gitlab-shell hook execution against the internal API. | Invokes internal APIs directly, bypassing branch commit rules. | Silent code tampering without standard audit trail generation. |
Possession of secret_key_base allows administrative session forgery:
# Construct forged administrative session payload
key = ActiveSupport::KeyGenerator.new(secret_key_base).generate_key("encrypted cookie")
encryptor = ActiveSupport::MessageEncryptor.new(key, cipher: 'aes-256-gcm')
forged_cookie = encryptor.encrypt_and_sign({ "warden.user.user.key" => [[1], "$2a$10$forged..."], "session_id" => "recon_active" })
Forensic Log Hunting Guide
To determine whether an instance was probed or exfiltrated, security teams must inspect Nginx access logs (/var/log/gitlab/nginx/gitlab_access.log) and Workhorse logs (/var/log/gitlab/gitlab-workhorse/current).
Identifying Traversal Payloads and Successful Exfiltrations
GitLab's detection rules for this flaw refer to attempts to read gitlab.yml and to the metadata.path parameter, so search for both along with generic traversal strings. These patterns are a starting point; they are not GitLab's own signatures.
Inspect access and application logs for traversal signatures and successful HTTP 200 responses returning data:
# Hunt Nginx logs for directory traversal signatures
grep -E -i '(\.\.%2f|%2e%2e%2f|%2e%2e/|\.\.%5c|%252e%252e|gitlab-secrets|gitlab\.yml|metadata\.path|secrets\.yml|passwd)' \
/var/log/gitlab/nginx/gitlab_access.log*
# Isolate successful data exfiltrations (HTTP 200 with response body > 500 bytes)
awk '($9 == 200 && $10 > 500 && ($7 ~ /\.\./ || $7 ~ /%2e%2e/i || $7 ~ /secrets/)) {print $1, $4, $7, $9, $10}' \
/var/log/gitlab/nginx/gitlab_access.log
Auditing Session Forgery in Rails JSON Logs
Adversaries leveraging forged cookies execute administrative actions without preceding sign-in entries:
# Detect administrative controller access in Rails logs
grep '"controller":"Admin::' /var/log/gitlab/gitlab-rails/production_json.log | \
jq '{time: .time, remote_ip: .remote_ip, user_id: .user_id, path: .path, status: .status}'
GitLab Secrets Rotation Runbook and Incident Recovery
Critical Warning: Modifying
db_key_basein/etc/gitlab/gitlab-secrets.jsonbreaks existing database ciphertext, causingOpenSSL::Cipher::CipherError: bad decryptexceptions on all encrypted records. Teams must follow a staged invalidation and token reset process.
Phase 1: Quarantine and Invalidate Forged Sessions
- Enable the maintenance page and back up configurations:
sudo gitlab-ctl deploy-page up
sudo cp /etc/gitlab/gitlab-secrets.json /etc/gitlab/gitlab-secrets.json.bak
sudo gitlab-rake gitlab:doctor:secrets VERBOSE=1
- Generate a 128-character hex string and replace
secret_key_basein/etc/gitlab/gitlab-secrets.json:
NEW_KEY=$(openssl rand -hex 64)
# Replace "secret_key_base" in gitlab-secrets.json with $NEW_KEY
- Purge session keys in Redis to invalidate active adversary sessions:
sudo gitlab-rake cache:clear
sudo gitlab-redis-cli -s /var/opt/gitlab/redis/redis.socket \
EVAL "for i, name in ipairs(redis.call('KEYS', 'session:gitlab:*')) do redis.call('DEL', name) end" 0
sudo gitlab-ctl reconfigure && sudo gitlab-ctl restart
Phase 2: Mitigate Database Encryption and CI/CD Compromise
- Reset encrypted internal tokens across system models:
sudo gitlab-rake gitlab:doctor:reset_encrypted_tokens MODEL_NAMES="Project,Group,User,ApplicationSetting"
- Rotate external cloud credentials:
- Revoke AWS IAM keys, GCP service account tokens, and database passwords stored in CI/CD variables.
- Re-enter updated values via the GitLab web interface or REST API to write newly encrypted records to PostgreSQL.
- Cycle runner authentication tokens via the API:
curl --request POST --header "PRIVATE-TOKEN: <ADMIN_PAT>" \
"https://gitlab.example.com/api/v4/runners/<RUNNER_ID>/reset_authentication_token"
- Restore production traffic:
sudo gitlab-rake gitlab:check SANITIZE=true
sudo gitlab-ctl deploy-page down
Perimeter Defenses and Remediation Workflow
GitLab's notice offers no workaround, and upgrading is the fix. If an upgrade has to wait a short time, the generic traversal filters below may reduce exposure. They are not tested against CVE-2026-85706, may not match its requests, and do not replace upgrading. Apply perimeter filter rules at the Web Application Firewall (WAF) or reverse proxy layer. Network management-plane appliances face the same isolation imperative, covered in the Arista VeloCloud Orchestrator zero-day demanding active threat hunting.
ModSecurity / OWASP Core Rule Set
SecRule REQUEST_URI_RAW "@rx (?i)(?:\.\.(?:\/|%2f|\\|%5c)|%2e%2e(?:\/|%2f|\\|%5c)|%252e%252e)" \
"id:1000001,phase:1,deny,status:403,log,msg:'GitLab Traversal Blocked'"
SecRule REQUEST_URI "@rx (?i)(?:gitlab-secrets\.json|secrets\.yml|database\.yml|\/etc\/passwd)" \
"id:1000002,phase:1,deny,status:403,log,msg:'GitLab Configuration File Read Blocked'"
Fronting Nginx Proxy Filtering
if ($request_uri ~* "(\.\.%2f|%2e%2e%2f|%2e%2e/|\.\.%5c|gitlab-secrets|secrets\.yml)") {
return 403 "Forbidden: Exploit Signature Detected";
}
Official Binary Package Upgrade
Upgrade to the latest patch release of your supported GitLab line, and no lower than 19.3.2, 19.2.6, 19.1.8, 19.0.9 or 18.11.12. Check GitLab's releases page for the current patch version, as newer releases may have shipped since this correction. Follow GitLab's upgrade path documentation for your install type (Omnibus, source or Helm).
Upgrading patches the file-read flaw, but true incident closure requires completing secrets rotation and verifying application logs for indicators of pre-patch data compromise.
Related reading
- Critical Jenkins Flaw Weaponized for Ransomware: How CVE-2024-23897 Threatens CI/CD Infrastructure
- Interlock Ransomware Weaponizes Critical Cisco FMC Flaw: Why Standard Patching Fails
- Beyond the Patch: Evicting CosmicSting (CVE-2024-34102) Backdoors and StyleSmuggler Skimmers in Magento and Adobe Commerce