Jul 28, 2026·6 min read·4 visits
A trailing slash on request paths allows remote attackers to bypass goshs ACLs and blocklists, exposing sensitive configuration files and password hashes.
CVE-2026-66064 is an access control list (ACL) and blocklist bypass vulnerability in the goshs file server prior to version 2.1.5. Due to an inconsistency between uncleaned raw URI path evaluation and normalized file access, remote unauthenticated attackers can retrieve protected files, including the configuration file containing password hashes, by appending a trailing slash to the requested path.
CVE-2026-66064 identifies an access control list (ACL) and blocklist bypass vulnerability in goshs, a feature-rich, single-binary file server designed for developers and red teamers. The issue is present in all versions prior to 2.1.5. This server utilizes ACLs and blocklists to restrict remote access to specific sensitive files, such as internal directories and the .goshs configuration file itself.
An attacker can bypass these protection mechanisms by appending a trailing slash to the requested URI. This mismatch occurs because the server evaluates security restrictions using an uncleaned, raw request path, while the underlying operating system resolves the file using a normalized path. The resulting discrepancy permits unauthorized remote actors to read restricted assets without authentication.
This behavior is classified under CWE-41 (Improper Resolution of Path Equivalence) and CWE-863 (Incorrect Authorization). The vulnerability is particularly severe because the .goshs file often contains security configurations, including bcrypt credential hashes used for basic authentication.
The vulnerability exists in the sendFile function located within httpserver/handler.go. When processing an HTTP request, goshs extracts the final path component of the target file to determine whether access should be blocked. It does this by splitting the string representation of the request URL path on the forward slash character (/) and referencing the last item in the resulting slice.
If an attacker appends a trailing slash to the URL path (such as /blocked-directory/secret.txt/), the string split operation yields an empty string as the final segment of the path array. As a result, the local variable representing the target filename resolves to "". Because "" does not match the blocklist definitions or the protected configuration name .goshs, the security validations succeed without raising any exceptions.
While the security module evaluates the empty string, the routing layer processes the file path using canonical path sanitization functions such as filepath.Clean. This normalizes the request by removing the trailing slash before opening the file descriptor on the disk. Consequently, the operating system opens the actual file (e.g., secret.txt), bypassing the security controls that were evaluated against the empty string.
The vulnerability is highlighted by the discrepancy between path evaluation and actual file access. Below is the vulnerable logic from httpserver/handler.go before version 2.1.5:
// Vulnerable code in httpserver/handler.go
pathSplit := strings.Split(req.URL.Path, "/")
filename := pathSplit[len(pathSplit)-1]
if filename == ".goshs" {
fs.handleError(w, req, fmt.Errorf("open %s: no such file or directory", file.Name()), 404)
return
}
if fs.isBlocked(filename) {
fs.handleError(w, req, fmt.Errorf("open %s: permission denied", file.Name()), 403)
return
}To resolve this flaw, the patch implemented in commit f3ef599e409151d1380866e47de8b1afb0bb54fa shifts the validation from the raw request URL to the verified file descriptor metadata. The code now extracts the real base name of the file by querying the filesystem directly via file.Stat():
// Patched code in httpserver/handler.go (v2.1.5)
stat, err := file.Stat()
if err != nil {
fs.handleError(w, req, err, http.StatusInternalServerError)
return
}
// Retrieve the real filename from the physical file descriptor
filename := stat.Name()
if filename == ".goshs" {
fs.handleError(w, req, fmt.Errorf("open %s: no such file or directory", file.Name()), 404)
return
}
if fs.isBlocked(filename) {
fs.handleError(w, req, fmt.Errorf("open %s: permission denied", file.Name()), 403)
return
}By utilizing stat.Name(), the application guarantees that the authorization checks are conducted against the actual file being retrieved from disk. Even if an attacker manipulates the URI with trailing slashes, the operating system's file system interface ensures that the resulting FileInfo struct contains the canonical file name, preventing any divergence.
Exploiting this vulnerability does not require authentication and has low technical complexity. An attacker must first identify an active goshs server instance and determine the location of restricted directories or files. The attacker then constructs an HTTP GET request containing the targeted resource path with an appended trailing slash.
For example, if the target configuration file is located at /secret/.goshs, the attacker sends the request GET /secret/.goshs/ HTTP/1.1. The server receives the path, parses the filename as an empty string, and skips the ACL check. Simultaneously, the normalized path resolution opens /secret/.goshs and returns the file payload to the client.
This behavior is illustrated in the sequence diagram below:
This technique allows complete retrieval of blocklisted documents and configuration files. In configurations where basic authentication is active, downloading the .goshs file provides direct access to bcrypt-hashed credentials, which can be extracted and targeted in offline brute-force attacks.
The security impact of CVE-2026-66064 is classified as moderate, receiving an official CVSS v3.1 score of 5.3. The primary impact is a partial loss of confidentiality. Because goshs is designed as a lightweight utility often deployed in temporary or local sharing contexts, the scope is generally limited to the host system's shared web root directory.
However, in environments where goshs is utilized to serve sensitive red team payloads or restrict administrative tools, the disclosure of protected configurations introduces severe secondary risks. Obtaining the .goshs control file exposes the access patterns, blocklists, and password hashes. If weak passwords are used, offline cracking attempts will succeed, allowing attackers to pivot to authorized user roles.
The vulnerability does not allow direct write operations, and thus integrity and availability are unaffected. The attack requires no special privileges, no user interaction, and can be executed over any network interface exposing the goshs port. Because automated tooling can easily scan and detect the trailing-slash anomaly, public-facing instances face high risk of immediate discovery.
The definitive solution for CVE-2026-66064 is upgrading goshs to version 2.1.5 or later. This update modifies the filename resolution sequence to use metadata derived from the open file descriptor instead of raw URI parsing. Administrators should download the patched binary from the official release channels or rebuild it using Go modules.
If immediate patching is not possible, temporary mitigations can be applied at the network or reverse-proxy level. A front-end reverse proxy, such as Nginx or Apache, can be configured to inspect incoming requests and reject URIs that attempt to access files with a trailing slash. For example, a configuration rule can deny access to any request ending in /.goshs/ or containing multiple trailing slashes.
Additionally, security teams should audit existing .goshs files for the presence of password hashes. In the event that an instance was exposed prior to patching, any active credentials must be rotated immediately. Implementing defensive hosting strategies, such as binding the server strictly to localhost or utilizing virtual private networks (VPNs) for remote access, reduces the threat surface.
CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:L/I:N/A:N| Product | Affected Versions | Fixed Version |
|---|---|---|
goshs goshs-labs | < 2.1.5 | 2.1.5 |
| Attribute | Detail |
|---|---|
| CWE ID | CWE-41 |
| Attack Vector | Network |
| CVSS v3.1 Score | 5.3 |
| Exploit Status | PoC / Regression Tests Available |
| Impact | Partial Confidentiality Loss |
| KEV Status | Not Listed |
The software receives input that contains equivalent paths but treats them as different, allowing attackers to bypass checks.
CVE-2025-6120 is a critical memory corruption vulnerability in the Open Asset Import Library (Assimp) affecting versions up to and including 5.4.3. The flaw is located in the Half-Life 1 MDL file format loader, specifically within the read_meshes function in HL1MDLLoader.cpp. It arises due to a lack of verification checks on array, bone, skin, or vertex indices parsed directly from a binary stream, resulting in a heap-based buffer overflow or out-of-bounds memory access.
A local file disclosure vulnerability exists in the Rust-based package skilo. When copying files during skill installation, the application recursively traverses directories but dereferences symbolic links, resulting in unauthorized local file reading.
Pagy, an agile pagination gem for plain Ruby, contains a directory traversal vulnerability in its internationalization (I18n) module prior to version 43.5.6. An unauthenticated remote attacker can exploit this flaw by submitting path traversal sequences to the locale setter, allowing them to probe the server filesystem. The resulting behavior creates a highly reliable file existence and readability side-channel oracle for YAML files.
CVE-2026-54719 is a high-severity Access Control List (ACL) authorization bypass vulnerability in goshs, a lightweight HTTPS-capable server used for file sharing. The issue allows unauthenticated network attackers to completely bypass file-level and directory-level authentication mechanisms and blocklists by requesting protected resources via the bulk ZIP-download route (?bulk). This vulnerability represents a residual flaw following a partial remediation attempt for CVE-2026-40189.
NocoBase, an extensible low-code platform, was found to contain an information exposure vulnerability in its SQL Collection plugin. The validator designed to inspect SQL queries used an incomplete keyword-based blacklist, allowing users with administrative or collection creation privileges to bypass restrictions and execute arbitrary SELECT queries against PostgreSQL system catalogs. This flaw permits unauthenticated or privilege-escalated access to critical system files, active connection listings, and system user password hashes.
An issue in the ruby-oauth2 gem allows unauthenticated attackers to steal OAuth access tokens or perform Server-Side Request Forgery (SSRF) via a protocol-relative URI in HTTP Location redirect headers.