{"schema_version":"1.9.0","id":"GHSA-mr74-928f-rw69","published":"2026-03-02T20:15:46Z","modified":"2026-03-23T04:56:00.211469829Z","aliases":["CVE-2026-28492","GO-2026-4585"],"summary":"FileBrowser has Path Traversal in Public Share Links that Exposes Files Outside Shared Directory","details":"### Summary\nWhen a user creates a public share link for a **directory**, the `withHashFile` middleware in `http/public.go` (line 59) uses `filepath.Dir(link.Path)` to compute the `BasePathFs` root. This sets the filesystem root to the **parent directory** instead of the shared directory itself, allowing anyone with the share link to browse and download files from all sibling directories.\n\n### Details\nIn `http/public.go` lines 52-64, the `withHashFile` function handles public share link requests:\n\n```go\nbasePath := link.Path    // e.g. \"/documents/shared\"\nfilePath := \"\"\n\nif file.IsDir {\n    basePath = filepath.Dir(basePath)  // BUG: becomes \"/documents\" (parent!)\n    filePath = ifPath\n}\n\nd.user.Fs = afero.NewBasePathFs(d.user.Fs, basePath)\n```\n\nWhen a directory at `/documents/shared` is shared, `filepath.Dir(\"/documents/shared\")` evaluates to `\"/documents\"`. The `BasePathFs` is then rooted at the parent directory `/documents/`, giving the share link access to **everything** under `/documents/` - not just the intended `/documents/shared/`.\n\nThis affects both `publicShareHandler` (directory listing via `/api/public/share/{hash}`) and `publicDlHandler` (file download via `/api/public/dl/{hash}/path`).\n\n### PoC\n\n1. Set up filebrowser with a user whose scope contains:\n2.    - `/documents/shared/public-file.txt` (intended to be shared)\n3.    - `/documents/secrets/passwords.txt` (NOT intended to be shared)\n4.    - `/documents/private/financial.csv` (NOT intended to be shared)\n2. Create a public share link for the directory `/documents/shared` (via POST `/api/share/documents/shared`)\n3. Access the share link: `GET /api/public/share/{hash}`\n4.    - **Expected**: Lists only contents of `/documents/shared/`\n5.    - **Actual**: Lists contents of `/documents/` (parent), revealing `secrets/`, `private/`, and `shared/` directories\n4. Download sibling files: `GET /api/public/dl/{hash}/secrets/passwords.txt`\n5.    - **Expected**: 404 or 403 (file outside share scope)\n6.    - **Actual**: 200 with file contents (sibling file downloaded successfully)\n**Standalone Go test** reproducing the exact vulnerable code path with `afero.NewBasePathFs`:\n\n```go\nfunc TestShareScopeEscape(t *testing.T) {\n    baseFs := afero.NewMemMapFs()\n    afero.WriteFile(baseFs, \"/documents/shared/public.txt\", []byte(\"public\"), 0644)\n    afero.WriteFile(baseFs, \"/documents/secrets/passwords.txt\", []byte(\"admin:hunter2\"), 0644)\n\n    linkPath := \"/documents/shared\"\n    basePath := filepath.Dir(linkPath) // BUG: \"/documents\"\n    scopedFs := afero.NewBasePathFs(baseFs, basePath)\n\n    // Sibling file is accessible through the share:\n    f, err := scopedFs.Open(\"/secrets/passwords.txt\")\n    // err is nil - file accessible! Content: \"admin:hunter2\"\n}\n```\n\nThis test passes, confirming the vulnerability.\n\n### Impact\n\n**Unauthenticated information disclosure (CWE-200, CWE-706)**. Anyone with a public share link for a directory can:\n- Browse all sibling directories and files of the shared directory\n- - Download any file within the parent directory scope\n- - This works without authentication (public shares) or after providing the share password (password-protected shares)\nAll filebrowser v2.x installations that use directory sharing are affected.\n\n### Recommended Fix\n\nRemove the `filepath.Dir()` call and use `link.Path` directly as the `BasePathFs` root:\n\n```go\nif file.IsDir {\n    // Don't change basePath - keep it as link.Path\n    filePath = ifPath\n}\nd.user.Fs = afero.NewBasePathFs(d.user.Fs, basePath)\n```\n\n**Affected commit**: e3d00d591b567a8bfe3b02e42ba586859002c77d (latest)\n**File**: `http/public.go`, line 59","affected":[{"package":{"name":"github.com/filebrowser/filebrowser/v2","ecosystem":"Go","purl":"pkg:golang/github.com/filebrowser/filebrowser/v2"},"ranges":[{"type":"SEMVER","events":[{"introduced":"0"},{"fixed":"2.61.0"}]}],"database_specific":{"last_known_affected_version_range":"<= 2.60.0","source":"https://github.com/github/advisory-database/blob/main/advisories/github-reviewed/2026/03/GHSA-mr74-928f-rw69/GHSA-mr74-928f-rw69.json"}}],"references":[{"type":"WEB","url":"https://github.com/filebrowser/filebrowser/security/advisories/GHSA-mr74-928f-rw69"},{"type":"ADVISORY","url":"https://nvd.nist.gov/vuln/detail/CVE-2026-28492"},{"type":"WEB","url":"https://github.com/filebrowser/filebrowser/commit/31194fb57a5b92e7155219d7ec7273028fcb2e83"},{"type":"PACKAGE","url":"https://github.com/filebrowser/filebrowser"},{"type":"WEB","url":"https://github.com/filebrowser/filebrowser/releases/tag/v2.61.0"}],"database_specific":{"cwe_ids":["CWE-200"],"github_reviewed":true,"github_reviewed_at":"2026-03-02T20:15:46Z","nvd_published_at":"2026-03-05T21:16:22Z","severity":"HIGH"},"severity":[{"type":"CVSS_V4","score":"CVSS:4.0/AV:N/AC:L/AT:N/PR:L/UI:N/VC:H/VI:N/VA:N/SC:N/SI:N/SA:N"}]}