Phoca Download 6.1.3/6.1.4 — large ZIP uploads always rejected by content scan (false positive) + uncaught FilesystemExc
Posted: 14 Aug 2026, 14:53
Hello Jan,
First of all, thank you for the quick security work in 6.1.3/6.1.4 around the authenticated upload RCE. I'd like to report a serious false-positive side effect of that fix, still present in 6.1.4, that effectively breaks uploading of large binary files (ZIPs) from the admin file manager.
Environment: Joomla 6.1.2, PHP 8.4.14 (php-fpm), Phoca Download 6.1.3 (verified against the 6.1.4 source on GitHub — the relevant code is unchanged), multiple upload (HTML5), backend.
Symptom: Uploading a ~59 MB ZIP via Multiple Upload always fails. Small ZIPs work, so it looks like a size limit, but PHP limits are not involved (the file arrives intact in $_FILES with error=0; limits are 128M).
Root cause: In 6.1.3 the File::upload() calls in admin/libraries/phocadownload/file/fileupload.php dropped the 4th argument $allowUnsafe = true. With the scan active, Joomla's File::isSafeFile() applies the fobidden_ext_in_content rule to archives (zip is in php_ext_content_extensions): it searches the raw compressed bytes for every FORBIDDEN_FILE_EXTENSIONS entry as a plain substring — including 2-letter extensions like pl and py. In a large compressed archive the 3-byte patterns .pl/.py occur by pure chance (~3–4 expected hits each per 59 MB), so any large ZIP is rejected with near-certainty. I confirmed by bisection: 59 MiB of zeros uploads fine; 59 MiB of random data or any real large ZIP always fails; a tiny ZIP passes.
Secondary bug: the code checks if (!File::upload(...)), but Joomla\Filesystem\File::upload() does not return false on a failed security check — it throws FilesystemException ("File not uploaded for security reasons!"). The exception is never caught, so the user gets an HTTP 500 Joomla error page and the upload queue shows a generic, misleading message instead of the component's JSON error.
Suggestion: now that 6.1.4 hardens upload folders against script execution (hardenFolder writing .htaccess/web.config), the content scan could be relaxed for authenticated backend uploads — either restore $allowUnsafe = true there, or pass $safeFileOptions with 'fobidden_ext_in_content' => false (keeping the <?php and phar-stub checks, which have a negligible false-positive rate). Independently, wrapping the File::upload() calls in try/catch would let failures surface as a proper jsonrpc error with a meaningful message.
First of all, thank you for the quick security work in 6.1.3/6.1.4 around the authenticated upload RCE. I'd like to report a serious false-positive side effect of that fix, still present in 6.1.4, that effectively breaks uploading of large binary files (ZIPs) from the admin file manager.
Environment: Joomla 6.1.2, PHP 8.4.14 (php-fpm), Phoca Download 6.1.3 (verified against the 6.1.4 source on GitHub — the relevant code is unchanged), multiple upload (HTML5), backend.
Symptom: Uploading a ~59 MB ZIP via Multiple Upload always fails. Small ZIPs work, so it looks like a size limit, but PHP limits are not involved (the file arrives intact in $_FILES with error=0; limits are 128M).
Root cause: In 6.1.3 the File::upload() calls in admin/libraries/phocadownload/file/fileupload.php dropped the 4th argument $allowUnsafe = true. With the scan active, Joomla's File::isSafeFile() applies the fobidden_ext_in_content rule to archives (zip is in php_ext_content_extensions): it searches the raw compressed bytes for every FORBIDDEN_FILE_EXTENSIONS entry as a plain substring — including 2-letter extensions like pl and py. In a large compressed archive the 3-byte patterns .pl/.py occur by pure chance (~3–4 expected hits each per 59 MB), so any large ZIP is rejected with near-certainty. I confirmed by bisection: 59 MiB of zeros uploads fine; 59 MiB of random data or any real large ZIP always fails; a tiny ZIP passes.
Secondary bug: the code checks if (!File::upload(...)), but Joomla\Filesystem\File::upload() does not return false on a failed security check — it throws FilesystemException ("File not uploaded for security reasons!"). The exception is never caught, so the user gets an HTTP 500 Joomla error page and the upload queue shows a generic, misleading message instead of the component's JSON error.
Suggestion: now that 6.1.4 hardens upload folders against script execution (hardenFolder writing .htaccess/web.config), the content scan could be relaxed for authenticated backend uploads — either restore $allowUnsafe = true there, or pass $safeFileOptions with 'fobidden_ext_in_content' => false (keeping the <?php and phar-stub checks, which have a negligible false-positive rate). Independently, wrapping the File::upload() calls in try/catch would let failures surface as a proper jsonrpc error with a meaningful message.