diff --git a/core/lib/Drupal/Core/Action/ActionBase.php b/core/lib/Drupal/Core/Action/ActionBase.php
index cb009c30ef..407ebe15d6 100644
--- a/core/lib/Drupal/Core/Action/ActionBase.php
+++ b/core/lib/Drupal/Core/Action/ActionBase.php
@@ -23,4 +23,11 @@ public function executeMultiple(array $entities) {
     }
   }
 
+  /**
+   * {@inheritdoc}
+   */
+  public function getLabelArguments() {
+    return [];
+  }
+
 }
diff --git a/core/lib/Drupal/Core/Action/ActionInterface.php b/core/lib/Drupal/Core/Action/ActionInterface.php
index 5158f96a1f..bcceb73767 100644
--- a/core/lib/Drupal/Core/Action/ActionInterface.php
+++ b/core/lib/Drupal/Core/Action/ActionInterface.php
@@ -58,4 +58,11 @@ public function executeMultiple(array $objects);
    */
   public function access($object, AccountInterface $account = NULL, $return_as_object = FALSE);
 
+  /**
+   * Arguments for FormattableMarkup for a the label.
+   *
+   * @return string[]
+   */
+  public function getLabelArguments();
+
 }
diff --git a/core/modules/action/src/ActionFormBase.php b/core/modules/action/src/ActionFormBase.php
index 3fafd035ee..07e625d691 100644
--- a/core/modules/action/src/ActionFormBase.php
+++ b/core/modules/action/src/ActionFormBase.php
@@ -86,7 +86,7 @@ public function form(array $form, FormStateInterface $form_state) {
     ];
 
     if ($this->plugin instanceof PluginFormInterface) {
-      $form += $this->plugin->buildConfigurationForm($form, $form_state);
+      $form = $this->plugin->buildConfigurationForm($form, $form_state);
     }
 
     return parent::form($form, $form_state);
diff --git a/core/modules/simpletest/src/AssertContentTrait.php b/core/modules/simpletest/src/AssertContentTrait.php
index 5a6c8c06ef..cdb5036006 100644
--- a/core/modules/simpletest/src/AssertContentTrait.php
+++ b/core/modules/simpletest/src/AssertContentTrait.php
@@ -522,6 +522,18 @@ protected function assertNoEscaped($raw, $message = '', $group = 'Other') {
     return $this->assert(strpos($this->getRawContent(), Html::escape($raw)) === FALSE, $message, $group);
   }
 
+
+  /**
+   * Temporary assert.
+   * @param $raw
+   * @param $out
+   * @return mixed
+   */
+  protected function assertNotEscaped($raw, $out) {
+    $message = 'ESCAPÉ "' . Html::escape($raw) . '" NOT FOUND';
+    return $this->assert(strpos($out, Html::escape($raw)) === FALSE, $message, $group = 'Other');
+  }
+
   /**
    * Passes if the page (with HTML stripped) contains the text.
    *
diff --git a/core/modules/simpletest/src/WebTestBase.php b/core/modules/simpletest/src/WebTestBase.php
index b1a0258b57..31080194d6 100644
--- a/core/modules/simpletest/src/WebTestBase.php
+++ b/core/modules/simpletest/src/WebTestBase.php
@@ -912,6 +912,8 @@ protected function drupalGet($path, array $options = [], array $headers = []) {
     $verbose .= '<hr />' . $out;
 
     $this->verbose($verbose);
+    $this->assertNoEscaped('&lt;', $out);
+    $this->assertNoEscaped('&amp;', $out);
     return $out;
   }
 
@@ -1164,6 +1166,8 @@ protected function drupalPostForm($path, $edit, $submit, array $options = [], ar
           $verbose .= '<hr />' . $out;
 
           $this->verbose($verbose);
+          $this->assertNotEscaped('&lt;', $out);
+          $this->assertNotEscaped('&amp;', $out);
           return $out;
         }
       }
@@ -1465,7 +1469,7 @@ protected function drupalProcessAjaxResponse($content, array $ajax_response, arr
    * @see WebTestBase::curlExec()
    */
   protected function drupalPost($path, $accept, array $post, $options = []) {
-    return $this->curlExec([
+    $out = $this->curlExec([
       CURLOPT_URL => $this->buildUrl($path, $options),
       CURLOPT_POST => TRUE,
       CURLOPT_POSTFIELDS => $this->serializePostValues($post),
@@ -1474,6 +1478,10 @@ protected function drupalPost($path, $accept, array $post, $options = []) {
         'Content-Type: application/x-www-form-urlencoded',
       ],
     ]);
+
+    $this->assertNotEscaped('&lt;', $out);
+    $this->assertNotEscaped('&amp;', $out);
+    return $out;
   }
 
   /**
diff --git a/core/modules/system/src/Entity/Action.php b/core/modules/system/src/Entity/Action.php
index a4128384e2..ef17672ec7 100644
--- a/core/modules/system/src/Entity/Action.php
+++ b/core/modules/system/src/Entity/Action.php
@@ -2,8 +2,11 @@
 
 namespace Drupal\system\Entity;
 
+use Drupal\Component\Render\FormattableMarkup;
+use Drupal\Component\Render\PlainTextOutput;
 use Drupal\Core\Config\Entity\ConfigEntityBase;
 use Drupal\Core\Config\Entity\ConfigEntityInterface;
+use Drupal\Core\Entity\EntityStorageInterface;
 use Drupal\Core\Entity\EntityWithPluginCollectionInterface;
 use Drupal\system\ActionConfigEntityInterface;
 use Drupal\Core\Action\ActionPluginCollection;
@@ -81,6 +84,7 @@ class Action extends ConfigEntityBase implements ActionConfigEntityInterface, En
    */
   protected function getPluginCollection() {
     if (!$this->pluginCollection) {
+      $this->configuration['original_label'] = parent::label();
       $this->pluginCollection = new ActionPluginCollection(\Drupal::service('plugin.manager.action'), $this->plugin, $this->configuration);
     }
     return $this->pluginCollection;
@@ -150,4 +154,24 @@ public static function sort(ConfigEntityInterface $a, ConfigEntityInterface $b)
     return parent::sort($a, $b);
   }
 
+  /**
+   * @inheritDoc
+   */
+  public function label() {
+    $plugin = $this->getPlugin();
+    $label = new FormattableMarkup(parent::label(), $plugin->getLabelArguments());
+    // Remove the safeness from the label as the label can contain user input.
+    return PlainTextOutput::renderFromHtml($label);
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function preSave(EntityStorageInterface $storage) {
+    parent::preSave($storage);
+    // Remove original label when saving so as this does not need to be stored
+    // in configuration.
+    unset($this->configuration['original_label']);
+  }
+
 }
diff --git a/core/modules/system/src/Plugin/views/field/BulkForm.php b/core/modules/system/src/Plugin/views/field/BulkForm.php
index 65fdc51cc7..392ac85a65 100644
--- a/core/modules/system/src/Plugin/views/field/BulkForm.php
+++ b/core/modules/system/src/Plugin/views/field/BulkForm.php
@@ -287,7 +287,9 @@ public function viewsForm(&$form, FormStateInterface $form_state) {
       $form['header'][$this->options['id']]['action'] = [
         '#type' => 'select',
         '#title' => $this->options['action_title'],
-        '#options' => $this->getBulkOptions(),
+        // This is a select list therefore apply the plain text formatter to the
+        // the options which are escaped for display in HTML.
+        '#options' =>  array_map('\Drupal\Component\Render\PlainTextOutput::renderFromHtml', $this->getBulkOptions()),
       ];
 
       // Duplicate the form actions into the action container in the header.
diff --git a/core/modules/user/src/Plugin/Action/ChangeUserRoleBase.php b/core/modules/user/src/Plugin/Action/ChangeUserRoleBase.php
index de4c4040fe..0c2945d6b0 100644
--- a/core/modules/user/src/Plugin/Action/ChangeUserRoleBase.php
+++ b/core/modules/user/src/Plugin/Action/ChangeUserRoleBase.php
@@ -9,6 +9,7 @@
 use Drupal\Core\Plugin\ContainerFactoryPluginInterface;
 use Drupal\Core\Session\AccountInterface;
 use Drupal\user\RoleInterface;
+use Drupal\user\RoleStorageInterface;
 use Symfony\Component\DependencyInjection\ContainerInterface;
 
 /**
@@ -26,11 +27,19 @@
   protected $entityType;
 
   /**
+   * The user role storage.
+   *
+   * @var \Drupal\Core\Entity\EntityTypeInterface
+   */
+  protected $roleStorage;
+
+  /**
    * {@inheritdoc}
    */
-  public function __construct(array $configuration, $plugin_id, $plugin_definition, EntityTypeInterface $entity_type) {
+  public function __construct(array $configuration, $plugin_id, $plugin_definition, EntityTypeInterface $entity_type, RoleStorageInterface $role_storage) {
     parent::__construct($configuration, $plugin_id, $plugin_definition);
     $this->entityType = $entity_type;
+    $this->roleStorage = $role_storage;
   }
 
   /**
@@ -41,7 +50,8 @@ public static function create(ContainerInterface $container, array $configuratio
       $configuration,
       $plugin_id,
       $plugin_definition,
-      $container->get('entity.manager')->getDefinition('user_role')
+      $container->get('entity.manager')->getDefinition('user_role'),
+      $container->get('entity.manager')->getStorage('user_role')
     );
   }
 
@@ -58,6 +68,14 @@ public function defaultConfiguration() {
    * {@inheritdoc}
    */
   public function buildConfigurationForm(array $form, FormStateInterface $form_state) {
+    // The label supports replacing @label with the role's label.
+    $form['label'] = [
+      '#type' => 'textfield',
+      '#title' => $this->t('Label'),
+      '#default_value' => $this->configuration['original_label'],
+      '#maxlength' => '255',
+      '#description' => $this->t('A unique label for this advanced action. This label will be displayed in the interface of modules that integrate with actions. @role_label is replaced with the role\'s label.'),
+    ];
     $roles = user_role_names(TRUE);
     unset($roles[RoleInterface::AUTHENTICATED_ID]);
     $form['rid'] = [
@@ -99,4 +117,15 @@ public function access($object, AccountInterface $account = NULL, $return_as_obj
     return $return_as_object ? $access : $access->isAllowed();
   }
 
+  /**
+   * {@inheritdoc}
+   */
+  public function getLabelArguments() {
+    if (!empty($this->configuration['rid'])) {
+      $role = $this->roleStorage->load($this->configuration['rid']);
+      return ['@role_label' => $role->label()];
+    }
+    return [];
+  }
+
 }
diff --git a/core/modules/user/tests/src/Unit/Plugin/Action/AddRoleUserTest.php b/core/modules/user/tests/src/Unit/Plugin/Action/AddRoleUserTest.php
index 5ca694b84e..5f7d803855 100644
--- a/core/modules/user/tests/src/Unit/Plugin/Action/AddRoleUserTest.php
+++ b/core/modules/user/tests/src/Unit/Plugin/Action/AddRoleUserTest.php
@@ -23,7 +23,7 @@ public function testExecuteAddExistingRole() {
       ->will($this->returnValue(TRUE));
 
     $config = ['rid' => 'test_role_1'];
-    $remove_role_plugin = new AddRoleUser($config, 'user_add_role_action', ['type' => 'user'], $this->userRoleEntityType);
+    $remove_role_plugin = new AddRoleUser($config, 'user_add_role_action', ['type' => 'user'], $this->userRoleEntityType, $this->roleStorage);
 
     $remove_role_plugin->execute($this->account);
   }
@@ -41,7 +41,7 @@ public function testExecuteAddNonExistingRole() {
       ->will($this->returnValue(FALSE));
 
     $config = ['rid' => 'test_role_1'];
-    $remove_role_plugin = new AddRoleUser($config, 'user_remove_role_action', ['type' => 'user'], $this->userRoleEntityType);
+    $remove_role_plugin = new AddRoleUser($config, 'user_remove_role_action', ['type' => 'user'], $this->userRoleEntityType, $this->roleStorage);
 
     $remove_role_plugin->execute($this->account);
   }
diff --git a/core/modules/user/tests/src/Unit/Plugin/Action/RoleUserTestBase.php b/core/modules/user/tests/src/Unit/Plugin/Action/RoleUserTestBase.php
index a487d82ee1..adf6b46217 100644
--- a/core/modules/user/tests/src/Unit/Plugin/Action/RoleUserTestBase.php
+++ b/core/modules/user/tests/src/Unit/Plugin/Action/RoleUserTestBase.php
@@ -3,6 +3,7 @@
 namespace Drupal\Tests\user\Unit\Plugin\Action;
 
 use Drupal\Tests\UnitTestCase;
+use Drupal\user\RoleStorageInterface;
 
 /**
  * Provides a base class for user role action tests.
@@ -24,6 +25,13 @@
   protected $userRoleEntityType;
 
   /**
+   * The role storage.
+   *
+   * @var \Drupal\user\RoleStorageInterface|\PHPUnit_Framework_MockObject_MockObject
+   */
+  protected $roleStorage;
+
+  /**
    * {@inheritdoc}
    */
   protected function setUp() {
@@ -34,6 +42,7 @@ protected function setUp() {
       ->disableOriginalConstructor()
       ->getMock();
     $this->userRoleEntityType = $this->getMock('Drupal\Core\Entity\EntityTypeInterface');
+    $this->roleStorage = $this->getMock(RoleStorageInterface::class);
   }
 
 }
diff --git a/core/modules/user/user.module b/core/modules/user/user.module
index b865e958d9..610a10c847 100644
--- a/core/modules/user/user.module
+++ b/core/modules/user/user.module
@@ -1003,7 +1003,7 @@ function user_user_role_insert(RoleInterface $role) {
     $action = Action::create([
       'id' => $add_id,
       'type' => 'user',
-      'label' => t('Add the @label role to the selected users', ['@label' => $role->label()]),
+      'label' => t('Add the @role_label role to the selected users'),
       'configuration' => [
         'rid' => $role->id(),
       ],
@@ -1016,7 +1016,7 @@ function user_user_role_insert(RoleInterface $role) {
     $action = Action::create([
       'id' => $remove_id,
       'type' => 'user',
-      'label' => t('Remove the @label role from the selected users', ['@label' => $role->label()]),
+      'label' => t('Remove the @role_label role from the selected users'),
       'configuration' => [
         'rid' => $role->id(),
       ],
