{"id":"CVE-2026-94618","aliases":["GHSA-f74m-x83r-c4v4"],"title":"FileGator: Missing authorization in GET /batchdownload allows cross-user retrieval of another user's archive","titleSource":"OSV","descriptionSource":"OSV","declaredSeverity":"MODERATE","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 => 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=<John's id>` 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&uniqid='+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.","severity":"medium","score":5.4,"published":"2026-11-06T21:30:39.923Z","modified":"2026-11-10T20:19:21.659Z","withdrawn":false,"knownExploited":false,"affected":[{"ecosystem":"Packagist","name":"filegator/filegator","sources":[{"name":"OSV · GHSA-f74m-x83r-c4v4","url":"https://osv.dev/vulnerability/GHSA-f74m-x83r-c4v4"}],"ranges":[{"events":[{"introduced":"0"},{"fixed":"7.15.0"}],"type":"ECOSYSTEM"}],"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"],"fixed":["7.15.0"]}],"sourceAffected":[],"references":["https://github.com/filegator/filegator/security/advisories/GHSA-f74m-x83r-c4v4","https://nvd.nist.gov/vuln/detail/CVE-2026-94618","https://github.com/filegator/filegator/pull/597","https://github.com/filegator/filegator/commit/638737e560cbf20cbeb5da4e4e6c974f8a080531","https://github.com/filegator/filegator","https://github.com/filegator/filegator/releases/tag/v7.15.0"],"sources":[{"name":"OSV","id":"GHSA-f74m-x83r-c4v4","modified":"2026-11-09T22:30:04.103779163Z","url":"https://osv.dev/vulnerability/GHSA-f74m-x83r-c4v4"},{"name":"CVE","id":"CVE-2026-94618","modified":"2026-11-10T20:19:21.659Z","url":"https://www.cve.org/CVERecord?id=CVE-2026-94618"}],"assessments":[{"source":"OSV","vector":"CVSS:3.1/AV:N/AC:H/PR:L/UI:R/S:U/C:H/I:N/A:L","score":5.4},{"source":"GitHub_M","vector":"CVSS:3.1/AV:N/AC:H/PR:L/UI:R/S:U/C:H/I:N/A:L","score":5.4}],"cve":{"records":[{"id":"CVE-2026-94618","source":"GitHub_M","state":"PUBLISHED","reasons":[],"replacements":[],"disputed":false,"unsupportedWhenAssigned":false,"reserved":"2026-09-21T21:32:23.742Z","published":"2026-11-06T21:30:39.923Z","modified":"2026-11-10T20:19:21.659Z"}],"publishers":[{"name":"GitHub_M","role":"CNA","organizationId":"a0819718-46f1-4df5-94e2-005712e83aaa","modified":"2026-11-06T21:30:39.923Z"},{"name":"CISA-ADP","role":"ADP","organizationId":"134c704f-9b21-4f2e-91b3-4a467353bcc0","modified":"2026-11-10T20:19:21.659Z"}],"references":[{"url":"https://github.com/filegator/filegator/security/advisories/GHSA-f74m-x83r-c4v4","tags":["x_refsource_CONFIRM"],"source":"GitHub_M"},{"url":"https://github.com/filegator/filegator/pull/597","tags":["x_refsource_MISC"],"source":"GitHub_M"},{"url":"https://github.com/filegator/filegator/commit/638737e560cbf20cbeb5da4e4e6c974f8a080531","tags":["x_refsource_MISC"],"source":"GitHub_M"},{"url":"https://github.com/filegator/filegator/releases/tag/v7.15.0","tags":["x_refsource_MISC"],"source":"GitHub_M"},{"url":"https://github.com/filegator/filegator/security/advisories/GHSA-f74m-x83r-c4v4","tags":["exploit"],"source":"CISA-ADP"}],"weaknesses":[{"id":"CWE-330","description":"CWE-330: Use of Insufficiently Random Values","source":"GitHub_M"},{"id":"CWE-862","description":"CWE-862: Missing Authorization","source":"GitHub_M"}],"applicability":[],"prioritization":[{"source":"CISA-ADP","type":"SSVC","role":"CISA Coordinator","timestamp":"2026-11-10T20:18:24.532439Z","decisions":[{"name":"Exploitation","value":"poc"},{"name":"Automatable","value":"no"},{"name":"Technical Impact","value":"partial"}]}]},"products":[{"vendor":"filegator","name":"filegator","platforms":[],"versions":[{"version":"< 7.15.0","status":"affected"}],"cpes":[],"source":"GitHub_M","url":"https://www.cve.org/CVERecord?id=CVE-2026-94618"}],"remediation":[],"observedAt":"2026-11-10T22:59:57.514Z","kev":{"status":"not-listed","checkedAt":"2026-11-15T03:10:34.932Z"},"coverage":[{"source":"NVD","status":"available","checkedAt":"2026-11-06T22:35:36.087Z","attemptedAt":"2026-11-06T22:35:36.087Z"},{"source":"GHSA","status":"no-result","checkedAt":"2026-11-06T22:35:36.086Z","attemptedAt":"2026-11-06T22:35:36.086Z"},{"source":"EUVD","status":"available","checkedAt":"2026-11-06T22:35:36.974Z","attemptedAt":"2026-11-06T22:35:36.974Z"},{"source":"EPSS","status":"no-result","checkedAt":"2026-11-06T22:35:36.089Z","attemptedAt":"2026-11-06T22:35:36.089Z"}],"evidence":[{"source":"NVD","id":"CVE-2026-94618","url":"https://nvd.nist.gov/vuln/detail/CVE-2026-94618","modified":"2026-11-06T22:18:00.133","score":5.4,"vector":"CVSS:3.1/AV:N/AC:H/PR:L/UI:R/S:U/C:H/I:N/A:L","checkedAt":"2026-11-06T22:35:36.087Z"},{"source":"ENISA EUVD","id":"EUVD-2026-118519","url":"https://euvd.enisa.europa.eu/vulnerability/EUVD-2026-118519","modified":"Nov 6, 2026, 9:30:39 PM","score":5.4,"vector":"CVSS:3.1/AV:N/AC:H/PR:L/UI:R/S:U/C:H/I:N/A:L","checkedAt":"2026-11-06T22:35:36.974Z"}],"aiSummary":{"text":"FileGator versions before 7.15.0 have a missing authorization vulnerability in the GET /batchdownload endpoint, allowing a low-privileged user to download another user's batch archive. The attacker must have a valid session and the uniqid of the target archive. This vulnerability can disclose files across the per-user home-directory boundary in multi-user deployments.","model":"@cf/meta/llama-3.3-70b-instruct-fp8-fast","generatedAt":"2026-11-12T10:41:06.160Z","sources":[{"name":"OSV","url":"https://osv.dev/vulnerability/GHSA-f74m-x83r-c4v4"},{"name":"CVE","url":"https://www.cve.org/CVERecord?id=CVE-2026-94618"}]}}