diff --git a/core/includes/theme.inc b/core/includes/theme.inc
index 6f05be09ada3c0f1a66445313fc87317c4925968..329ff58c626d5fbe663e419131064941de1135ce 100644
--- a/core/includes/theme.inc
+++ b/core/includes/theme.inc
@@ -20,7 +20,6 @@
 use Drupal\Core\Theme\ThemeSettings;
 use Drupal\Component\Utility\NestedArray;
 use Drupal\Core\Render\Element;
-use Drupal\Core\Render\SafeString;
 
 /**
  * @defgroup content_flags Content markers
@@ -1242,8 +1241,7 @@ function template_preprocess_html(&$variables) {
   }
   if (!empty($variables['page']['#title'])) {
     $head_title = array(
-      // Marking the title as safe since it has had the tags stripped.
-      'title' => SafeString::create(trim(strip_tags($variables['page']['#title']))),
+      'title' => trim(strip_tags($variables['page']['#title'])),
       'name' => $site_config->get('name'),
     );
   }
diff --git a/core/lib/Drupal/Core/Field/Plugin/Field/FieldFormatter/BasicStringFormatter.php b/core/lib/Drupal/Core/Field/Plugin/Field/FieldFormatter/BasicStringFormatter.php
index 9d2b7306fc3e83d012cf3db4b8406c437e5274cf..c03b96d2018253711c8460594a9fceb73c706506 100644
--- a/core/lib/Drupal/Core/Field/Plugin/Field/FieldFormatter/BasicStringFormatter.php
+++ b/core/lib/Drupal/Core/Field/Plugin/Field/FieldFormatter/BasicStringFormatter.php
@@ -7,7 +7,7 @@
 
 namespace Drupal\Core\Field\Plugin\Field\FieldFormatter;
 
-use Drupal\Component\Utility\Html;
+use Drupal\Component\Utility\SafeMarkup;
 use Drupal\Core\Field\FormatterBase;
 use Drupal\Core\Field\FieldItemListInterface;
 
@@ -37,7 +37,7 @@ public function viewElements(FieldItemListInterface $items) {
     foreach ($items as $delta => $item) {
       // The text value has no text format assigned to it, so the user input
       // should equal the output, including newlines.
-      $elements[$delta] = array('#markup' => nl2br(Html::escape($item->value)));
+      $elements[$delta] = array('#markup' => nl2br(SafeMarkup::checkPlain($item->value)));
     }
 
     return $elements;
diff --git a/core/lib/Drupal/Core/Field/Plugin/Field/FieldFormatter/LanguageFormatter.php b/core/lib/Drupal/Core/Field/Plugin/Field/FieldFormatter/LanguageFormatter.php
index e4b41b82b8866a31c05cc608f84fe45797041cb1..dea2989ad8b5c3641a200fc2fe13f294b7ee3690 100644
--- a/core/lib/Drupal/Core/Field/Plugin/Field/FieldFormatter/LanguageFormatter.php
+++ b/core/lib/Drupal/Core/Field/Plugin/Field/FieldFormatter/LanguageFormatter.php
@@ -7,6 +7,7 @@
 
 namespace Drupal\Core\Field\Plugin\Field\FieldFormatter;
 
+use Drupal\Component\Utility\SafeMarkup;
 use Drupal\Core\Entity\EntityManagerInterface;
 use Drupal\Core\Field\FieldDefinitionInterface;
 use Drupal\Core\Field\FieldItemInterface;
@@ -122,9 +123,7 @@ protected function viewValue(FieldItemInterface $item) {
     // storage by LanguageManager::getLanguages()) or in its native language
     // name. That only depends on formatter settings and no language condition.
     $languages = $this->getSetting('native_language') ? $this->languageManager->getNativeLanguages(LanguageInterface::STATE_ALL) : $this->languageManager->getLanguages(LanguageInterface::STATE_ALL);
-    return [
-      '#plain_text' => $item->language && isset($languages[$item->language->getId()]) ? $languages[$item->language->getId()]->getName() : ''
-    ];
+    return $item->language && isset($languages[$item->language->getId()]) ? SafeMarkup::checkPlain($languages[$item->language->getId()]->getName()) : '';
   }
 
 }
diff --git a/core/lib/Drupal/Core/Field/Plugin/Field/FieldFormatter/StringFormatter.php b/core/lib/Drupal/Core/Field/Plugin/Field/FieldFormatter/StringFormatter.php
index fd5c3bbb5027cc8f9aabc075a101b7bff31aeec2..6276f9538c3ebadf19a67ebb579c2929c949f5c7 100644
--- a/core/lib/Drupal/Core/Field/Plugin/Field/FieldFormatter/StringFormatter.php
+++ b/core/lib/Drupal/Core/Field/Plugin/Field/FieldFormatter/StringFormatter.php
@@ -7,7 +7,7 @@
 
 namespace Drupal\Core\Field\Plugin\Field\FieldFormatter;
 
-use Drupal\Component\Utility\Html;
+use Drupal\Component\Utility\SafeMarkup;
 use Drupal\Core\Entity\EntityManagerInterface;
 use Drupal\Core\Entity\RevisionableInterface;
 use Drupal\Core\Field\FieldDefinitionInterface;
@@ -128,16 +128,16 @@ public function viewElements(FieldItemListInterface $items) {
     }
 
     foreach ($items as $delta => $item) {
-      $view_value = $this->viewValue($item);
+      $string = $this->viewValue($item);
       if ($url) {
         $elements[$delta] = [
           '#type' => 'link',
-          '#title' => $view_value,
+          '#title' => $string,
           '#url' => $url,
         ];
       }
       else {
-        $elements[$delta] = is_array($view_value) ? $view_value : ['#markup' => $view_value];
+        $elements[$delta] = ['#markup' => $string];
       }
     }
     return $elements;
@@ -149,15 +149,13 @@ public function viewElements(FieldItemListInterface $items) {
    * @param \Drupal\Core\Field\FieldItemInterface $item
    *   One field item.
    *
-   * @return array
-   *   The textual output generated as a render array.
+   * @return string
+   *   The textual output generated.
    */
   protected function viewValue(FieldItemInterface $item) {
     // The text value has no text format assigned to it, so the user input
     // should equal the output, including newlines.
-    return [
-      '#markup' => nl2br(Html::escape($item->value))
-    ];
+    return nl2br(SafeMarkup::checkPlain($item->value));
   }
 
 }
diff --git a/core/lib/Drupal/Core/Field/WidgetBase.php b/core/lib/Drupal/Core/Field/WidgetBase.php
index 575daf925308cb72d29a26cd2b0d92bcacada3e1..0103071cd3113ae4ca648add6ec56b0b1e33a357 100644
--- a/core/lib/Drupal/Core/Field/WidgetBase.php
+++ b/core/lib/Drupal/Core/Field/WidgetBase.php
@@ -10,6 +10,7 @@
 use Drupal\Component\Utility\Html;
 use Drupal\Component\Utility\NestedArray;
 use Drupal\Component\Utility\SortArray;
+use Drupal\Component\Utility\SafeMarkup;
 use Drupal\Core\Form\FormStateInterface;
 use Drupal\Core\Render\Element;
 use Symfony\Component\Validator\ConstraintViolationInterface;
@@ -84,7 +85,7 @@ public function form(FieldItemListInterface $items, array &$form, FormStateInter
     if ($this->handlesMultipleValues() || isset($get_delta)) {
       $delta = isset($get_delta) ? $get_delta : 0;
       $element = array(
-        '#title' => $this->fieldDefinition->getLabel(),
+        '#title' => SafeMarkup::checkPlain($this->fieldDefinition->getLabel()),
         '#description' => FieldFilteredString::create(\Drupal::token()->replace($this->fieldDefinition->getDescription())),
       );
       $element = $this->formSingleElement($items, $delta, $element, $form, $form_state);
@@ -163,7 +164,7 @@ protected function formMultipleElements(FieldItemListInterface $items, array &$f
         break;
     }
 
-    $title = $this->fieldDefinition->getLabel();
+    $title = SafeMarkup::checkPlain($this->fieldDefinition->getLabel());
     $description = FieldFilteredString::create(\Drupal::token()->replace($this->fieldDefinition->getDescription()));
 
     $elements = array();
@@ -178,7 +179,7 @@ protected function formMultipleElements(FieldItemListInterface $items, array &$f
       // table.
       if ($is_multiple) {
         $element = [
-          '#title' => $this->t('@title (value @number)', ['@title' => $title, '@number' => $delta + 1]),
+          '#title' => $title . ' ' . $this->t('(value @number)', ['@number' => $delta + 1]),
           '#title_display' => 'invisible',
           '#description' => '',
         ];
diff --git a/core/modules/block/src/BlockViewBuilder.php b/core/modules/block/src/BlockViewBuilder.php
index 9a582352343ef6f179adc3229fcd3d395b2e2857..6e99faae00de324a85670de6065220cd6c56a0ea 100644
--- a/core/modules/block/src/BlockViewBuilder.php
+++ b/core/modules/block/src/BlockViewBuilder.php
@@ -7,6 +7,7 @@
 
 namespace Drupal\block;
 
+use Drupal\Component\Utility\SafeMarkup;
 use Drupal\Core\Block\MainContentBlockPluginInterface;
 use Drupal\Core\Cache\Cache;
 use Drupal\Core\Cache\CacheableMetadata;
@@ -163,6 +164,8 @@ protected static function buildPreRenderableBlock($entity, ModuleHandlerInterfac
       '#block' => $entity,
     ];
 
+    $build['#configuration']['label'] = SafeMarkup::checkPlain($configuration['label']);
+
     // If an alter hook wants to modify the block contents, it can append
     // another #pre_render hook.
     $module_handler->alter(['block_view', "block_view_$base_id"], $build, $plugin);
diff --git a/core/modules/block/src/Controller/BlockLibraryController.php b/core/modules/block/src/Controller/BlockLibraryController.php
index 972dd73155d7f07edde83592116ca811605d64ef..2a0148fda0f10a47473369a8de9df17c822faae2 100644
--- a/core/modules/block/src/Controller/BlockLibraryController.php
+++ b/core/modules/block/src/Controller/BlockLibraryController.php
@@ -8,6 +8,7 @@
 namespace Drupal\block\Controller;
 
 use Drupal\Component\Serialization\Json;
+use Drupal\Component\Utility\SafeMarkup;
 use Drupal\Core\Block\BlockManagerInterface;
 use Drupal\Core\Controller\ControllerBase;
 use Drupal\Core\EventSubscriber\MainContentViewSubscriber;
@@ -108,7 +109,7 @@ public function listBlocks(Request $request, $theme) {
         '#prefix' => '<div class="block-filter-text-source">',
         '#suffix' => '</div>',
       ];
-      $row['category']['data'] = $plugin_definition['category'];
+      $row['category']['data'] = SafeMarkup::checkPlain($plugin_definition['category']);
       $links['add'] = [
         'title' => $this->t('Place block'),
         'url' => Url::fromRoute('block.admin_add', ['plugin_id' => $plugin_id, 'theme' => $theme]),
diff --git a/core/modules/color/color.module b/core/modules/color/color.module
index 46ddce5f18edd31d9db0b4ee254536f5852c8e9c..fa9499b1011202d84a4d1eaf1bbde10f903e63b1 100644
--- a/core/modules/color/color.module
+++ b/core/modules/color/color.module
@@ -8,6 +8,7 @@
 use Drupal\Core\Asset\CssOptimizer;
 use Drupal\Component\Utility\Bytes;
 use Drupal\Component\Utility\Environment;
+use Drupal\Component\Utility\SafeMarkup;
 use Drupal\Core\Cache\Cache;
 use Drupal\Core\Form\FormStateInterface;
 use Drupal\Core\Language\LanguageInterface;
@@ -250,7 +251,7 @@ function color_scheme_form($complete_form, FormStateInterface $form_state, $them
     if (isset($names[$name])) {
       $form['palette'][$name] = array(
         '#type' => 'textfield',
-        '#title' => $names[$name],
+        '#title' => SafeMarkup::checkPlain($names[$name]),
         '#value_callback' => 'color_palette_color_value',
         '#default_value' => $value,
         '#size' => 8,
diff --git a/core/modules/comment/src/CommentTypeListBuilder.php b/core/modules/comment/src/CommentTypeListBuilder.php
index f8a34510266d74da01c54b61924c63371a691376..4f998718e9d580e9cda95a9205366ebfa85bc3a9 100644
--- a/core/modules/comment/src/CommentTypeListBuilder.php
+++ b/core/modules/comment/src/CommentTypeListBuilder.php
@@ -7,6 +7,8 @@
 
 namespace Drupal\comment;
 
+use Drupal\Component\Utility\SafeMarkup;
+use Drupal\Component\Utility\Xss;
 use Drupal\Core\Config\Entity\ConfigEntityListBuilder;
 use Drupal\Core\Entity\EntityInterface;
 
@@ -43,7 +45,7 @@ public function buildHeader() {
    * {@inheritdoc}
    */
   public function buildRow(EntityInterface $entity) {
-    $row['type'] = $entity->label();
+    $row['type'] = SafeMarkup::checkPlain($entity->label());
     $row['description']['data'] = ['#markup' => $entity->getDescription()];
     return $row + parent::buildRow($entity);
   }
diff --git a/core/modules/config_translation/src/Controller/ConfigTranslationBlockListBuilder.php b/core/modules/config_translation/src/Controller/ConfigTranslationBlockListBuilder.php
index c6e8a491639f3f3578468acd31b787abeb9c357b..74e276a9d591e823eb5d4878c50312412c43dfb9 100644
--- a/core/modules/config_translation/src/Controller/ConfigTranslationBlockListBuilder.php
+++ b/core/modules/config_translation/src/Controller/ConfigTranslationBlockListBuilder.php
@@ -7,6 +7,7 @@
 
 namespace Drupal\config_translation\Controller;
 
+use Drupal\Component\Utility\SafeMarkup;
 use Drupal\Core\Entity\EntityInterface;
 use Drupal\Core\Entity\EntityStorageInterface;
 use Drupal\Core\Entity\EntityTypeInterface;
@@ -69,12 +70,12 @@ public function buildRow(EntityInterface $entity) {
     );
 
     $row['theme'] = array(
-      'data' => $this->themes[$theme]->info['name'],
+      'data' => SafeMarkup::checkPlain($this->themes[$theme]->info['name']),
       'class' => 'table-filter-text-source',
     );
 
     $row['category'] = array(
-      'data' => $plugin_definition['category'],
+      'data' => SafeMarkup::checkPlain($plugin_definition['category']),
       'class' => 'table-filter-text-source',
     );
 
diff --git a/core/modules/config_translation/src/Controller/ConfigTranslationFieldListBuilder.php b/core/modules/config_translation/src/Controller/ConfigTranslationFieldListBuilder.php
index 282d3eb4915d1061edb75007932248e69b6a7a53..1b2a08b6b036c3c3d9c25c77ee21a301cc7bde42 100644
--- a/core/modules/config_translation/src/Controller/ConfigTranslationFieldListBuilder.php
+++ b/core/modules/config_translation/src/Controller/ConfigTranslationFieldListBuilder.php
@@ -7,6 +7,7 @@
 
 namespace Drupal\config_translation\Controller;
 
+use Drupal\Component\Utility\SafeMarkup;
 use Drupal\Component\Utility\Unicode;
 use Drupal\Core\Entity\EntityInterface;
 use Drupal\Core\Entity\EntityManagerInterface;
@@ -122,7 +123,7 @@ public function buildRow(EntityInterface $entity) {
     if ($this->displayBundle()) {
       $bundle = $entity->get('bundle');
       $row['bundle'] = array(
-        'data' => $this->baseEntityBundles[$bundle]['label'],
+        'data' => SafeMarkup::checkPlain($this->baseEntityBundles[$bundle]['label']),
         'class' => 'table-filter-text-source',
       );
     }
diff --git a/core/modules/config_translation/src/Controller/ConfigTranslationMapperList.php b/core/modules/config_translation/src/Controller/ConfigTranslationMapperList.php
index 5c954526323d8713926d4562469b67abc5217b6e..e32714b975cd0a697ef66a05519d2337d96e079a 100644
--- a/core/modules/config_translation/src/Controller/ConfigTranslationMapperList.php
+++ b/core/modules/config_translation/src/Controller/ConfigTranslationMapperList.php
@@ -7,6 +7,7 @@
 
 namespace Drupal\config_translation\Controller;
 
+use Drupal\Component\Utility\SafeMarkup;
 use Drupal\config_translation\ConfigMapperInterface;
 use Drupal\Core\Controller\ControllerBase;
 use Symfony\Component\DependencyInjection\ContainerInterface;
@@ -93,7 +94,7 @@ public function render() {
    *   A render array structure of fields for this mapper.
    */
   public function buildRow(ConfigMapperInterface $mapper) {
-    $row['label'] = $mapper->getTypeLabel();
+    $row['label'] = SafeMarkup::checkPlain($mapper->getTypeLabel());
     $row['operations']['data'] = $this->buildOperations($mapper);
     return $row;
   }
diff --git a/core/modules/config_translation/src/Tests/ConfigTranslationOverviewTest.php b/core/modules/config_translation/src/Tests/ConfigTranslationOverviewTest.php
index eb5cf75c5aaa7f2c333c13a5da77bf7c538fa51e..221b7d6680ea910a6106c7eed67a3a7c6dd1084e 100644
--- a/core/modules/config_translation/src/Tests/ConfigTranslationOverviewTest.php
+++ b/core/modules/config_translation/src/Tests/ConfigTranslationOverviewTest.php
@@ -7,6 +7,7 @@
 
 namespace Drupal\config_translation\Tests;
 
+use Drupal\Component\Utility\SafeMarkup;
 use Drupal\language\Entity\ConfigurableLanguage;
 use Drupal\simpletest\WebTestBase;
 
@@ -102,7 +103,7 @@ public function testMapperListPage() {
       $base_url = 'admin/structure/config_test/manage/' . $test_entity->id();
       $this->drupalGet('admin/config/regional/config-translation/config_test');
       $this->assertLinkByHref($base_url . '/translate');
-      $this->assertEscaped($test_entity->label());
+      $this->assertText(SafeMarkup::checkPlain($test_entity->label()));
 
       // Make sure there is only a single 'Translate' operation for each
       // dropbutton.
diff --git a/core/modules/config_translation/src/Tests/ConfigTranslationUiTest.php b/core/modules/config_translation/src/Tests/ConfigTranslationUiTest.php
index e4a4e3fde2f944215d03cf9d9b3a37d34604ce4d..41840ad96b9669e1e816a570e7dbbb5b7216f630 100644
--- a/core/modules/config_translation/src/Tests/ConfigTranslationUiTest.php
+++ b/core/modules/config_translation/src/Tests/ConfigTranslationUiTest.php
@@ -753,9 +753,9 @@ public function testFieldConfigTranslation() {
     $this->clickLink('Add');
 
     $this->assertText('Translatable field setting');
-    $this->assertEscaped($translatable_field_setting);
+    $this->assertRaw(SafeMarkup::checkPlain($translatable_field_setting));
     $this->assertText('Translatable storage setting');
-    $this->assertEscaped($translatable_storage_setting);
+    $this->assertRaw(SafeMarkup::checkPlain($translatable_storage_setting));
   }
 
   /**
diff --git a/core/modules/contact/src/Controller/ContactController.php b/core/modules/contact/src/Controller/ContactController.php
index 1abd33c58f362bfd7dd9b0c23b3ccccb1fdc6406..7233bb8747931871085369398defc763b79f8e4b 100644
--- a/core/modules/contact/src/Controller/ContactController.php
+++ b/core/modules/contact/src/Controller/ContactController.php
@@ -11,6 +11,7 @@
 use Drupal\contact\ContactFormInterface;
 use Drupal\Core\Render\RendererInterface;
 use Drupal\user\UserInterface;
+use Drupal\Component\Utility\SafeMarkup;
 use Symfony\Component\DependencyInjection\ContainerInterface;
 use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
 
@@ -86,7 +87,7 @@ public function contactSitePage(ContactFormInterface $contact_form = NULL) {
       ));
 
     $form = $this->entityFormBuilder()->getForm($message);
-    $form['#title'] = $contact_form->label();
+    $form['#title'] = SafeMarkup::checkPlain($contact_form->label());
     $form['#cache']['contexts'][] = 'user.permissions';
     $this->renderer->addCacheableDependency($form, $config);
     return $form;
diff --git a/core/modules/dblog/src/Controller/DbLogController.php b/core/modules/dblog/src/Controller/DbLogController.php
index eff66268aebc8b73bb083d7963aa20222fbcffb4..08d826bc0eab1c9d99d4490bc03d18a51954997b 100644
--- a/core/modules/dblog/src/Controller/DbLogController.php
+++ b/core/modules/dblog/src/Controller/DbLogController.php
@@ -8,7 +8,9 @@
 namespace Drupal\dblog\Controller;
 
 use Drupal\Component\Utility\Html;
+use Drupal\Component\Utility\SafeMarkup;
 use Drupal\Component\Utility\Unicode;
+use Drupal\Component\Utility\Xss;
 use Drupal\Core\Controller\ControllerBase;
 use Drupal\Core\Database\Connection;
 use Drupal\Core\Datetime\DateFormatter;
@@ -281,7 +283,7 @@ public function eventDetails($event_id) {
         ),
         array(
           array('data' => $this->t('Hostname'), 'header' => TRUE),
-          $dblog->hostname,
+          SafeMarkup::checkPlain($dblog->hostname),
         ),
         array(
           array('data' => $this->t('Operations'), 'header' => TRUE),
diff --git a/core/modules/field/src/Tests/String/UuidFormatterTest.php b/core/modules/field/src/Tests/String/UuidFormatterTest.php
index 4d849cda8d168e9993dc39bd1bbad8ced22fc08e..2eaf7e9424664bf026092a32a7ddd1a0aaca7087 100644
--- a/core/modules/field/src/Tests/String/UuidFormatterTest.php
+++ b/core/modules/field/src/Tests/String/UuidFormatterTest.php
@@ -51,7 +51,7 @@ public function testUuidStringFormatter() {
 
     $render_array = $uuid_field->view(['settings' => ['link_to_entity' => TRUE]]);
     $this->assertIdentical($render_array[0]['#type'], 'link');
-    $this->assertIdentical($render_array[0]['#title']['#markup'], $entity->uuid());
+    $this->assertIdentical($render_array[0]['#title'], $entity->uuid());
     $this->assertIdentical($render_array[0]['#url']->toString(), $entity->url());
   }
 
diff --git a/core/modules/field_ui/src/FieldConfigListBuilder.php b/core/modules/field_ui/src/FieldConfigListBuilder.php
index 1dd2c7cc86c5ee46a0de1ce5d4adf11375ee5a26..d3feac1257f0ab5881c52e123b1433ab46a58073 100644
--- a/core/modules/field_ui/src/FieldConfigListBuilder.php
+++ b/core/modules/field_ui/src/FieldConfigListBuilder.php
@@ -8,6 +8,7 @@
 namespace Drupal\field_ui;
 
 use Drupal\Component\Utility\Html;
+use Drupal\Component\Utility\SafeMarkup;
 use Drupal\Core\Config\Entity\ConfigEntityListBuilder;
 use Drupal\Core\Entity\EntityInterface;
 use Drupal\Core\Entity\EntityManagerInterface;
@@ -130,7 +131,7 @@ public function buildRow(EntityInterface $field_config) {
     $row = array(
       'id' => Html::getClass($field_config->getName()),
       'data' => array(
-        'label' => $field_config->getLabel(),
+        'label' => SafeMarkup::checkPlain($field_config->getLabel()),
         'field_name' => $field_config->getName(),
         'field_type' => array(
           'data' => array(
diff --git a/core/modules/file/src/Plugin/Field/FieldFormatter/BaseFieldFileFormatterBase.php b/core/modules/file/src/Plugin/Field/FieldFormatter/BaseFieldFileFormatterBase.php
index 31d5e0571f4a4180b5b84144c4fbcb7078c13959..865471200a9ee64d8390e87d17ed931af51de015 100644
--- a/core/modules/file/src/Plugin/Field/FieldFormatter/BaseFieldFileFormatterBase.php
+++ b/core/modules/file/src/Plugin/Field/FieldFormatter/BaseFieldFileFormatterBase.php
@@ -56,17 +56,17 @@ public function viewElements(FieldItemListInterface $items) {
     }
 
     foreach ($items as $delta => $item) {
-      $view_value = $this->viewValue($item);
+      $string = $this->viewValue($item);
 
       if ($url) {
         $elements[$delta] = [
           '#type' => 'link',
-          '#title' => $view_value,
+          '#title' => $string,
           '#url' => Url::fromUri($url),
         ];
       }
       else {
-        $elements[$delta] = is_array($view_value) ? $view_value : ['#markup' => $view_value];
+        $elements[$delta] = is_array($string) ? $string : ['#markup' => $string];
       }
     }
 
diff --git a/core/modules/file/src/Plugin/Field/FieldWidget/FileWidget.php b/core/modules/file/src/Plugin/Field/FieldWidget/FileWidget.php
index acba472018a67cc5b60dc496d90230c2f62cba48..fb69d9cd9240eadb66b9be5900a79ba5cc429704 100644
--- a/core/modules/file/src/Plugin/Field/FieldWidget/FileWidget.php
+++ b/core/modules/file/src/Plugin/Field/FieldWidget/FileWidget.php
@@ -7,6 +7,7 @@
 
 namespace Drupal\file\Plugin\Field\FieldWidget;
 
+use Drupal\Component\Utility\SafeMarkup;
 use Drupal\Component\Utility\NestedArray;
 use Drupal\Core\Field\FieldDefinitionInterface;
 use Drupal\Core\Field\FieldFilteredString;
@@ -118,7 +119,7 @@ protected function formMultipleElements(FieldItemListInterface $items, array &$f
         break;
     }
 
-    $title = $this->fieldDefinition->getLabel();
+    $title = SafeMarkup::checkPlain($this->fieldDefinition->getLabel());
     $description = FieldFilteredString::create($this->fieldDefinition->getDescription());
 
     $elements = array();
diff --git a/core/modules/filter/src/FilterFormatListBuilder.php b/core/modules/filter/src/FilterFormatListBuilder.php
index 685112a761974c2f7766960f287c167deb283bd8..5ae317e4f0fca958d070277b2e48712bdeaeba9c 100644
--- a/core/modules/filter/src/FilterFormatListBuilder.php
+++ b/core/modules/filter/src/FilterFormatListBuilder.php
@@ -98,10 +98,10 @@ public function buildRow(EntityInterface $entity) {
     if ($entity->isFallbackFormat()) {
       $fallback_choice = $this->configFactory->get('filter.settings')->get('always_show_fallback_choice');
       if ($fallback_choice) {
-        $row['roles']['#markup'] = $this->t('All roles may use this format');
+        $roles_markup = $this->t('All roles may use this format');
       }
       else {
-        $row['roles']['#markup'] = $this->t('This format is shown when no other formats are available');
+        $roles_markup = $this->t('This format is shown when no other formats are available');
       }
       // Emphasize the fallback role text since it is important to understand
       // how it works which configuring filter formats. Additionally, it is not
@@ -110,14 +110,12 @@ public function buildRow(EntityInterface $entity) {
       $row['roles']['#suffix'] = '</em>';
     }
     else {
-      $row['roles'] = [
-        '#theme' => 'item_list',
-        '#items' => filter_get_roles_by_format($entity),
-        '#empty' => $this->t('No roles may use this format'),
-        '#context' => ['list_style' => 'comma-list'],
-      ];
+      $roles = array_map('\Drupal\Component\Utility\SafeMarkup::checkPlain', filter_get_roles_by_format($entity));
+      $roles_markup = $roles ? implode(', ', $roles) : $this->t('No roles may use this format');
     }
 
+    $row['roles']['#markup'] = $roles_markup;
+
     return $row + parent::buildRow($entity);
   }
 
diff --git a/core/modules/filter/src/Plugin/Filter/FilterHtml.php b/core/modules/filter/src/Plugin/Filter/FilterHtml.php
index 4708cc6f1c386d7986161a3745959e6fdf37c384..63e3f5706ae516a1c2c0ca46871c2971b81512d7 100644
--- a/core/modules/filter/src/Plugin/Filter/FilterHtml.php
+++ b/core/modules/filter/src/Plugin/Filter/FilterHtml.php
@@ -149,7 +149,7 @@ public function tips($long = FALSE) {
           array('data' =>
             array(
               '#prefix' => '<code>',
-              '#plain_text' => $tips[$tag][1],
+              '#markup' => Html::escape($tips[$tag][1]),
               '#suffix' => '</code>'
             ),
             'class' => array('type')),
@@ -193,7 +193,7 @@ public function tips($long = FALSE) {
         array(
           'data' => array(
             '#prefix' => '<code>',
-            '#plain_text' => $entity[1],
+            '#markup' => Html::escape($entity[1]),
             '#suffix' => '</code>',
           ),
           'class' => array('type'),
diff --git a/core/modules/help/src/Controller/HelpController.php b/core/modules/help/src/Controller/HelpController.php
index 4ebd4c8ef3b857018d4611468af3c003b690a168..802f9d9c1a52108692eea42375772e5e3515fa84 100644
--- a/core/modules/help/src/Controller/HelpController.php
+++ b/core/modules/help/src/Controller/HelpController.php
@@ -12,6 +12,7 @@
 use Drupal\Core\Url;
 use Symfony\Component\DependencyInjection\ContainerInterface;
 use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
+use Drupal\Component\Utility\SafeMarkup;
 
 /**
  * Controller routines for help routes.
@@ -114,7 +115,7 @@ public function helpPage($name) {
     $build = array();
     if ($this->moduleHandler()->implementsHook($name, 'help')) {
       $module_name =  $this->moduleHandler()->getName($name);
-      $build['#title'] = $module_name;
+      $build['#title'] = SafeMarkup::checkPlain($module_name);
 
       $temp = $this->moduleHandler()->invoke($name, 'help', array("help.page.$name", $this->routeMatch));
       if (empty($temp)) {
diff --git a/core/modules/language/src/Form/NegotiationConfigureForm.php b/core/modules/language/src/Form/NegotiationConfigureForm.php
index 7f230451577ad7863053f592d3625fec721aa549..938564e11a885166e02c484a676672fbcd14cf5f 100644
--- a/core/modules/language/src/Form/NegotiationConfigureForm.php
+++ b/core/modules/language/src/Form/NegotiationConfigureForm.php
@@ -8,6 +8,7 @@
 namespace Drupal\language\Form;
 
 use Drupal\Core\Block\BlockManagerInterface;
+use Drupal\Component\Utility\SafeMarkup;
 use Drupal\Component\Utility\Unicode;
 use Drupal\Component\Utility\Xss;
 use Drupal\Core\Config\ConfigFactoryInterface;
@@ -276,22 +277,22 @@ protected function configureFormTable(array &$form, $type)  {
 
       if (isset($types[$type])) {
         $table_form['#language_negotiation_info'][$method_id] = $method;
-        $method_name = $method['name'];
+        $method_name = SafeMarkup::checkPlain($method['name']);
 
         $table_form['weight'][$method_id] = array(
           '#type' => 'weight',
-          '#title' => $this->t('Weight for @title language detection method', array('@title' => Unicode::strtolower($method_name))),
+          '#title' => $this->t('Weight for !title language detection method', array('!title' => Unicode::strtolower($method_name))),
           '#title_display' => 'invisible',
           '#default_value' => $weight,
           '#attributes' => array('class' => array("language-method-weight-$type")),
           '#delta' => 20,
         );
 
-        $table_form['title'][$method_id] = array('#plain_text' => $method_name);
+        $table_form['title'][$method_id] = array('#markup' => $method_name);
 
         $table_form['enabled'][$method_id] = array(
           '#type' => 'checkbox',
-          '#title' => $this->t('Enable @title language detection method', array('@title' => Unicode::strtolower($method_name))),
+          '#title' => $this->t('Enable !title language detection method', array('!title' => Unicode::strtolower($method_name))),
           '#title_display' => 'invisible',
           '#default_value' => $enabled,
         );
diff --git a/core/modules/locale/src/Form/TranslateEditForm.php b/core/modules/locale/src/Form/TranslateEditForm.php
index dbd450a12e9a4421b5e95e92eb172ecec55e4822..e9c5359d61d1ccec6035ffd758946d8bd4d79fff 100644
--- a/core/modules/locale/src/Form/TranslateEditForm.php
+++ b/core/modules/locale/src/Form/TranslateEditForm.php
@@ -7,6 +7,7 @@
 
 namespace Drupal\locale\Form;
 
+use Drupal\Component\Utility\Html;
 use Drupal\Core\Form\FormStateInterface;
 use Drupal\Core\Render\Element;
 use Drupal\locale\SourceString;
@@ -72,9 +73,7 @@ public function buildForm(array $form, FormStateInterface $form_state) {
             '#type' => 'item',
             '#title' => $this->t('Source string (@language)', array('@language' => $this->t('Built-in English'))),
             '#title_display' => 'invisible',
-            '#plain_text' => $source_array[0],
-            '#preffix' => '<span lang="en">',
-            '#suffix' => '</span>',
+            '#markup' => '<span lang="en">' . Html::escape($source_array[0]) . '</span>',
           );
         }
         else {
@@ -83,16 +82,13 @@ public function buildForm(array $form, FormStateInterface $form_state) {
           $original_singular = [
             '#type' => 'item',
             '#title' => $this->t('Singular form'),
-            '#plain_text' => $source_array[0],
-            '#prefix' => '<span class="visually-hidden">' . $this->t('Source string (@language)', array('@language' => $this->t('Built-in English'))) . '</span><span lang="en">',
-            '#suffix' => '</span>',
+            '#markup' => '<span lang="en">' . Html::escape($source_array[0]) . '</span>',
+            '#prefix' => '<span class="visually-hidden">' . $this->t('Source string (@language)', array('@language' => $this->t('Built-in English'))) . '</span>',
           ];
           $original_plural = [
             '#type' => 'item',
             '#title' => $this->t('Plural form'),
-            '#plain_text' => $source_array[1],
-            '#preffix' => '<span lang="en">',
-            '#suffix' => '</span>',
+            '#markup' => '<span lang="en">' . Html::escape($source_array[1]) . '</span>',
           ];
           $form['strings'][$string->lid]['original'] = [
             $original_singular,
diff --git a/core/modules/locale/src/Form/TranslationStatusForm.php b/core/modules/locale/src/Form/TranslationStatusForm.php
index f71ec525f33c780a8d2dc314a9d0573c17ab8325..d2571399a74009715b78b5d4c9465374ec2f0d8b 100644
--- a/core/modules/locale/src/Form/TranslationStatusForm.php
+++ b/core/modules/locale/src/Form/TranslationStatusForm.php
@@ -7,6 +7,7 @@
 
 namespace Drupal\locale\Form;
 
+use Drupal\Component\Utility\SafeMarkup;
 use Drupal\Core\Extension\ModuleHandlerInterface;
 use Drupal\Core\Form\FormBase;
 use Drupal\Core\Form\FormStateInterface;
@@ -81,7 +82,7 @@ public function buildForm(array $form, FormStateInterface $form_state) {
 
       // Build data options for the select table.
       foreach ($updates as $langcode => $update) {
-        $title = $languages[$langcode]->getName();
+        $title = SafeMarkup::checkPlain($languages[$langcode]->getName());
         $locale_translation_update_info = array('#theme' => 'locale_translation_update_info');
         foreach (array('updates', 'not_found') as $update_status) {
           if (isset($update[$update_status])) {
@@ -93,7 +94,7 @@ public function buildForm(array $form, FormStateInterface $form_state) {
             'class' => array('label'),
             'data' => array(
               '#title' => $title,
-              '#plain_text' => $title,
+              '#markup' => $title,
             ),
           ),
           'status' => array(
diff --git a/core/modules/node/src/NodeListBuilder.php b/core/modules/node/src/NodeListBuilder.php
index 26f28763aebab56dc87ae1545217a09e5eb01ab1..7acbfc9296f6b7a82726ef0d8d7b86449f78369e 100644
--- a/core/modules/node/src/NodeListBuilder.php
+++ b/core/modules/node/src/NodeListBuilder.php
@@ -7,6 +7,7 @@
 
 namespace Drupal\node;
 
+use Drupal\Component\Utility\SafeMarkup;
 use Drupal\Core\Datetime\DateFormatter;
 use Drupal\Core\Entity\EntityInterface;
 use Drupal\Core\Entity\EntityListBuilder;
@@ -118,7 +119,7 @@ public function buildRow(EntityInterface $entity) {
       '#suffix' => ' ' . drupal_render($mark),
       '#url' => $uri,
     );
-    $row['type'] = node_get_type_label($entity);
+    $row['type'] = SafeMarkup::checkPlain(node_get_type_label($entity));
     $row['author']['data'] = array(
       '#theme' => 'username',
       '#account' => $entity->getOwner(),
diff --git a/core/modules/node/src/NodeTypeForm.php b/core/modules/node/src/NodeTypeForm.php
index 24b47b3545e1d4a8c98a546aa0a02135e8dbe237..ff757f98b37921cb54fd5a1fce081a4349dd2040 100644
--- a/core/modules/node/src/NodeTypeForm.php
+++ b/core/modules/node/src/NodeTypeForm.php
@@ -9,6 +9,7 @@
 
 use Drupal\Core\Entity\EntityForm;
 use Drupal\Core\Entity\EntityManagerInterface;
+use Drupal\Component\Utility\SafeMarkup;
 use Drupal\Core\Entity\EntityTypeInterface;
 use Drupal\Core\Form\FormStateInterface;
 use Drupal\Core\Url;
@@ -54,7 +55,7 @@ public function form(array $form, FormStateInterface $form_state) {
 
     $type = $this->entity;
     if ($this->operation == 'add') {
-      $form['#title'] = $this->t('Add content type');
+      $form['#title'] = SafeMarkup::checkPlain($this->t('Add content type'));
       $fields = $this->entityManager->getBaseFieldDefinitions('node');
       // Create a node with a fake bundle using the type's UUID so that we can
       // get the default values for workflow settings.
diff --git a/core/modules/node/src/Plugin/Search/NodeSearch.php b/core/modules/node/src/Plugin/Search/NodeSearch.php
index ce5ddb66aefc3d996f5b35d8bb2632db768d7a2a..bab5cc953ec4d39f6fad8f4df14dc5fe9d73f9d7 100644
--- a/core/modules/node/src/Plugin/Search/NodeSearch.php
+++ b/core/modules/node/src/Plugin/Search/NodeSearch.php
@@ -7,6 +7,7 @@
 
 namespace Drupal\node\Plugin\Search;
 
+use Drupal\Component\Utility\SafeMarkup;
 use Drupal\Core\Access\AccessResult;
 use Drupal\Core\Config\Config;
 use Drupal\Core\Database\Connection;
@@ -345,7 +346,7 @@ protected function prepareResults(StatementInterface $found) {
 
       $result = array(
         'link' => $node->url('canonical', array('absolute' => TRUE, 'language' => $language)),
-        'type' => $type->label(),
+        'type' => SafeMarkup::checkPlain($type->label()),
         'title' => $node->label(),
         'node' => $node,
         'extra' => $extra,
@@ -445,15 +446,9 @@ protected function indexNode(NodeInterface $node) {
       $build = $node_render->view($node, 'search_index', $language->getId());
 
       unset($build['#theme']);
+      $rendered = $this->renderer->renderPlain($build);
 
-      // Add the title to text so it is searchable.
-      $build['search_title'] = [
-        '#prefix' => '<h1>',
-        '#plain_text' => $node->label($language->getId()),
-        '#suffix' => '</h1>',
-        '#weight' => -1000
-      ];
-      $text = $this->renderer->renderPlain($build);
+      $text = '<h1>' . SafeMarkup::checkPlain($node->label($language->getId())) . '</h1>' . $rendered;
 
       // Fetch extra data normally not visible.
       $extra = $this->moduleHandler->invokeAll('node_update_index', array($node, $language->getId()));
diff --git a/core/modules/node/src/Tests/NodeTitleTest.php b/core/modules/node/src/Tests/NodeTitleTest.php
index 40460a6a58a1ecadc68c67d83c88cae254626256..ddf1fc62021c188510124266839c7438badefea4 100644
--- a/core/modules/node/src/Tests/NodeTitleTest.php
+++ b/core/modules/node/src/Tests/NodeTitleTest.php
@@ -8,7 +8,6 @@
 namespace Drupal\node\Tests;
 
 use Drupal\comment\Tests\CommentTestTrait;
-use Drupal\Component\Utility\Html;
 
 /**
  * Tests node title.
@@ -86,22 +85,5 @@ function testNodeTitle() {
     // Test that 0 appears in the template <h1>.
     $xpath = '//h1';
     $this->assertEqual(current($this->xpath($xpath)), 0, 'Node title is displayed as 0.', 'Node');
-
-    // Test edge case where node title contains special characters.
-    $edge_case_title = 'article\'s "title".';
-    $settings = array(
-      'title' => $edge_case_title,
-    );
-    $node = $this->drupalCreateNode($settings);
-    // Test that the title appears as <title>. The title will be escaped on the
-    // the page.
-    $edge_case_title_escaped = Html::escape($edge_case_title);
-    $this->drupalGet('node/' . $node->id());
-    $this->assertTitle($edge_case_title_escaped . ' | Drupal', 'Page title is equal to article\'s "title".', 'Node');
-
-    // Test that the title appears as <title> when reloading the node page.
-    $this->drupalGet('node/' . $node->id());
-    $this->assertTitle($edge_case_title_escaped . ' | Drupal', 'Page title is equal to article\'s "title".', 'Node');
-
   }
 }
diff --git a/core/modules/node/src/Tests/NodeTitleXSSTest.php b/core/modules/node/src/Tests/NodeTitleXSSTest.php
index 70e4498e2f027577d7431c856a6ced45bdaf22ad..f0e80eaf4f175282f3b056d7a4a55e67b9e273e5 100644
--- a/core/modules/node/src/Tests/NodeTitleXSSTest.php
+++ b/core/modules/node/src/Tests/NodeTitleXSSTest.php
@@ -7,8 +7,6 @@
 
 namespace Drupal\node\Tests;
 
-use Drupal\Component\Utility\Html;
-
 /**
  * Create a node with dangerous tags in its title and test that they are
  * escaped.
@@ -36,8 +34,8 @@ function testNodeTitleXSS() {
     $node = $this->drupalCreateNode($settings);
 
     $this->drupalGet('node/' . $node->id());
-    // Titles should be escaped.
-    $this->assertTitle(Html::escape($title) . ' | Drupal', 'Title is displayed when viewing a node.');
+    // assertTitle() decodes HTML-entities inside the <title> element.
+    $this->assertTitle($title . ' | Drupal', 'Title is displayed when viewing a node.');
     $this->assertNoRaw($xss, 'Harmful tags are escaped when viewing a node.');
 
     $this->drupalGet('node/' . $node->id() . '/edit');
diff --git a/core/modules/path/src/Form/EditForm.php b/core/modules/path/src/Form/EditForm.php
index a1f4a771186791e8d37a479c0a8d4fdb223ed8fb..fc85a42e095a099536915de7e3b8a017432cc14f 100644
--- a/core/modules/path/src/Form/EditForm.php
+++ b/core/modules/path/src/Form/EditForm.php
@@ -7,6 +7,7 @@
 
 namespace Drupal\path\Form;
 
+use Drupal\Component\Utility\SafeMarkup;
 use Drupal\Core\Form\FormStateInterface;
 use Drupal\Core\Url;
 
@@ -35,7 +36,7 @@ protected function buildPath($pid) {
   public function buildForm(array $form, FormStateInterface $form_state, $pid = NULL) {
     $form = parent::buildForm($form, $form_state, $pid);
 
-    $form['#title'] = $this->path['alias'];
+    $form['#title'] = SafeMarkup::checkPlain($this->path['alias']);
     $form['pid'] = array(
       '#type' => 'hidden',
       '#value' => $this->path['pid'],
diff --git a/core/modules/simpletest/src/AssertContentTrait.php b/core/modules/simpletest/src/AssertContentTrait.php
index eaf4b4195d100fbb819a5f31ba263f20c73d00f6..c6019434fdb5445e7d45832eed296e07ddaa8103 100644
--- a/core/modules/simpletest/src/AssertContentTrait.php
+++ b/core/modules/simpletest/src/AssertContentTrait.php
@@ -775,19 +775,14 @@ protected function assertTextPattern($pattern, $message = NULL, $group = 'Other'
    *   TRUE on pass, FALSE on fail.
    */
   protected function assertTitle($title, $message = '', $group = 'Other') {
-    // Don't use xpath as it messes with HTML escaping.
-    preg_match('@<title>(.*)</title>@', $this->getRawContent(), $matches);
-    if (isset($matches[1])) {
-      $actual = $matches[1];
-      if (!$message) {
-        $message = SafeMarkup::format('Page title @actual is equal to @expected.', array(
-          '@actual' => var_export($actual, TRUE),
-          '@expected' => var_export($title, TRUE),
-        ));
-      }
-      return $this->assertEqual($actual, $title, $message, $group);
+    $actual = (string) current($this->xpath('//title'));
+    if (!$message) {
+      $message = SafeMarkup::format('Page title @actual is equal to @expected.', array(
+        '@actual' => var_export($actual, TRUE),
+        '@expected' => var_export($title, TRUE),
+      ));
     }
-    return $this->fail('No title element found on the page.');
+    return $this->assertEqual($actual, $title, $message, $group);
   }
 
   /**
diff --git a/core/modules/system/src/Form/ModulesListForm.php b/core/modules/system/src/Form/ModulesListForm.php
index 0a52d2f8c2a0993598e18b63bfdea2d9bc6747a4..289928f4d0fcfe15acf9cf1a7cfd37de58d1fb89 100644
--- a/core/modules/system/src/Form/ModulesListForm.php
+++ b/core/modules/system/src/Form/ModulesListForm.php
@@ -7,6 +7,7 @@
 
 namespace Drupal\system\Form;
 
+use Drupal\Component\Utility\SafeMarkup;
 use Drupal\Component\Utility\Unicode;
 use Drupal\Core\Config\PreExistingConfigException;
 use Drupal\Core\Config\UnmetDependenciesException;
@@ -168,7 +169,7 @@ public function getFormId() {
    */
   public function buildForm(array $form, FormStateInterface $form_state) {
     require_once DRUPAL_ROOT . '/core/includes/install.inc';
-    $distribution = drupal_install_profile_distribution_name();
+    $distribution = SafeMarkup::checkPlain(drupal_install_profile_distribution_name());
 
     // Include system.admin.inc so we can use the sort callbacks.
     $this->moduleHandler->loadInclude('system', 'inc', 'system.admin');
diff --git a/core/modules/system/src/Tests/System/PageTitleTest.php b/core/modules/system/src/Tests/System/PageTitleTest.php
index 56fa556b4876965661207302cc208fdf15224964..369b55439f85645b1780416455810843ac50a5b3 100644
--- a/core/modules/system/src/Tests/System/PageTitleTest.php
+++ b/core/modules/system/src/Tests/System/PageTitleTest.php
@@ -147,6 +147,15 @@ public function testRoutingTitle() {
     $this->drupalGet('test-page-cached-controller');
     $this->assertTitle('Cached title | Drupal');
     $this->assertRaw(Html::escape('<span>Cached title</span>') . '</h1>');
+
+    // Ensure that titles are cacheable and are escaped normally if the
+    // controller escapes them use Html::escape().
+    $this->drupalGet('test-page-cached-controller-safe');
+    $this->assertTitle('<span>Cached title</span> | Drupal');
+    $this->assertRaw(Html::escape('<span>Cached title</span>') . '</h1>');
+    $this->drupalGet('test-page-cached-controller-safe');
+    $this->assertTitle('<span>Cached title</span> | Drupal');
+    $this->assertRaw(Html::escape('<span>Cached title</span>') . '</h1>');
   }
 
 }
diff --git a/core/modules/system/tests/modules/database_test/src/Form/DatabaseTestForm.php b/core/modules/system/tests/modules/database_test/src/Form/DatabaseTestForm.php
index 73f39b1fa5d64aa631f86bb63db5569800339d1f..342151e2295301c9eb93f68cd5f403adffb94bf6 100644
--- a/core/modules/system/tests/modules/database_test/src/Form/DatabaseTestForm.php
+++ b/core/modules/system/tests/modules/database_test/src/Form/DatabaseTestForm.php
@@ -7,6 +7,7 @@
 
 namespace Drupal\database_test\Form;
 
+use Drupal\Component\Utility\SafeMarkup;
 use Drupal\Core\Form\FormBase;
 use Drupal\Core\Form\FormStateInterface;
 use Drupal\user\Entity\User;
@@ -55,8 +56,8 @@ public function buildForm(array $form, FormStateInterface $form_state) {
 
     foreach (User::loadMultiple($uids) as $account) {
       $options[$account->id()] = array(
-        'title' => array('data' => array('#title' => $account->getUsername())),
-        'username' => $account->getUsername(),
+        'title' => array('data' => array('#title' => SafeMarkup::checkPlain($account->getUsername()))),
+        'username' => SafeMarkup::checkPlain($account->getUsername()),
         'status' =>  $account->isActive() ? t('active') : t('blocked'),
       );
     }
diff --git a/core/modules/system/tests/modules/form_test/src/FormTestArgumentsObject.php b/core/modules/system/tests/modules/form_test/src/FormTestArgumentsObject.php
index 9c347be09e45f44009cedef1c60b95e980951607..a7fa82ce2a016207dde7feec9811f4a004380358 100644
--- a/core/modules/system/tests/modules/form_test/src/FormTestArgumentsObject.php
+++ b/core/modules/system/tests/modules/form_test/src/FormTestArgumentsObject.php
@@ -7,6 +7,7 @@
 
 namespace Drupal\form_test;
 
+use Drupal\Component\Utility\SafeMarkup;
 use Drupal\Core\Form\ConfigFormBase;
 use Drupal\Core\Form\FormStateInterface;
 
@@ -37,7 +38,7 @@ public function buildForm(array $form, FormStateInterface $form_state, $arg = NU
 
     $form['bananas'] = array(
       '#type' => 'textfield',
-      '#default_value' => $arg,
+      '#default_value' => SafeMarkup::checkPlain($arg),
       '#title' => $this->t('Bananas'),
     );
 
diff --git a/core/modules/system/tests/modules/test_page_test/src/Controller/Test.php b/core/modules/system/tests/modules/test_page_test/src/Controller/Test.php
index 934e6a2be00b8166e499298d9a0126099ff659b8..b0d4136b3d228c2c62a25b83e3422a7dc03ebe52 100644
--- a/core/modules/system/tests/modules/test_page_test/src/Controller/Test.php
+++ b/core/modules/system/tests/modules/test_page_test/src/Controller/Test.php
@@ -7,7 +7,7 @@
 
 namespace Drupal\test_page_test\Controller;
 
-use Drupal\Component\Utility\Html;
+use Drupal\Component\Utility\SafeMarkup;
 
 /**
  * Defines a test controller for page titles.
@@ -54,13 +54,19 @@ public function dynamicTitle() {
   /**
    * Defines a controller with a cached render array.
    *
+   * @param bool $mark_safe
+   *   Whether or not to mark the title as safe use SafeMarkup::checkPlain.
+   *
    * @return array
    *   A render array
    */
-  public function controllerWithCache() {
+  public function controllerWithCache($mark_safe = FALSE) {
     $build = [];
     $build['#title'] = '<span>Cached title</span>';
-    $build['#cache']['keys'] = ['test_controller', 'with_title'];
+    if ($mark_safe) {
+      $build['#title'] = SafeMarkup::checkPlain($build['#title']);
+    }
+    $build['#cache']['keys'] = ['test_controller', 'with_title', $mark_safe];
 
     return $build;
   }
diff --git a/core/modules/system/tests/modules/test_page_test/test_page_test.routing.yml b/core/modules/system/tests/modules/test_page_test/test_page_test.routing.yml
index 240842349af3f3c7673f83892af455e0c2b17fbd..5330be824b36512670eb615f8c4f0411c3399661 100644
--- a/core/modules/system/tests/modules/test_page_test/test_page_test.routing.yml
+++ b/core/modules/system/tests/modules/test_page_test/test_page_test.routing.yml
@@ -28,6 +28,14 @@ test_page_test.cached_controller:
   requirements:
     _access: 'TRUE'
 
+test_page_test.cached_controller.safe:
+  path: '/test-page-cached-controller-safe'
+  defaults:
+    _controller: '\Drupal\test_page_test\Controller\Test::controllerWithCache'
+    mark_safe: true
+  requirements:
+    _access: 'TRUE'
+
 test_page_test.dynamic_title:
   path: '/test-page-dynamic-title'
   defaults:
diff --git a/core/modules/tracker/tracker.pages.inc b/core/modules/tracker/tracker.pages.inc
index 47bd3efedb3abe6d97b60ba21bbbde21d14ad495..ffbf316fe9dcc1011092c63efb7a7a9a1285f1d5 100644
--- a/core/modules/tracker/tracker.pages.inc
+++ b/core/modules/tracker/tracker.pages.inc
@@ -5,6 +5,7 @@
  * User page callbacks for tracker.module.
  */
 
+use Drupal\Component\Utility\SafeMarkup;
 use Drupal\Core\Cache\Cache;
 use Drupal\node\Entity\Node;
 
@@ -84,7 +85,7 @@ function tracker_page($account = NULL) {
       }
 
       $row = array(
-        'type' => node_get_type_label($node),
+        'type' => SafeMarkup::checkPlain(node_get_type_label($node)),
         'title' => array(
           'data' => array(
             '#type' => 'link',
diff --git a/core/modules/update/src/Form/UpdateManagerUpdate.php b/core/modules/update/src/Form/UpdateManagerUpdate.php
index cafa4d13f95d4914eeb33f4e6a5483b732eed152..f0f64ea32d557eb0c81d5f017bb93221e5542350 100644
--- a/core/modules/update/src/Form/UpdateManagerUpdate.php
+++ b/core/modules/update/src/Form/UpdateManagerUpdate.php
@@ -7,6 +7,7 @@
 
 namespace Drupal\update\Form;
 
+use Drupal\Component\Utility\SafeMarkup;
 use Drupal\Core\Extension\ModuleHandlerInterface;
 use Drupal\Core\Form\FormBase;
 use Drupal\Core\Form\FormStateInterface;
@@ -114,14 +115,14 @@ public function buildForm(array $form, FormStateInterface $form_state) {
           $project_name = $this->l($project['title'], Url::fromUri($project['link']));
         }
         else {
-          $project_name = $project['title'];
+          $project_name = SafeMarkup::checkPlain($project['title']);
         }
       }
       elseif (!empty($project['info']['name'])) {
-        $project_name = $project['info']['name'];
+        $project_name = SafeMarkup::checkPlain($project['info']['name']);
       }
       else {
-        $project_name = $name;
+        $project_name = SafeMarkup::checkPlain($name);
       }
       if ($project['project_type'] == 'theme' || $project['project_type'] == 'theme-disabled') {
         $project_name .= ' ' . $this->t('(Theme)');
diff --git a/core/modules/user/src/Form/UserPermissionsForm.php b/core/modules/user/src/Form/UserPermissionsForm.php
index e96efda0c3254ba55c882e2adbb9c97c13c267bb..0e0a01a5e0af4e1e78e5c4fc23446818026da1ee 100644
--- a/core/modules/user/src/Form/UserPermissionsForm.php
+++ b/core/modules/user/src/Form/UserPermissionsForm.php
@@ -7,6 +7,7 @@
 
 namespace Drupal\user\Form;
 
+use Drupal\Component\Utility\SafeMarkup;
 use Drupal\Core\Extension\ModuleHandlerInterface;
 use Drupal\Core\Form\FormBase;
 use Drupal\Core\Form\FormStateInterface;
@@ -93,7 +94,7 @@ public function buildForm(array $form, FormStateInterface $form_state) {
     $admin_roles = array();
     foreach ($this->getRoles() as $role_name => $role) {
       // Retrieve role names for columns.
-      $role_names[$role_name] = $role->label();
+      $role_names[$role_name] = SafeMarkup::checkPlain($role->label());
       // Fetch permissions for the roles.
       $role_permissions[$role_name] = $role->getPermissions();
       $admin_roles[$role_name] = $role->isAdmin();
diff --git a/core/modules/user/src/Plugin/views/access/Permission.php b/core/modules/user/src/Plugin/views/access/Permission.php
index fab8f882b020422587c5ef7ad844cb295bf1c59d..0dc5165db57b963c92faf64e2d903c6f6645d1c0 100644
--- a/core/modules/user/src/Plugin/views/access/Permission.php
+++ b/core/modules/user/src/Plugin/views/access/Permission.php
@@ -7,6 +7,7 @@
 
 namespace Drupal\user\Plugin\views\access;
 
+use Drupal\Component\Utility\SafeMarkup;
 use Drupal\Core\Extension\ModuleHandlerInterface;
 use Drupal\Core\Form\FormStateInterface;
 use Drupal\Core\Session\AccountInterface;
@@ -120,7 +121,7 @@ public function buildOptionsForm(&$form, FormStateInterface $form_state) {
     foreach ($permissions as $perm => $perm_item) {
       $provider = $perm_item['provider'];
       $display_name = $this->moduleHandler->getName($provider);
-      $perms[$display_name][$perm] = strip_tags($perm_item['title']);
+      $perms[$display_name][$perm] = SafeMarkup::checkPlain(strip_tags($perm_item['title']));
     }
 
     $form['perm'] = array(
diff --git a/core/modules/user/src/UserListBuilder.php b/core/modules/user/src/UserListBuilder.php
index 85b52f2e24aab533528076e7149d4a3f3cb11cb1..7575b867270d6caf0f5665925fa1ab647c281d59 100644
--- a/core/modules/user/src/UserListBuilder.php
+++ b/core/modules/user/src/UserListBuilder.php
@@ -138,7 +138,7 @@ public function buildRow(EntityInterface $entity) {
     );
     $row['status'] = $entity->isActive() ? $this->t('active') : $this->t('blocked');
 
-    $roles = user_role_names(TRUE);
+    $roles = array_map('\Drupal\Component\Utility\SafeMarkup::checkPlain', user_role_names(TRUE));
     unset($roles[RoleInterface::AUTHENTICATED_ID]);
     $users_roles = array();
     foreach ($entity->getRoles() as $role) {
diff --git a/core/modules/views/src/Plugin/views/display/Block.php b/core/modules/views/src/Plugin/views/display/Block.php
index 08e44675244b7d41b87276dc79946ce04a4f174b..411c50ee24187f6af541be55c11f3dca5c1d3c63 100644
--- a/core/modules/views/src/Plugin/views/display/Block.php
+++ b/core/modules/views/src/Plugin/views/display/Block.php
@@ -7,6 +7,7 @@
 
 namespace Drupal\views\Plugin\views\display;
 
+use Drupal\Component\Utility\SafeMarkup;
 use Drupal\Core\Entity\EntityManagerInterface;
 use Drupal\Core\Form\FormStateInterface;
 use Drupal\views\Plugin\Block\ViewsBlock;
@@ -148,7 +149,7 @@ public function optionsSummary(&$categories, &$options) {
     if (empty($block_description)) {
       $block_description = $this->t('None');
     }
-    $block_category = $this->getOption('block_category');
+    $block_category = SafeMarkup::checkPlain($this->getOption('block_category'));
 
     $options['block_description'] = array(
       'category' => 'block',
diff --git a/core/modules/views/src/Plugin/views/display/DisplayPluginBase.php b/core/modules/views/src/Plugin/views/display/DisplayPluginBase.php
index 534925c91324ad80f2d296821ad9059543b3b56e..f9ae57a0584a6119d4655c0a3a160c6c1fc28b50 100644
--- a/core/modules/views/src/Plugin/views/display/DisplayPluginBase.php
+++ b/core/modules/views/src/Plugin/views/display/DisplayPluginBase.php
@@ -1062,7 +1062,7 @@ public function getArgumentsTokens() {
       }
        // Use strip tags as there should never be HTML in the path.
        // However, we need to preserve special characters like " that
-       // were encoded by \Drupal\Component\Utility\Html::escape().
+       // were removed by SafeMarkup::checkPlain().
       $tokens["!$count"] = isset($this->view->args[$count - 1]) ? strip_tags(Html::decodeEntities($this->view->args[$count - 1])) : '';
     }
 
@@ -1394,7 +1394,7 @@ public function buildOptionsForm(&$form, FormStateInterface $form_state) {
     if ($this->defaultableSections($section)) {
       views_ui_standard_display_dropdown($form, $form_state, $section);
     }
-    $form['#title'] = $this->display['display_title'] . ': ';
+    $form['#title'] = SafeMarkup::checkPlain($this->display['display_title']) . ': ';
 
     // Set the 'section' to highlight on the form.
     // If it's the item we're looking at is pulling from the default display,
diff --git a/core/modules/views/src/Plugin/views/filter/FilterPluginBase.php b/core/modules/views/src/Plugin/views/filter/FilterPluginBase.php
index 8c716f19a8742dbabe71609be3515a25d70e2f58..d2e9fe895b28aba0ee892b58db74a539943b44c1 100644
--- a/core/modules/views/src/Plugin/views/filter/FilterPluginBase.php
+++ b/core/modules/views/src/Plugin/views/filter/FilterPluginBase.php
@@ -766,7 +766,7 @@ public function groupForm(&$form, FormStateInterface $form_state) {
       $value = $this->options['group_info']['identifier'];
 
       $form[$value] = array(
-        '#title' => $this->options['group_info']['label'],
+        '#title' => SafeMarkup::checkPlain($this->options['group_info']['label']),
         '#type' => $this->options['group_info']['widget'],
         '#default_value' => $this->group_info,
         '#options' => $groups,
diff --git a/core/modules/views/src/Tests/SearchIntegrationTest.php b/core/modules/views/src/Tests/SearchIntegrationTest.php
index 78c43ac359df9a9892cc733b74d0fddd85375e46..2edd22da7ea12f55b5c7992f89e9891691d3b2e7 100644
--- a/core/modules/views/src/Tests/SearchIntegrationTest.php
+++ b/core/modules/views/src/Tests/SearchIntegrationTest.php
@@ -108,16 +108,15 @@ public function testSearchIntegration() {
       'type' => $type->id(),
     ];
     $this->drupalCreateNode($node);
-    $node['title'] = "Drupal's search rocks <em>really</em> rocks!";
+    $node['title'] = "Drupal's search rocks really rocks!";
     $this->drupalCreateNode($node);
     $this->cronRun();
     $this->drupalGet('test-arg/rocks');
     $xpath = '//div[@class="views-row"]//a';
     /** @var \SimpleXMLElement[] $results */
     $results = $this->xpath($xpath);
-    $this->assertEqual((string) $results[0], "Drupal's search rocks <em>really</em> rocks!");
+    $this->assertEqual((string) $results[0], "Drupal's search rocks really rocks!");
     $this->assertEqual((string) $results[1], "Drupal's search rocks.");
-    $this->assertEscaped("Drupal's search rocks <em>really</em> rocks!");
 
     // Test sorting with another set of titles.
     $node = [
diff --git a/core/modules/views_ui/src/Tests/XssTest.php b/core/modules/views_ui/src/Tests/XssTest.php
index a8474347cd44b0549590502282dcbc26becf58b0..21080cbfcd3699cc51d82b38ba42fe70f03c4274 100644
--- a/core/modules/views_ui/src/Tests/XssTest.php
+++ b/core/modules/views_ui/src/Tests/XssTest.php
@@ -23,10 +23,10 @@ class XssTest extends UITestBase {
 
   public function testViewsUi() {
     $this->drupalGet('admin/structure/views');
-    $this->assertEscaped('<script>alert("foo");</script>, <marquee>test</marquee>', 'The view tag is properly escaped.');
+    $this->assertRaw('&lt;script&gt;alert(&quot;foo&quot;);&lt;/script&gt;, &lt;marquee&gt;test&lt;/marquee&gt;', 'The view tag is properly escaped.');
 
     $this->drupalGet('admin/structure/views/view/sa_contrib_2013_035');
-    $this->assertEscaped('<marquee>test</marquee>', 'Field admin label is properly escaped.');
+    $this->assertRaw('&amp;lt;marquee&amp;gt;test&amp;lt;/marquee&amp;gt;', 'Field admin label is properly escaped.');
 
     $this->drupalGet('admin/structure/views/nojs/handler/sa_contrib_2013_035/page_1/header/area');
     $this->assertRaw('[title] == &amp;lt;marquee&amp;gt;test&amp;lt;/marquee&amp;gt;', 'Token label is properly escaped.');
diff --git a/core/modules/views_ui/src/ViewEditForm.php b/core/modules/views_ui/src/ViewEditForm.php
index e13ae62f03de137eaba22052bfa4c55b71bd25b4..05bc5fd7241d2cc88c79be9608e798315c592200 100644
--- a/core/modules/views_ui/src/ViewEditForm.php
+++ b/core/modules/views_ui/src/ViewEditForm.php
@@ -494,7 +494,7 @@ public function getDisplayDetails($view, $display) {
       $build['top']['display_title'] = array(
         '#theme' => 'views_ui_display_tab_setting',
         '#description' => $this->t('Display name'),
-        '#link' => $view->getExecutable()->displayHandlers->get($display['id'])->optionLink($display_title, 'display_title'),
+        '#link' => $view->getExecutable()->displayHandlers->get($display['id'])->optionLink(SafeMarkup::checkPlain($display_title), 'display_title'),
       );
     }
 
@@ -1060,7 +1060,7 @@ public function getFormBucket(ViewUI $view, $type, $display) {
         continue;
       }
 
-      $field_name = $handler->adminLabel(TRUE);
+      $field_name = SafeMarkup::checkPlain($handler->adminLabel(TRUE));
       if (!empty($field['relationship']) && !empty($relationships[$field['relationship']])) {
         $field_name = '(' . $relationships[$field['relationship']] . ') ' . $field_name;
       }
diff --git a/core/modules/views_ui/src/ViewListBuilder.php b/core/modules/views_ui/src/ViewListBuilder.php
index 0d8125b81c99686232b7b86fe0c76ffd139be8b1..ece0acfdd3acb0ed701f7a80c9ad46619dd22df7 100644
--- a/core/modules/views_ui/src/ViewListBuilder.php
+++ b/core/modules/views_ui/src/ViewListBuilder.php
@@ -7,6 +7,7 @@
 
 namespace Drupal\views_ui;
 
+use Drupal\Component\Utility\SafeMarkup;
 use Drupal\Component\Plugin\PluginManagerInterface;
 use Drupal\Core\Entity\EntityInterface;
 use Drupal\Core\Config\Entity\ConfigEntityListBuilder;
@@ -277,7 +278,7 @@ protected function getDisplayPaths(EntityInterface $view) {
           $all_paths[] = \Drupal::l('/' . $path, Url::fromUserInput('/' . $path));
         }
         else {
-          $all_paths[] = '/' . $path;
+          $all_paths[] = SafeMarkup::checkPlain('/' . $path);
         }
       }
     }
diff --git a/core/modules/views_ui/tests/src/Unit/ViewListBuilderTest.php b/core/modules/views_ui/tests/src/Unit/ViewListBuilderTest.php
index 4089d3a2e89d8486a5bb94fd346abfb62263f85a..d4bc2b6bd1e78e6c5902437fcb6ce85bfd2409e5 100644
--- a/core/modules/views_ui/tests/src/Unit/ViewListBuilderTest.php
+++ b/core/modules/views_ui/tests/src/Unit/ViewListBuilderTest.php
@@ -7,7 +7,6 @@
 
 namespace Drupal\Tests\views_ui\Unit;
 
-use Drupal\Component\Utility\SafeMarkup;
 use Drupal\Core\DependencyInjection\ContainerBuilder;
 use Drupal\Core\Entity\EntityInterface;
 use Drupal\Tests\UnitTestCase;
@@ -166,10 +165,7 @@ public function testBuildRowEntityList() {
     $this->assertEquals($expected_displays, $row['data']['view_name']['data']['#displays']);
 
     $display_paths = $row['data']['path']['data']['#items'];
-    // These values will be escaped by Twig when rendered.
-    $this->assertEquals('/test_page, /<object>malformed_path</object>, /<script>alert("placeholder_page/%")</script>', implode(', ', $display_paths));
-    $this->assertFalse(SafeMarkup::isSafe('/<object>malformed_path</object>'), '/<script>alert("/<object>malformed_path</object> is not marked safe.');
-    $this->assertFalse(SafeMarkup::isSafe('/<script>alert("placeholder_page/%")'), '/<script>alert("/<script>alert("placeholder_page/%") is not marked safe.');
+    $this->assertEquals('/test_page, /&lt;object&gt;malformed_path&lt;/object&gt;, /&lt;script&gt;alert(&quot;placeholder_page/%&quot;)&lt;/script&gt;', implode(', ', $display_paths));
   }
 
 }