diff --git a/core/includes/bootstrap.inc b/core/includes/bootstrap.inc
index 481adea..29f5d8c 100644
--- a/core/includes/bootstrap.inc
+++ b/core/includes/bootstrap.inc
@@ -1406,6 +1406,17 @@ function check_plain($text) {
   return String::checkPlain($text);
 }
 
+function drupal_mark_safe($string) {
+  global $safe_strings;
+  $safe_strings[$string] = TRUE;
+  return $string;
+}
+
+function drupal_is_safe($string) {
+  global $safe_strings;
+  return isset($safe_strings[$string]);
+}
+
 /**
  * Checks whether a string is valid UTF-8.
  *
diff --git a/core/includes/common.inc b/core/includes/common.inc
index 1980f2f..bc6fac6 100644
--- a/core/includes/common.inc
+++ b/core/includes/common.inc
@@ -413,7 +413,7 @@ function drupal_add_feed($url = NULL, $title = '') {
  */
 function drupal_get_feeds($delimiter = "\n") {
   $feeds = drupal_add_feed();
-  return implode($feeds, $delimiter);
+  return drupal_mark_safe(implode($feeds, $delimiter));
 }
 
 /**
@@ -1366,7 +1366,9 @@ function l($text, $path, array $options = array()) {
   // Sanitize the link text if necessary.
   $text = $variables['options']['html'] ? $variables['text'] : check_plain($variables['text']);
 
-  return '<a href="' . $url . '"' . $attributes . '>' . $text . '</a>';
+  $string = ('<a href="' . $url . '"' . $attributes . '>' . $text . '</a>');
+  $GLOBALS['safe_strings'][$string] = TRUE;
+  return $string;
 }
 
 /**
@@ -3916,7 +3918,7 @@ function drupal_render(&$elements) {
 
   $prefix = isset($elements['#prefix']) ? $elements['#prefix'] : '';
   $suffix = isset($elements['#suffix']) ? $elements['#suffix'] : '';
-  $output = $prefix . $elements['#children'] . $suffix;
+  $output = ($prefix) . $elements['#children'] . ($suffix);
 
   // Cache the processed element if #cache is set.
   if (isset($elements['#cache'])) {
diff --git a/core/includes/theme.inc b/core/includes/theme.inc
index da3df24..4819ae9 100644
--- a/core/includes/theme.inc
+++ b/core/includes/theme.inc
@@ -1122,7 +1122,8 @@ function theme($hook, $variables = array()) {
 
   // restore path_to_theme()
   $theme_path = $temp;
-  return $output;
+  $GLOBALS['safe_strings'][$output] = TRUE;
+  return ($output);
 }
 
 /**
diff --git a/core/lib/Drupal/Component/Utility/String.php b/core/lib/Drupal/Component/Utility/String.php
index 3cd6472..81968b3 100644
--- a/core/lib/Drupal/Component/Utility/String.php
+++ b/core/lib/Drupal/Component/Utility/String.php
@@ -29,7 +29,9 @@ class String {
    * @ingroup sanitization
    */
   public static function checkPlain($text) {
-    return htmlspecialchars($text, ENT_QUOTES, 'UTF-8');
+    $string = (htmlspecialchars($text, ENT_QUOTES, 'UTF-8'));
+    $GLOBALS['safe_strings'][$string] = TRUE;
+    return $string;
   }
 
   /**
@@ -105,7 +107,7 @@ public static function format($string, array $args = array()) {
           // Pass-through.
       }
     }
-    return strtr($string, $args);
+    return drupal_mark_safe(strtr($string, $args));
   }
 
   /**
diff --git a/core/lib/Drupal/Component/Utility/Xss.php b/core/lib/Drupal/Component/Utility/Xss.php
index 8d0d257..7b0780e 100644
--- a/core/lib/Drupal/Component/Utility/Xss.php
+++ b/core/lib/Drupal/Component/Utility/Xss.php
@@ -71,7 +71,7 @@ public static function filter($string, $allowed_tags = array('a', 'em', 'strong'
     // Named entities.
     $string = preg_replace('/&amp;([A-Za-z][A-Za-z0-9]*;)/', '&\1', $string);
 
-    return preg_replace_callback('%
+    return drupal_mark_safe(preg_replace_callback('%
       (
       <(?=[^a-zA-Z!/])  # a lone <
       |                 # or
@@ -80,7 +80,7 @@ public static function filter($string, $allowed_tags = array('a', 'em', 'strong'
       <[^>]*(>|$)       # a string that starts with a <, up until the > or the end of the string
       |                 # or
       >                 # just a >
-      )%x', '\Drupal\Component\Utility\Xss::split', $string);
+      )%x', '\Drupal\Component\Utility\Xss::split', $string));
   }
 
   /**
diff --git a/core/lib/Drupal/Core/CoreServiceProvider.php b/core/lib/Drupal/Core/CoreServiceProvider.php
index a6cb957..36c7deb 100644
--- a/core/lib/Drupal/Core/CoreServiceProvider.php
+++ b/core/lib/Drupal/Core/CoreServiceProvider.php
@@ -118,9 +118,7 @@ public static function registerTwig(ContainerBuilder $container) {
         // files folder is writable.
         'cache' => drupal_installation_attempted() ? FALSE : settings()->get('twig_cache', TRUE),
         'base_template_class' => 'Drupal\Core\Template\TwigTemplate',
-        // @todo Remove in followup issue
-        // @see http://drupal.org/node/1712444.
-        'autoescape' => FALSE,
+        'autoescape' => TRUE,
         // @todo Remove in followup issue
         // @see http://drupal.org/node/1806538.
         'strict_variables' => FALSE,
diff --git a/core/lib/Drupal/Core/StringTranslation/TranslationManager.php b/core/lib/Drupal/Core/StringTranslation/TranslationManager.php
index 130ee9d..6826359 100644
--- a/core/lib/Drupal/Core/StringTranslation/TranslationManager.php
+++ b/core/lib/Drupal/Core/StringTranslation/TranslationManager.php
@@ -137,6 +137,7 @@ public function translate($string, array $args = array(), array $options = array
     $string = $translation === FALSE ? $string : $translation;
 
     if (empty($args)) {
+      // @todo: Deliberately not marked as safe. Or should it be?
       return $string;
     }
     else {
diff --git a/core/lib/Drupal/Core/Template/Attribute.php b/core/lib/Drupal/Core/Template/Attribute.php
index 076cfd3..386feaa 100644
--- a/core/lib/Drupal/Core/Template/Attribute.php
+++ b/core/lib/Drupal/Core/Template/Attribute.php
@@ -30,7 +30,7 @@
  *  // Produces <cat class="cat black-cat white-cat black-white-cat" id="socks">
  * @endcode
  */
-class Attribute implements \ArrayAccess, \IteratorAggregate {
+class Attribute extends \Twig_Markup implements \ArrayAccess, \IteratorAggregate {
 
   /**
    * Stores the attribute data.
@@ -73,6 +73,9 @@ public function offsetSet($name, $value) {
     elseif (!is_object($value)) {
       $value = new AttributeString($name, $value);
     }
+    elseif ($value instanceof \Twig_Markup) {
+      $value = new AttributeString($name, (string)$value);
+    }
     // The $name could be NULL.
     if (isset($name)) {
       $this->storage[$name] = $value;
diff --git a/core/lib/Drupal/Core/Template/AttributeValueBase.php b/core/lib/Drupal/Core/Template/AttributeValueBase.php
index df187df..4411c0b 100644
--- a/core/lib/Drupal/Core/Template/AttributeValueBase.php
+++ b/core/lib/Drupal/Core/Template/AttributeValueBase.php
@@ -12,7 +12,7 @@
  *
  * @see Drupal\Core\Template\Attribute
  */
-abstract class AttributeValueBase {
+abstract class AttributeValueBase extends \Twig_Markup {
 
   /**
    * Whether this attribute hsa been printed already.
@@ -69,6 +69,8 @@ public function printed() {
   /**
    * Implements the magic __toString() method.
    */
-  abstract function __toString();
+  public function __toString() {
+    return parent::__toString();
+  }
 
 }
diff --git a/core/lib/Drupal/Core/Template/TwigExtension.php b/core/lib/Drupal/Core/Template/TwigExtension.php
index 9cd17b0..7425e90 100644
--- a/core/lib/Drupal/Core/Template/TwigExtension.php
+++ b/core/lib/Drupal/Core/Template/TwigExtension.php
@@ -40,6 +40,8 @@ public function getFilters() {
       // @see TwigNodeTrans::compileString()
       'passthrough' => new \Twig_Filter_Function('twig_raw_filter'),
       'placeholder' => new \Twig_Filter_Function('twig_raw_filter'),
+      // Helper filter used to replace twig's original raw() filter.
+      'twig_raw' => 'twig_raw',
     );
   }
 
diff --git a/core/lib/Drupal/Core/Template/TwigNodeVisitor.php b/core/lib/Drupal/Core/Template/TwigNodeVisitor.php
index 710faa0..e14a311 100644
--- a/core/lib/Drupal/Core/Template/TwigNodeVisitor.php
+++ b/core/lib/Drupal/Core/Template/TwigNodeVisitor.php
@@ -58,6 +58,8 @@ function enterNode(\Twig_NodeInterface $node, \Twig_Environment $env) {
    * We use this to inject a call to render_var -> twig_render_var()
    * before anything is printed.
    *
+   * We also change the 'raw' filter to our own 'twig_raw' filter.
+   *
    * @see twig_render
    */
   function leaveNode(\Twig_NodeInterface $node, \Twig_Environment $env) {
@@ -70,6 +72,10 @@ function leaveNode(\Twig_NodeInterface $node, \Twig_Environment $env) {
         $node->getLine()
       );
     }
+    else if ($node instanceof \Twig_Node_Expression_Filter && 'raw' == $node->getNode('filter')->getAttribute('value')) {
+      // Use our own twig_raw filter that returns Twig_Markup
+      $node->getNode('filter')->setAttribute('value', 'twig_raw');
+    }
 
     if ($this->isReference) {
       if ($node instanceof \Twig_Node_Expression_Name) {
diff --git a/core/modules/filter/filter.module b/core/modules/filter/filter.module
index 1a0d9d1..23b9db6 100644
--- a/core/modules/filter/filter.module
+++ b/core/modules/filter/filter.module
@@ -711,7 +711,8 @@ function check_markup($text, $format_id = NULL, $langcode = '', $cache = FALSE,
   if ($cache) {
     $cache_id = $format->format . ':' . $langcode . ':' . hash('sha256', $text);
     if ($cached = cache('filter')->get($cache_id)) {
-      return $cached->data;
+      // @todo: The caller is responsible that this is really safe.
+      return drupal_mark_safe($cached->data);
     }
   }
 
@@ -752,7 +753,8 @@ function check_markup($text, $format_id = NULL, $langcode = '', $cache = FALSE,
     cache('filter')->set($cache_id, $text, CacheBackendInterface::CACHE_PERMANENT, array('filter_format' => $format->format));
   }
 
-  return $text;
+  // @todo: The caller is responsible that this is really safe.
+  return drupal_mark_safe($text);
 }
 
 /**
diff --git a/core/themes/engines/twig/twig.engine b/core/themes/engines/twig/twig.engine
index b541cdc..bc7e75d 100644
--- a/core/themes/engines/twig/twig.engine
+++ b/core/themes/engines/twig/twig.engine
@@ -110,12 +110,20 @@ function twig_render_var($arg) {
     return NULL;
   }
 
-  // Keep Twig_Markup objects intact to prepare for later autoescaping support
+  // Keep Twig_Markup objects intact to support autoescaping.
   if ($arg instanceOf Twig_Markup) {
     return $arg;
   }
 
+  // Treat output from RenderWrapper as safe, return a Twig_Markup instance.
+  if ($arg instanceof \Drupal\Core\Template\RenderWrapper) {
+    return new Twig_Markup((string) $arg, 'UTF-8');
+  }
+
   if (is_scalar($arg)) {
+    if (isset($GLOBALS['safe_strings'][$arg])) {
+      return new Twig_Markup($arg, 'UTF-8');
+    }
     return $arg;
   }
 
@@ -127,7 +135,7 @@ function twig_render_var($arg) {
   }
 
   // This is a normal render array.
-  return render($arg);
+  return new Twig_Markup(render($arg), 'UTF-8');
 }
 
 /**
@@ -155,3 +163,20 @@ function twig_show($element) {
   }
   // @todo Add warning in else case
 }
+
+/**
+ * Replacement function for twig's raw filter
+ *
+ * This needs to be used, because the default raw
+ * filter gets optimized out.
+ *
+ * As we wrap everything that is printed in twig_render()
+ * we need to return Twig_Markup instead.
+ * This allows to hold the information that a value was
+ * marked 'raw' by the template author.
+ *
+ * @see TwigNodeVisitor
+ */
+function twig_raw($string) {
+  return new Twig_Markup($string, 'UTF-8');
+}
diff --git a/core/vendor/twig/twig/lib/Twig/Extension/Core.php b/core/vendor/twig/twig/lib/Twig/Extension/Core.php
index 26e7017..fa92f5e 100644
--- a/core/vendor/twig/twig/lib/Twig/Extension/Core.php
+++ b/core/vendor/twig/twig/lib/Twig/Extension/Core.php
@@ -847,7 +847,7 @@ function twig_in_filter($value, $compare)
  */
 function twig_escape_filter(Twig_Environment $env, $string, $strategy = 'html', $charset = null, $autoescape = false)
 {
-    if ($autoescape && is_object($string) && $string instanceof Twig_Markup) {
+    if ($autoescape && $string instanceof Twig_Markup) {
         return $string;
     }
 
