CVE-2026-23535: Verified Reproduction
CVE-2026-23535: wlc: Path traversal via unsanitized API slugs in download command
CVE-2026-23535 is verified against wlc · pip. Affected versions: wlc < 1.17.2. Fixed in wlc 1.17.2. Vulnerability class: Path Traversal. This high reproduction includes runnable sandbox proof, artifacts, and a plain-text agent view under REPRO-2026-00070.
What Is CVE-2026-23535?
CVE-2026-23535 is a high-severity path traversal in the Weblate command-line client (wlc) before 1.17.2. A malicious Weblate server can make the client write files to an arbitrary location during a multi-translation download. Pruva reproduced it (reproduction REPRO-2026-00070).
CVE-2026-23535 Severity & CVSS Score
CVE-2026-23535 is rated high severity, with a CVSS base score of 8.0 out of 10.
High — serious impact or readily exploitable. Prioritize remediation.
Affected wlc Versions
wlc · pip versions wlc < 1.17.2 are affected.
How to Reproduce CVE-2026-23535
pruva-verify REPRO-2026-00070 curl -O https://www.pruva.dev/api/v1/reproductions/REPRO-2026-00070/artifacts/repro/reproduction_steps.sh && chmod +x reproduction_steps.sh && ./reproduction_steps.sh Proof of Reproduction for CVE-2026-23535
Reproduced by Pruva's autonomous agents — 216 tool calls over 21 min. Full root-cause analysis and the complete transcript are below.
How the agent worked
Root Cause and Exploit Chain for CVE-2026-23535
- Affected versions: All releases prior to 1.17.2
- Risk: High – a crafted server (or MITM) can force the client to overwrite arbitrary files (e.g.,
/etc/cron.d/...) duringwlc download --multi, leading to privilege escalation or system compromise on any machine that runs the command.
Root Cause
wlc.main.Download.download_component() builds the destination path as Path(output_dir) / f"{component.project.slug}-{component.slug}.zip". The values component.project.slug and component.slug come directly from API responses without sanitization. When a malicious server returns an absolute path such as /tmp/weblate-owned for the project slug, pathlib.Path treats it as an absolute path and drops the intended base directory, writing the downloaded archive to that attacker-chosen location. The issue is fixed upstream in https://github.com/WeblateOrg/wlc/pull/1128 (released in 1.17.2) which normalizes and validates slugs before using them in filesystem paths.
Reproduction Steps
- Run
repro/reproduction_steps.sh. - The script provisions a Python venv, installs
wlc==1.17.1, starts a mock Weblate HTTP server that serves a component listing whose project slug is/tmp/weblate-owned, and then executeswlc download --output repro-outputagainst it. - Successful reproduction is indicated by creation of
/tmp/weblate-owned-absolute-component.zip(outside the requested output directory) and logs stored inlogs/.
Evidence
- Log artifacts:
logs/mock_server.log,logs/wlc_download.log,logs/evidence.txt. - Key excerpt (
logs/evidence.txt):-rw-r--r-- 1 root root 58 ... /tmp/weblate-owned-absolute-component.zip- Intended output directory
repro-output/remains empty, proving the write escaped the sandbox.
- Environment: Python 3.11 virtualenv with
wlc==1.17.1on Ubuntu (container) as provisioned by the script.
Recommendations / Next Steps
- Upgrade
wlcclients to 1.17.2 or later, which sanitizes slugs before constructing output paths. - For additional defense-in-depth, consider enforcing a jail by resolving all download outputs relative to the configured directory and rejecting absolute inputs from the server.
- Add regression tests that simulate malicious slugs to ensure future changes preserve the validation.
Additional Notes
repro/reproduction_steps.shis idempotent: running it twice in succession succeeds, recreating the evidence and overwriting the malicious file each time.- The mock server only implements the minimal endpoints needed for this PoC; real-world instances may require authentication, but the vulnerability manifests regardless once the client processes attacker-controlled component metadata.
CVE-2026-23535 Reproduction Transcript
The agent's step-by-step process — every tool call, every handoff, the moment the exploit fired.
Full session Replay every step — scrub the timeline or play it back.
Unknown error
cd /root/.pruva/runs/ghsa-mmwx-79f6-67jg_20260117-214540 && python3 -m venv venv && /root/.pruva/runs/ghsa-mmwx-79f6-67jg_20260117-214540/venv/bin/pip install --upgrade pip setuptools wheelRequirement already satisfied: pip in ./venv/lib/python3.11/site-packages (24.0) Collecting pip Using cached pip-25.3-py3-none-any.whl.metadata (4.7 kB) Requirement already satisfied: setuptools in ./venv/lib/python3.11/site-packages (79.0.1) Collecting setuptools Using cached setuptools-80.9.0-py3-none-any.whl.metadata (6.6 kB) Collecting wheel Using cached wheel-0.45.1-py3-none-any.whl.metadata (2.3 kB)
Artifacts and Evidence for CVE-2026-23535
Scripts, logs, diffs, and output captured during the reproduction.
How to Fix CVE-2026-23535
Upgrade wlc · pip to wlc 1.17.2 or later.
FAQ: CVE-2026-23535
What has to happen to exploit CVE-2026-23535?
Which versions of wlc are affected by CVE-2026-23535, and where is it fixed?
How can I reproduce CVE-2026-23535?
References for CVE-2026-23535
Authoritative sources for CVE-2026-23535 — official vulnerability databases and the upstream advisory. Pruva's reproduction verifies the issue firsthand; these are the primary records to corroborate it.