Aug 25, 2026·7 min read·1 visit
Unauthenticated users can download files from deleted, expired, or password-protected shares by replaying a cached context hint within a 300-second window, completely bypassing authorization checks.
Cloudreve is vulnerable to an incorrect authorization bypass. When listing files, Cloudreve returns a context_hint (represented as a UUID) to the client. If this context hint is replayed on the /file/url or /file/thumb routes, Cloudreve's database file system caches the shareNavigatorState containing the loaded share root. Within the cache lifetime (TTL of 300 seconds), if the user re-requests the same file with the cached hint, the system restores the state and completely bypasses the root security checks (which validate share expiration, remaining download limits, owner status, and passwords). This allows unauthorized users to continue generating signed file URLs and downloading files even after a share has been deleted, has expired, or has reached its download limit.
The Cloudreve system incorporates a high-performance database file system (DBFS) layer to manage files, directories, and sharing operations. To optimize user experience and reduce database lookup overhead during sequential file queries, the backend uses an optimization identifier called a "context hint" (represented as a UUID) transmitted via the X-Cr-Context-Hint HTTP header. This hint assists the backend in matching user sessions to cacheable directory states, accelerating file traversal.
A critical broken access control vulnerability exists in this caching flow. When listing a share, Cloudreve generates a context hint and transmits it to the client. If an attacker replays this context hint during requests to retrieve download links (/file/url) or generating thumbnails (/file/thumb), Cloudreve's database file system (DBFS) attempts to restore the cached file navigator state.
This state restoration completely skips subsequent security policy evaluation. The root cause lies in the system trusting the presence of the cached navigator object as proof of continuous, validated authorization. Because the cache retains this authorization state for a default Time-To-Live (TTL) of 300 seconds, an attacker can obtain valid file download URLs and generate file thumbnails even after a share has been manually deleted, expired, or depleted its download quota.
The vulnerability is classified under CWE-863 (Incorrect Authorization). When processing a request for file retrieval, the system relies on shareNavigator to resolve path pointers to database files. Under normal operating conditions (without a cached state), the routing engine invokes the Root() method of the navigator, which validates the share integrity by querying inventory.IsValidShare(share). This process checks if the share is active, validates expiration dates, ensures download limits are not reached, and verifies the share password.
However, when a context hint is supplied in the request headers, the ContextHint middleware extracts the UUID and retrieves the corresponding shareNavigatorState from the key-value store. This state includes a populated shareRoot object. When resolving the target path through To(), the code evaluates whether n.shareRoot is nil. Because the state restoration process populates n.shareRoot, this evaluation returns false, causing the execution flow to bypass the Root() method entirely.
Furthermore, the system fails to handle the post-execution hooks defensively. When a file download is initiated, the system executes the hook fs.HookTypeBeforeDownload to update download counters in the database. If the share has been deleted or is otherwise invalid, this database operation fails. However, instead of halting execution, the file manager merely logs the failure as a warning and proceeds to generate the signed download URL, thereby rendering the security control entirely ineffective.
The vulnerable state-restoration logic in share_navigator.go can be analyzed in the transition method To(). The original codebase implements the path resolution as follows:
// From share_navigator.go
func (n *shareNavigator) To(ctx context.Context, path *fs.URI) (*File, error) {
// If shareRoot is already restored from cache, the Root() call is bypassed.
if n.shareRoot == nil {
root, err := n.Root(ctx, path)
if err != nil {
return nil, err
}
n.shareRoot = root
}
// Execution continues to resolve the child node without re-validating the share.
return n.resolveChild(ctx, n.shareRoot, path)
}In this implementation, the cached state maps directly to n.shareRoot during restoration. The check if n.shareRoot == nil acts as an optimization gate. If n.shareRoot is loaded from the cache, the conditional block is skipped, preventing the invocation of n.Root(). The n.Root() method is the only location where inventory.IsValidShare(share) and password validation checks are executed.
// From share_navigator.go (Root validation logic)
func (n *shareNavigator) Root(ctx context.Context, path *fs.URI) (*Folder, error) {
// Crucial validation routines are situated here
if err := inventory.IsValidShare(n.share); err != nil {
return nil, err
}
if n.share.Password != "" && !n.isPasswordVerified() {
return nil, ErrPasswordRequired
}
...
}Because the execution bypasses the conditional check when n.shareRoot is restored, the safety constraints enforced inside Root() are not evaluated. This design flaw permits unauthorized requests to leverage the stored state to acquire signed URLs via /file/url or request thumbnail resources through /file/thumb.
Exploitation requires that the attacker has previously accessed a valid share or possesses a valid context hint generated during an active sharing session. The attack sequence exploits the 300-second cache TTL window to maintain access after the resource is revoked.
First, the attacker requests the share's file listing, capturing the context hint (UUID) from the response header or body. Second, the attacker triggers a request to /api/v4/file/url, causing the server to register a cache miss, execute the normal authorization checks, and store the authenticated state in the database file system (DBFS) key-value cache under the key navigator_state_<hint>_share.
Once the cache is populated ("warmed"), the owner of the share deletes or revokes the share. This action deletes the corresponding records in the sharing tables. However, the cached navigator_state remains active in memory.
Within the 300-second TTL window, the attacker re-sends the request to /api/v4/file/url using the cached context hint in the X-Cr-Context-Hint header. The server matches the cached state, restores n.shareRoot directly, skips Root(), and issues a signed download URL.
Here is the flow of the exploitation process:
This vulnerability breaks the fundamental access controls governing file-sharing in Cloudreve. Users rely on share revocation, expiration times, and download limits to protect sensitive data from prolonged exposure. Bypassing these mechanisms means that files remain accessible to unauthorized recipients even after explicit deletion.
In enterprise or private cloud environments, this flaw could result in the unauthorized exfiltration of proprietary datasets, credentials, or personal documents. The attack complexity is low, and no specialized privileges or user interactions are required to trigger the exploit.
Because the vulnerability allows the direct generation of signed download URLs, the attacker achieves read access to the underlying storage backend. Although the attacker cannot modify files or upload new contents (preserving integrity and availability), the compromise of confidentiality is complete within the cache lifetime window.
To resolve this logical flaw, developers must ensure that state restoration does not bypass authorization checks. The caching mechanism should serve solely as a performance layer, not an authorization shortcut.
The primary correction requires forcing validation on state restoration. When RestoreState is invoked, the database record for the share must be queried and re-evaluated using inventory.IsValidShare(share). If the database check reveals that the share has been deleted, has expired, or has reached its download limit, the cached state must be discarded, and the request must be denied.
Additionally, modification of download hook behavior is required. In pkg/filemanager/manager/entity.go, the application must treat failures in the execution of navigator hooks as fatal errors. If ExecuteNavigatorHooks fails during the pre-download phase (for example, due to a missing share database entry), the engine must abort the process and return an authorization error to prevent URL generation.
As an immediate, temporary mitigation when patching is not possible, system administrators can deploy a Web Application Firewall (WAF) or modify reverse proxy configurations (such as Nginx) to strip the X-Cr-Context-Hint header from requests sent to /api/v4/file/url and /api/v4/file/thumb. This forces Cloudreve to execute authorization validation on every request, neutralizing the cache bypass.
CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:L/I:N/A:N| Product | Affected Versions | Fixed Version |
|---|---|---|
Cloudreve Cloudreve | <= 4.0.0-20260606032813-26b6b1044b02 | None |
| Attribute | Detail |
|---|---|
| Vulnerability Type | Incorrect Authorization (CWE-863) |
| Attack Vector | Network |
| CVSS v3.1 Score | 5.3 (Medium) |
| Exploit Status | Proof of Concept (PoC) |
| Cache Window TTL | 300 Seconds |
| CISA KEV Status | Not Listed |
The software performs authorization checks, but the implementation is flawed, allowing actors to access resources or perform actions that should be restricted based on security policies.
A security vulnerability in the github.com/gorilla/websocket Go library allows remote attackers to predict client-to-server frame masking keys. This occurs because the library generates 32-bit mask keys using Go's non-cryptographically secure pseudo-random number generator (math/rand). Predicting these keys enables adversaries to bypass proxy-based security protections, facilitating HTTP request smuggling and cache poisoning attacks.
MHSanaei 3X-UI is a web control panel for managing Xray-core servers. In versions prior to 3.3.1, an authenticated administrator can abuse database import functions or raw template config fields to overwrite or append to arbitrary files on the host filesystem. This is achieved by altering the Xray log configuration variables to target system files, leveraging logging components to inject payloads.
A path traversal vulnerability exists in Cloudreve's remote download workflow, where improper sanitization of file paths returned by configured remote downloaders (such as aria2) allows authenticated users to write files outside the designated target folder.
An integer overflow vulnerability exists in the HTTP/1.x chunked encoding parser of the vibeio-http library. The flaw is caused by unchecked integer addition when calculating the total buffer size required for processing parsed chunk lengths. By sending a maliciously crafted HTTP request containing an extremely large chunk size, an unauthenticated remote attacker can trigger a runtime panic, leading to complete denial of service.
netfoil, an allowlist-based DNS proxy, failed to sanitize ALPN fields parsed from untrusted DNS-over-HTTPS (DoH) HTTPS Resource Records. This allowed attackers to inject ANSI escape sequences into log files or trigger Denial of Service (DoS) via uncontrolled memory allocations.
An issue was discovered in the tokio-postgres library for Rust prior to version 0.7.18. A trust assumption mismatch between the PostgreSQL protocol messages sent by a server and how they are parsed and indexed by the client-side library allows a rogue or compromised database server to trigger a Denial of Service (DoS) crash via an unhandled out-of-bounds slice indexing panic.