diff --git a/core/lib/Drupal/Component/Utility/AttributeSafeStringInterface.php b/core/lib/Drupal/Component/Utility/AttributeSafeStringInterface.php
new file mode 100644
index 0000000..ade7311
--- /dev/null
+++ b/core/lib/Drupal/Component/Utility/AttributeSafeStringInterface.php
@@ -0,0 +1,56 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\Component\Utility\AttributeSafeStringInterface.
+ */
+
+namespace Drupal\Component\Utility;
+
+/**
+ * Marks an object's __toString() method as returning escaped markup.
+ *
+ * All objects that implement this interface should be marked @internal.
+ *
+ * This interface should only be used on objects that emit escaped strings
+ * from their __toString() method that are suitable to be used for HTML
+ * attribute values. If there is any risk of the method returning
+ * user-entered data that has not been escaped, it must not be used.
+ *
+ * If the object is going to be used directly in Twig templates it should
+ * implement \Countable so it can be used in if statements.
+ *
+ * @internal
+ *   This interface is marked as internal because it should only be used by
+ *   objects used during rendering. This interface should be used by modules if
+ *   they interrupt the render pipeline and explicitly deal with SafeString
+ *   objects created by the render system. Additionally, if a module reuses the
+ *   regular render pipeline internally and passes processed data into it. For
+ *   example, Views implements a custom render pipeline in order to render JSON
+ *   and to fast render fields.
+ *
+ * @see \Drupal\Component\Utility\SafeStringTrait
+ * @see \Drupal\Component\Utility\SafeMarkup::isSafe()
+ * @see \Drupal\Core\Template\TwigExtension::escapeFilter()
+ */
+interface AttributeSafeStringInterface {
+
+  /**
+   * Returns a safe string.
+   *
+   * @return string
+   *   The safe string.
+   */
+  public function __toString();
+
+  /**
+   * Creates a new object after applying escaping to a string.
+   *
+   * @param mixed $string
+   *   The string to mark as safe. This value will be cast to a string.
+   *
+   * @return string|\Drupal\Component\Utility\AttributeSafeStringInterface
+   *   A new object.
+   */
+  public static function createFromHtml($string);
+}
diff --git a/core/lib/Drupal/Component/Utility/UriAttributeSafeStringInterface.php b/core/lib/Drupal/Component/Utility/UriAttributeSafeStringInterface.php
new file mode 100644
index 0000000..d92d238
--- /dev/null
+++ b/core/lib/Drupal/Component/Utility/UriAttributeSafeStringInterface.php
@@ -0,0 +1,57 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\Component\Utility\UriAttributeSafeStringInterface.
+ */
+
+namespace Drupal\Component\Utility;
+
+/**
+ * Marks a __toString() method as returning protocol-filtered, escaped markup.
+ *
+ * All objects that implement this interface should be marked @internal.
+ *
+ * This interface should only be used on objects that emit escaped strings
+ * that have had dangerous protocols filtered out from their __toString() method
+ * that are suitable to be used for HTML URI attribute values like HREF and SRC.
+ * If there is any risk of the method returning user-entered data that has not
+ * been escaped, it must not be used.
+ *
+ * If the object is going to be used directly in Twig templates it should
+ * implement \Countable so it can be used in if statements.
+ *
+ * @internal
+ *   This interface is marked as internal because it should only be used by
+ *   objects used during rendering. This interface should be used by modules if
+ *   they interrupt the render pipeline and explicitly deal with SafeString
+ *   objects created by the render system. Additionally, if a module reuses the
+ *   regular render pipeline internally and passes processed data into it. For
+ *   example, Views implements a custom render pipeline in order to render JSON
+ *   and to fast render fields.
+ *
+ * @see \Drupal\Component\Utility\SafeStringTrait
+ * @see \Drupal\Component\Utility\SafeMarkup::isSafe()
+ * @see \Drupal\Core\Template\TwigExtension::escapeFilter()
+ */
+interface UriAttributeSafeStringInterface {
+
+  /**
+   * Returns a safe string.
+   *
+   * @return string
+   *   The safe string.
+   */
+  public function __toString();
+
+  /**
+   * Creates a new object after applying escaping to a string.
+   *
+   * @param mixed $string
+   *   The string to mark as safe. This value will be cast to a string.
+   *
+   * @return string|\Drupal\Component\Utility\AttributeSafeStringInterface
+   *   A new object.
+   */
+  public static function createFromHtml($string);
+}
diff --git a/core/lib/Drupal/Core/Render/AttributeSafeString.php b/core/lib/Drupal/Core/Render/AttributeSafeString.php
new file mode 100644
index 0000000..835e55b
--- /dev/null
+++ b/core/lib/Drupal/Core/Render/AttributeSafeString.php
@@ -0,0 +1,92 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\Core\Render\AttributeSafeString.
+ */
+
+namespace Drupal\Core\Render;
+
+use Drupal\Component\Utility\AttributeSafeStringInterface;
+use Drupal\Component\Utility\SafeStringInterface;
+use Drupal\Core\Render\Element\Html;
+
+/**
+ * Defines an object that holds a string that is safe to use in HTML attributes.
+ *
+ * This object should only be constructed with a known safe string that is
+ * escaped and suitable to be used for HTML attribute values. If there is any
+ * risk of the method returning user-entered data that has not been escaped, it
+ * must not be used.
+ *
+ * @internal
+ *   This object is marked as internal because it should only be used whilst
+ *   rendering.
+ *
+ * @see \Drupal\Core\Template\TwigExtension::escapeFilter
+ * @see \Twig_Markup
+ * @see \Drupal\Component\Utility\SafeMarkup
+ */
+final class AttributeSafeString implements AttributeSafeStringInterface, SafeStringInterface {
+  /**
+   * The safe string.
+   *
+   * @var string
+   */
+  protected $string;
+
+  /**
+   * Creates a SafeString object if necessary.
+   *
+   * If $string is equal to a blank string then it is not necessary to create a
+   * SafeString object. If $string is an object that implements
+   * SafeStringInterface it is returned unchanged.
+   *
+   * @param mixed $string
+   *   The string to mark as safe. This value will be cast to a string.
+   *
+   * @return string|\Drupal\Component\Utility\SafeStringInterface
+   *   A safe string.
+   */
+  public static function create($string) {
+    if ($string instanceof AttributeSafeStringInterface) {
+      return $string;
+    }
+    $string = (string) $string;
+    if ($string === '') {
+      return '';
+    }
+    $safe_string = new static();
+    $safe_string->string = $string;
+    return $safe_string;
+  }
+
+  /**
+   * @{inheritdoc}
+   */
+  public static function createFromHtml($string) {
+    // @todo use HtmlAttributeValueOutput::renderFromHtml() when
+    //   https://www.drupal.org/node/2509218 is done.
+    return static::create(Html::escape(Html::decodeEntities(strip_tags((string) $string))));
+  }
+
+  /**
+   * Returns the string version of the SafeString object.
+   *
+   * @return string
+   *   The safe string content.
+   */
+  public function __toString() {
+    return $this->string;
+  }
+
+  /**
+   * Returns a representation of the object for use in JSON serialization.
+   *
+   * @return string
+   *   The safe string content.
+   */
+  public function jsonSerialize() {
+    return $this->__toString();
+  }
+}
