XPECTRA RESEARCH · AUTONOMOUS RESEARCH LAB
# Case 004: CVE-2026-85706
## GitLab CE/EE unauthenticated path traversal, reconstructed for defenders
A controlled AI agent investigation of the critical GitLab repository commits
API vulnerability. The case reproduces the unauthenticated file read on a stock
vulnerable release, verifies the vendor fix on the patched arm, follows the
downstream risk inside a fictional CI environment, and ships detections with
their validation evidence.
**This is not a discovery.** GitLab disclosed the vulnerability on 2026-09-10,
credited `s3ntago` for the report, released fixes in 19.3.2, 19.2.6 and 19.1.8,
and states that the CVE was added to CISA's Known Exploited Vulnerabilities
catalog. See the [GitLab critical patch release](https://docs.gitlab.com/releases/patches/patch-release-gitlab-19-3-2-released/).
What this case contributes is a reproducible stock-versus-patched closure
record, an evidence-backed explanation of the vulnerable path, a bounded impact
chain showing why arbitrary file read can become broader compromise, and four
defensive rules tested against the laboratory evidence.
Read the paper ·
Watch the full run ·
Open the defender kit
> [!IMPORTANT]
> The laboratory used stock GitLab CE container images for 19.3.1 and 19.3.2. The vulnerable and patched arms were kept on an isolated internal network. The extended credential, runner and defacement sequence uses only fictional assets created for this case and demonstrates downstream risk after the file-read primitive; it is not presented as the direct effect of the CVE alone.
> [!CAUTION]
> This case contains offensive code and a chained impact demonstration for controlled analysis. Publication does not authorize testing against any system. Use it only inside an isolated laboratory that you own or are explicitly authorized to test.
## Case at a glance
| Item | Case record |
|---|---|
| Product | GitLab Community Edition and Enterprise Edition, self-managed |
| Public classification | CVSS 10.0, CWE-22 path traversal |
| Threat status | Listed in CISA KEV; GitLab published detections for self-managed instances |
| Vulnerable arm | GitLab CE 19.3.1 |
| Fixed arm | GitLab CE 19.3.2; vendor fixes also released in 19.2.6 and 19.1.8 |
| Laboratory result | Unauthenticated arbitrary file read reproduced when at least one public project exists; patched arm returns a uniform 401 with no file disclosure |
| Extended impact | A leaked fictional automation credential is chained to project takeover and code execution on a deliberately bounded laboratory runner |
| Defender outputs | Two Nuclei templates and two Sigma rules with fire and replay records |
## Reproduce (isolated laboratory only)
```
lab/build-lab.sh stock # pulls gitlab/gitlab-ce:19.3.1-ce.0 onto the internal bridge
lab/verify.sh stock # 14/14 health gate (network isolation, sink md5, public project)
python3 exploit/gitlab_cve202685706.py --target http://172.30.99.20 \
--project 1 --read /tmp/cve2026-85706-proof.txt # see exploit/README.md
lab/verify.sh patched # against the 19.3.2 arm: uniform 401, zero leak
```
## Research boundary
Everything under `evidence/` was produced in a purpose-built, zero-runtime-egress
laboratory: `gitlab/gitlab-ce:19.3.1-ce.0` and `19.3.2-ce.0` stock registry
images on a Docker `--internal` bridge (`172.30.99.0/24`, verified single-homed,
no default route), an attacker host on the bridge gateway, and fictional
credentials only (the toy `root` account of the throwaway container and its
fictional `lab-app` project). Accounts, domains, tokens, passwords and
proof-of-execution markers in this pack are laboratory toys, declared in
[`licenses/ATTRIBUTION.md`](licenses/ATTRIBUTION.md); no real system was
contacted. Vendor image layers are never redistributed here - the scripts pull
them at run time under a documented one-time build egress.
## Package map
| Path | What it is |
|---|---|
| `paper/CVE-2026-85706-paper.pdf` | The 8-page IEEE-format paper (plus `main.tex`, `tex/IEEEtran.cls`, `build-log-summary.md`, `figures-manifest.md`) |
| `exploit/` | The Python PoC (`gitlab_cve202685706.py`), README, offline test suite + golden wire fixtures, the probe set with the raw third-party captures it was built against, and the impact-chain driver (`chain-rce.py`, `revshell-listener.py`) |
| `rules/` + `detection/` | Defender kit: 4 CVE rules (2 nuclei, 2 sigma) with rule-fire transcripts, the offline sigma replay harness, TESTS.md |
| `evidence/` | The curated record: image A/B extract of the vendor patch, the fix-verification closure matrix run, paper-audit rounds with renders, raw-research primary sources, the sink file, image digests, verify gates, the parent re-fire, and the frozen impact-chain artifacts (`evidence/chain/`) |
| `video-verification/` | `claims.json` (paper claim gate, 19 claims) and `claims-video.json` (frame-claim spec) plus the frame-audit pin lists - the machine-readable specification the counted gates re-derive, re-runnable from the case pack |
| `videos/` | `main.mp4` + `reel.mp4` only; provenance in `videos/README.md` |
| `designs/facts.json` | The canonical-values ledger the claim gate derives from |
| `attempt-log.md` | The honest attempt log the paper cites by entry number |
| `licenses/` | Code license, CC BY 4.0, CC0 music license text, third-party attribution |
| `tools/validate-stage-case004.sh` | This pack's own re-verification instrument |
| `MANIFEST.sha256` | SHA-256 integrity record for every file in this pack |
## Watch the run
Two cuts record the full operation end to end: `videos/main.mp4` (238.5 s,
1920x1080, single take, live typed desktop with a per-command interactive
shell) and `videos/reel.mp4` (85.3 s, native portrait). The main film carries
the complete impact chain as recorded live: pre-auth file read through the
CVE, the leaked automation credential, project takeover, root code execution
on the CI runner, an interactive root reverse shell, and an anonymous public
defacement; the reel carries the read-impact arc end to end (leak -> leaked
credential -> anonymous defacement). The machine-readable
frame-claim spec ships in `video-verification/claims-video.json`; the film
production record (drivers, counted quality gates, frame audit with signed
stills, raw takes) stays with the case research pack, as declared in
`videos/README.md`.
## How this research was produced
The research and production pipeline was executed by AI agents operating
through the Hermes harness with locally hosted models. The exact served model
and engine are retained in the case production record and are not exposed by
the public package, so this README does not infer or invent them.
**Miguel Zabala, Founder of Xpectra.ai and Human Research Supervisor**, defined
the objective, contributed offensive-security judgment, controlled scope,
reviewed the results and authorized publication. The investigation, laboratory
execution, evidence collection, detection engineering, documentation and media
production were performed by the agents.
The local pipeline runs on hardware provided by Dell Technologies through its
Ambassador Program and powered by NVIDIA accelerated computing. See the
[project overview](../README.md) for the research infrastructure.
## Integrity
`sha256sum -c MANIFEST.sha256` verifies every file; `./tools/validate-stage-case004.sh`
re-runs the pack's whole mechanical battery (syntax, formats, rule compilers,
media decode, PDF integrity, videos/ purity, secret and vocabulary sweeps,
claim-gate re-derivability note, manifest coverage).
## Re-verify the published numbers
`video-verification/claims.json` is the derivation spec for every number the
paper states (19 claims: versions, line counts, byte counts, sha prefixes,
matrix tallies, and the five impact-chain artifacts). Re-run it from the case
research pack with the case claim
gate (`claim_gate.py`) after re-deriving each `path`+`pattern` pair against
the artifacts shipped here: the expected verdict is **19/19 PASS**, closed
2026-09-13 (attempt-log gate ledger). The shipped tree contains exactly the
artifacts those derivations read.