Sep 23, 2026·7 min read·4 visits
A TOCTOU race condition in Cloudreve allows authenticated users to bypass their storage quota limits via concurrent upload sessions, causing host disk exhaustion.
Cloudreve before version 4.18.0 contains a Time-of-Check to Time-of-Use (TOCTOU) race condition in its storage-quota verification logic. Authenticated attackers with basic write access can trigger multiple parallel upload sessions to bypass their storage limits, leading to host disk space exhaustion and Denial of Service.
Cloudreve is an open-source, self-hosted file management and sharing system that provides multi-user storage orchestration. In configurations utilizing local storage policies, Cloudreve monitors and enforces storage quotas on a per-user basis to prevent storage resource exhaustion. This restriction is managed inside the database and verified during the file upload initialization sequence.
Prior to version 4.18.0, the validation of a user's storage quota and the actual update of that quota were split into disjoint, non-atomic database operations. This architecture exposes a classic Time-of-Check to Time-of-Use (TOCTOU) race condition in the PrepareUpload handler located in pkg/filemanager/fs/dbfs/upload.go. An authenticated attacker with basic write privileges (Files.Write) can exploit this timing window to bypass assigned storage quotas.
By executing parallel upload requests, an attacker can trick the server into authorizing concurrent sessions that collectively exceed the account's allocation limits. The resulting unauthorized sessions allow the physical allocation of massive files to disk, ultimately resulting in server-wide disk space exhaustion and a total Denial of Service (DoS) for all tenants on the affected system.
The vulnerability stems from an unsynchronized read-then-write pattern on the user capacity record during upload initialization. When a user prepares an upload, Cloudreve first executes f.validateUserCapacity to read the current state of the user's storage limit from the database or an in-memory cache. This value is compared against the maximum allowed threshold, and if the requested file size fits within the remaining space, the application proceeds to initialize the transaction.
Because no database row lock is acquired during this validation phase, multiple concurrent threads can evaluate the same capacity snapshot simultaneously. If an attacker initiates multiple concurrent upload sessions before the database records are updated, each individual thread observes a stale representation of the user's remaining storage capacity. Each thread determines that the user has sufficient quota, and thus all threads approve the request.
Once the validation checks pass, Cloudreve commits the file placeholders and subsequently executes the storage allocation write via CommitWithStorageDiff. Because this charge occurs unconditionally and outside of the transaction that validates the quota, the system registers the total size of all parallel uploads. This design allows the final committed storage value to significantly exceed the user's hard limit, breaking the storage security policy.
The fundamental code flaw existed in pkg/filemanager/fs/dbfs/upload.go within the PrepareUpload function. The original code queried the user capacity object, checked it, and then opened a transaction to insert the file metadata without securing an exclusive database-level lock on the user's row. The allocation update occurred downstream, completely decoupled from the check.
To remediate this issue, the patch introduces an atomic, database-backed reservation system inside inventory/user.go and inventory/tx.go. Instead of relying on application-level checks of stale values, the database update itself enforces the quota constraints in a single SQL operation. Below is the patched atomic storage reservation function implemented in the update:
// ReserveStorage atomically adds size bytes to user uid's storage while
// enforcing an optional quota.
func (c *userClient) ReserveStorage(ctx context.Context, uid int, size, maxTotal int64) error {
if size == 0 {
return nil
}
if size < 0 {
return c.ReleaseStorage(ctx, uid, -size)
}
q := c.client.User.Update().Where(user.ID(uid))
if maxTotal > 0 {
// storage + size <= maxTotal <=> storage <= maxTotal - size
q = q.Where(user.StorageLTE(maxTotal - size))
}
n, err := q.AddStorage(size).Save(ctx)
if err != nil {
return err
}
if n == 0 {
return ErrInsufficientCapacity
}
return nil
}By leveraging the user.StorageLTE(maxTotal - size) predicate, the application forces the underlying relational database management system to perform a conditional write. Under standard ACID database isolation levels, the row representing the user is locked during the UPDATE statement. Concurrent transaction threads seeking to modify the same user record will be blocked and serialized, preventing race conditions from manipulating the storage counter.
Exploitation of this TOCTOU race condition requires only an authenticated account with write access (Files.Write) to the Cloudreve instance. An attacker begins by identifying their active storage quota and their current usage statistics. For instance, if an attacker has an account with a 10 GB limit and has consumed 9.9 GB, they have 100 MB of legitimate remaining capacity.
To trigger the vulnerability, the attacker constructs a script designed to fire a burst of parallel HTTP POST requests targeting the /api/v3/file/upload preparation endpoint. Each request declares a large file payload, such as 5 GB. Under normal execution, any single request of this size would be rejected because 5 GB exceeds the 100 MB remaining space.
When the concurrent requests hit the application, multiple threads handle the incoming payloads in parallel. Because the database row is not locked during the capacity check, every thread reads the stale 9.9 GB usage figure. Each thread verifies that the current usage (9.9 GB) is less than the limit (10 GB) and authorizes the upload session. The server generates upload session tokens for all requests, allowing the attacker to upload multiple 5 GB chunks and exhaust the storage system.
The main security impact of CVE-2026-77633 is a storage-based Denial of Service (DoS) and the bypass of system resource boundaries. By default, Cloudreve instances are deployed using local storage policies, where uploaded files are written directly to the host's primary disk partition. Successful exploitation allows a standard user to allocate infinite gigabytes of arbitrary file data.
Once the parallel upload sessions are authorized, the attacker can write chunked payloads directly to the underlying server. Because these sessions were successfully initialized, the application accepts the incoming data chunks, rapidly consuming physical disk space on the host machine. If the underlying partition is exhausted, critical system services and database operations on the host will fail, resulting in an unrecoverable system crash.
This vulnerability is tracked with a CVSS 3.1 base score of 7.1 (High). The impact is limited to availability and integrity, as it does not allow confidentiality leaks or direct remote code execution. However, because it can be exploited using default permissions assigned to standard users, the threat to self-hosted environments remains substantial.
The primary fix for this vulnerability is to upgrade the Cloudreve instance to version 4.18.0 or later. This release restructures the upload flow to enforce storage pre-allocation before file placeholders are created. The patched codebase uses atomic SQL updates to ensure that no two threads can allocate storage based on the same capacity state.
If upgrading is not immediately feasible, system administrators should implement strict rate limiting at the reverse proxy layer. Configuring Nginx or Cloudflare to limit the rate of requests to /api/v3/file/upload prevents attackers from executing parallel requests fast enough to win the race condition. Limiting clients to 1 or 2 active upload preparation connections per second reduces the likelihood of successful exploitation.
Additionally, administrators can mitigate the physical impact by shifting storage policies from local storage to cloud object storage like AWS S3 or Backblaze B2. When utilizing cloud object storage, the local host's disk space is protected from sudden exhaustion. Finally, setting up disk quota monitoring at the operating system level for the user running the Cloudreve service can prevent disk write exhaustion from crashing the entire system host.
CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:N/I:L/A:H| Product | Affected Versions | Fixed Version |
|---|---|---|
Cloudreve Cloudreve | < 4.18.0 | 4.18.0 |
| Attribute | Detail |
|---|---|
| CWE ID | CWE-367 / CWE-770 |
| Attack Vector | Network (AV:N) |
| CVSS v3.1 | 7.1 (High) |
| Exploit Status | PoC / Conceptual |
| KEV Status | Not Listed |
| Impact | Denial of Service (DoS) via Disk Exhaustion |
The software checks the state of a resource before using that resource, but the resource's state can change between the check and the use in a way that invalidates the results of the check.
An Insecure Direct Object Reference (IDOR) vulnerability exists in Spree open-source e-commerce solution versions 5.4.0 through 5.4.3 and 5.5.0 through 5.5.3. An authenticated attacker can predict or enumerate guest cart identifiers generated via Sqids and associate them with their own account. This unauthorized association leaks sensitive customer personally identifiable information (PII) and disrupts the checkout flow of active guest sessions.
CVE-2026-77637 is a privilege scope bypass vulnerability in Cloudreve. It allows authenticated clients possessing read-only administrative credentials to access sensitive administrative tool endpoints that should require write-level permissions.
An incorrect authorization vulnerability (CWE-863) in Gardener's customverbauthorizer admission plugin allows project administrators lacking the manage-members permission to inject arbitrary Group or ServiceAccount subjects, granting unauthorized access to project resources.
Cloudreve versions prior to 4.18.0 contain a Server-Side Request Forgery (SSRF) vulnerability. The application's validation logic fails to canonicalize various IPv4-in-IPv6 transition formats, such as NAT64, 6to4, and Teredo addresses. Consequently, an authenticated user with remote-download permissions can issue requests that bypass SSRF network boundaries, enabling connection routing to loopback, private, or cloud metadata endpoints.
Hatchet V1 Dispatcher before version 0.95.3 fails to enforce proper tenant boundaries when managing active stream connections for durable task completions. Because the global lookup map is keyed solely by task external identifiers, authenticated attackers who obtain a victim's task UUID can register a stream subscription and receive task results belonging to another tenant.
CVE-2026-88978 is a critical cross-tenant data exposure vulnerability in Hatchet, a platform for orchestrating background tasks and durable workflows. The flaw exists in the durable-task event retrieval system where client-supplied task, node, and branch UUIDs are resolved via the ListSatisfiedEntries database query without verifying the tenant ownership of the requesting worker context.