Sep 3, 2026·6 min read·61 visits
SeaweedFS Filer prior to 4.24 uses raw prefix matching on raw path strings during JWT validation, allowing scoped tokens to authorize unauthorized access to sibling directories (e.g., /tenant1 matching /tenant1234).
SeaweedFS is a distributed storage system. Prior to version 4.24, the Filer JWT validation mechanism used a raw prefix match, allowing scoped tokens to access sibling directories sharing similar name prefixes.
SeaweedFS is a high-performance distributed storage system designed to store billions of files efficiently. Within its architecture, the Filer component provides a filesystem abstraction layer over the volume servers, supporting metadata storage and access control. To secure multi-tenant environments, the Filer uses JSON Web Tokens (JWT) to enforce directory-level access restrictions.
Prior to version 4.24, the SeaweedFS Filer implemented a path authorization mechanism that contained a significant logic flaw. When validating scoped tokens containing the allowed_prefixes claim, the server used a simple prefix comparison. This check relied on a raw string-matching function rather than a component-aware path evaluation.
This vulnerability, tracked as CVE-2026-72921, allows an attacker with a valid scoped JWT to access unauthorized directories sharing a common string prefix. For instance, a token authorized only for /tenant1 would also grant access to /tenant1234 or /tenant1backup. The issue has been assigned a Common Vulnerability Scoring System (CVSS) v3.1 base score of 8.1.
The underlying flaw resides within the Filer handler authorization logic inside weed/server/filer_server_handlers.go. When a request is received, the server extracts the JWT claims and iterates over the prefixes specified in claims.AllowedPrefixes. For each configured prefix, the server determines authorization by executing strings.HasPrefix(r.URL.Path, prefix).
The function strings.HasPrefix performs a literal byte-by-byte comparison from the start of the target string. Because this function has no awareness of path delimiters, it treats the path as an arbitrary sequence of characters. It fails to distinguish between a matching directory path component and a sibling path that merely shares a prefix sequence.
Consequently, any folder namespace that begins with the exact characters of an authorized prefix evaluates to true. If a system contains tenants named /tenant1 and /tenant10, the token for the former permits full access to the latter. Furthermore, the lack of path sanitization on input parameters increases the likelihood of inconsistent path resolution down the stack.
The vulnerable implementation of the authorization check is shown below. This logic evaluates the HTTP request path against the scoped prefixes using raw string manipulation:
// Vulnerable implementation in weed/server/filer_server_handlers.go
if len(claims.AllowedPrefixes) > 0 {
hasPrefix := false
for _, prefix := range claims.AllowedPrefixes {
// Raw string matching without boundary checks
if strings.HasPrefix(r.URL.Path, prefix) {
hasPrefix = true
break
}
}
// ...
}The patch introduced in SeaweedFS version 4.24 resolves the issue by replacing the literal string check with a structured path segment analysis. The system now utilizes a dedicated helper function called pathHasComponentPrefix. This helper ensures that matches occur exclusively on complete path segment boundaries.
// Patched implementation utilizing path normalization and component checks
func pathHasComponentPrefix(reqPath, prefix string) bool {
if prefix == "" {
return false
}
// Normalise paths to resolve directory traversal and empty elements
cleanedPath := path.Clean(reqPath)
if cleanedPath == "." {
cleanedPath = "/"
}
cleanedPrefix := path.Clean(prefix)
if cleanedPrefix == "." {
cleanedPrefix = "/"
}
if cleanedPrefix == "/" {
return true
}
if cleanedPath == cleanedPrefix {
return true
}
// Enforce segment boundaries by requiring a trailing slash
return strings.HasPrefix(cleanedPath, cleanedPrefix+"/")
}The helper function first normalizes both the request path and the prefix using Go's path.Clean library. This step removes redundant slashes and resolves relative segments like . and ... By appending a trailing slash / to the prefix during the comparison, the function restricts matches to exact folders or their immediate subdirectories.
An attacker requires a valid JWT with an active allowed_prefixes scope to execute this exploit. The attack vector is entirely network-based and demands low privileges, making it accessible to compromised or malicious tenants. No user interaction or administrative intervention is required to complete the authorization bypass.
The exploitation sequence begins with the attacker identifying sibling directory names that share the suffix boundary of their own authorized folder. In multi-tenant systems, names such as /tenant1_backup or /tenant1-development are highly predictable. The attacker crafts an HTTP request targeting the target sibling directory, embedding their legitimate scoped JWT within the Authorization header.
When the Filer receives the request, the authorization middleware validates the token signature successfully. It then evaluates the target path /tenant1_backup/file.json against the claim /tenant1. The vulnerable strings.HasPrefix check evaluates to true, granting the request read or write access depending on the HTTP method utilized.
Below is a sequence diagram illustrating the vulnerability mechanism:
The impact of CVE-2026-72921 is significant within multi-tenant distributed environments. This vulnerability compromises the fundamental isolation boundary between tenants. An attacker can perform unauthorized read and write operations across any folder that matches their assigned prefix sequence.
Unauthorized read access allows for the exfiltration of proprietary data, database backups, and intellectual property stored in adjacent sibling paths. Write access enables an attacker to modify, delete, or overwrite critical files belonging to other tenants. This capability can be leveraged to corrupt systems or inject malicious payloads into shared application paths.
The vulnerability has been assigned a CVSS v3.1 score of 8.1. The vector string CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:N reflects high confidentiality and integrity impact. Although there is no direct impact on system availability, data deletion and corruption can result in operational disruption.
The primary remediation strategy is to upgrade all SeaweedFS instances to version 4.24 or later. This release completely replaces the vulnerable matching logic with the secure segment-aware verification function. System administrators should verify that the update has been applied across all Filer nodes.
If an immediate upgrade is not feasible, temporary workarounds can be applied via JWT claim configuration. Administrators can modify token issuance policies to append a trailing slash to all AllowedPrefixes values. For example, issuing a scope of /tenant1/ instead of /tenant1 forces the vulnerable string check to require a trailing slash, neutralizing matches against sibling paths like /tenant1234.
Additionally, tenant namespaces can be refactored to eliminate shared character prefixes. Placing tenant directories under structurally unique parents prevents suffix collisions. Security groups should also monitor Filer logs for anomalous access requests targeting paths outside of a user's normal scope.
CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:N| Product | Affected Versions | Fixed Version |
|---|---|---|
SeaweedFS seaweedfs | < 4.24 | 4.24 |
| Attribute | Detail |
|---|---|
| CWE ID | CWE-863 |
| Attack Vector | Network (AV:N) |
| CVSS v3.1 Score | 8.1 (High) |
| EPSS Score | 0.00238 (0.24%) |
| Exploit Status | none |
| KEV Status | Not Listed |
The software performs an authorization check when an actor attempts to access a resource or perform an action, but it does not correctly obtain or evaluate the access rights of the actor, leading to unauthorized access.
A heap-based buffer overflow vulnerability in Pillow PyPI binary wheels (versions 11.1.0 to 12.x) allows remote code execution or application crash via crafted JPEG 2000 files processed by the bundled libopenjp2 library.
CVE-2026-109618 (dubbed PHP2Shell) is a critical vulnerability in the PHP engine core resulting from improper out-of-memory exception handling via longjmp(). When request allocation fails mid-processing, non-local control flow bypasses cleanup procedures, leaving memory structures uninitialized or in a use-after-free state during request shutdown.
CVE-2026-109619 (PHP2Shell) is a critical Use-After-Free vulnerability in the core PHP engine caused by improper global state cleanup during out-of-memory exception handling across persistent worker requests.
In Python virtualenv prior to version 21.14.9, activation script generators and configuration writers use Path.exists() before writing files. Because Path.exists() resolves symbolic links, it returns False for dangling symlinks. Consequently, virtualenv skips unlinking pre-planted symbolic links or hard links, writing data directly to target locations outside the intended virtual environment directory.
A remote code execution vulnerability exists in Microsoft .NET due to untrusted data deserialization within the PresentationCore component. The flaw stems from implicit auto-conversion flags during clipboard data retrieval operations.
An out-of-bounds write vulnerability in Microsoft .NET Framework, .NET runtime, and Visual Studio allows unauthenticated remote attackers to execute arbitrary code via crafted pixel-shader bytecode or auto-converted clipboard payloads.