GHSA-wvhv-qcqf-f3cx fixed the per-folder .goshs ACL bypass on the state-changing routes (PUT/POST upload/?mkdir/?delete) and added recursive ACL resolution, and its description states the read/list path correctly enforces .goshs. That premise does not hold for the ?bulk zip-download route. bulkDownload (httpserver/updown.go) takes one or more ?file= parameters, runs each through sanitizePath(fs.Webroot, file), and streams the contents back as a ZIP without ever calling findEffectiveACL/applyCustomAuth. It is dispatched from earlyBreakParameters (?bulk) before …
Start goshs v2.1.3 with -b 'admin:' -sftp. No -fkf. SFTP accepts connections without password. CVE-2026-40884 blocks the empty-username variant (-b ':pass'). The empty-password variant bypasses that fix.
sendFile derives the served filename from the raw request path while opening the file from the cleaned path, so appending a trailing slash empties the derived name and defeats both the never-serve rule for the ACL file and the block list.
The multipart upload filename fix splits on the path separator but never rejects dot-dot, allowing a write outside the served tree.
The WebDAV mode-flag guard added to fix GHSA-3whc-qvhv-xqjp still does not enforce –no-delete on the WebDAV MOVE verb. MOVE deletes the source file (rename removes it from its original path), and with Overwrite: T it additionally performs an explicit RemoveAll on the destination. Under -w –no-delete, DELETE is correctly blocked (403) but MOVE still destroys existing files, defeating the documented "Disable the delete option" boundary. This is a residual of …
When goshs is launched with WebDAV enabled (-w), the mode-restriction flags –read-only, –upload-only, and –no-delete are enforced only on the primary HTTP port. The WebDAV port is wired straight to golang.org/x/net/webdav.Handler with no equivalent guard, so an authenticated WebDAV client can PUT, DELETE, MKCOL, MOVE, and COPY despite the operator's stated intent.
ShareHandler reads the share token's DownloadLimit under RLock, releases the lock, serves the file, then re-acquires the lock to increment the counter. Concurrent requests all read the same Downloaded/DownloadLimit snapshot, all pass the check, and all are served — exceeding the operator's intended cap.
The –tunnel / -t flag opens an outbound SSH connection to localhost.run:22 with HostKeyCallback: ssh.InsecureIgnoreHostKey(). The Go documentation for that function states verbatim: "It should not be used for production code." With the callback disabled the client accepts any host key the server presents, so an attacker who can intercept the operator's TCP connection to localhost.run:22 (any router on the path, malicious local network, ARP/DNS spoof on the operator's LAN, …