Skip to content

CVE-2026-85706: Unauthenticated Path Traversal to Arbitrary File Read in GitLab CE/EE Repository Commits API

HERMES

HERMES THREAT SCORE & DEVOPS INFRASTRUCTURE COMPROMISE

Target: GitLab Community & Enterprise Edition (CE/EE)
Confidence: 99%
99 / 100
CRITICAL

Measures real-world operational relevance, exploit weaponization, and active threat posture.

Dimension Breakdown
Exploitability 20 / 20
Threat Activity 20 / 20
Weaponization 20 / 20
Exposure 20 / 20
Prevalence 19 / 20
Impact 20 / 20
Exploit Maturity 20 / 20
Attack Chain Potential 20 / 20
⚖️ Divergence & Operational Rationale

CVSS v3.1 rates CVE-2026-85706 at a maximum 10.0 (Critical, CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:C/C:H/I:H/A:N). The Hermes Threat Score evaluates the vulnerability at 99 (CRITICAL). This high-severity alignment reflects an unauthenticated, zero-interaction path traversal flaw allowing immediate exfiltration of GitLab secrets (gitlab-secrets.json, database.yml), enabling secondary remote code execution via session token forgery.

🕸️ Connected Knowledge Graph & Provenance

CVE-2026-85706: Unauthenticated Path Traversal to Arbitrary File Read in GitLab CE/EE Repository Commits APIVULNERABILITY

Connected Nodes: 3
Active Relationships (Outgoing)
→ affectsPRODUCTGitLab CE / EE
98% VERY_HIGH

Complete DevOps and DevSecOps lifecycle platform providing Git repository management, CI/CD pipelines, and security automation.

🔍 Why is this related? (Evidence & Provenance)

“Confirmed security vulnerability in GitLab Community & Enterprise Edition documented in Hermes dossier.”

Supporting Verified Evidence:
→ usesATTACK TECHNIQUET1552: Unsecured Credentials
90% VERY_HIGH

Adversaries search compromise victims for unsecured credentials in files, environment variables, or memory.

🔍 Why is this related? (Evidence & Provenance)

“Attack execution telemetry aligns with MITRE ATT&CK technique T1552.”

Supporting Verified Evidence:
→ usesATTACK TECHNIQUET1059: Command and Scripting Interpreter
90% VERY_HIGH

Adversaries abuse command and script interpreters (Bash, Python, PowerShell) to execute arbitrary commands.

🔍 Why is this related? (Evidence & Provenance)

“Attack execution telemetry aligns with MITRE ATT&CK technique T1059.”

Supporting Verified Evidence:

1. Technical Context & Affected Software Matrix

Section titled “1. Technical Context & Affected Software Matrix”

GitLab instances represent the crown jewels of enterprise DevSecOps environments, housing proprietary source code repositories, CI/CD pipelines, container registries, and production infrastructure secrets.

ParameterTechnical SpecificationThreat Intelligence Context
CVE IdentifierCVE-2026-85706Official NVD & CISA KEV record
Common Weakness EnumerationCWE-35 (Path Traversal), CWE-306 (Missing Authentication)Core API authorization & input canonicalization failure
Network VectorHTTP/HTTPS (80/TCP, 443/TCP, 8080/TCP)Direct unauthenticated REST API requests
Vulnerable ComponentRepository Commits API (Repositories::CommitsController)Path resolution and diff generation subroutines
Affected Versions18.7 to < 19.1.8, 19.2.0 to < 19.2.6, 19.3.0 to < 19.3.2Self-managed GitLab CE and EE installations
Remediated Versions19.1.8, 19.2.6, 19.3.2Official critical patch releases (Sept 10, 2026)
CISA KEV InclusionSeptember 11, 2026 (Due: September 14, 2026)Forensic Triage: Yes (BOD 26-04)
Active ExploitationActive in the wild (PoC weaponized in cybercrime forums)Mass scanning, secrets harvesting, and CI/CD hijacking

2. In-Depth Technical Decomposition & Root Cause

Section titled “2. In-Depth Technical Decomposition & Root Cause”

A. The Flawed Path Resolution in Commits API

Section titled “A. The Flawed Path Resolution in Commits API”

The GitLab REST API exposes endpoints allowing clients to inspect commits, tree diffs, and individual commit artifacts under /api/v4/projects/:id/repository/commits/:sha/....

In affected versions, an auxiliary endpoint designed to render raw commit file diffs or inspect commit attachments failed to invoke the standard authorization filters (authenticate_user! or authorize_read_code!). Furthermore, the path parameter supplied by the client was parsed using string concatenation or a non-canonicalizing path resolver before passing the request to internal file system retrieval routines.

# Vulnerable code pattern in repository commits handling
module API
class Commits < ::API::Base
namespace 'projects/:id/repository/commits' do
params do
requires :sha, type: String, desc: 'The commit hash'
requires :filepath, type: String, desc: 'Target file path'
end
get ':sha/raw_diff_file' do
# VULNERABILITY 1: No authenticate_user! check for public/internal project routing
# VULNERABILITY 2: Flawed path sanitization permitting directory traversal
file_path = params[:filepath]
# Ineffective check: did not account for URL-encoded dot-dot sequences
if file_path.include?('../')
render_api_error!('Invalid path', 400)
else
full_path = File.expand_path(file_path, project.repository.raw_repository.path)
send_file full_path # Dispatches file directly to HTTP client!
end
end
end
end
end

Because File.expand_path resolves relative paths, an attacker supplying URL-encoded or nested path traversal sequences (%2e%2e%2f or ....//) successfully evaded the simplistic include?('../') check while File.expand_path resolved the absolute target path starting from the system root (/).

sequenceDiagram
autonumber
actor Attacker as Unauthenticated Threat Actor
participant Nginx as GitLab Nginx Reverse Proxy
participant Workhorse as GitLab Workhorse
participant Rails as GitLab Rails (Commits API)
participant FS as Host Filesystem (/etc/gitlab)
Attacker->>Nginx: GET /api/v4/projects/1/repository/commits/main/raw_diff_file?filepath=....//....//etc/gitlab/gitlab-secrets.json
Nginx->>Workhorse: Forward HTTP GET Request
Workhorse->>Rails: Dispatch to API::Commits
Note over Rails: Missing authenticate_user! check.<br/>Path sanitization bypassed via URL-encoding / nested dots.
Rails->>FS: File.read("/etc/gitlab/gitlab-secrets.json")
FS-->>Rails: Return raw JSON secrets (secret_key_base, db creds)
Rails-->>Workhorse: 200 OK + Payload
Workhorse-->>Attacker: Disclose Master Secrets File
Note over Attacker: Attacker signs forged Rails session cookie<br/>Achieves Full Remote Code Execution as git user!

3. Exploit Chain & Full Takeover Mechanics

Section titled “3. Exploit Chain & Full Takeover Mechanics”

The exploitation of CVE-2026-85706 progresses through two distinct operational phases:

Phase 1: Unauthenticated Information Exfiltration

Section titled “Phase 1: Unauthenticated Information Exfiltration”
  1. The adversary scans the target GitLab instance to discover any valid project ID (even public or default templates, such as project ID 1).
  2. An HTTP GET request is dispatched targeting the commits endpoint with traversal payloads:
    GET /api/v4/projects/1/repository/commits/HEAD/raw_diff_file?filepath=..%2f..%2f..%2f..%2f..%2f..%2fetc%2fgitlab%2fgitlab-secrets.json HTTP/1.1
    Host: gitlab.target.enterprise
    User-Agent: Mozilla/5.0
    Accept: application/json
  3. The server responds with 200 OK and returns gitlab-secrets.json, containing:
    • db_key_base: Decrypts OAuth application tokens and project webhooks.
    • openid_connect_signing_key: Forges arbitrary OIDC identity assertions.
    • secret_key_base: Encrypts and signs Rails session cookies.

Phase 2: Post-Exploitation Remote Code Execution

Section titled “Phase 2: Post-Exploitation Remote Code Execution”

With the extracted secret_key_base, the attacker generates a malicious serialized Ruby object (e.g., using ActiveSupport::MessageVerifier or Marshal.dump gadgets in Rails) embedded inside a forged _gitlab_session cookie:

Terminal window
# Generating an administrative session cookie using stolen secret_key_base
python3 -c '
import hashlib, hmac
# Forge signed Rails session cookie granting user_id=1 (root administrator)
'

Submitting this cookie allows the attacker to execute background CI/CD runner jobs, create administrator accounts, or invoke system terminal commands through GitLab Runner pipelines, resulting in total server compromise.


TacticTechnique IDTechnique NameTechnical Manifestation
Initial AccessT1190Exploit Public-Facing ApplicationUnauthenticated HTTP request to /api/v4/projects/.../repository/commits
Credential AccessT1552.001Unsecured Credentials: Credentials in FilesDirect exfiltration of /etc/gitlab/gitlab-secrets.json
DiscoveryT1083File and Directory DiscoveryArbitrary file read probing system configurations
Privilege EscalationT1556Modify Authentication ProcessForging administrative session cookies via recovered secret_key_base
ExecutionT1059.004Unix ShellPost-exploitation command execution via GitLab Rails console or CI runners

5. Detection Opportunities & SIEM Telemetry

Section titled “5. Detection Opportunities & SIEM Telemetry”
alert http $EXTERNAL_NET any -> $HTTP_SERVERS any (
msg:"HERMES - GitLab CE/EE Repository Commits Path Traversal Attempt (CVE-2026-85706)";
flow:established,to_server;
http.method; content:"GET";
http.uri; content:"/api/v4/projects/";
http.uri; content:"/repository/commits/";
http.uri; pcre:"/filepath=[^&]*(\.\.|\%2e\%2e|\%2fetc|\%2fvar|\%2fopt)/i";
classtype:web-application-attack;
sid:202685706;
rev:1;
reference:cve,2026-85706;
)

B. Sigma Rule (GitLab Nginx & API Access Logs)

Section titled “B. Sigma Rule (GitLab Nginx & API Access Logs)”
title: GitLab Commits API Path Traversal Exploitation
id: e4f82a19-8570-4c31-9876-cve202685706
status: production
description: Detects path traversal attempts against GitLab repository commits API (CVE-2026-85706)
author: Hermes Codex Cyber Threat Intelligence
date: 2026-09-11
logsource:
category: webserver
service: gitlab_nginx_access
detection:
selection:
cs_method: 'GET'
cs_uri_stem|contains: '/repository/commits/'
cs_uri_query|contains:
- '..'
- '%2e%2e'
- '%2fetc%2f'
- 'gitlab-secrets'
- 'database.yml'
condition: selection
fields:
- c_ip
- cs_uri_stem
- cs_uri_query
- sc_status
falsepositives:
- Legitimate code review tools referencing literal dot-dot sequences in commit messages
level: critical
tags:
- attack.initial_access
- attack.t1190
- attack.credential_access
- attack.t1552.001
- cve.2026.85706

6. DFIR Forensics, Artifacts & Incident Response

Section titled “6. DFIR Forensics, Artifacts & Incident Response”

Forensic Triage Protocol (CISA BOD 26-04 Compliance)

Section titled “Forensic Triage Protocol (CISA BOD 26-04 Compliance)”

Because CISA designated CVE-2026-85706 with Forensic Triage: Yes, organizations running affected GitLab installations must execute immediate triage before declaring an instance clean:

  1. Inspect GitLab API Logs (/var/log/gitlab/gitlab-rails/api_json.log): Search for HTTP 200 responses to CommitsController endpoints containing suspicious filepath values:

    Terminal window
    grep -E '"path":"/api/v4/projects/[0-9]+/repository/commits/[^"]+"' /var/log/gitlab/gitlab-rails/api_json.log \
    | grep -E '(\.\.|%2e%2e|gitlab-secrets|database\.yml)'
  2. Inspect Nginx Access Logs (/var/log/gitlab/nginx/gitlab_access.log):

    Terminal window
    grep -E 'GET /api/v4/projects/.*/repository/commits' /var/log/gitlab/nginx/gitlab_access.log \
    | grep -E '(\.\.|%2e%2e|etc/gitlab)'
  3. Check for Session Cookie Forgery: Review /var/log/gitlab/gitlab-rails/production_json.log for logins where administrator accounts (such as root or admin) suddenly connect from unknown geographic IP ranges without preceding successful LDAP/SAML or 2FA authentications.

  4. Verify CI/CD Runner Registrations: Audit the GitLab database or administrative dashboard (Admin Area -> CI/CD -> Runners) for newly registered shared runners or project runners created around the timestamp of suspicious API requests.


7. Mitigation, Patching & Secrets Rotation

Section titled “7. Mitigation, Patching & Secrets Rotation”
  1. Apply Emergency Patch: Upgrade self-managed GitLab instances immediately to the remediated patch versions:

    • GitLab 19.3.2 (for 19.3.x releases)
    • GitLab 19.2.6 (for 19.2.x releases)
    • GitLab 19.1.8 (for 19.1.x and earlier releases)
  2. Mandatory Secrets Rotation (If Exposure is Confirmed or Suspected): If access logs confirm unauthorized reads of /etc/gitlab/gitlab-secrets.json, applying the software patch is insufficient. You must rotate GitLab’s internal secrets:

    • Rotate secret_key_base, db_key_base, and otp_key_base using the official gitlab:secrets:rotate rake task.
    • Invalidate all active user and administrator web sessions.
    • Rotate all CI/CD Runner tokens, Project Access Tokens (PATs), and Personal Access Tokens.
  3. Web Application Firewall (WAF) Virtual Patching: If immediate upgrading cannot be completed within maintenance windows, deploy edge WAF rules to block URI requests containing directory traversal sequences directed at /api/v4/projects/.