Jul 25, 2026·6 min read·18 visits
OpenList version 4.2.3 and below is vulnerable to an authorization bypass where authenticated users can access sibling directories due to literal string prefix matching on user base paths.
An authorization bypass vulnerability in OpenList version 4.2.3 and below allows authenticated users to read arbitrary files outside of their designated base directories due to an insecure path prefix check using Go's standard strings.HasPrefix function.
The target system is OpenList, a Go-based file manager and sharing application designed to facilitate secure multi-tenant hosting. The application allows administrators to restrict individual user accounts to specified root folders, termed base paths. This restriction is intended to enforce logical partition boundaries, ensuring that users can only search, read, or share resources contained within their directory sandbox.
A critical authorization bypass vulnerability, identified as GHSA-86cx-wwf4-phq4, affects all versions of OpenList up to and including version 4.2.3. The flaw lies in the handling of user-controlled paths inside the file-sharing creation, update, and search application program interfaces (APIs). These interfaces rely on string-based verification logic to check boundaries, exposing an attack surface to authenticated users.
The vulnerability enables authenticated tenants to traverse beyond their assigned base directories and access files residing in adjacent directories. If an administrator assigns a base path that shares a partial name with a sibling directory, the string-matching logic fails. This failure bypasses file-system access control policies, leading to unauthorized data exposure without administrative privileges.
The root cause of GHSA-86cx-wwf4-phq4 is a path prefix confusion vulnerability, classified under CWE-639. The vulnerability is located in the validation logic within server/handles/sharing.go and server/handles/search.go. During file operations, the application must verify that any target file path resides strictly inside the user's configured BasePath directory.
To perform this verification, the application evaluates the requested path using Go's standard library function strings.HasPrefix(requested_path, user.BasePath). This function performs a literal, character-by-character comparison of the two strings. It does not parse the inputs as filesystem paths, nor does it consider directory boundary separators such as the forward slash character.
Consequently, if a restricted user's base path is /base and they request access to a resource inside a sibling directory named /base2, the application evaluates strings.HasPrefix("/base2/secret_document.txt", "/base"). Because the literal string /base2/secret_document.txt starts with the sequence /base, the function returns a true value. This allows the request to bypass access controls and generate a persistent share link or return search results for files belonging to another tenant.
A review of the codebase confirms that the validation checks failed to handle boundary separators correctly. Below is the vulnerable validation structure located in server/handles/sharing.go for creating shares:
// Vulnerable implementation in server/handles/sharing.go
func CreateSharing(c *gin.Context) {
// ...
for i, s := range req.Files {
s = utils.FixAndCleanPath(s)
req.Files[i] = s
// Literal string prefix check allows substring confusion
if !reqUser.IsAdmin() && !strings.HasPrefix(s, user.BasePath) {
common.ErrorStrResp(c, fmt.Sprintf("permission denied to share path [%s]", s), 500)
return
}
}
// ...
}The remediation patch introduces a dedicated helper function, utils.IsSubPath, which performs boundary-aware path validation rather than raw string comparison. This function ensures that the target path matches the base path as an exact directory or as a true descendant. The patched code in server/handles/sharing.go is implemented as follows:
// Patched implementation in server/handles/sharing.go
func CreateSharing(c *gin.Context) {
// ...
for i, s := range req.Files {
s = utils.FixAndCleanPath(s)
req.Files[i] = s
// Patched boundary-aware containment verification
if !reqUser.IsAdmin() && !utils.IsSubPath(user.BasePath, s) {
common.ErrorStrResp(c, fmt.Sprintf("permission denied to share path [%s]", s), 500)
return
}
}
// ...
}Additionally, the patch implements dynamic re-validation in the GetSharingUnwrapPath helper inside internal/op/sharing.go. This change establishes defense-in-depth, preventing cases where an administrator subsequently modifies a user's BasePath but the user's previously generated share links continue to expose files that are now out-of-scope:
// Defense-in-depth dynamic validation in internal/op/sharing.go
if sharing.Creator != nil && !sharing.Creator.IsAdmin() {
for _, f := range sharing.Files {
// Enforce that files are still within the creator's current BasePath
if !utils.IsSubPath(sharing.Creator.BasePath, f) {
return "", errors.Errorf("sharing path [%s] is outside the creator's base path", f)
}
}
}Exploitation of GHSA-86cx-wwf4-phq4 requires that the attacker has an authenticated account with permission to share or search files. The attacker must also identify or guess adjacent directory naming schemes on the target server. If the target server hosts a directory named /data_user_1 and the attacker's base path is /data_user, the prefix confusion condition is satisfied.
The exploitation flow begins with the attacker issuing an authenticated HTTP POST request to the /api/share/create endpoint. The attacker sets the files array to target a sensitive file in the adjacent directory. Because the string value /data_user_1/confidential.txt begins with /data_user, the application validates the path and registers a sharing record in the database.
Upon receiving a successful HTTP 200 response containing the generated share_id, the attacker requests the share's files through public endpoints. The server fetches the absolute path from the database and resolves it, returning the target file contents.
POST /api/share/create HTTP/1.1
Host: target-server.local
Authorization: Bearer <attacker_jwt_token>
Content-Type: application/json
{
"files": ["/data_user_1/confidential.txt"],
"pwd": "",
"max_accessed": 0
}The security impact of this vulnerability is significant, particularly in environments hosting multiple tenants. An attacker can bypass logical folder isolation to read configuration files, private datasets, or system secrets stored in adjacent directories. This vulnerability does not directly provide remote code execution, but the arbitrary file read capability can be used to harvest database credentials or API tokens, facilitating further compromise.
The vulnerability has been assigned a CVSS v3.1 base score of 6.5. The vector string is CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:H/I:N/A:N. This reflects network-based accessibility with low attack complexity, requiring low administrative privileges, and carrying high confidentiality impact with no immediate integrity or availability impacts.
Because there is no associated CVE ID, standard vulnerability metadata databases do not report an EPSS score or track KEV status for this advisory. No wild exploitation or automated scanner signatures have been observed targeting this flaw in public threat intelligence databases.
To address the path prefix confusion vulnerability, operators must update all OpenList deployments to version 4.2.4 or later. This release completely replaces the flawed strings.HasPrefix logic with proper subpath validation utilities.
If updating the application is not immediately possible, administrators can apply defensive configuration workarounds. To prevent prefix confusion, ensure that all user base paths configured in the application database end with a trailing slash. For example, change /data_user to /data_user/. This modification forces the character comparison to evaluate the directory boundary separator, blocking substring matches against /data_user_1.
Additionally, administrators can mitigate the risk by auditing and temporarily revoking sharing privileges from non-administrative users. Reviewing the database tables for existing sharing records where the target path does not match the active base path of the creator is also recommended to detect prior exploitation.
| Product | Affected Versions | Fixed Version |
|---|---|---|
OpenList OpenListTeam | <= 4.2.3 | 4.2.4 |
| Attribute | Detail |
|---|---|
| CWE ID | CWE-639: Authorization Bypass Through User-Controlled Key |
| Attack Vector | Network (AV:N) |
| CVSS v3.1 Score | 6.5 (Medium) |
| EPSS Score | Not Applicable |
| Impact | Arbitrary File Read / Authorization Bypass |
| Exploit Status | Proof of Concept (PoC) documented |
| CISA KEV Status | Not Listed |
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.
ASP.NET Core contains a thread deadlock vulnerability (CWE-833) that allows an unauthenticated remote attacker to cause a denial of service over the network by exhausting server thread pool resources.
CVE-2026-70035 is a high-severity Remote Code Execution (RCE) vulnerability in Microsoft .NET Framework, .NET runtime, and Visual Studio caused by improper handling during the deserialization of untrusted data (CWE-502). An unauthenticated attacker can execute arbitrary code within the context of the affected process by delivering a crafted serialized payload.