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-10053-lab — Reproducible lab for CVE-2026-10053 (GitLab npm package-registry path traversal -> arbitrary file write as git). Vulnerable 19.2.1 vs patched 19.2.2, deterministic oracle. | Kitploit
Tools/GitHubGitHub/dinosn/cve-2026-10053-lab
Vulnerability AnalysisExploitationWeb Application ExploitationWeb SecurityLearning & EducationLabs & Practice
GitHubdinosn/cve-2026-10053-lab

CVE-2026-10053-lab

Reproducible lab for CVE-2026-10053 (GitLab npm package-registry path traversal -> arbitrary file write as git). Vulnerable 19.2.1 vs patched 19.2.2, deterministic oracle.

View Repository
41 day 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-10053 — reproducible verification lab

Self-contained lab that proves the GitLab npm package-registry path traversal (CVE-2026-10053) and shows it fixed, using a deterministic on-disk oracle — not HTTP status.

What is and isn't proven. This lab proves authenticated arbitrary file write as the git OS user on vulnerable GitLab, and that the patched release blocks it. It is not a standalone remote-code-execution PoC — see Scope. Don't cite it as RCE.

Download Tool
VulnerabilityCWE-22 path traversal in the npm package registry (TOCTOU: check ran before :cache, not before :store)
CVSS8.5 High — AV:N/AC:H/PR:L/UI:N/S:C/C:H/I:H/A:H
AffectedGitLab CE/EE 18.8 → <19.0.6, 19.1 → <19.1.4, 19.2 → <19.2.2
Fixed19.0.6 / 19.1.4 / 19.2.2 — commit 435cf863 "Re-validate upload path traversal before store"

Requirements

  • Docker + docker compose, python3, git, curl on the host.
  • ~8 GB free RAM (two GitLab instances, ~4 GB each) and ~10 GB disk. First boot: 4–8 min/instance.
  • Run only against these local lab instances. Authorized/defensive testing of software you control.

Run

root@kitploit:~
./run.sh            # up + provision + exploit + verify BOTH; exits 0 iff vuln writes AND patched blocks

Expected result:

root@kitploit:~
================ CVE-2026-10053 verification ================
  INSTANCE                   EXPECT    RESULT    STATUS
  gitlab-vuln  (19.2.1)      written   written   PASS
  gitlab-patched (19.2.2)    blocked   blocked   PASS
  ------------------------------------------------------------
  PROVEN: authenticated arbitrary file write as git on 19.2.1.
  NOT a standalone RCE — see README.md 'Scope' and ./run.sh rce-gate.
============================================================

Other subcommands:

root@kitploit:~
./run.sh up         # just start + wait until healthy
./run.sh rce-gate   # honest exec-bit-gate demo (below)
./run.sh down       # docker compose down -v

How the oracle works (no HTTP-200 cheating)

Both the vulnerable and patched servers answer the malicious publish with HTTP 200 {"status":"processing"} — the file is written later, in the finalize worker. So HTTP status is not an oracle. exploit/poc.py --verify-docker <container> instead polls inside the container for the controlled file at the traversed path and compares its SHA-1:

  • vulnerable → /var/tmp/CVE_2026_10053_PROOF-1.0.0.tgz appears (owner git:git, our bytes) → exit 0.
  • patched → file never appears; the worker logs Gitlab::PathTraversal::PathTraversalAttackError: Invalid path → exit 2.

The exploit itself is nothing but the authenticated PUT …/packages/npm/:pkg request; the traversal lives entirely in the JSON body name (file_name = "#{name}-#{version}.tgz", only blank-checked). The docker exec calls are verification and setup, never part of the attacker's capability.

Scope

  • Proven: an authenticated user (Developer+ can publish packages; this lab uses a root PAT for setup convenience) writes attacker-controlled bytes to any git-writable path. Files land 0644.
  • Not proven here: RCE. The stored basename is forced to end -<semver>.tgz (NUL is rejected by the kernel, newline doesn't truncate), so no exact-name target (secrets.yml, authorized_keys, a .rb, gitaly binaries) can be overwritten. The only filename-agnostic executor, custom_hooks/<hook>.d/, runs any filename but only if executable — and this write is 0644. Overwriting a pre-existing 0755 file does not help: the store replaces the inode, resetting it to 0644. So RCE needs a separate executable-bit / execution primitive this PoC does not supply.

./run.sh rce-gate demonstrates exactly this honestly: it plants a pre-receive.d hook via the traversal, pushes, and shows the 0644 hook does not execute. ./rce_gate_demo.sh --illustrate-gate additionally sets +x via docker exec chmod (an out-of-band docker-root action, not attacker capability) purely to show gitaly would run it — underscoring that the missing lever is the exec bit.

Root cause & fix

See ANALYSIS.md for the full analysis. In short: app/uploaders/gitlab_uploader.rb validated the storage path only before :cache; at before :store the model-derived file_name (attacker-controlled, unvalidated) was written verbatim. The fix adds before :store, :protect_from_path_traversal!.

Files

root@kitploit:~
docker-compose.yml   vuln (19.2.1) + patched (19.2.2) GitLab CE
run.sh               one-command harness with deterministic file oracle + PASS/FAIL
provision.rb         lab setup: mint root PAT + create project (NOT part of the exploit)
exploit/poc.py       the PoC sender + --verify-docker oracle
rce_gate_demo.sh     honest exec-bit-gate demonstration