CVE-2026-42091: Verified Repro With Script Download
CVE-2026-42091: goshs: PUT upload accepts cross-origin requests without CSRF token
CVE-2026-42091 is verified against github.com/patrickhener/goshs · go. Affected versions: <= v2.0.1 (commit f5671ea). Fixed in v2.0.2. Vulnerability class: CSRF. This medium reproduction includes runnable sandbox proof, artifacts, and a plain-text agent view under REPRO-2026-00158.
What Is CVE-2026-42091?
CVE-2026-42091 (GHSA-rhf7-wvw3-vjvm) is a medium-severity Cross-Site Request Forgery vulnerability (CWE-352) in goshs, a Go-based HTTP file server, in which the PUT upload endpoint accepts cross-origin requests without a CSRF token. Pruva reproduced it (reproduction REPRO-2026-00158).
CVE-2026-42091 Severity & CVSS Score
CVE-2026-42091 is rated medium severity, with a CVSS base score of 6.5 out of 10.
Medium — meaningful risk under specific conditions. Schedule a fix in the normal cycle.
Affected github.com/patrickhener/goshs Versions
github.com/patrickhener/goshs · go versions <= v2.0.1 (commit f5671ea) are affected.
How to Reproduce CVE-2026-42091
pruva-verify REPRO-2026-00158 curl -O https://pruva.dev/api/v1/reproductions/REPRO-2026-00158/artifacts/reproduction_steps.sh && chmod +x reproduction_steps.sh && ./reproduction_steps.sh Proof of Reproduction for CVE-2026-42091
Reproduced by Pruva's autonomous agents — 171 tool calls over 35 min. Full root-cause analysis and the complete transcript are below.
How the agent worked
Root Cause and Exploit Chain for CVE-2026-42091
Summary
goshs (a Go-based HTTP file server CLI) versions ≤ v2.0.1 are vulnerable to Cross-Site Request Forgery (CSRF) on the PUT upload endpoint. While the POST upload handler enforced CSRF token validation via checkCSRF(), the put() handler in httpserver/updown.go omitted this check entirely. Combined with permissive CORS headers (Access-Control-Allow-Origin: *), a malicious cross-origin webpage can silently issue an HTTP PUT and write arbitrary files to any reachable goshs instance.
Impact
- Package:
github.com/patrickhener/goshs - Affected versions:
≤ v2.0.1 - Fixed version:
v2.0.2 - CWE: CWE-352 (Cross-Site Request Forgery)
- Severity: Medium (CVSS 3.1 base 6.5)
- Risk: Any website visited by a user whose browser can reach a goshs upload server (loopback, LAN, VPN, etc.) can upload arbitrary files without user consent.
Root Cause
The put() handler in httpserver/updown.go did not call fs.checkCSRF(w, req) before processing the request. The checkCSRF() function (present in httpserver/handler.go) validates the X-CSRF-Token header, absence of Origin/Referer (non-browser clients), or same-origin requests. Because put() skipped this validation, a browser-initiated cross-origin PUT request—bearing an arbitrary Origin header but no valid token—was accepted and the file was written to disk.
The fix commit 0e715b94e10c3d1aa552276000f15f104dee2f32 adds the missing checkCSRF() call at the top of put().
Reproduction Steps
The reproduction is fully automated by repro/reproduction_steps.sh. It performs the following:
- Clones the
goshsrepository (or reuses an existing clone). - Builds the vulnerable binary at tag
v2.0.1(goshs_v2.0.1). - Builds the fixed binary at tag
v2.0.2(goshs_v2.0.2). - Starts each binary in a separate scratch upload directory with upload enabled.
- Sends a cross-origin-style PUT request (
curl -X PUT -H "Origin: http://evil.com" --data-binary 'pwned' http://localhost:<port>/pwned.txt). - Captures the HTTP response status and checks whether
pwned.txtwas created.
Expected evidence of reproduction:
- v2.0.1 (vulnerable): HTTP
200 OKandpwned.txtis created in the upload directory. - v2.0.2 (fixed): HTTP
403 Forbiddenandpwned.txtis not created.
Evidence
All logs are written to logs/:
logs/vuln.log— goshs v2.0.1 server output.logs/vuln_result.json— captured HTTP status (200), response body, andfile_created: true.logs/fixed.log— goshs v2.0.2 server output.logs/fixed_result.json— captured HTTP status (403), response body (Forbidden), andfile_created: false.
Excerpt from logs/vuln_result.json:
{
"version": "vuln",
"http_status": "200",
"response_body": "",
"file_created": true,
"upload_dir": ".../logs/upload_vuln"
}
Excerpt from logs/fixed_result.json:
{
"version": "fixed",
"http_status": "403",
"response_body": "Forbidden",
"file_created": false,
"upload_dir": ".../logs/upload_fixed"
}
Environment:
- Go version used for build:
go1.24.7(v2.0.1) /go1.25.0(v2.0.2) - OS: Linux (containerized)
- Network: localhost (
127.0.0.1)
Recommendations / Next Steps
- Immediate fix: Upgrade to
goshs v2.0.2or later, which enforcescheckCSRF()on every mutating handler (PUT, POST, DELETE). - Defense in depth: If running goshs on a publicly reachable interface, pair it with
--basic-auth(-b user:pass). When basic auth is configured, the CORS preflight already fails in browsers, providing an additional layer of protection. - Regression testing: Any future change to upload handlers should be accompanied by a test that sends a cross-origin request with a mismatched
Originheader and asserts403 Forbidden.
Additional Notes
- Idempotency: The reproduction script was executed twice consecutively and produced identical results both times.
- Edge cases: The script simulates a browser cross-origin request by explicitly sending an
Originheader. Without this header,curlrequests are treated as non-browser clients and are allowed by design (seecheckCSRFlogic). The vulnerability specifically affects browser-based CSRF attacks. - Limitations: The reproduction does not require a real browser or a second origin; the malicious cross-origin behavior is accurately modeled with
curland theOriginheader.
CVE-2026-42091 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.
cd /tmp && git clone --depth=100 https://github.com/patrickhener/goshs.git 2>&1 | tail -5{"cwd":"/root/.pruva/runs/cve-2026-42091_20260523-061423","duration_ms":5435,"exit_code":0,"stderr":"","stdout":"Cloning into 'goshs'...\nUpdating files: 28% (63/225)\rUpdating files: 29% (66/225)\rUpdating files: 30% (68/225)\rUpdating files: 31% (70/225)\rUpdating files: 32% (72/225)\rUpdating files: 33% (75/225)\rUpdating files: 34% (77/225)\rUpdating files: 35% (79/225)\rUpdating files: 36% (81/225)\rUpdating files: 37% (84/225)\rUpdating files: 38% (86/225)\rUpdating files: 39% (88/225)\rUpdating files: 40% (90/225)\rUpdating files: 41% (93/225)\rUpdating files: 42% (95/225)\rUpdating files: 43% (97/225)\rUpdating files: 44% (99/225)\rUpdating files: 45% (102/225)\rUpdating files: 46% (104/225)\rUpdating files: 47% (106/225)\rUpdating files: 48% (108/225)\rUpdating files: 49% (111/225)\rUpdating files: 50% (113/225)\rUpdating files: 51% (115/225)\rUpdating files: 52% (117/225)\rUpdating files: 53% (120/225)\rUpdating files: 54% (122/225)\rUpdating files: 55% (124/225)\rUpdating files: 56% (126/225)\rUpdating files: 57% (129/225)\rUpdating files: 58% (131/225)\rUpdating files: 59% (133/225)\rUpdating files: 60% (135/225)\rUpdating files: 61% (1… [truncated]Artifacts and Evidence for CVE-2026-42091
Scripts, logs, diffs, and output captured during the reproduction.
No artifacts available
How to Fix CVE-2026-42091
Upgrade github.com/patrickhener/goshs · go to v2.0.2 or later.
FAQ: CVE-2026-42091
How does the CVE-2026-42091 CSRF attack work?
Which goshs versions are affected by CVE-2026-42091, and where is it fixed?
How severe is CVE-2026-42091?
How can I reproduce CVE-2026-42091?
References for CVE-2026-42091
Authoritative sources for CVE-2026-42091 — official vulnerability databases and the upstream advisory. Pruva's reproduction verifies the issue firsthand; these are the primary records to corroborate it.