Jul 29, 2026·4 min read·20 visits
An unauthenticated path traversal vulnerability in the goshs multipart upload handler allows arbitrary file writes outside the served directory.
CVE-2026-66063 is an unauthenticated directory traversal and arbitrary file write vulnerability in goshs before version 2.1.5. Due to improper sanitization of file upload names, an unauthenticated attacker can write files outside the served web root. A related trailing slash bypass in the same version allows unauthorized file retrieval.
goshs is a file server built in Go designed to facilitate file sharing and directory serving. It features administrative facilities, such as path-based access control list (ACL) rules stored in .goshs files, to restrict resource access. Unauthenticated users can access the server's public endpoints, including the multipart upload handler.\n\nThis security report covers CVE-2026-66063, a medium-severity directory traversal flaw in the multipart upload parser. In parallel, researchers addressed an access control bypass issue involving path-canonicalization differences when handling trailing slashes. Both flaws permit attackers to subvert the configured directory restrictions.
The root cause of CVE-2026-66063 resides in the upload utility function located inside httpserver/updown.go. When a multipart upload is initiated, the server retrieves the client-supplied filename from the request headers. The application attempts to prevent directory traversal by splitting the path string on forward slash characters and selecting the final slice element.\n\nThis sanitization pattern fails to handle input where the final element of the path is a double-dot (..) sequence. When an attacker provides a filename of '..', the splitting logic extracts '..' as the sanitized filename. The server then executes filepath.Join with targetDir and the traversal sequence, returning the parent folder of the served root.\n\nFinally, the code appends a trailing tilde character to the resolved destination path to create a temporary write location. The application calls os.Create on this out-of-bounds destination. Consequently, the application writes the uploaded content to a file located outside the served directory structure.
Prior to version 2.1.5, the path cleaning logic in httpserver/updown.go used the following sequence:\n\ngo\nfilenameSlice := strings.Split(part.FileName(), \"/\")\nfilenameClean := filenameSlice[len(filenameSlice)-1]\n\nif filenameClean == \".goshs\" {\n logger.Warnf(\"blocked attempt to upload file named .goshs\")\n continue\n}\n\nfinalPath := filepath.Join(targetDir, filenameClean)\ntempPath := finalPath + \"~\"\ndst, err := os.Create(tempPath)\n\n\nThe code contains no validation to reject empty strings, single dots, or double dots. The developers resolved this in commit f3ef599e409151d1380866e47de8b1afb0bb54fa by implementing boundary checks on the extracted filename:\n\ngo\nif filenameClean == \"\" || filenameClean == \".\" || filenameClean == \"..\" {\n logger.Warnf(\"blocked upload with invalid filename %q\", part.FileName())\n continue\n}\n\n\nAdditionally, a defense-in-depth sanitization layer was added using the sanitizePath function. This validates that the resolved absolute path of the uploaded file resides within the boundary of the target directory:\n\ngo\nif _, err := sanitizePath(targetDir, filenameClean); err != nil {\n logger.Warnf(\"blocked upload escaping target directory: %q\", part.FileName())\n continue\n}\n
To exploit CVE-2026-66063, an unauthenticated attacker sends an HTTP POST request targeting the /upload endpoint. The payload is structured as multipart/form-data. The attacker specifies a filename attribute of '..' within the content disposition header.\n\nhttp\nPOST /upload HTTP/1.1\nHost: vulnerable-goshs-server:8000\nContent-Type: multipart/form-data; boundary=---------------------------97384973289\n\n-----------------------------97384973289\nContent-Disposition: form-data; name=\"files\"; filename=\"..\"\nContent-Type: text/plain\n\nPAYLOAD_CONTENT\n-----------------------------97384973289--\n\n\nThe server receives this request, processes the part, and creates a temporary file appended with a tilde in the parent directory of targetDir. For instance, if targetDir is /opt/shared, the server writes the payload to /opt/shared~.\n\nTo exploit the trailing slash access control bypass, an attacker issues a GET request targeting a restricted file name appended with a trailing slash, such as /blocked/secret.txt/. The server checks the URI segment which resolves to an empty string, bypasses the blocklist, and subsequently uses Go's file system handler to open and return the blocked file.
The primary impact of CVE-2026-66063 is unauthenticated arbitrary file write capabilities. However, because the server appends a trailing tilde character to the target path, the attacker cannot overwrite arbitrary existing files directly. They are instead restricted to creating new files with a trailing tilde in the parent directory of the served web root.\n\nThe secondary impact is the exposure of sensitive files protected by directory-level ACLs. Attackers can bypass access controls to download private files, such as internal keys or configuration files, by appending a trailing slash to the target path. The combined effect of these vulnerabilities lowers the overall security posture of the host system.\n\nThe CVSS v3.1 base score is 6.5, reflecting a medium-severity rating. The attack vector is Network, complexity is Low, and no privileges are required to perform the exploits.
The most effective remediation is upgrading the goshs installation to version 2.1.5 or newer. This version resolves the directory traversal vulnerability by rejecting invalid filename patterns and validates path canonicalization.\n\nIf upgrading is not immediately possible, apply the following mitigations:\n\n* Interface Binding: Bind the goshs server to the loopback interface (127.0.0.1) instead of public interfaces to prevent external access.\n* Reverse Proxy Normalization: Implement a reverse proxy, such as Nginx or Caddy, configured to sanitize URI paths. Ensure the proxy cleans trailing slashes and blocks double-dot traversal sequences before passing requests to the backend.
CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:L/I:L/A:N| Product | Affected Versions | Fixed Version |
|---|---|---|
goshs goshs-labs | < 2.1.5 | 2.1.5 |
| Attribute | Detail |
|---|---|
| CWE ID | CWE-22 |
| Attack Vector | Network (AV:N) |
| CVSS v3.1 | 6.5 |
| Exploit Status | PoC level |
| KEV Status | Not listed |
The software uses external input to construct a pathname that should be within a restricted directory, but it does not properly neutralize sequences such as '..' that can resolve to a location outside of the directory.
A path traversal vulnerability (CWE-22) in Contao CMS allows unauthenticated remote attackers to bypass directory boundary restrictions in ImagesController and access files within the project directory.
Contao Open Source CMS versions 4.0.0 through 5.3.49 and 5.4.0-RC1 through 5.7.11 contain a Cross-Site Request Forgery (CSRF) vulnerability in backend parameter handling. The `RequestTokenListener` component validates anti-CSRF tokens solely for HTTP POST requests, while GET-based declarative guards run only when an `act` parameter is present in the query string. Consequently, custom backend actions dispatched via alternative parameters such as `key=` can execute without CSRF token verification when triggered by an authenticated user.
Contao CMS versions 4.1.0 through 5.3.49 and 5.4.0-RC1 through 5.7.11 fail to validate form submission tokens and enforce rate limiting when processing activation email resend requests via HTTP POST, enabling resource exhaustion and account state enumeration.
An information disclosure vulnerability in Contao CMS allows unauthenticated site visitors to view protected page titles, URLs, and text excerpts through search queries when protected page indexing is disabled after previously being enabled.
In Vikunja prior to version 2.6.0, relation creation via the CalDAV endpoint fails to invoke the TaskRelation.CanCreate authorization check. This missing access control allows an authenticated user to establish unauthorized relationships and perform write operations against any task, provided its unique identifier (UID) is known.
A cross-project information disclosure vulnerability in Vikunja allows authenticated users with read access to one project to view private task details from unauthorized projects via subtask expansion parameters.