From 62fb9199255869941abed70a1e0099af9692ba57 Mon Sep 17 00:00:00 2001
From: Alex Pott <alex.a.pott@googlemail.com>
Date: Tue, 30 Jul 2024 10:26:12 +0100
Subject: [PATCH] Issue #637538 by pooja_sharma, mr.baileys, AaronBauman,
 Bhanu951, alexpott, rteijeiro, greggles, pwolanin, meba, Nikhil_110,
 smustgrave, quietone, casey, naveenvalecha, sime, humansky, dawehner: Module
 and theme names are not filtered on output

(cherry picked from commit 4c82b7eaac3142e3c705bbfa5ebc24f0724f0e78)
---
 .../system/src/Form/ModulesListForm.php       |  6 ++-
 core/modules/system/system.admin.inc          |  4 +-
 .../system/tests/modules/evil/evil.info.yml   |  5 ++
 .../ModuleThemePageXssVulnerabilityTest.php   | 53 +++++++++++++++++++
 .../system/tests/themes/evil/evil.info.yml    |  5 ++
 5 files changed, 70 insertions(+), 3 deletions(-)
 create mode 100644 core/modules/system/tests/modules/evil/evil.info.yml
 create mode 100644 core/modules/system/tests/src/Functional/ModuleThemePageXssVulnerabilityTest.php
 create mode 100644 core/modules/system/tests/themes/evil/evil.info.yml

diff --git a/core/modules/system/src/Form/ModulesListForm.php b/core/modules/system/src/Form/ModulesListForm.php
index 8df4971db032..ec01d8bbeee7 100644
--- a/core/modules/system/src/Form/ModulesListForm.php
+++ b/core/modules/system/src/Form/ModulesListForm.php
@@ -17,10 +17,12 @@
 use Drupal\Core\KeyValueStore\KeyValueStoreExpirableInterface;
 use Drupal\Core\Link;
 use Drupal\Core\Render\Element;
+use Drupal\Core\Render\Markup;
 use Drupal\Core\Session\AccountInterface;
 use Drupal\user\PermissionHandlerInterface;
 use Drupal\Core\Url;
 use Symfony\Component\DependencyInjection\ContainerInterface;
+use Drupal\Component\Utility\Xss;
 
 /**
  * Provides module installation interface.
@@ -207,7 +209,7 @@ public function buildForm(array $form, FormStateInterface $form_state) {
     foreach (Element::children($form['modules']) as $package) {
       $form['modules'][$package] += [
         '#type' => 'details',
-        '#title' => $this->t($package),
+        '#title' => Markup::create(Xss::filterAdmin($this->t($package))),
         '#open' => TRUE,
         '#theme' => 'system_modules_details',
         '#attributes' => ['class' => ['package-listing']],
@@ -272,7 +274,7 @@ protected function buildRow(array $modules, Extension $module, $distribution) {
           ])
         )->toString();
     }
-    $row['description']['#markup'] = $this->t($module->info['description']);
+    $row['description']['#markup'] = (string) $this->t($module->info['description']);
     $row['version']['#markup'] = $module->info['version'];
 
     // Generate link for module's help page. Assume that if a hook_help()
diff --git a/core/modules/system/system.admin.inc b/core/modules/system/system.admin.inc
index bdadaddff9ae..b9fa2f7c32ec 100644
--- a/core/modules/system/system.admin.inc
+++ b/core/modules/system/system.admin.inc
@@ -6,8 +6,10 @@
  */
 
 use Drupal\Component\Utility\Html;
+use Drupal\Component\Utility\Xss;
 use Drupal\Core\Link;
 use Drupal\Core\Render\Element;
+use Drupal\Core\Render\Markup;
 use Drupal\Core\Template\Attribute;
 use Drupal\Core\Url;
 
@@ -296,7 +298,7 @@ function template_preprocess_system_themes_page(&$variables) {
       }
 
       // Localize the theme description.
-      $current_theme['description'] = t($theme->info['description']);
+      $current_theme['description'] = Markup::create(Xss::filterAdmin(t($theme->info['description'])));
 
       $current_theme['attributes'] = new Attribute();
       $current_theme['name'] = $theme->info['name'];
diff --git a/core/modules/system/tests/modules/evil/evil.info.yml b/core/modules/system/tests/modules/evil/evil.info.yml
new file mode 100644
index 000000000000..f7b8df749f1f
--- /dev/null
+++ b/core/modules/system/tests/modules/evil/evil.info.yml
@@ -0,0 +1,5 @@
+name: <script>alert('Evil module name');</script>
+type: module
+description: <script>alert('Evil module desc');</script>
+package: Testing
+version: VERSION
diff --git a/core/modules/system/tests/src/Functional/ModuleThemePageXssVulnerabilityTest.php b/core/modules/system/tests/src/Functional/ModuleThemePageXssVulnerabilityTest.php
new file mode 100644
index 000000000000..c9af3437e201
--- /dev/null
+++ b/core/modules/system/tests/src/Functional/ModuleThemePageXssVulnerabilityTest.php
@@ -0,0 +1,53 @@
+<?php
+
+declare(strict_types=1);
+
+namespace Drupal\Tests\system\Functional;
+
+use Drupal\Tests\BrowserTestBase;
+
+/**
+ * Tests module and theme pages do not have XSS vulnerabilities.
+ *
+ * @group system
+ */
+class ModuleThemePageXssVulnerabilityTest extends BrowserTestBase {
+
+  /**
+   * {@inheritdoc}
+   */
+  protected static $modules = ['system'];
+
+  /**
+   * {@inheritdoc}
+   */
+  protected $defaultTheme = 'stark';
+
+  /**
+   * {@inheritdoc}
+   */
+  protected function setUp(): void {
+    parent::setUp();
+
+    $admin = $this->drupalCreateUser([
+      'administer modules',
+      'administer themes',
+    ]);
+    $this->drupalLogin($admin);
+  }
+
+  /**
+   * Tests extension info cannot create XSS vulnerabilities.
+   */
+  public function testExtensionInfoXss(): void {
+    $this->drupalGet("admin/modules");
+    $this->assertSession()->pageTextContains("alert('Evil module name');");
+    $this->assertSession()->pageTextContains("alert('Evil module desc');");
+    $this->assertSession()->responseNotContains("<script>alert(");
+    $this->drupalGet("admin/appearance");
+    $this->assertSession()->pageTextContains("alert('Evil theme name');");
+    $this->assertSession()->pageTextContains("alert('Evil theme desc');");
+    $this->assertSession()->responseNotContains("<script>alert(");
+  }
+
+}
diff --git a/core/modules/system/tests/themes/evil/evil.info.yml b/core/modules/system/tests/themes/evil/evil.info.yml
new file mode 100644
index 000000000000..32b3196fe05f
--- /dev/null
+++ b/core/modules/system/tests/themes/evil/evil.info.yml
@@ -0,0 +1,5 @@
+name: <script>alert('Evil theme name');</script>
+type: theme
+description: <script>alert('Evil theme desc');</script>
+version: VERSION
+base theme: false
-- 
GitLab