Jul 28, 2026·6 min read·4 visits
Unauthenticated network attackers can completely bypass directory-level basic authentication and file blocklists in goshs by requesting protected files via the ?bulk ZIP-download route. This flaw is resolved in version 2.1.1.
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.
The goshs server is a lightweight, Go-based HTTPS-capable system designed for collaborative file sharing and serving local directory structures. To control permissions within the directories it serves, the application implements a file-based Access Control List (ACL) mechanism. Administrators can place a hidden .goshs configuration file inside any directory to enforce Basic Authentication or specify file blocklists, ensuring that sensitive files are protected from unauthorized readers.\n\nThe attack surface exposed by this application includes a bulk download route designed to package multiple files into a single ZIP archive for ease of retrieval. However, in version 2.1.0 and prior, this bulk ZIP download endpoint fails to check the directory-level ACL configuration files before reading resources. Consequently, unauthenticated attackers can request and download any file underneath the server webroot, even if those resources are explicitly blocked or password-protected. This bug class is categorized as Incorrect Authorization (CWE-863) and Missing Authorization (CWE-862).
The technical root cause of CVE-2026-54719 resides in the request-handling order and the execution flow of the bulk download route. Inside the HTTP router component, incoming parameters are analyzed during an early processing phase via the earlyBreakParameters routine. When the server detects the ?bulk query parameter, control is immediately diverted to the bulkDownload function, which is located inside the httpserver/updown.go source file.\n\nNormally, standard file and directory retrieval paths flow through the doDir, doFile, or sendFile routes. These standard routes act as gates that invoke the findEffectiveACL and applyCustomAuth routines. These security routines parse directory-level configuration files and validate client credentials or verify blocklists.\n\nBecause the bulkDownload route is processed outside the standard file-handling pipeline, it completely bypassed these security routines. The function processed targeted files by merely validating them against path-traversal patterns using sanitizePath to verify that the target path resolved inside the server webroot. Once confirmed, the file contents were retrieved directly from the disk and streamed to the attacker inside a generated ZIP file without checking for local credentials.
An analysis of the patch submitted in commit 7cf911a26ace737e1a55b7dc073e307a25f7fd1d shows how the authorization logic was integrated into the updown.go file. Prior to the fix, the validation loop inside bulkDownload cleaned paths using sanitizePath but did not execute authorization logic:\n\ngo\n// Vulnerable loop in v2.1.0 and earlier\nfor _, file := range files {\n absPath, err := sanitizePath(fs.Webroot, file)\n if err != nil {\n continue\n }\n filesCleaned = append(filesCleaned, absPath)\n}\n\n\nThe patch inserts authorization validation inline directly inside the path sanitization loop of bulkDownload. The fix retrieves the directory's ACL configuration and enforces authentication and blocklist checks prior to adding the file paths to the packaging list:\n\ngo\n// Patched loop in v2.1.1\nfor _, file := range files {\n absPath, err := sanitizePath(fs.Webroot, file)\n if err != nil {\n continue\n }\n // Retrieve the target directory's effective ACL policy\n acl, aclErr := fs.findEffectiveACL(filepath.Dir(absPath))\n if aclErr == nil {\n // Validate authentication state against the ACL\n if ok := fs.applyCustomAuth(w, req, acl); !ok {\n return\n }\n // Verify if the requested file base name is in the blocklist\n if slices.Contains(acl.Block, filepath.Base(absPath)) {\n fs.handleError(w, req, fmt.Errorf(\"requested file is blocked\"), http.StatusNotFound)\n return\n }\n }\n filesCleaned = append(filesCleaned, absPath)\n}\n
A detailed analysis of the remediation in commit 7cf911a26ace737e1a55b7dc073e307a25f7fd1d reveals three structural design weaknesses that could allow residual bypasses.\n\nFirst, the ACL validation block is guarded by if aclErr == nil. This implementation creates a fail-open condition. If the findEffectiveACL function encounters a file system lock, a file system error, or a parsing error due to a malformed .goshs JSON file, it returns a non-nil error. Consequently, the server silently skips both the applyCustomAuth credential check and the blocklist verification, letting the download complete successfully.\n\nSecond, the blocklist validation uses slices.Contains to check file base names against acl.Block. This lookup is strictly case-sensitive. When goshs is hosted on case-insensitive filesystems (such as Windows NTFS or macOS APFS), an attacker can query for Secret.txt instead of secret.txt. If the blocklist only specifies secret.txt, the blocklist verification returns false, bypassing the block, while the underlying OS still opens and reads the target file.\n\nThird, physical symbolic links are not thoroughly resolved during sanitization. If the server does not enforce physical canonical path resolution, an attacker could exploit a symlink in an unrestricted directory pointing to a file in a restricted directory. This path manipulation can cause the ACL engine to read the security settings of the unrestricted parent folder instead of the target folder's settings.
An unauthenticated network attacker can exploit the vulnerability by constructing an HTTP GET request to the bulk download endpoint. This request uses the ?bulk query parameter alongside the file query parameter pointing to the target resource. No administrative credentials or prior authentication states are required to invoke this route.\n\nmermaid\ngraph LR\n client[\"Attacker Client\"] -->|\"GET /?bulk&file=/protected/secret.txt\"| router[\"Router (earlyBreakParameters)\"]\n router -->|\"Bypasses Standard Auth Route\"| bulk[\"bulkDownload Function\"]\n bulk -->|\"Reads directly from disk\"| zip[\"ZIP Archiver\"]\n zip -->|\"Streams raw data without basic auth check\"| client\n\n\nTo reproduce the exploit against an affected server, consider a target file located in a basic-auth protected folder named /protected/secret.txt. Sending a direct request for the file returns a 401 Unauthorized response. However, submitting the request as an argument to the bulk endpoint (GET /?bulk&file=/protected/secret.txt) causes the server to reply with a 200 OK status. The response body contains a ZIP archive containing the unredacted target file.\n\nThis same method successfully bypasses the directory-level blocklist. If the operator placed a file named blocked.txt into the ACL blocklist, a standard request results in a 404 response. Constructing a bulk request targeting /protected/blocked.txt bypasses the block check completely, packing the restricted file into the retrieved ZIP archive.
Security teams should audit their goshs server logs for patterns matching the bulk-download attack vector. Specifically, look for requests targeting the root path / or sub-folders containing the query string ?bulk or &bulk combined with parameters pointing to path structures inside protected directories.\n\nBecause bulk downloads do not generate standard individual file access logs inside the standard handler, finding multiple files being zipped within single log entries is a primary indicator of compromise. Intrusion detection and prevention systems can be tuned to detect and drop these query string arguments.\n\nTo remediate the vulnerability, operators should update the server binary to version 2.1.1 or later. In environments where upgrading is not immediately feasible, operators should run goshs with a server-wide basic authentication profile using the -b CLI argument. This configuration implements authentication via a global middleware handler that processes requests before they reach the bulk download logic. Alternatively, reverse proxies such as Nginx or HAProxy can be configured to drop requests containing the bulk query parameter.
CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:N/A:N| Product | Affected Versions | Fixed Version |
|---|---|---|
goshs goshs-labs | < 2.1.1 | v2.1.1 |
| Attribute | Detail |
|---|---|
| CWE ID | CWE-862, CWE-863 |
| Attack Vector | Network |
| CVSS Base Score | 7.5 (High) |
| EPSS Score | 0.00% (Insufficient telemetry data) |
| Impact | Unauthenticated arbitrary file read under the server's webroot |
| Exploit Status | poc |
| KEV Status | Not Listed |
The application fails to perform an authorization check or performs an incorrect authorization check when a user attempts to access a resource through an alternative path.
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-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.
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.
Quiet-Terminal-Interactive's QTINeon version 1.0.0 is vulnerable to uncontrolled resource consumption and relay-to-host network amplification. The reconnect request handler lacks table size constraints, rate limiting, and request deduplication, allowing unauthenticated attackers to crash the relay server and overwhelm target hosts.
An authentication bypass vulnerability exists in the pytonapi library when custom paths are registered in the TonapiWebhookDispatcher. The application fails to retrieve or store secure tokens for custom paths, leading to a fail-open authorization check that allows unauthenticated remote attackers to send spoofed webhook events directly to internal handlers.