CVE-2021-41750: Improper Neutralization of Input During Web Page Generation ('Cross-site Scripting') (CWE-79)
value: A cross-site scripting (XSS) vulnerability in the SEOmatic plugin 3.4.10 for Craft CMS 3 allows remote attackers to inject arbitrary web script via a GET to /index.php?action=seomatic/file/seo-file-link with url parameter containing the base64 encoded URL of a malicious web page / file and fileName parameter containing an arbitrary filename with the intended content-type to be rendered in the user's browser as the extension.
CWE description: The product does not neutralize or incorrectly neutralizes user-controllable input before it is placed in output that is used as a web page that is served to other users.
CVSS v3 base score: 6.1
Published: 2022-06-12T12:15Z
Repository: https://github.com/nystudio107/craft-seomatic
Language: PHP
Files changed: src/controllers/FileController.php
Commit date: 2021-09-23 21:25:40 -0400
Commit message: Ensure that only files with the extensions listed in `allowedFileExtensions` General Config setting can be used with the SEO File Link controller

Signed-off-by: Andrew Welch <andrew@nystudio107.com>

Diff: diff --git a/src/controllers/FileController.php b/src/controllers/FileController.php
index 1e1f1b1d2..33d7f0582 100644
--- a/src/controllers/FileController.php
+++ b/src/controllers/FileController.php
@@ -13,16 +13,19 @@ namespace nystudio107\seomatic\controllers;
 
 use nystudio107\seomatic\helpers\UrlHelper;
 use nystudio107\seomatic\Seomatic;
 
 use Craft;
+use craft\elements\Asset;
 use craft\helpers\FileHelper;
+use craft\helpers\Assets as AssetsHelper;
 use craft\web\Controller;
 
 use yii\web\NotFoundHttpException;
 use yii\web\HttpException;
 use yii\web\Response;
+use yii\web\ServerErrorHttpException;
 
 /**
  * @author    nystudio107
  * @package   Seomatic
  * @since     3.0.0
@@ -85,10 +88,19 @@ class FileController extends Controller
             // Add the Link header
             if (!empty($canonical)) {
                 $headerValue = '<'.$canonical.'>; rel="canonical"';
                 $response->headers->add('Link', $headerValue);
             }
+            // Ensure the file type is allowed
+            // ref: https://craftcms.com/docs/3.x/config/config-settings.html#allowedfileextensions
+            $allowedExtensions = Craft::$app->getConfig()->getGeneral()->allowedFileExtensions;
+            if (($ext = pathinfo($fileName, PATHINFO_EXTENSION)) !== '') {
+                $ext = strtolower($ext);
+            }
+            if ($ext === '' || !in_array($ext, $allowedExtensions, true)) {
+                throw new ServerErrorHttpException(Craft::t('seomatic', 'File format not allowed.'));
+            }
             // Send the file as a stream, so it can exist anywhere
             $response->sendContentAsFile(
                 $contents,
                 $fileName,
                 [

Fixed code: use craft\elements\Asset;
use craft\helpers\Assets as AssetsHelper;
use yii\web\ServerErrorHttpException;
            // Ensure the file type is allowed
            // ref: https://craftcms.com/docs/3.x/config/config-settings.html#allowedfileextensions
            $allowedExtensions = Craft::$app->getConfig()->getGeneral()->allowedFileExtensions;
            if (($ext = pathinfo($fileName, PATHINFO_EXTENSION)) !== '') {
                $ext = strtolower($ext);
            }
            if ($ext === '' || !in_array($ext, $allowedExtensions, true)) {
                throw new ServerErrorHttpException(Craft::t('seomatic', 'File format not allowed.'));
            }