CVE-2023-31144: Improper Neutralization of Input During Web Page Generation ('Cross-site Scripting') (CWE-79)
value: Craft CMS is a content management system. Starting in version 3.0.0 and prior to versions 3.8.4 and 4.4.4, a malformed title in the feed widget can deliver a cross-site scripting payload. This issue is fixed in version 3.8.4 and 4.4.4.
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: 2023-05-09T16:15Z
Repository: https://github.com/craftcms/cms
Language: PHP
Files changed: CHANGELOG.md, src/fields/Table.php, src/web/assets/cp/CpAsset.php
Commit date: 2023-03-17 15:34:58 -0700
Commit message: Merge branch 'v3' of https://github.com/craftcms/cms into develop

# Conflicts:
#	src/fields/Table.php

Diff: diff --cc CHANGELOG.md
index 7e1f6899835,fcc138fd1ad..35a3676db78
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@@ -1,22 -1,17 +1,24 @@@
 -# Release Notes for Craft CMS 3.x
 +# Release Notes for Craft CMS 4
  
  ## Unreleased
  
 +- Input autofocussing has been reintroduced thorughout the control panel. ([#12921](https://github.com/craftcms/cms/discussions/12921))
  - The `|json_encode` Twig filter now calls `craft\helpers\Json::encode()` internally, improving error handling. ([#12919](https://github.com/craftcms/cms/issues/12919))
+ - `craft\helpers\Json::encode()` no longer sets the `JSON_UNESCAPED_SLASHES` flag by default.
  - Fixed a JavaScript error that occurred when resolving an asset move conflict. ([#12920](https://github.com/craftcms/cms/issues/12920))
 +- Fixed an error that could occur when rebuilding the project config, if there were any custom source definitions for element types that weren’t Composer-installed. ([#12881](https://github.com/craftcms/cms/issues/12881))
++- Fixed an XSS vulnerability.
  
 -## 3.8.3 - 2023-03-16
 +## 4.4.3 - 2023-03-16
  
  - Customize Sources modals no longer hide when the <kbd>Esc</kbd> key is pressed on the surrounding area is clicked on. ([#12895](https://github.com/craftcms/cms/issues/12895))
 +- Sections created via `entrify` commands no longer get a “Primary entry page” preview target by default, unless it was sourced from a category group with URLs. ([#12897](https://github.com/craftcms/cms/issues/12897))
 +- `entrify` commands and the `sections/create` command now prompt for the initial entry type name and handle. ([#12894](https://github.com/craftcms/cms/discussions/12894))
  - Added `craft\helpers\FileHelper::uniqueName()`.
 +- Added `craft\helpers\StringHelper::emojiToShortcodes()`.
 +- Added `craft\helpers\StringHelper::shortcodesToEmoji()`.
  - Fixed an error that occurred when uploading an asset with a filename over 250 characters long. ([#12889](https://github.com/craftcms/cms/issues/12889))
  - Fixed an error that could occur when preparing licensing alerts, if any licenses were invalid. ([#12899](https://github.com/craftcms/cms/issues/12899))
  - Fixed a bug where it wasn’t possible to drag nested Neo blocks. ([#12896](https://github.com/craftcms/cms/issues/12896))
  - Fixed a bug where fields with reduced widths in Matrix blocks were becoming full-width while dragged. ([#12909](https://github.com/craftcms/cms/issues/12909))
  - Fixed a bug where multi-edition plugins weren’t showing their edition labels within the Plugin Store cart. ([#12910](https://github.com/craftcms/cms/issues/12910))
diff --cc src/fields/Table.php
index f783d45c139,3c421f1b5b8..bf307750fab
--- a/src/fields/Table.php
+++ b/src/fields/Table.php
@@@ -308,20 -291,20 +308,20 @@@ class Table extends Fiel
          $view = Craft::$app->getView();
  
          $view->registerAssetBundle(TimepickerAsset::class);
          $view->registerAssetBundle(TableSettingsAsset::class);
          $view->registerJs('new Craft.TableFieldSettings(' .
-             Json::encode($view->namespaceInputName('columns'), JSON_UNESCAPED_UNICODE) . ', ' .
-             Json::encode($view->namespaceInputName('defaults'), JSON_UNESCAPED_UNICODE) . ', ' .
-             Json::encode($this->columns, JSON_UNESCAPED_UNICODE) . ', ' .
-             Json::encode($this->defaults ?? [], JSON_UNESCAPED_UNICODE) . ', ' .
-             Json::encode($columnSettings, JSON_UNESCAPED_UNICODE) . ', ' .
-             Json::encode($dropdownSettingsHtml, JSON_UNESCAPED_UNICODE) . ', ' .
-             Json::encode($dropdownSettingsCols, JSON_UNESCAPED_UNICODE) .
+             Json::encode($view->namespaceInputName('columns')) . ', ' .
+             Json::encode($view->namespaceInputName('defaults')) . ', ' .
+             Json::encode($this->columns) . ', ' .
 -            Json::encode($this->defaults) . ', ' .
++            Json::encode($this->defaults ?? []) . ', ' .
+             Json::encode($columnSettings) . ', ' .
+             Json::encode($dropdownSettingsHtml) . ', ' .
+             Json::encode($dropdownSettingsCols) .
              ');');
  
 -        $columnsField = $view->renderTemplate('_components/fieldtypes/Table/columntable', [
 +        $columnsField = $view->renderTemplate('_components/fieldtypes/Table/columntable.twig', [
              'cols' => $columnSettings,
              'rows' => $this->columns,
              'errors' => $this->getErrors('columns'),
          ]);
  
diff --cc src/web/assets/cp/CpAsset.php
index 1dc2ad422f6,605ccdd92e7..01354db1d24
--- a/src/web/assets/cp/CpAsset.php
+++ b/src/web/assets/cp/CpAsset.php
@@@ -99,21 -94,18 +99,21 @@@ class CpAsset extends AssetBundl
          if ($view instanceof View) {
              $this->_registerTranslations($view);
          }
  
          // Define the Craft object
-         $craftJson = Json::encode($this->_craftData(), JSON_UNESCAPED_UNICODE);
+         $craftJson = Json::encode($this->_craftData());
          $js = <<<JS
 -window.Craft = {$craftJson};
 +window.Craft = $craftJson;
  JS;
          $view->registerJs($js, View::POS_HEAD);
      }
  
 -    private function _registerTranslations(View $view)
 +    /**
 +     * @param View $view
 +     */
 +    private function _registerTranslations(View $view): void
      {
          $view->registerTranslations('app', [
              '(blank)',
              '<span class="visually-hidden">Characters left:</span> {chars, number}',
              'A server error occurred.',

Vulnerable code:              Json::encode($view->namespaceInputName('columns'), JSON_UNESCAPED_UNICODE) . ', ' .
             Json::encode($view->namespaceInputName('defaults'), JSON_UNESCAPED_UNICODE) . ', ' .
             Json::encode($this->columns, JSON_UNESCAPED_UNICODE) . ', ' .
             Json::encode($this->defaults ?? [], JSON_UNESCAPED_UNICODE) . ', ' .
             Json::encode($columnSettings, JSON_UNESCAPED_UNICODE) . ', ' .
             Json::encode($dropdownSettingsHtml, JSON_UNESCAPED_UNICODE) . ', ' .
             Json::encode($dropdownSettingsCols, JSON_UNESCAPED_UNICODE) .
         $craftJson = Json::encode($this->_craftData(), JSON_UNESCAPED_UNICODE);
Fixed code:  - `craft\helpers\Json::encode()` no longer sets the `JSON_UNESCAPED_SLASHES` flag by default.
+- Fixed an XSS vulnerability.
             Json::encode($view->namespaceInputName('columns')) . ', ' .
             Json::encode($view->namespaceInputName('defaults')) . ', ' .
             Json::encode($this->columns) . ', ' .
+            Json::encode($this->defaults ?? []) . ', ' .
             Json::encode($columnSettings) . ', ' .
             Json::encode($dropdownSettingsHtml) . ', ' .
             Json::encode($dropdownSettingsCols) .
         $craftJson = Json::encode($this->_craftData());