aboutsummaryrefslogtreecommitdiff
path: root/app
diff options
context:
space:
mode:
authorGravatar Alexandre Alapetite <alexandre@alapetite.fr> 2025-04-07 08:47:42 +0200
committerGravatar GitHub <noreply@github.com> 2025-04-07 08:47:42 +0200
commit0c33d2713957eaf6cc0222150df7ebbcb53beaed (patch)
treea9a011c370e2d8ecf3c3290dfb1afd86c9cea0bc /app
parentd3d9acca9f905fc03d6151f6ad75567256310831 (diff)
Secure serving of user files from extensions (#7495)
* Secure serving of user files from extensions fix https://github.com/FreshRSS/FreshRSS/issues/4930 * More fixes * Typo
Diffstat (limited to 'app')
-rw-r--r--app/Controllers/extensionController.php36
-rw-r--r--app/views/extension/serve.phtml0
2 files changed, 36 insertions, 0 deletions
diff --git a/app/Controllers/extensionController.php b/app/Controllers/extensionController.php
index f08013e7d..5afa43bd8 100644
--- a/app/Controllers/extensionController.php
+++ b/app/Controllers/extensionController.php
@@ -298,4 +298,40 @@ class FreshRSS_extension_Controller extends FreshRSS_ActionController {
Minz_Request::forward($url_redirect, true);
}
+
+ // Supported types with their associated content type
+ public const MIME_TYPES = [
+ 'css' => 'text/css; charset=UTF-8',
+ 'gif' => 'image/gif',
+ 'jpeg' => 'image/jpeg',
+ 'jpg' => 'image/jpeg',
+ 'js' => 'application/javascript; charset=UTF-8',
+ 'png' => 'image/png',
+ 'svg' => 'image/svg+xml',
+ ];
+
+ public function serveAction(): void {
+ $extensionName = Minz_Request::paramString('x');
+ $filename = Minz_Request::paramString('f');
+ $mimeType = pathinfo($filename, PATHINFO_EXTENSION);
+ if ($extensionName === '' || $filename === '' || $mimeType === '' || empty(self::MIME_TYPES[$mimeType])) {
+ header('HTTP/1.1 400 Bad Request');
+ die('Bad Request!');
+ }
+ $extension = Minz_ExtensionManager::findExtension($extensionName);
+ if ($extension === null || !$extension->isEnabled() || ($mtime = $extension->mtimeFile($filename)) === null) {
+ header('HTTP/1.1 404 Not Found');
+ die('Not Found!');
+ }
+
+ $this->view->_layout(null);
+
+ $content_type = self::MIME_TYPES[$mimeType];
+ header("Content-Type: {$content_type}");
+ header("Content-Disposition: inline; filename='{$filename}'");
+ header('Referrer-Policy: same-origin');
+ if (!httpConditional($mtime, cacheSeconds: 604800, cachePrivacy: 2)) {
+ echo $extension->getFile($filename);
+ }
+ }
}
diff --git a/app/views/extension/serve.phtml b/app/views/extension/serve.phtml
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/app/views/extension/serve.phtml