diff --git a/core/lib/Drupal/Core/Utility/Token.php b/core/lib/Drupal/Core/Utility/Token.php
index f1f80cc..7e05ff4 100644
--- a/core/lib/Drupal/Core/Utility/Token.php
+++ b/core/lib/Drupal/Core/Utility/Token.php
@@ -7,6 +7,8 @@
 
 namespace Drupal\Core\Utility;
 
+use Drupal\Component\Utility\Html;
+use Drupal\Component\Utility\SafeMarkup;
 use Drupal\Core\Cache\Cache;
 use Drupal\Core\Cache\CacheableDependencyInterface;
 use Drupal\Core\Cache\CacheBackendInterface;
@@ -160,12 +162,6 @@ public function __construct(ModuleHandlerInterface $module_handler, CacheBackend
    *     final text.
    *   - clear: A boolean flag indicating that tokens should be removed from the
    *     final text if no replacement value can be generated.
-   *   - sanitize: A boolean flag indicating that tokens should be sanitized for
-   *     display to a web browser. Defaults to TRUE. Developers who set this
-   *     option to FALSE assume responsibility for running
-   *     \Drupal\Component\Utility\Xss::filter(),
-   *     \Drupal\Component\Utility\Html::escape() or other appropriate scrubbing
-   *     functions before displaying data to users.
    * @param \Drupal\Core\Render\BubbleableMetadata $bubbleable_metadata|null
    *   (optional) An object to which static::generate() and the hooks and
    *   functions that it invokes will add their required bubbleable metadata.
@@ -210,8 +206,12 @@ public function replace($text, array $data = array(), array $options = array(),
       $function($replacements, $data, $options, $bubbleable_metadata);
     }
 
-    $tokens = array_keys($replacements);
-    $values = array_values($replacements);
+    $tokens = [];
+    $values = [];
+    foreach ($replacements as $token => $value) {
+      $tokens[] = $token;
+      $values[] = SafeMarkup::isSafe($value) ? (string) $value : Html::escape($value);
+    }
 
     // If a local $bubbleable_metadata object was created, apply the metadata
     // it collected to the renderer's currently active render context.
@@ -282,11 +282,6 @@ public function scan($text) {
    *     array of token replacements after they are generated. Can be used when
    *     modules require special formatting of token text, for example URL
    *     encoding or truncation to a specific length.
-   *   - sanitize: A boolean flag indicating that tokens should be sanitized for
-   *     display to a web browser. Developers who set this option to FALSE assume
-   *     responsibility for running \Drupal\Component\Utility\Xss::filter(),
-   *     \Drupal\Component\Utility\Html::escape() or other appropriate scrubbing
-   *     functions before displaying data to users.
    * @param \Drupal\Core\Render\BubbleableMetadata $bubbleable_metadata
    *    The bubbleable metadata. This is passed to the token replacement
    *    implementations so that they can attach their metadata.
@@ -300,8 +295,6 @@ public function scan($text) {
    * @see hook_tokens_alter()
    */
   public function generate($type, array $tokens, array $data, array $options, BubbleableMetadata $bubbleable_metadata) {
-    $options += array('sanitize' => TRUE);
-
     foreach ($data as $object) {
       if ($object instanceof CacheableDependencyInterface || $object instanceof AttachmentsInterface) {
         $bubbleable_metadata->addCacheableDependency($object);
diff --git a/core/lib/Drupal/Core/Utility/token.api.php b/core/lib/Drupal/Core/Utility/token.api.php
index 57a1e6d..8c8e434 100644
--- a/core/lib/Drupal/Core/Utility/token.api.php
+++ b/core/lib/Drupal/Core/Utility/token.api.php
@@ -65,7 +65,8 @@
  *
  * @return array
  *   An associative array of replacement values, keyed by the raw [type:token]
- *   strings from the original text.
+ *   strings from the original text. The returned values may contain unsafe
+ *   user input and other HTML and must be escaped or filtered before output.
  *
  * @see hook_token_info()
  * @see hook_tokens_alter()
@@ -81,8 +82,6 @@ function hook_tokens($type, $tokens, array $data, array $options, \Drupal\Core\R
   else {
     $langcode = NULL;
   }
-  $sanitize = !empty($options['sanitize']);
-
   $replacements = array();
 
   if ($type == 'node' && !empty($data['node'])) {
@@ -97,7 +96,7 @@ function hook_tokens($type, $tokens, array $data, array $options, \Drupal\Core\R
           break;
 
         case 'title':
-          $replacements[$original] = $sanitize ? Html::escape($node->getTitle()) : $node->getTitle();
+          $replacements[$original] = $node->getTitle();
           break;
 
         case 'edit-url':
@@ -107,7 +106,7 @@ function hook_tokens($type, $tokens, array $data, array $options, \Drupal\Core\R
         // Default values for the chained tokens handled below.
         case 'author':
           $account = $node->getOwner() ? $node->getOwner() : User::load(0);
-          $replacements[$original] = $sanitize ? Html::escape($account->label()) : $account->label();
+          $replacements[$original] = $account->label();
           $bubbleable_metadata->addCacheableDependency($account);
           break;
 
diff --git a/core/modules/action/src/Plugin/Action/MessageAction.php b/core/modules/action/src/Plugin/Action/MessageAction.php
index c87b606..8463c05 100644
--- a/core/modules/action/src/Plugin/Action/MessageAction.php
+++ b/core/modules/action/src/Plugin/Action/MessageAction.php
@@ -7,11 +7,11 @@
 
 namespace Drupal\action\Plugin\Action;
 
-use Drupal\Component\Utility\Xss;
 use Drupal\Core\Access\AccessResult;
 use Drupal\Core\Action\ConfigurableActionBase;
 use Drupal\Core\Form\FormStateInterface;
 use Drupal\Core\Plugin\ContainerFactoryPluginInterface;
+use Drupal\Core\Render\Renderer;
 use Drupal\Core\Session\AccountInterface;
 use Drupal\Core\Utility\Token;
 use Symfony\Component\DependencyInjection\ContainerInterface;
@@ -28,16 +28,33 @@
 class MessageAction extends ConfigurableActionBase implements ContainerFactoryPluginInterface {
 
   /**
+   * The renderer.
+   *
+   * We depend on the XSS filtering in
+   * \Drupal\Core\Render|Renderer::renderPlain(), so we cannot type hint on
+   * \Drupal\Core\Render\RendererInterface.
+   *
+   * @var \Drupal\Core\Render\Renderer
+   */
+  protected $renderer;
+
+  /**
    * @var \Drupal\Core\Utility\Token
    */
   protected $token;
 
   /**
    * Constructs a MessageAction object.
+   *
+   * @param \Drupal\Core\Render\Renderer $renderer
+   *   The renderer. We depend on the XSS filtering in
+   *   \Drupal\Core\Render|Renderer::renderPlain(), so we cannot type hint on
+   *   \Drupal\Core\Render\RendererInterface.
    */
-  public function __construct(array $configuration, $plugin_id, $plugin_definition, Token $token) {
+  public function __construct(array $configuration, $plugin_id, $plugin_definition, Token $token, Renderer $renderer) {
     parent::__construct($configuration, $plugin_id, $plugin_definition);
 
+    $this->renderer = $renderer;
     $this->token = $token;
   }
 
@@ -45,7 +62,13 @@ public function __construct(array $configuration, $plugin_id, $plugin_definition
    * {@inheritdoc}
    */
   public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition) {
-    return new static($configuration, $plugin_id, $plugin_definition, $container->get('token'));
+    return new static(
+      $configuration,
+      $plugin_id,
+      $plugin_definition,
+      $container->get('token'),
+      $container->get('renderer')
+    );
   }
 
   /**
@@ -55,7 +78,15 @@ public function execute($entity = NULL) {
     if (empty($this->configuration['node'])) {
       $this->configuration['node'] = $entity;
     }
-    $message = $this->token->replace(Xss::filterAdmin($this->configuration['message']), $this->configuration);
+
+    // Depend on \Drupal\Core\Render\Renderer::renderPlain()'s sanitization of
+    // the message, so it won't be fully escaped during the main rendering
+    // process.
+    $build = [
+      '#markup' => $this->token->replace($this->configuration['message'], $this->configuration),
+    ];
+    $message = $this->renderer->renderPlain($build);
+
     drupal_set_message($message);
   }
 
diff --git a/core/modules/comment/comment.tokens.inc b/core/modules/comment/comment.tokens.inc
index 500533e..3293c57 100644
--- a/core/modules/comment/comment.tokens.inc
+++ b/core/modules/comment/comment.tokens.inc
@@ -119,8 +119,6 @@ function comment_tokens($type, $tokens, array $data, array $options, BubbleableM
   else {
     $langcode = NULL;
   }
-  $sanitize = !empty($options['sanitize']);
-
   $replacements = array();
 
   if ($type == 'comment' && !empty($data['comment'])) {
@@ -136,7 +134,7 @@ function comment_tokens($type, $tokens, array $data, array $options, BubbleableM
 
         // Poster identity information for comments.
         case 'hostname':
-          $replacements[$original] = $sanitize ? Html::escape($comment->getHostname()) : $comment->getHostname();
+          $replacements[$original] = $comment->getHostname();
           break;
 
         case 'mail':
@@ -146,23 +144,23 @@ function comment_tokens($type, $tokens, array $data, array $options, BubbleableM
           if ($comment->getOwnerId()) {
             $bubbleable_metadata->addCacheableDependency($comment->getOwner());
           }
-          $replacements[$original] = $sanitize ? Html::escape($mail) : $mail;
+          $replacements[$original] = $mail;
           break;
 
         case 'homepage':
-          $replacements[$original] = $sanitize ? UrlHelper::filterBadProtocol($comment->getHomepage()) : $comment->getHomepage();
+          $replacements[$original] = $comment->getHomepage();
           break;
 
         case 'title':
-          $replacements[$original] = $sanitize ? Xss::filter($comment->getSubject()) : $comment->getSubject();
+          $replacements[$original] = $comment->getSubject();
           break;
 
         case 'body':
-          $replacements[$original] = $sanitize ? $comment->comment_body->processed : $comment->comment_body->value;
+          $replacements[$original] = $comment->comment_body->processed;
           break;
 
         case 'langcode':
-          $replacements[$original] = $sanitize ? Html::escape($comment->language()->getId()) : $comment->language()->getId();
+          $replacements[$original] = $comment->language()->getId();
           break;
 
         // Comment related URLs.
@@ -183,14 +181,14 @@ function comment_tokens($type, $tokens, array $data, array $options, BubbleableM
           if ($comment->getOwnerId()) {
             $bubbleable_metadata->addCacheableDependency($comment->getOwner());
           }
-          $replacements[$original] = $sanitize ? Xss::filter($name) : $name;
+          $replacements[$original] = $name;
           break;
 
         case 'parent':
           if ($comment->hasParentComment()) {
             $parent = $comment->getParentComment();
             $bubbleable_metadata->addCacheableDependency($parent);
-            $replacements[$original] = $sanitize ? Xss::filter($parent->getSubject()) : $parent->getSubject();
+            $replacements[$original] = $parent->getSubject();
           }
           break;
 
@@ -210,7 +208,7 @@ function comment_tokens($type, $tokens, array $data, array $options, BubbleableM
           $entity = $comment->getCommentedEntity();
           $bubbleable_metadata->addCacheableDependency($entity);
           $title = $entity->label();
-          $replacements[$original] = $sanitize ? Xss::filter($title) : $title;
+          $replacements[$original] = $title;
           break;
       }
     }
diff --git a/core/modules/content_translation/content_translation.module b/core/modules/content_translation/content_translation.module
index 36557cd..cbba524 100644
--- a/core/modules/content_translation/content_translation.module
+++ b/core/modules/content_translation/content_translation.module
@@ -471,14 +471,7 @@ function content_translation_language_configuration_element_process(array $eleme
     );
 
     $submit_name = isset($form['actions']['save_continue']) ? 'save_continue' : 'submit';
-    // Only add the submit handler on the submit button if the #submit property
-    // is already available, otherwise this breaks the form submit function.
-    if (isset($form['actions'][$submit_name]['#submit'])) {
-      $form['actions'][$submit_name]['#submit'][] = 'content_translation_language_configuration_element_submit';
-    }
-    else {
-      $form['#submit'][] = 'content_translation_language_configuration_element_submit';
-    }
+    $form['actions'][$submit_name]['#submit'][] = 'content_translation_language_configuration_element_submit';
   }
   return $element;
 }
diff --git a/core/modules/file/file.module b/core/modules/file/file.module
index 3c677ea..9a6a97c 100644
--- a/core/modules/file/file.module
+++ b/core/modules/file/file.module
@@ -951,7 +951,6 @@ function file_tokens($type, $tokens, array $data, array $options, BubbleableMeta
   else {
     $langcode = NULL;
   }
-  $sanitize = !empty($options['sanitize']);
 
   $replacements = array();
 
@@ -968,15 +967,15 @@ function file_tokens($type, $tokens, array $data, array $options, BubbleableMeta
 
         // Essential file data
         case 'name':
-          $replacements[$original] = $sanitize ? Html::escape($file->getFilename()) : $file->getFilename();
+          $replacements[$original] = $file->getFilename();
           break;
 
         case 'path':
-          $replacements[$original] = $sanitize ? Html::escape($file->getFileUri()) : $file->getFileUri();
+          $replacements[$original] = $file->getFileUri();
           break;
 
         case 'mime':
-          $replacements[$original] = $sanitize ? Html::escape($file->getMimeType()) : $file->getMimeType();
+          $replacements[$original] = $file->getMimeType();
           break;
 
         case 'size':
@@ -984,7 +983,7 @@ function file_tokens($type, $tokens, array $data, array $options, BubbleableMeta
           break;
 
         case 'url':
-          $replacements[$original] = $sanitize ? Html::escape(file_create_url($file->getFileUri())) : file_create_url($file->getFileUri());
+          $replacements[$original] = file_create_url($file->getFileUri());
           break;
 
         // These tokens are default variations on the chained tokens handled below.
@@ -1004,7 +1003,7 @@ function file_tokens($type, $tokens, array $data, array $options, BubbleableMeta
           $owner = $file->getOwner();
           $bubbleable_metadata->addCacheableDependency($owner);
           $name = $owner->label();
-          $replacements[$original] = $sanitize ? Html::escape($name) : $name;
+          $replacements[$original] = $name;
           break;
       }
     }
diff --git a/core/modules/file/src/Plugin/Field/FieldType/FileItem.php b/core/modules/file/src/Plugin/Field/FieldType/FileItem.php
index afff2a3..6be6e77 100644
--- a/core/modules/file/src/Plugin/Field/FieldType/FileItem.php
+++ b/core/modules/file/src/Plugin/Field/FieldType/FileItem.php
@@ -260,7 +260,7 @@ public static function validateMaxFilesize($element, FormStateInterface $form_st
    *   An array of token objects to pass to token_replace().
    *
    * @return string
-   *   A file directory URI with tokens replaced.
+   *   An unsanitized file directory URI with tokens replaced.
    *
    * @see token_replace()
    */
@@ -268,7 +268,7 @@ public function getUploadLocation($data = array()) {
     $settings = $this->getSettings();
     $destination = trim($settings['file_directory'], '/');
 
-    // Replace tokens.
+    // Replace tokens. We do not apply any sanitization to the destination here.
     $destination = \Drupal::token()->replace($destination, $data);
 
     return $settings['uri_scheme'] . '://' . $destination;
diff --git a/core/modules/link/src/Plugin/Field/FieldFormatter/LinkFormatter.php b/core/modules/link/src/Plugin/Field/FieldFormatter/LinkFormatter.php
index ed80376..a57c8b8 100644
--- a/core/modules/link/src/Plugin/Field/FieldFormatter/LinkFormatter.php
+++ b/core/modules/link/src/Plugin/Field/FieldFormatter/LinkFormatter.php
@@ -188,9 +188,7 @@ public function viewElements(FieldItemListInterface $items) {
 
       // If the title field value is available, use it for the link text.
       if (empty($settings['url_only']) && !empty($item->title)) {
-        // Unsanitized token replacement here because the entire link title
-        // gets auto-escaped during link generation.
-        $link_title = \Drupal::token()->replace($item->title, array($entity->getEntityTypeId() => $entity), array('sanitize' => FALSE, 'clear' => TRUE));
+        $link_title = \Drupal::token()->replace($item->title, array($entity->getEntityTypeId() => $entity), array('clear' => TRUE));
       }
 
       // Trim the link text to the desired length.
diff --git a/core/modules/link/src/Plugin/Field/FieldFormatter/LinkSeparateFormatter.php b/core/modules/link/src/Plugin/Field/FieldFormatter/LinkSeparateFormatter.php
index 3ea2770..26d2547 100644
--- a/core/modules/link/src/Plugin/Field/FieldFormatter/LinkSeparateFormatter.php
+++ b/core/modules/link/src/Plugin/Field/FieldFormatter/LinkSeparateFormatter.php
@@ -54,9 +54,7 @@ public function viewElements(FieldItemListInterface $items) {
 
       // If the link text field value is available, use it for the text.
       if (empty($settings['url_only']) && !empty($item->title)) {
-        // Unsanitized token replacement here because the entire link title
-        // gets auto-escaped during link generation.
-        $link_title = \Drupal::token()->replace($item->title, array($entity->getEntityTypeId() => $entity), array('sanitize' => FALSE, 'clear' => TRUE));
+        $link_title = \Drupal::token()->replace($item->title, array($entity->getEntityTypeId() => $entity), array('clear' => TRUE));
       }
 
       // The link_separate formatter has two titles; the link text (as in the
diff --git a/core/modules/node/node.tokens.inc b/core/modules/node/node.tokens.inc
index 3294044..9388d68 100644
--- a/core/modules/node/node.tokens.inc
+++ b/core/modules/node/node.tokens.inc
@@ -96,8 +96,6 @@ function node_tokens($type, $tokens, array $data, array $options, BubbleableMeta
   else {
     $langcode = LanguageInterface::LANGCODE_DEFAULT;
   }
-  $sanitize = !empty($options['sanitize']);
-
   $replacements = array();
 
   if ($type == 'node' && !empty($data['node'])) {
@@ -116,16 +114,16 @@ function node_tokens($type, $tokens, array $data, array $options, BubbleableMeta
           break;
 
         case 'type':
-          $replacements[$original] = $sanitize ? Html::escape($node->getType()) : $node->getType();
+          $replacements[$original] = $node->getType();
           break;
 
         case 'type-name':
           $type_name = node_get_type_label($node);
-          $replacements[$original] = $sanitize ? Html::escape($type_name) : $type_name;
+          $replacements[$original] = $type_name;
           break;
 
         case 'title':
-          $replacements[$original] = $sanitize ? Html::escape($node->getTitle()) : $node->getTitle();
+          $replacements[$original] = $node->getTitle();
           break;
 
         case 'body':
@@ -133,14 +131,13 @@ function node_tokens($type, $tokens, array $data, array $options, BubbleableMeta
           $translation = \Drupal::entityManager()->getTranslationFromContext($node, $langcode, array('operation' => 'node_tokens'));
           if ($translation->hasField('body') && ($items = $translation->get('body')) && !$items->isEmpty()) {
             $item = $items[0];
-            $field_definition = \Drupal::entityManager()->getFieldDefinitions('node', $node->bundle())['body'];
             // If the summary was requested and is not empty, use it.
             if ($name == 'summary' && !empty($item->summary)) {
-              $output = $sanitize ? $item->summary_processed : $item->summary;
+              $output = $item->summary_processed;
             }
             // Attempt to provide a suitable version of the 'body' field.
             else {
-              $output = $sanitize ? $item->processed : $item->value;
+              $output = $item->processed;
               // A summary was requested.
               if ($name == 'summary') {
                 // Generate an optionally trimmed summary of the body field.
@@ -164,7 +161,7 @@ function node_tokens($type, $tokens, array $data, array $options, BubbleableMeta
           break;
 
         case 'langcode':
-          $replacements[$original] = $sanitize ? Html::escape($node->language()->getId()) : $node->language()->getId();
+          $replacements[$original] = $node->language()->getId();
           break;
 
         case 'url':
@@ -179,7 +176,7 @@ function node_tokens($type, $tokens, array $data, array $options, BubbleableMeta
         case 'author':
           $account = $node->getOwner() ? $node->getOwner() : User::load(0);
           $bubbleable_metadata->addCacheableDependency($account);
-          $replacements[$original] = $sanitize ? Html::escape($account->label()) : $account->label();
+          $replacements[$original] = $account->label();
           break;
 
         case 'created':
diff --git a/core/modules/system/system.tokens.inc b/core/modules/system/system.tokens.inc
index a11f55d..a3af309 100644
--- a/core/modules/system/system.tokens.inc
+++ b/core/modules/system/system.tokens.inc
@@ -100,8 +100,6 @@ function system_tokens($type, $tokens, array $data, array $options, BubbleableMe
   else {
     $langcode = NULL;
   }
-  $sanitize = !empty($options['sanitize']);
-
   $replacements = array();
 
   if ($type == 'site') {
@@ -111,14 +109,14 @@ function system_tokens($type, $tokens, array $data, array $options, BubbleableMe
           $config = \Drupal::config('system.site');
           $bubbleable_metadata->addCacheableDependency($config);
           $site_name = $config->get('name');
-          $replacements[$original] = $sanitize ? Html::escape($site_name) : $site_name;
+          $replacements[$original] = $site_name;
           break;
 
         case 'slogan':
           $config = \Drupal::config('system.site');
           $bubbleable_metadata->addCacheableDependency($config);
           $slogan = $config->get('slogan');
-          $replacements[$original] = $sanitize ? Xss::filterAdmin($slogan) : $slogan;
+          $replacements[$original] = $slogan;
           break;
 
         case 'mail':
@@ -178,7 +176,7 @@ function system_tokens($type, $tokens, array $data, array $options, BubbleableMe
           break;
 
         case 'raw':
-          $replacements[$original] = $sanitize ? Html::escape($date) : $date;
+          $replacements[$original] = $date;
           break;
       }
     }
diff --git a/core/modules/taxonomy/taxonomy.tokens.inc b/core/modules/taxonomy/taxonomy.tokens.inc
index daf690b..6c33f57 100644
--- a/core/modules/taxonomy/taxonomy.tokens.inc
+++ b/core/modules/taxonomy/taxonomy.tokens.inc
@@ -97,7 +97,6 @@ function taxonomy_tokens($type, $tokens, array $data, array $options, Bubbleable
   $token_service = \Drupal::token();
 
   $replacements = array();
-  $sanitize = !empty($options['sanitize']);
   $taxonomy_storage = \Drupal::entityManager()->getStorage('taxonomy_term');
   if ($type == 'term' && !empty($data['term'])) {
     $term = $data['term'];
@@ -109,11 +108,11 @@ function taxonomy_tokens($type, $tokens, array $data, array $options, Bubbleable
           break;
 
         case 'name':
-          $replacements[$original] = $sanitize ? Html::escape($term->getName()) : $term->getName();
+          $replacements[$original] = $term->getName();
           break;
 
         case 'description':
-          $replacements[$original] = $sanitize ? $term->description->processed : $term->getDescription();
+          $replacements[$original] = $term->description->processed;
           break;
 
         case 'url':
@@ -131,14 +130,14 @@ function taxonomy_tokens($type, $tokens, array $data, array $options, Bubbleable
         case 'vocabulary':
           $vocabulary = Vocabulary::load($term->bundle());
           $bubbleable_metadata->addCacheableDependency($vocabulary);
-          $replacements[$original] = Html::escape($vocabulary->label());
+          $replacements[$original] = $vocabulary->label();
           break;
 
         case 'parent':
           if ($parents = $taxonomy_storage->loadParents($term->id())) {
             $parent = array_pop($parents);
             $bubbleable_metadata->addCacheableDependency($parent);
-            $replacements[$original] = Html::escape($parent->getName());
+            $replacements[$original] = $parent->getName();
           }
           break;
       }
@@ -165,11 +164,11 @@ function taxonomy_tokens($type, $tokens, array $data, array $options, Bubbleable
           break;
 
         case 'name':
-          $replacements[$original] = $sanitize ? Html::escape($vocabulary->label()) : $vocabulary->label();
+          $replacements[$original] = $vocabulary->label();
           break;
 
         case 'description':
-          $replacements[$original] = $sanitize ? Xss::filter($vocabulary->getDescription()) : $vocabulary->getDescription();
+          $replacements[$original] = $vocabulary->getDescription();
           break;
 
         case 'term-count':
diff --git a/core/modules/tour/src/Plugin/tour/tip/TipPluginText.php b/core/modules/tour/src/Plugin/tour/tip/TipPluginText.php
index bedb4bd..f525d83 100644
--- a/core/modules/tour/src/Plugin/tour/tip/TipPluginText.php
+++ b/core/modules/tour/src/Plugin/tour/tip/TipPluginText.php
@@ -121,7 +121,7 @@ public function getAttributes() {
    */
   public function getOutput() {
     $output = '<h2 class="tour-tip-label" id="tour-tip-' . $this->getAriaId() . '-label">' . Html::escape($this->getLabel()) . '</h2>';
-    $output .= '<p class="tour-tip-body" id="tour-tip-' . $this->getAriaId() . '-contents">' . Xss::filterAdmin($this->token->replace($this->getBody())) . '</p>';
+    $output .= '<p class="tour-tip-body" id="tour-tip-' . $this->getAriaId() . '-contents">' . $this->token->replace($this->getBody()) . '</p>';
     return array('#markup' => $output);
   }
 
diff --git a/core/modules/user/user.module b/core/modules/user/user.module
index 73b9413..a811ba1 100644
--- a/core/modules/user/user.module
+++ b/core/modules/user/user.module
@@ -915,9 +915,8 @@ function user_mail($key, &$message, $params) {
   $language_manager->setConfigOverrideLanguage($language);
   $mail_config = \Drupal::config('user.mail');
 
-   // We do not sanitize the token replacement, since the output of this
-   // replacement is intended for an email message, not a web browser.
-  $token_options = array('langcode' => $langcode, 'callback' => 'user_mail_tokens', 'sanitize' => FALSE, 'clear' => TRUE);
+  // @todo fix this
+  $token_options = array('langcode' => $langcode, 'callback' => 'user_mail_tokens', 'clear' => TRUE);
   $message['subject'] .= $token_service->replace($mail_config->get($key . '.subject'), $variables, $token_options);
   $message['body'][] = $token_service->replace($mail_config->get($key . '.body'), $variables, $token_options);
 
diff --git a/core/modules/user/user.tokens.inc b/core/modules/user/user.tokens.inc
index 9cb61f6..c8b88e6 100644
--- a/core/modules/user/user.tokens.inc
+++ b/core/modules/user/user.tokens.inc
@@ -77,8 +77,6 @@ function user_tokens($type, $tokens, array $data, array $options, BubbleableMeta
   else {
     $langcode = NULL;
   }
-  $sanitize = !empty($options['sanitize']);
-
   $replacements = array();
 
   if ($type == 'user' && !empty($data['user'])) {
@@ -97,11 +95,11 @@ function user_tokens($type, $tokens, array $data, array $options, BubbleableMeta
           if ($account->isAnonymous()) {
             $bubbleable_metadata->addCacheableDependency(\Drupal::config('user.settings'));
           }
-          $replacements[$original] = $sanitize ? Html::escape($name) : $name;
+          $replacements[$original] = $name;
           break;
 
         case 'mail':
-          $replacements[$original] = $sanitize ? Html::escape($account->getEmail()) : $account->getEmail();
+          $replacements[$original] = $account->getEmail();
           break;
 
         case 'url':
diff --git a/core/modules/views/views.tokens.inc b/core/modules/views/views.tokens.inc
index 33d162b..cbdfea9 100644
--- a/core/modules/views/views.tokens.inc
+++ b/core/modules/views/views.tokens.inc
@@ -74,8 +74,6 @@ function views_tokens($type, $tokens, array $data, array $options, BubbleableMet
   if (isset($options['language'])) {
     $url_options['language'] = $options['language'];
   }
-  $sanitize = !empty($options['sanitize']);
-
   $replacements = array();
 
   if ($type == 'view' && !empty($data['view'])) {
@@ -87,11 +85,11 @@ function views_tokens($type, $tokens, array $data, array $options, BubbleableMet
     foreach ($tokens as $name => $original) {
       switch ($name) {
         case 'label':
-          $replacements[$original] = $sanitize ? Html::escape($view->storage->label()) : $view->storage->label();
+          $replacements[$original] = $view->storage->label();
           break;
 
         case 'description':
-          $replacements[$original] = $sanitize ? Html::escape($view->storage->get('description')) : $view->storage->get('description');
+          $replacements[$original] = $view->storage->get('description');
           break;
 
         case 'id':
@@ -100,7 +98,7 @@ function views_tokens($type, $tokens, array $data, array $options, BubbleableMet
 
         case 'title':
           $title = $view->getTitle();
-          $replacements[$original] = $sanitize ? Html::escape($title) : $title;
+          $replacements[$original] = $title;
           break;
 
         case 'url':
