{"id":"CVE-2026-94618","aliases":["EUVD-2026-118519","GHSA-f74m-x83r-c4v4"],"status":"published","title":"FileGator: Missing authorization in GET /batchdownload allows cross-user retrieval of another user's archive","description":"FileGator is a multi-user file manager. Prior to 7.15.0, GET /batchdownload in backend/Controllers/DownloadController.php uses batchDownloadStart() to stream a shared temporary archive selected by the request-supplied uniqid without checking that the current session created it. In deployments with distinct per-user home directories, a valid user with read, download, and batchdownload permissions who obtains another user's active archive id can cross that boundary and retrieve the victim's batch archive. The archive lifetime and id-acquisition requirement limit exploitation, but a successful replay also deletes the victim's pending archive. This issue is fixed in version 7.15.0.","severity":{"version":"3.1","score":5.4,"vector":"CVSS:3.1/AV:N/AC:H/PR:L/UI:R/S:U/C:H/I:N/A:L","level":"medium","assessor":"cna","from":"cve"},"epss":{"day":"2026-11-12","score":0.00189,"percentile":0.0866,"model":"v2026.06.15"},"facts":{"in_kev":false,"known_exploited":false,"public_exploit":false,"fix_available":true},"cwes":["CWE-330","CWE-862"],"published":"2026-11-06T21:30:39Z","modified":"2026-11-10T20:19:21Z","fixes":[{"ecosystem":"Packagist","package":"filegator/filegator","fixed_in":["7.15.0"],"sources":["ghsa","osv"]}],"affected":[{"source":"ghsa","ecosystem":"Packagist","package":"filegator/filegator","ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"0"},{"last_affected":"7.14.4"},{"fixed":"7.15.0"}]}]},{"source":"osv","ecosystem":"Packagist","package":"filegator/filegator","ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"0"},{"fixed":"7.15.0"}]}],"versions":["v7.0.0","v7.0.0-RC1","v7.0.0-RC2","v7.0.0-RC3","v7.0.1","v7.1.0","v7.1.1","v7.1.2","v7.1.3","v7.1.4","v7.1.5","v7.1.6","v7.10.0","v7.10.1","v7.11.0","v7.11.1","v7.12.0","v7.13.0","v7.13.1","v7.13.2","v7.13.3","v7.13.4","v7.13.5","v7.14.0","v7.14.1","v7.14.2","v7.14.3","v7.14.4","v7.2.0","v7.2.1","v7.3.0","v7.3.1","v7.3.2","v7.3.3","v7.3.4","v7.3.5","v7.4.0","v7.4.1","v7.4.2","v7.4.3","v7.4.4","v7.4.5","v7.4.6","v7.4.7","v7.5.0","v7.5.1","v7.5.2","v7.5.3","v7.6.0","v7.7.0","v7.7.1","v7.7.2","v7.8.0","v7.8.1","v7.8.2","v7.8.3","v7.8.4","v7.8.5","v7.8.6","v7.8.7","v7.9.0","v7.9.1","v7.9.2","v7.9.3"]}],"products":[{"vendor":"filegator","product":"filegator"}],"references":[{"url":"https://github.com/filegator/filegator/security/advisories/GHSA-f74m-x83r-c4v4","tags":["x_refsource_CONFIRM","exploit","advisory","web"]},{"url":"https://github.com/filegator/filegator/pull/597","tags":["x_refsource_MISC","fix","web"]},{"url":"https://github.com/filegator/filegator/commit/638737e560cbf20cbeb5da4e4e6c974f8a080531","tags":["x_refsource_MISC","fix","web"]},{"url":"https://github.com/filegator/filegator/releases/tag/v7.15.0","tags":["x_refsource_MISC","web"]},{"url":"https://nvd.nist.gov/vuln/detail/CVE-2026-94618","tags":["advisory"]},{"url":"https://github.com/advisories/GHSA-f74m-x83r-c4v4"},{"url":"https://github.com/CVEProject/cvelistV5/tree/main/cves/2026/94xxx/CVE-2026-94618.json","tags":["advisory"]},{"url":"https://github.com/filegator/filegator","tags":["package"]}],"sources":{"cve":[{"id":"CVE-2026-94618","title":"FileGator: Missing authorization in GET /batchdownload allows cross-user retrieval of another user's archive","description":"FileGator is a multi-user file manager. Prior to 7.15.0, GET /batchdownload in backend/Controllers/DownloadController.php uses batchDownloadStart() to stream a shared temporary archive selected by the request-supplied uniqid without checking that the current session created it. In deployments with distinct per-user home directories, a valid user with read, download, and batchdownload permissions who obtains another user's active archive id can cross that boundary and retrieve the victim's batch archive. The archive lifetime and id-acquisition requirement limit exploitation, but a successful replay also deletes the victim's pending archive. This issue is fixed in version 7.15.0.","status":"published","published":"2026-11-06T21:30:39.923Z","modified":"2026-11-10T20:19:21.659Z","cvss":[{"version":"3.1","score":5.4,"vector":"CVSS:3.1/AV:N/AC:H/PR:L/UI:R/S:U/C:H/I:N/A:L","level":"medium","assessor":"cna"}],"cwes":["CWE-330","CWE-862"],"updated_at":"2026-11-10T22:18:30.298108Z"}],"euvd":[{"id":"EUVD-2026-118519","description":"FileGator is a multi-user file manager. Prior to 7.15.0, GET /batchdownload in backend/Controllers/DownloadController.php uses batchDownloadStart() to stream a shared temporary archive selected by the request-supplied uniqid without checking that the current session created it. In deployments with distinct per-user home directories, a valid user with read, download, and batchdownload permissions who obtains another user's active archive id can cross that boundary and retrieve the victim's batch archive. The archive lifetime and id-acquisition requirement limit exploitation, but a successful replay also deletes the victim's pending archive. This issue is fixed in version 7.15.0.","status":"published","published":"2026-11-06T21:30:39Z","modified":"2026-11-10T20:19:21Z","cvss":[{"version":"3.1","score":5.4,"vector":"CVSS:3.1/AV:N/AC:H/PR:L/UI:R/S:U/C:H/I:N/A:L","level":"medium"}],"updated_at":"2026-11-10T21:23:25.936552Z"}],"ghsa":[{"id":"GHSA-f74m-x83r-c4v4","title":"FileGator: Missing authorization in GET /batchdownload allows cross-user retrieval of another user's archive","description":"### Summary\n`GET /batchdownload` streams a batch ZIP to any requester who supplies its `uniqid`, without checking that the current user/session created it. In deployments where users have separate home directories, a valid low-privileged user who obtains an active archive id can download another user's batch archive, disclosing files the per-user boundary otherwise protects. Reported with explicit preconditions and bounded impact — not a universal \"any user steals any file\" issue.\n\n### Details\nThe archive id is generated with plain `uniqid()` and no ownership metadata is bound to it before streaming.\n\n- `backend/Services/Archiver/Adapters/ZipArchiver.php:44` — `createArchive()` uses plain `uniqid()`.\n- `backend/Controllers/DownloadController.php:144-145` — `batchDownloadStart()` reads the tmpfs file by the request-supplied `uniqid` after only a charset `preg_replace()`.\n- `backend/Controllers/DownloadController.php:158` — the tmpfs archive is removed only after streaming.\n- `backend/Controllers/routes.php:207-226` — both batch endpoints are exposed to normal roles with `read`, `download`, `batchdownload`.\n\nNo user id, session id, home directory, or creator check is applied before streaming. The code path is unchanged since commit `3f03a40` (2022-05-31) and is present in the latest release `v7.14.3`.\n\n### PoC\nPreconditions: a multi-user deployment with distinct per-user `homedir`s (set per-user in `users.json`, or `private_repos =\u003e true` on the WordPress/LDAP adapter). The shipped sample config (`admin`/`guest` both at `/`, `guest` with no perms) does not create this boundary on its own. Attacker is a valid user with `read`, `download`, `batchdownload`.\n\n1. User John (`homedir /john`) creates `secret.txt`, signs in, and creates a batch archive via `POST /batchdownload`. The JSON response returns the archive `uniqid`.\n2. User Jane (`homedir /jane`, with `batchdownload`) signs in normally.\n3. Jane's direct `GET /download` of `/secret.txt` returns `302` — the normal home-directory boundary blocks the file.\n4. Jane sends `GET /batchdownload?uniqid=\u003cJohn's id\u003e` and receives a valid ZIP containing `secret.txt` with John's content.\n\nA PHPUnit proof with two real sessions reproduces this end to end (`OK, 3 tests / 29 assertions`), plus a lifecycle test (`OK, 2 tests / 9 assertions`). Full test files, run logs, and a real Apache access-log replay demo are available on request.\n\nLifetime / acquisition: a normal completed download removes the archive at the end of streaming, limiting the window. An aborted/failed download leaves the archive in tmpfs (cleanup never reached). The frontend issues the download as a top-level navigation (`window.open('.../batchdownload\u0026uniqid='+ret.uniqid, '_blank')`), so the id appears in standard web access logs. That access-log path only adds meaningful impact when log visibility is decoupled from host filesystem access (e.g. a log-aggregation/shared-hosting/downstream-sink reader) and the archive is still alive; if the reader is ops/root on the same host they can already read the storage tree directly. The `uniqid()` token is timestamp-derived (1,000,000-value space per known second) — included to justify a CSPRNG, not presented as a practical universal brute force.\n\n### Impact\nMissing authorization (CWE-862) on a temporary download object, leading to cross-user file disclosure across the per-user home-directory boundary in configured multi-user deployments. Secondary effect: a successful replay deletes the victim's pending archive (the GET removes the tmpfs file after streaming), denying the victim their own download if not yet consumed.\n\nRemediation: generate ids with `bin2hex(random_bytes(32))`; store creator user/session + home dir + expiry per archive id; verify the requester matches before streaming and return `403`/`404` on mismatch or unknown/expired id; delete metadata with the tmpfs file.","status":"published","published":"2026-11-09T22:17:36Z","modified":"2026-11-09T22:17:37Z","cvss":[{"version":"3.1","score":5.4,"vector":"CVSS:3.1/AV:N/AC:H/PR:L/UI:R/S:U/C:H/I:N/A:L","level":"medium"}],"cwes":["CWE-330","CWE-862"],"updated_at":"2026-11-09T22:20:10.289641Z"}],"nvd":[{"id":"CVE-2026-94618","description":"FileGator is a multi-user file manager. Prior to 7.15.0, GET /batchdownload in backend/Controllers/DownloadController.php uses batchDownloadStart() to stream a shared temporary archive selected by the request-supplied uniqid without checking that the current session created it. In deployments with distinct per-user home directories, a valid user with read, download, and batchdownload permissions who obtains another user's active archive id can cross that boundary and retrieve the victim's batch archive. The archive lifetime and id-acquisition requirement limit exploitation, but a successful replay also deletes the victim's pending archive. This issue is fixed in version 7.15.0.","status":"published","published":"2026-11-06T22:18:00.133Z","modified":"2026-11-10T21:21:54.123Z","cvss":[{"version":"3.1","score":5.4,"vector":"CVSS:3.1/AV:N/AC:H/PR:L/UI:R/S:U/C:H/I:N/A:L","level":"medium","assessor":"secondary"}],"cwes":["CWE-330","CWE-862"],"updated_at":"2026-11-11T00:21:53.107469Z"}],"osv":[{"id":"CVE-2026-94618","title":"FileGator: Missing authorization in GET /batchdownload allows cross-user retrieval of another user's archive","description":"FileGator is a multi-user file manager. Prior to 7.15.0, GET /batchdownload in backend/Controllers/DownloadController.php uses batchDownloadStart() to stream a shared temporary archive selected by the request-supplied uniqid without checking that the current session created it. In deployments with distinct per-user home directories, a valid user with read, download, and batchdownload permissions who obtains another user's active archive id can cross that boundary and retrieve the victim's batch archive. The archive lifetime and id-acquisition requirement limit exploitation, but a successful replay also deletes the victim's pending archive. This issue is fixed in version 7.15.0.","status":"published","published":"2026-11-06T21:30:39.923Z","modified":"2026-11-11T10:30:50.610924638Z","cvss":[{"version":"3.1","score":5.4,"vector":"CVSS:3.1/AV:N/AC:H/PR:L/UI:R/S:U/C:H/I:N/A:L","level":"medium"}],"cwes":["CWE-330","CWE-862"],"updated_at":"2026-11-08T03:29:44.777002Z"},{"id":"GHSA-f74m-x83r-c4v4","title":"FileGator: Missing authorization in GET /batchdownload allows cross-user retrieval of another user's archive","description":"### Summary\n`GET /batchdownload` streams a batch ZIP to any requester who supplies its `uniqid`, without checking that the current user/session created it. In deployments where users have separate home directories, a valid low-privileged user who obtains an active archive id can download another user's batch archive, disclosing files the per-user boundary otherwise protects. Reported with explicit preconditions and bounded impact — not a universal \"any user steals any file\" issue.\n\n### Details\nThe archive id is generated with plain `uniqid()` and no ownership metadata is bound to it before streaming.\n\n- `backend/Services/Archiver/Adapters/ZipArchiver.php:44` — `createArchive()` uses plain `uniqid()`.\n- `backend/Controllers/DownloadController.php:144-145` — `batchDownloadStart()` reads the tmpfs file by the request-supplied `uniqid` after only a charset `preg_replace()`.\n- `backend/Controllers/DownloadController.php:158` — the tmpfs archive is removed only after streaming.\n- `backend/Controllers/routes.php:207-226` — both batch endpoints are exposed to normal roles with `read`, `download`, `batchdownload`.\n\nNo user id, session id, home directory, or creator check is applied before streaming. The code path is unchanged since commit `3f03a40` (2022-05-31) and is present in the latest release `v7.14.3`.\n\n### PoC\nPreconditions: a multi-user deployment with distinct per-user `homedir`s (set per-user in `users.json`, or `private_repos =\u003e true` on the WordPress/LDAP adapter). The shipped sample config (`admin`/`guest` both at `/`, `guest` with no perms) does not create this boundary on its own. Attacker is a valid user with `read`, `download`, `batchdownload`.\n\n1. User John (`homedir /john`) creates `secret.txt`, signs in, and creates a batch archive via `POST /batchdownload`. The JSON response returns the archive `uniqid`.\n2. User Jane (`homedir /jane`, with `batchdownload`) signs in normally.\n3. Jane's direct `GET /download` of `/secret.txt` returns `302` — the normal home-directory boundary blocks the file.\n4. Jane sends `GET /batchdownload?uniqid=\u003cJohn's id\u003e` and receives a valid ZIP containing `secret.txt` with John's content.\n\nA PHPUnit proof with two real sessions reproduces this end to end (`OK, 3 tests / 29 assertions`), plus a lifecycle test (`OK, 2 tests / 9 assertions`). Full test files, run logs, and a real Apache access-log replay demo are available on request.\n\nLifetime / acquisition: a normal completed download removes the archive at the end of streaming, limiting the window. An aborted/failed download leaves the archive in tmpfs (cleanup never reached). The frontend issues the download as a top-level navigation (`window.open('.../batchdownload\u0026uniqid='+ret.uniqid, '_blank')`), so the id appears in standard web access logs. That access-log path only adds meaningful impact when log visibility is decoupled from host filesystem access (e.g. a log-aggregation/shared-hosting/downstream-sink reader) and the archive is still alive; if the reader is ops/root on the same host they can already read the storage tree directly. The `uniqid()` token is timestamp-derived (1,000,000-value space per known second) — included to justify a CSPRNG, not presented as a practical universal brute force.\n\n### Impact\nMissing authorization (CWE-862) on a temporary download object, leading to cross-user file disclosure across the per-user home-directory boundary in configured multi-user deployments. Secondary effect: a successful replay deletes the victim's pending archive (the GET removes the tmpfs file after streaming), denying the victim their own download if not yet consumed.\n\nRemediation: generate ids with `bin2hex(random_bytes(32))`; store creator user/session + home dir + expiry per archive id; verify the requester matches before streaming and return `403`/`404` on mismatch or unknown/expired id; delete metadata with the tmpfs file.","status":"published","published":"2026-11-09T22:17:36Z","modified":"2026-11-09T22:30:04.103779163Z","cvss":[{"version":"3.1","score":5.4,"vector":"CVSS:3.1/AV:N/AC:H/PR:L/UI:R/S:U/C:H/I:N/A:L","level":"medium"}],"cwes":["CWE-330","CWE-862"],"updated_at":"2026-11-09T22:41:08.537457Z"}]}}
