Skip to main content

File Browser EUVDEUVD-2026-39507

| CVE-2026-54091 HIGH
Incorrect Authorization (CWE-863)
2026-06-12 https://github.com/filebrowser/filebrowser GHSA-j9jx-hp4c-ghhh
7.5
CVSS 3.1 · Vendor: https://github.com/filebrowser/filebrowser
Share

Severity by source

Vendor (https://github.com/filebrowser/filebrowser) PRIMARY
7.5 HIGH
AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:N/A:N
vuln.today AI
7.5 HIGH

Network-reachable public share endpoint, no authentication when share is unprotected, no user interaction, confidentiality-only impact (read of blocked files) with no integrity or availability effect.

3.1 AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:N/A:N
4.0 AV:N/AC:L/AT:N/PR:N/UI:N/VC:H/VI:N/VA:N/SC:N/SI:N/SA:N

Primary rating from Vendor (https://github.com/filebrowser/filebrowser).

CVSS VectorVendor: https://github.com/filebrowser/filebrowser

CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:N/A:N
Attack Vector
Network
Attack Complexity
Low
Privileges Required
None
User Interaction
None
Scope
Unchanged
Confidentiality
High
Integrity
None
Availability
None

Lifecycle Timeline

3
Source Code Evidence Fetched
Jun 12, 2026 - 22:18 vuln.today
Analysis Generated
Jun 12, 2026 - 22:18 vuln.today
CVE Published
Jun 12, 2026 - 21:53 github-advisory
HIGH 7.5

DescriptionCVE.org

Summary

File Browser's public share handlers rebase the share owner's filesystem root to the shared directory and then evaluate descendant paths against the owner's global and per-user rules using the rebased relative path instead of the original path relative to the owner's scope.

As a result, an attacker who knows a public directory share URL can access files and subdirectories that the owner explicitly blocked with rules, as long as those blocked paths are located underneath the shared directory. In the simplest case this is an unauthenticated information disclosure through GET /api/public/share/* and GET /api/public/dl/*.

Details

The public share flow first resolves the original shared path under the owner's filesystem, but then switches d.user.Fs to a new BasePathFs rooted at the shared directory. The follow-up authorization check is still performed by d.Check, which compares the request path to rule strings using prefix matching.

When the share target is a directory, the path passed to d.Check becomes relative to the shared directory, while the rules remain relative to the owner's original scope. A deny rule such as /projects/private therefore no longer matches a public share request for /private/secret.txt, even though the rebased filesystem resolves that request to the real path /projects/private/secret.txt.

Core vulnerable code path:

go
// http/public.go
if file.IsDir {
    basePath = filepath.Clean(link.Path)
    filePath = ifPath
}

d.user.Fs = afero.NewBasePathFs(d.user.Fs, basePath)

file, err = files.NewFileInfo(&files.FileOptions{
    Fs:      d.user.Fs,
    Path:    filePath,
    Expand:  true,
    Checker: d,
})
go
// http/data.go and rules/rules.go
func (d *data) Check(path string) bool {
    allow := true
    for _, rule := range d.settings.Rules {
        if rule.Matches(path) {
            allow = rule.Allow
        }
    }
    for _, rule := range d.user.Rules {
        if rule.Matches(path) {
            allow = rule.Allow
        }
    }
    return allow
}

func (r *Rule) Matches(path string) bool {
    if path == r.Path {
        return true
    }
    prefix := r.Path
    if prefix != "/" && !strings.HasSuffix(prefix, "/") {
        prefix += "/"
    }
    return strings.HasPrefix(path, prefix)
}

The issue is reachable from the public endpoints registered in http/http.go for /api/public/share/* and /api/public/dl/*.

PoC

The attacker only needs a directory share URL. No authenticated session is required if the share is not password protected.

Reproduction flow:

  1. Prepare a directory owned by a normal user, for example /projects/.
  2. Inside it, create a sensitive child path such as /projects/private/secret.txt.
  3. Configure a deny rule for the share owner that blocks /projects/private.
  4. Have the owner create a public share for /projects/.
  5. Request the blocked child path through the public share endpoints.

PoC:

bash
# owner creates a public share for /projects/
curl -s -X POST 'http://HOST/api/share/projects/' \
  -H 'X-Auth: <OWNER_JWT>' \
  -H 'Content-Type: application/json' \
  -d '{}'

The response contains a share hash such as:

text
{"hash":"<HASH>","path":"/projects/","userID":2,"expire":0}

The attacker can then access a rule-blocked file below the shared directory:

bash
curl -i 'http://HOST/api/public/dl/<HASH>/private/secret.txt'

A blocked subdirectory can also be listed directly:

bash
curl -i 'http://HOST/api/public/share/<HASH>/private/'

the server returns 200 OK and serves the file content or directory listing, even though the share owner's rules should have made that path inaccessible.

Impact

This flaw allows public share recipients to read files and browse directories that the share owner explicitly intended to block with File Browser rules. Because the vulnerable path is the public share feature, the exposure can be unauthenticated and internet-reachable whenever a share link is exposed.

In practical deployments, this can disclose secrets, configuration files, backup material, private project directories, or any other content that administrators or users attempted to hide beneath a shared parent directory using the built-in rule system.

AnalysisAI

Unauthenticated information disclosure in File Browser (filebrowser/filebrowser) versions <= 2.63.5 allows public share recipients to bypass owner-defined deny rules and read or list files explicitly blocked beneath a shared directory. The flaw stems from the public share handler rebasing the filesystem root but evaluating access rules against the rebased relative path rather than the owner's original scope. No public exploit identified at time of analysis, but a detailed PoC accompanies the GHSA advisory and EPSS sits at 0.04% (13th percentile).

Technical ContextAI

File Browser is a Go-based self-hosted web file manager (github.com/filebrowser/filebrowser). The vulnerability resides in http/public.go and http/data.go: when a public share targets a directory, the handler swaps d.user.Fs for an afero BasePathFs rooted at the shared directory, but the authorization Check() function in rules/rules.go uses simple strings.HasPrefix matching against rule paths that remain anchored to the owner's original (un-rebased) filesystem scope. A deny rule like /projects/private therefore never matches the rebased request path /private/secret.txt even though it resolves to the same underlying file. This is a textbook CWE-863 (Incorrect Authorization) instance, specifically a path-namespace mismatch between the access-decision context and the enforcement context.

RemediationAI

Vendor-released patch: upgrade to File Browser v2.63.6 or later, which introduces a checkerPrefix on the data struct that re-joins the share base path before rule evaluation (commit e07c59df0b850f5924d5b1683e8609661ddcf534). Operators on the legacy github.com/filebrowser/filebrowser (v1) module path have no released fixed version and should migrate to the v2 module or apply the equivalent patch manually. As a compensating control until upgrade, restrict or disable public directory shares (share files individually rather than parent directories, since the bug only manifests when the share target is a directory) and enforce password protection on all public shares to require a secret beyond the URL itself - note this still permits anyone with the password to bypass owner rules, so it only reduces exposure to URL leaks rather than eliminating the bug. Additionally, place File Browser behind an authenticating reverse proxy or IP allowlist to remove unauthenticated internet reachability. Consult the advisory at https://github.com/filebrowser/filebrowser/security/advisories/GHSA-j9jx-hp4c-ghhh for details.

Share

EUVD-2026-39507 vulnerability details – vuln.today

This site uses cookies essential for authentication and security. No tracking or analytics cookies are used. Privacy Policy