diff --git a/core/lib/Drupal/Core/Render/RenderVariable.php b/core/lib/Drupal/Core/Render/RenderVariable.php
new file mode 100644
index 0000000..83e4497
--- /dev/null
+++ b/core/lib/Drupal/Core/Render/RenderVariable.php
@@ -0,0 +1,120 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\Core\Render\RenderVariable.
+ */
+
+namespace Drupal\Core\Render;
+
+use Drupal\Component\Utility\SafeMarkup;
+
+class RenderVariable {
+
+  /**
+   * Prefixes a render variable.
+   *
+   * @param string|\Drupal\Component\Utility\SafeStringInterface|array $thing
+   *   A render variable. Either a string, an object that is safe or a render
+   *   array.
+   * @param string|\Drupal\Component\Utility\SafeStringInterface...
+   *   Prefixes to add to the render variable. By default these will XSS admin
+   *   filtered.
+   *
+   * @return array
+   */
+  public static function prefix($thing) {
+    $args = func_get_args();
+    unset($args[0]);
+    if (empty($args)) {
+      throw new \InvalidArgumentException();
+    }
+    $output = $thing;
+    foreach (array_reverse($args) as $arg) {
+      $output = static::makeRenderArray($output);
+      $output['#prefix'] = $arg;
+    }
+    return $output;
+  }
+
+  /**
+   * Suffixes a render variable.
+   *
+   * @param string|\Drupal\Component\Utility\SafeStringInterface|array $thing
+   *   A render variable. Either a string, an object that is safe or a render
+   *   array.
+   * @param string|\Drupal\Component\Utility\SafeStringInterface...
+   *   Suffixes to add to the render variable. By default these will XSS admin
+   *   filtered.
+   *
+   * @return array
+   */
+  public static function suffix($thing) {
+    $args = func_get_args();
+    unset($args[0]);
+    if (empty($args)) {
+      throw new \InvalidArgumentException();
+    }
+    $output = $thing;
+    foreach ($args as $arg) {
+      $output = static::makeRenderArray($output);
+      $output['#suffix'] = $arg;
+    }
+    return $output;
+  }
+
+  /**
+   * Wraps a render variable.
+   *
+   * @param string|\Drupal\Component\Utility\SafeStringInterface|array $thing
+   *   A render variable. Either a string, an object that is safe or a render
+   *   array.
+   * @param string|\Drupal\Component\Utility\SafeStringInterface $prefix
+   *   Prefix to add to the render variable. By default this will XSS admin
+   *   filtered.
+   * @param string|\Drupal\Component\Utility\SafeStringInterface $suffix
+   *   Prefix to add to the render variable. By default this will XSS admin
+   *   filtered.
+   *
+   * @return array
+   */
+
+  public static function wrap($thing, $prefix, $suffix) {
+    $output = static::makeRenderArray($thing);
+    $output['#prefix'] = $prefix;
+    $output['#suffix'] = $suffix;
+    return $output;
+  }
+
+  /**
+   * Converts a render variable into a render array.
+   *
+   * @param string|\Drupal\Component\Utility\SafeStringInterface|array $thing
+   *   A render variable. Either a string, an object that is safe or a render
+   *   array.
+   *
+   * @return array
+   *   A render array.
+   */
+  protected static function makeRenderArray($thing) {
+    if (!is_array($thing)) {
+      if (SafeMarkup::isSafe($thing)) {
+        $output = [
+          '#markup' => $thing,
+        ];
+      }
+      else {
+        $output = [
+          '#plain_text' => $thing,
+        ];
+      }
+    }
+    else {
+      $output = [
+        $thing
+      ];
+    }
+    return $output;
+  }
+
+}
\ No newline at end of file
diff --git a/core/lib/Drupal/Core/Render/Renderer.php b/core/lib/Drupal/Core/Render/Renderer.php
index c2e03c9..41ac83f 100644
--- a/core/lib/Drupal/Core/Render/Renderer.php
+++ b/core/lib/Drupal/Core/Render/Renderer.php
@@ -435,7 +435,6 @@ protected function doRender(&$elements, $is_root_call = FALSE) {
     // Check the elements for insecure HTML and pass through sanitization.
     if (isset($elements)) {
       $markup_keys = array(
-        '#description',
         '#field_prefix',
         '#field_suffix',
       );
diff --git a/core/modules/entity_reference/src/Plugin/views/row/EntityReference.php b/core/modules/entity_reference/src/Plugin/views/row/EntityReference.php
index 3323933..ff396a0 100644
--- a/core/modules/entity_reference/src/Plugin/views/row/EntityReference.php
+++ b/core/modules/entity_reference/src/Plugin/views/row/EntityReference.php
@@ -8,6 +8,7 @@
 namespace Drupal\entity_reference\Plugin\views\row;
 
 use Drupal\Core\Form\FormStateInterface;
+use Drupal\Core\Render\RenderVariable;
 use Drupal\views\Plugin\views\row\Fields;
 
 /**
@@ -43,7 +44,7 @@ public function buildOptionsForm(&$form, FormStateInterface $form_state) {
     parent::buildOptionsForm($form, $form_state);
 
     // Expand the description of the 'Inline field' checkboxes.
-    $form['inline']['#description'] .= '<br />' . $this->t("<strong>Note:</strong> In 'Entity Reference' displays, all fields will be displayed inline unless an explicit selection of inline fields is made here." );
+    $form['inline']['#description'] = RenderVariable::suffix($form['inline']['#description'], '<br />', $this->t("<strong>Note:</strong> In 'Entity Reference' displays, all fields will be displayed inline unless an explicit selection of inline fields is made here."));
   }
 
   /**
diff --git a/core/modules/field_ui/src/Form/FieldConfigEditForm.php b/core/modules/field_ui/src/Form/FieldConfigEditForm.php
index ba972a9..7ea912c 100644
--- a/core/modules/field_ui/src/Form/FieldConfigEditForm.php
+++ b/core/modules/field_ui/src/Form/FieldConfigEditForm.php
@@ -65,7 +65,7 @@ public function form(array $form, FormStateInterface $form_state) {
       '#title' => $this->t('Help text'),
       '#default_value' => $this->entity->getDescription(),
       '#rows' => 5,
-      '#description' => $this->t('Instructions to present to the user below this field on the editing form.<br />Allowed HTML tags: @tags', array('@tags' => FieldFilteredString::displayAllowedTags())) . '<br />' . $this->t('This field supports tokens.'),
+      '#description' => $this->t('Instructions to present to the user below this field on the editing form.<br />Allowed HTML tags: @tags<br />This field supports tokens.', array('@tags' => FieldFilteredString::displayAllowedTags())),
       '#weight' => -10,
     );
 
diff --git a/core/modules/options/src/Plugin/Field/FieldType/ListItemBase.php b/core/modules/options/src/Plugin/Field/FieldType/ListItemBase.php
index bbca170..fddae99 100644
--- a/core/modules/options/src/Plugin/Field/FieldType/ListItemBase.php
+++ b/core/modules/options/src/Plugin/Field/FieldType/ListItemBase.php
@@ -101,7 +101,7 @@ public function storageSettingsForm(array &$form, FormStateInterface $form_state
       '#allowed_values' => $allowed_values,
     );
 
-    $element['allowed_values']['#description'] = $this->allowedValuesDescription();
+    $element['allowed_values']['#description'] = ['#markup' => $this->allowedValuesDescription()];
 
     $element['allowed_values_function'] = array(
       '#type' => 'item',
diff --git a/core/modules/system/system.admin.inc b/core/modules/system/system.admin.inc
index 11b72a5..9ff8fe9 100644
--- a/core/modules/system/system.admin.inc
+++ b/core/modules/system/system.admin.inc
@@ -261,7 +261,9 @@ function theme_system_modules_details($variables) {
       '#type' => 'details',
       '#title' => $title,
       '#attributes' => array('id' => $module['enable']['#id'] . '-description'),
-      '#description' => $description,
+      // #description is built up using lots of markup therefore we need to
+      // XSS admin filter it instead of auto-escape.
+      '#description' => ['#markup' => $description],
     );
     $row[] = ['class' => ['description', 'expand'], 'data' => $details];
 
diff --git a/core/modules/views/src/Plugin/EntityReferenceSelection/ViewsSelection.php b/core/modules/views/src/Plugin/EntityReferenceSelection/ViewsSelection.php
index 25e7393..d643bf7 100644
--- a/core/modules/views/src/Plugin/EntityReferenceSelection/ViewsSelection.php
+++ b/core/modules/views/src/Plugin/EntityReferenceSelection/ViewsSelection.php
@@ -67,7 +67,12 @@ public function buildConfigurationForm(array $form, FormStateInterface $form_sta
         '#required' => TRUE,
         '#options' => $options,
         '#default_value' => $default,
-        '#description' => '<p>' . $this->t('Choose the view and display that select the entities that can be referenced.<br />Only views with a display of type "Entity Reference" are eligible.') . '</p>',
+        '#description' => [
+          // @todo should we really be wrapping in <p>?
+          '#prefix' => '<p>',
+          '#markup' => $this->t('Choose the view and display that select the entities that can be referenced.<br />Only views with a display of type "Entity Reference" are eligible.'),
+          '#suffix' => '</p>',
+        ],
       );
 
       $default = !empty($view_settings['arguments']) ? implode(', ', $view_settings['arguments']) : '';
diff --git a/core/modules/views/src/Plugin/views/argument_default/ArgumentDefaultPluginBase.php b/core/modules/views/src/Plugin/views/argument_default/ArgumentDefaultPluginBase.php
index b5c2adf..8a9c0d8 100644
--- a/core/modules/views/src/Plugin/views/argument_default/ArgumentDefaultPluginBase.php
+++ b/core/modules/views/src/Plugin/views/argument_default/ArgumentDefaultPluginBase.php
@@ -8,6 +8,7 @@
 namespace Drupal\views\Plugin\views\argument_default;
 
 use Drupal\Core\Form\FormStateInterface;
+use Drupal\Core\Render\RenderVariable;
 use Drupal\views\ViewExecutable;
 use Drupal\views\Plugin\views\argument\ArgumentPluginBase;
 use Drupal\views\Plugin\views\PluginBase;
@@ -98,7 +99,7 @@ protected function checkAccess(&$form, $option_name) {
     if (!$this->access()) {
       $form[$option_name]['#disabled'] = TRUE;
       $form[$option_name]['#value'] = $form[$this->option_name]['#default_value'];
-      $form[$option_name]['#description'] .= ' <strong>' . $this->t('Note: you do not have permission to modify this. If you change the default filter type, this setting will be lost and you will NOT be able to get it back.') . '</strong>';
+      $form[$option_name]['#description'] = RenderVariable::suffix($form[$option_name]['#description'], ' <strong>', $this->t('Note: you do not have permission to modify this. If you change the default filter type, this setting will be lost and you will NOT be able to get it back.'), '</strong>');
     }
   }
 
diff --git a/core/modules/views/src/Plugin/views/argument_validator/ArgumentValidatorPluginBase.php b/core/modules/views/src/Plugin/views/argument_validator/ArgumentValidatorPluginBase.php
index 7a6cf67..017f992 100644
--- a/core/modules/views/src/Plugin/views/argument_validator/ArgumentValidatorPluginBase.php
+++ b/core/modules/views/src/Plugin/views/argument_validator/ArgumentValidatorPluginBase.php
@@ -8,6 +8,7 @@
 namespace Drupal\views\Plugin\views\argument_validator;
 
 use Drupal\Core\Form\FormStateInterface;
+use Drupal\Core\Render\RenderVariable;
 use Drupal\views\ViewExecutable;
 use Drupal\views\Plugin\views\argument\ArgumentPluginBase;
 use Drupal\views\Plugin\views\PluginBase;
@@ -93,7 +94,8 @@ protected function checkAccess(&$form, $option_name) {
     if (!$this->access()) {
       $form[$option_name]['#disabled'] = TRUE;
       $form[$option_name]['#value'] = $form[$this->option_name]['#default_value'];
-      $form[$option_name]['#description'] .= ' <strong>' . $this->t('Note: you do not have permission to modify this. If you change the default filter type, this setting will be lost and you will NOT be able to get it back.') . '</strong>';
+      // @todo - hmmm what.
+      $form[$option_name]['#description'] = RenderVariable::suffix($form[$option_name]['#description'], '<strong>', $this->t('Note: you do not have permission to modify this. If you change the default filter type, this setting will be lost and you will NOT be able to get it back.'), '</strong>');
     }
   }
 
diff --git a/core/tests/Drupal/Tests/Core/Render/RenderVariableTest.php b/core/tests/Drupal/Tests/Core/Render/RenderVariableTest.php
new file mode 100644
index 0000000..fd007c3
--- /dev/null
+++ b/core/tests/Drupal/Tests/Core/Render/RenderVariableTest.php
@@ -0,0 +1,95 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\Tests\Core\Render\RenderVariableTest.
+ */
+
+namespace Drupal\Tests\Core\Render;
+
+use Drupal\Core\Render\RenderVariable;
+use Drupal\Core\Render\SafeString;
+
+/**
+ * @coversDefaultClass \Drupal\Core\Render\RenderVariable
+ * @group Render
+ */
+class RenderVariableTest extends RendererTestBase {
+
+  /**
+   * @covers ::prefix
+   *
+   * @dataProvider providerRenderVariablePrefix
+   */
+  public function testRenderVariablePrefix($expected, $variable, array $prefixes) {
+    $args = $prefixes;
+    array_unshift($args, $variable);
+    $build = call_user_func_array([RenderVariable::class, 'prefix'], $args);
+    $render_output = $this->renderer->renderRoot($build);
+    $this->assertEquals($expected, (string) $render_output);
+  }
+
+  /**
+   * @return array
+   */
+  public function providerRenderVariablePrefix() {
+    $data = [];
+    $data[] = ['test&lt;em&gt;blah&lt;/em&gt;', '<em>blah</em>', ['test']];
+    $data[] = ['1 2 &lt;em&gt;blah&lt;/em&gt;', '<em>blah</em>', ['1', ' ', '2', ' ']];
+    $data[] = ['test<em>blah</em>', ['#markup' => '<em>blah</em>'], ['test']];
+    $data[] = ['test <em>blah</em>', ['#markup' => '<em>blah</em>'], ['test', ' ']];
+    $data[] = ['test<em>blah</em>', SafeString::create('<em>blah</em>'), ['test']];
+    $data[] = ['test <em>blah</em>', SafeString::create('<em>blah</em>'), ['test', ' ']];
+    return $data;
+  }
+
+  /**
+   * @covers ::suffix
+   *
+   * @dataProvider providerRenderVariableSuffix
+   */
+  public function testRenderVariableSuffix($expected, $variable, array $prefixes) {
+    $args = $prefixes;
+    array_unshift($args, $variable);
+    $build = call_user_func_array([RenderVariable::class, 'suffix'], $args);
+    $render_output = $this->renderer->renderRoot($build);
+    $this->assertEquals($expected, (string) $render_output);
+  }
+
+  /**
+   * @return array
+   */
+  public function providerRenderVariableSuffix() {
+    $data = [];
+    $data[] = ['&lt;em&gt;blah&lt;/em&gt;test', '<em>blah</em>', ['test']];
+    $data[] = ['&lt;em&gt;blah&lt;/em&gt;1 2', '<em>blah</em>', ['1', ' ', '2']];
+    $data[] = ['<em>blah</em>test', ['#markup' => '<em>blah</em>'], ['test']];
+    $data[] = ['<em>blah</em> test', ['#markup' => '<em>blah</em>'], [' ', 'test']];
+    $data[] = ['<em>blah</em>test', SafeString::create('<em>blah</em>'), ['test']];
+    $data[] = ['<em>blah</em> test', SafeString::create('<em>blah</em>'), [' ', 'test']];
+    return $data;
+  }
+
+  /**
+   * @covers ::wrap
+   *
+   * @dataProvider providerRenderVariableWrap
+   */
+  public function testRenderVariableWrap($expected, $variable, $prefix, $suffix) {
+    $build = RenderVariable::wrap($variable, $prefix, $suffix);
+    $render_output = $this->renderer->renderRoot($build);
+    $this->assertEquals($expected, (string) $render_output);
+  }
+
+  /**
+   * @return array
+   */
+  public function providerRenderVariableWrap() {
+    $data = [];
+    $data[] = ['<span>&lt;em&gt;blah&lt;/em&gt;</span>', '<em>blah</em>', '<span>', '</span>'];
+    $data[] = ['<span><em>blah</em></span>', ['#markup' => '<em>blah</em>'], '<span>', '</span>'];
+    $data[] = ['<span><em>bar</em></span>', SafeString::create('<em>bar</em>'), '<span>', '</span>'];
+    return $data;
+  }
+
+}
