goshs v2.1.7 was published on 28 September 2026. The notes call it a security release that resolves six advisories, with five GHSA ids written out, centered on httpserver.ProtocolACL. SFTP, FTP, TFTP, and SMB now apply the per folder .goshs rules that HTTP and WebDAV already enforced, and a folder with an auth entry is denied on those protocols because they cannot present the basic auth credential.
The full release notes and downloads are on the GitHub release page.
Shared ACL for SFTP, FTP, TFTP, and SMB ¶
A .goshs file in a folder stores bcrypt hashes for an auth entry and the block list. HTTP and WebDAV already consulted it. SFTP, FTP, TFTP, and SMB served the same webroot and skipped the file.
SFTP is the high severity item, GHSA-2m7f-jq4x-rcj7. Handlers only checked the webroot boundary, so one SFTP credential could read, write, list, rename, or delete files inside folders that .goshs protects or blocks over HTTP. ProtocolACL is now on every SFTP read, write, list, and command path, including the rename destination.
TFTP, FTP, and SMB had the same hole, GHSA-q8gg-q2wc-w52g (Medium). A protected subtree could be fetched anonymously over TFTP, including the .goshs file and its bcrypt hashes. TFTP checks the ACL on read and on write. FTP wraps its filesystem in an ACL layer that also filters listings. SMB checks at handle creation and on the rename destination, and it filters directory queries.
Those protocols cannot send the folder credential, so an auth entry is a deny, not a password prompt. Block list names and the .goshs file itself are always denied. Listings hide .goshs, blocked entries, and auth protected subdirectories. A job that used SFTP or FTP to reach an HTTP protected folder is refused while that auth entry remains. Move the job to HTTP or WebDAV, where the credential can be sent, or drop the entry.
Resolver failures and case folding ¶
A directory named .goshs used to wipe inherited rules. GHSA-mhxc-hfx2-7w79 (Medium) says creating that directory, including with ?mkdir, made the resolver return an empty ACL. Inherited per directory auth and block lists disappeared for the subtree, with no error.
The resolver now fails closed. Unreadable or unparsable .goshs content, including a dangling symlink, denies the folder and everything under it. A .goshs entry that is not a regular file is ignored, so the directory no longer clears parent policy. ?mkdir and uploads refuse any path component named .goshs.
GHSA-3x28-6v7h-gg87 (Medium) is an incomplete fix of CVE-2026-66064. Block list checks and never serve checks compared names with case sensitive equality. On Windows and macOS, SECRET.txt passed a block written as secret.txt. HTTP, WebDAV, SFTP, and the listing filters now compare without regard to case. The same comparison runs on a case sensitive disk, so one block entry covers every casing of that name.
Lockout, transfer bugs, and folder upload ¶
verifyCredentials split the failure counter around bcrypt. GHSA-8f9w-966j-qhq9 (Medium) is two locked sections with the compare in between. A burst of wrong passwords all passed the check, and the counter ended at 1, so the lockout after five failures never fired. Each attempt is now counted in the same locked section as the check, before the password is verified. One IP gets at most five guesses per window, even in parallel. Five simultaneous typos from one address can spend the window before a compare finishes.
FTP panicked on AUTH TLS when TLS was off. The driver returned an empty TLS configuration and the process hit a nil pointer panic, which took down the server rather than one session. With a certificate set as -s with -ss or -sk/-sc, FTP serves FTPS. Without TLS, AUTH TLS is refused and the process stays up.
SFTP on Windows prefixed the webroot twice (#292), so directory walks and transfers failed. The extra prefix is gone.
The web UI can upload a whole folder, including subdirectories (#227). The relative layout is kept. Sanitizing rejects .., so a relative path cannot leave the target directory, and a .goshs component is refused.
What follows in the notes is build and dependency maintenance, not server behavior. The Docker builder moves to Go 1.27 (golang:1.27-alpine), and the runtime image moves from 1.26-alpine to 1.27-alpine with an alpine digest refresh. github/codeql-action steps, including upload-sarif, share one pin, and Dependabot groups bumps into one pull request so split updates stop breaking CodeQL. Notable module steps are golang.org/x/crypto 0.54.0 to 0.57.0, golang.org/x/net 0.57.0 to 0.59.0, and github.com/fclairamb/ftpserverlib 0.32.3 to 0.32.4.
Upgrade notes ¶
Retest SFTP, FTP, TFTP, and SMB on a folder with a .goshs auth entry. Expect a denial. Listings should omit .goshs, blocked names, and auth protected children, and a TFTP read of the .goshs file should fail. A block on secret.txt now also blocks SECRET.txt.
An unreadable or unparsable .goshs, including a dangling symlink, denies the subtree. An entry at that name that is not a regular file is ignored, so parent rules stay. ?mkdir and folder upload reject a .goshs component. FTP clients that send AUTH TLS need -s with -ss or -sk/-sc, or the command is refused instead of crashing the process. On Windows, confirm SFTP paths from #292 are rooted once.
Where to get it ¶
- Release notes and downloads: goshs v2.1.7
- Repository: patrickhener/goshs
- Tag:
v2.1.7