GHSA-RHF7-WVW3-VJVM
Vulnerability from github – Published: 2026-04-23 14:28 – Updated: 2026-04-23 14:28Summary
The PUT upload handler (httpserver/updown.go) lacks the CSRF token validation that was added to the POST upload handler during the GHSA-jrq5-hg6x-j6g3 fix. Combined with the unconditional Access-Control-Allow-Origin: * on the OPTIONS preflight handler (httpserver/server.go), any website can write arbitrary files to a goshs instance through the victim's browser — bypassing network isolation (e.g. localhost, internal network).
Details
Root Cause 1 — Missing CSRF on PUT (httpserver/updown.go:19)
When GHSA-jrq5-hg6x-j6g3 was fixed (commit e3c3d37), checkCSRF() was added to the POST upload() function (line 78) but not to the PUT put() function directly above it in the same file. This means PUT requests are accepted without any CSRF token.
// POST — protected
func (fs *FileServer) upload(w http.ResponseWriter, req *http.Request) {
if !fs.checkCSRF(w, req) { return }
// ...
}
// PUT — unprotected
func (fs *FileServer) put(w http.ResponseWriter, req *http.Request) {
// No checkCSRF call
// ...
}
Root Cause 2 — Wildcard CORS (httpserver/server.go:126)
The OPTIONS handler unconditionally returns permissive CORS headers:
w.Header().Set("Access-Control-Allow-Origin", "*")
w.Header().Set("Access-Control-Allow-Methods", "POST, PUT, OPTIONS")
w.Header().Set("Access-Control-Allow-Headers", "Content-Type, Authorization")
This allows any website's JavaScript to pass the browser's CORS preflight check and send PUT requests to the goshs server.
PoC
Please extract the uploaded compressed file before proceeding
- bash poc.sh
Impact
- Arbitrary file write to the goshs webroot from any website the victim visits
- File overwrite — existing files can be silently replaced
{
"affected": [
{
"package": {
"ecosystem": "Go",
"name": "github.com/patrickhener/goshs/v2"
},
"ranges": [
{
"events": [
{
"introduced": "0"
},
{
"fixed": "2.0.2"
}
],
"type": "ECOSYSTEM"
}
]
},
{
"package": {
"ecosystem": "Go",
"name": "github.com/patrickhener/goshs"
},
"ranges": [
{
"events": [
{
"introduced": "0"
},
{
"last_affected": "1.1.4"
}
],
"type": "ECOSYSTEM"
}
]
}
],
"aliases": [],
"database_specific": {
"cwe_ids": [
"CWE-352"
],
"github_reviewed": true,
"github_reviewed_at": "2026-04-23T14:28:14Z",
"nvd_published_at": null,
"severity": "MODERATE"
},
"details": "### Summary\nThe PUT upload handler (`httpserver/updown.go`) lacks the CSRF token validation that was added to the POST upload handler during the GHSA-jrq5-hg6x-j6g3 fix. Combined with the unconditional `Access-Control-Allow-Origin: *` on the OPTIONS preflight handler (`httpserver/server.go`), any website can write arbitrary files to a goshs instance through the victim\u0027s browser \u2014 bypassing network isolation (e.g. localhost, internal network).\n\n### Details\n**Root Cause 1 \u2014 Missing CSRF on PUT** (`httpserver/updown.go:19`)\n\nWhen GHSA-jrq5-hg6x-j6g3 was fixed (commit `e3c3d37`), `checkCSRF()` was added to the POST `upload()` function (line 78) but not to the PUT `put()` function directly above it in the same file. This means PUT requests are accepted without any CSRF token.\n\n```go\n// POST \u2014 protected \nfunc (fs *FileServer) upload(w http.ResponseWriter, req *http.Request) {\n if !fs.checkCSRF(w, req) { return }\n // ...\n}\n\n// PUT \u2014 unprotected \nfunc (fs *FileServer) put(w http.ResponseWriter, req *http.Request) {\n // No checkCSRF call\n // ...\n}\n```\n\n**Root Cause 2 \u2014 Wildcard CORS** (`httpserver/server.go:126`)\n\nThe OPTIONS handler unconditionally returns permissive CORS headers:\n\n```go\nw.Header().Set(\"Access-Control-Allow-Origin\", \"*\")\nw.Header().Set(\"Access-Control-Allow-Methods\", \"POST, PUT, OPTIONS\")\nw.Header().Set(\"Access-Control-Allow-Headers\", \"Content-Type, Authorization\")\n```\n\nThis allows any website\u0027s JavaScript to pass the browser\u0027s CORS preflight check and send PUT requests to the goshs server.\n\n### PoC\n[poc.zip](https://github.com/user-attachments/files/26828829/poc.zip)\n\nPlease extract the uploaded compressed file before proceeding\n\n1. bash poc.sh\n\u003cimg width=\"543\" height=\"376\" alt=\"\u1109\u1173\u110f\u1173\u1105\u1175\u11ab\u1109\u1163\u11ba 2026-04-17 \u110b\u1169\u1112\u116e 11 08 13\" src=\"https://github.com/user-attachments/assets/a695cbc8-133e-4e80-a2f5-9fe9fd36b569\" /\u003e\n\n\n\n\n### Impact\n- Arbitrary file write to the goshs webroot from any website the victim visits\n- File overwrite \u2014 existing files can be silently replaced",
"id": "GHSA-rhf7-wvw3-vjvm",
"modified": "2026-04-23T14:28:14Z",
"published": "2026-04-23T14:28:14Z",
"references": [
{
"type": "WEB",
"url": "https://github.com/patrickhener/goshs/security/advisories/GHSA-rhf7-wvw3-vjvm"
},
{
"type": "PACKAGE",
"url": "https://github.com/patrickhener/goshs"
}
],
"schema_version": "1.4.0",
"severity": [
{
"score": "CVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:U/C:N/I:H/A:N",
"type": "CVSS_V3"
}
],
"summary": "goshs has Cross-Origin Arbitrary File Write via Missing CSRF on PUT and Wildcard CORS"
}
Sightings
| Author | Source | Type | Date |
|---|
Nomenclature
- Seen: The vulnerability was mentioned, discussed, or observed by the user.
- Confirmed: The vulnerability has been validated from an analyst's perspective.
- Published Proof of Concept: A public proof of concept is available for this vulnerability.
- Exploited: The vulnerability was observed as exploited by the user who reported the sighting.
- Patched: The vulnerability was observed as successfully patched by the user who reported the sighting.
- Not exploited: The vulnerability was not observed as exploited by the user who reported the sighting.
- Not confirmed: The user expressed doubt about the validity of the vulnerability.
- Not patched: The vulnerability was not observed as successfully patched by the user who reported the sighting.