diff --git a/core/modules/system/src/Form/ModulesListForm.php b/core/modules/system/src/Form/ModulesListForm.php index 8df4971db03206ce97cb4ff250381fd0483bf775..ec01d8bbeee71c8a3040f0c77610761a4b95f38e 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 bdadaddff9ae491e0867088940bc4e6085fe199c..b9fa2f7c32ecf97d3dafdbe5f6cdcb9b1a61cd62 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 0000000000000000000000000000000000000000..f7b8df749f1ffd379f50368bc8a9aea1a3fb1551 --- /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 0000000000000000000000000000000000000000..c9af3437e2016549a66da28bbd76f55b2a1afeb7 --- /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 0000000000000000000000000000000000000000..32b3196fe05fb143d8c4641d254444dc03160802 --- /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