 core/core.services.yml                                  |  2 +-
 .../src/Tests/BlockContentCacheTagsTest.php             |  2 +-
 core/modules/comment/src/Tests/CommentCacheTagsTest.php |  6 +-----
 core/modules/filter/src/Tests/FilterAPITest.php         |  1 +
 core/modules/menu_ui/src/Tests/MenuCacheTagsTest.php    |  3 ++-
 core/modules/node/src/Tests/NodeListBuilderTest.php     |  2 +-
 .../system/src/Tests/Entity/EntityCacheTagsTestBase.php | 17 +++++++++++++----
 .../system/src/Tests/Entity/EntityListBuilderTest.php   |  2 +-
 .../system/src/Tests/Entity/EntityViewBuilderTest.php   |  6 +++---
 .../src/Tests/Entity/EntityWithUriCacheTagsTestBase.php |  2 +-
 core/modules/tour/src/Tests/TourCacheTagsTest.php       |  2 ++
 sites/default/default.services.yml                      |  4 ++--
 12 files changed, 29 insertions(+), 20 deletions(-)

diff --git a/core/core.services.yml b/core/core.services.yml
index d44bcb1..afe30ba 100644
--- a/core/core.services.yml
+++ b/core/core.services.yml
@@ -2,7 +2,7 @@ parameters:
   session.storage.options: {}
   twig.config: {}
   renderer.config:
-    required_cache_contexts: ['languages:language_interface', 'theme']
+    required_cache_contexts: ['languages:language_interface', 'theme', 'user.permissions']
   factory.keyvalue:
     default: keyvalue.database
   factory.keyvalue.expirable:
diff --git a/core/modules/block_content/src/Tests/BlockContentCacheTagsTest.php b/core/modules/block_content/src/Tests/BlockContentCacheTagsTest.php
index 582d832..c8044dc 100644
--- a/core/modules/block_content/src/Tests/BlockContentCacheTagsTest.php
+++ b/core/modules/block_content/src/Tests/BlockContentCacheTagsTest.php
@@ -90,7 +90,7 @@ public function testBlock() {
     // Expected keys, contexts, and tags for the block.
     // @see \Drupal\block\BlockViewBuilder::viewMultiple()
     $expected_block_cache_keys = ['entity_view', 'block', $block->id()];
-    $expected_block_cache_contexts = ['languages:' . LanguageInterface::TYPE_INTERFACE, 'theme'];
+    $expected_block_cache_contexts = ['languages:' . LanguageInterface::TYPE_INTERFACE, 'theme', 'user.permissions'];
     $expected_block_cache_tags = Cache::mergeTags(['block_view', 'rendered'], $block->getCacheTags(), $block->getPlugin()->getCacheTags());
 
     // Expected contexts and tags for the BlockContent entity.
diff --git a/core/modules/comment/src/Tests/CommentCacheTagsTest.php b/core/modules/comment/src/Tests/CommentCacheTagsTest.php
index 5226434..2393d96 100644
--- a/core/modules/comment/src/Tests/CommentCacheTagsTest.php
+++ b/core/modules/comment/src/Tests/CommentCacheTagsTest.php
@@ -86,11 +86,7 @@ protected function createEntity() {
    * {@inheritdoc}
    */
   protected function getAdditionalCacheContextsForEntity(EntityInterface $entity) {
-    return [
-      // Field access for the user picture rendered as part of the node that
-      // this comment is created on.
-      'user.permissions',
-    ];
+    return [];
   }
 
   /**
diff --git a/core/modules/filter/src/Tests/FilterAPITest.php b/core/modules/filter/src/Tests/FilterAPITest.php
index 483bc22..4923962 100644
--- a/core/modules/filter/src/Tests/FilterAPITest.php
+++ b/core/modules/filter/src/Tests/FilterAPITest.php
@@ -264,6 +264,7 @@ function testProcessedTextElement() {
       // The default cache contexts for Renderer.
       'languages:' . LanguageInterface::TYPE_INTERFACE,
       'theme',
+      'user.permissions',
     ];
     $this->assertEqual($expected_cache_contexts, $build['#cache']['contexts'], 'Expected cache contexts present.');
     $expected_markup = '<p>Hello, world!</p><p>This is a dynamic llama.</p>';
diff --git a/core/modules/menu_ui/src/Tests/MenuCacheTagsTest.php b/core/modules/menu_ui/src/Tests/MenuCacheTagsTest.php
index 45a9df7..e0c0fc7 100644
--- a/core/modules/menu_ui/src/Tests/MenuCacheTagsTest.php
+++ b/core/modules/menu_ui/src/Tests/MenuCacheTagsTest.php
@@ -54,6 +54,7 @@ public function testMenuBlock() {
       'config:block_list',
       'config:block.block.' . $block->id(),
       'config:system.menu.llama',
+      'config:user.role.anonymous',
     );
     $this->verifyPageCache($url, 'HIT', $expected_tags);
 
@@ -107,7 +108,7 @@ public function testMenuBlock() {
     $this->verifyPageCache($url, 'MISS');
 
     // Verify a cache hit.
-    $this->verifyPageCache($url, 'HIT', ['config:block_list', 'rendered']);
+    $this->verifyPageCache($url, 'HIT', ['config:block_list', 'config:user.role.anonymous', 'rendered']);
   }
 
 }
diff --git a/core/modules/node/src/Tests/NodeListBuilderTest.php b/core/modules/node/src/Tests/NodeListBuilderTest.php
index 798a056..2d23604 100644
--- a/core/modules/node/src/Tests/NodeListBuilderTest.php
+++ b/core/modules/node/src/Tests/NodeListBuilderTest.php
@@ -39,7 +39,7 @@ public function testCacheContexts() {
     $build = $list_builder->render();
     $this->container->get('renderer')->renderRoot($build);
 
-    $this->assertEqual(['languages:' . LanguageInterface::TYPE_INTERFACE, 'theme', 'url.query_args.pagers:0', 'user.node_grants:view'], $build['#cache']['contexts']);
+    $this->assertEqual(['languages:' . LanguageInterface::TYPE_INTERFACE, 'theme', 'url.query_args.pagers:0', 'user.node_grants:view', 'user.permissions'], $build['#cache']['contexts']);
   }
 
 }
diff --git a/core/modules/system/src/Tests/Entity/EntityCacheTagsTestBase.php b/core/modules/system/src/Tests/Entity/EntityCacheTagsTestBase.php
index 0b365cb..df593d8 100644
--- a/core/modules/system/src/Tests/Entity/EntityCacheTagsTestBase.php
+++ b/core/modules/system/src/Tests/Entity/EntityCacheTagsTestBase.php
@@ -132,6 +132,8 @@ protected static function generateStandardizedInfo($entity_type_label, $group) {
   /**
    * Returns the access cache contexts for the tested entity.
    *
+   * Only list cache contexts that aren't part of the required cache contexts.
+   *
    * @param \Drupal\Core\Entity\EntityInterface $entity
    *   The entity to be tested, as created by createEntity().
    *
@@ -141,12 +143,14 @@ protected static function generateStandardizedInfo($entity_type_label, $group) {
    * @see \Drupal\Core\Entity\EntityAccessControlHandlerInterface
    */
   protected function getAccessCacheContextsForEntity(EntityInterface $entity) {
-    return ['user.permissions'];
+    return [];
   }
 
   /**
    * Returns the additional (non-standard) cache contexts for the tested entity.
    *
+   * Only list cache contexts that aren't part of the required cache contexts.
+   *
    * @param \Drupal\Core\Entity\EntityInterface $entity
    *   The entity to be tested, as created by createEntity().
    *
@@ -331,12 +335,16 @@ public function testReferencedEntity() {
     $nonempty_entity_listing_url = Url::fromRoute('entity.entity_test.collection_labels_alphabetically', ['entity_type_id' => $entity_type]);
 
     // The default cache contexts for rendered entities.
-    $default_cache_contexts = ['languages:' . LanguageInterface::TYPE_INTERFACE, 'theme'];
+    $default_cache_contexts = ['languages:' . LanguageInterface::TYPE_INTERFACE, 'theme', 'user.permissions'];
     $entity_cache_contexts = $default_cache_contexts;
 
     // Cache tags present on every rendered page.
     $page_cache_tags = Cache::mergeTags(
       ['rendered'],
+      // 'user.permissions' is a required cache context, and responses that vary
+      // by this cache context when requested by anonymous users automatically
+      // also get this cache tag, to ensure correct invalidation.
+      ['config:user.role.anonymous'],
       // If the block module is used, the Block page display variant is used,
       // which adds the block config entity type's list cache tags.
       \Drupal::moduleHandler()->moduleExists('block') ? ['config:block_list']: []
@@ -387,9 +395,10 @@ public function testReferencedEntity() {
     $cache_keys = ['entity_view', 'entity_test', $this->referencingEntity->id(), 'full'];
     $cid = $this->createCacheId($cache_keys, $entity_cache_contexts);
     $access_cache_contexts = $this->getAccessCacheContextsForEntity($this->entity);
+    $additional_cache_contexts = $this->getAdditionalCacheContextsForEntity($this->referencingEntity);
     $redirected_cid = NULL;
-    if (count($access_cache_contexts)) {
-      $redirected_cid = $this->createCacheId($cache_keys, Cache::mergeContexts($entity_cache_contexts, $this->getAdditionalCacheContextsForEntity($this->referencingEntity), $access_cache_contexts));
+    if (count($access_cache_contexts) || count($additional_cache_contexts)) {
+      $redirected_cid = $this->createCacheId($cache_keys, Cache::mergeContexts($entity_cache_contexts, $additional_cache_contexts, $access_cache_contexts));
     }
     $this->verifyRenderCache($cid, $referencing_entity_cache_tags, $redirected_cid);
 
diff --git a/core/modules/system/src/Tests/Entity/EntityListBuilderTest.php b/core/modules/system/src/Tests/Entity/EntityListBuilderTest.php
index 485e72c..e32b689 100644
--- a/core/modules/system/src/Tests/Entity/EntityListBuilderTest.php
+++ b/core/modules/system/src/Tests/Entity/EntityListBuilderTest.php
@@ -67,7 +67,7 @@ public function testCacheContexts() {
     $build = $list_builder->render();
     $this->container->get('renderer')->renderRoot($build);
 
-    $this->assertEqual(['entity_test_view_grants', 'languages:' . LanguageInterface::TYPE_INTERFACE, 'theme', 'url.query_args.pagers:0'], $build['#cache']['contexts']);
+    $this->assertEqual(['entity_test_view_grants', 'languages:' . LanguageInterface::TYPE_INTERFACE, 'theme', 'url.query_args.pagers:0', 'user.permissions'], $build['#cache']['contexts']);
   }
 
 }
diff --git a/core/modules/system/src/Tests/Entity/EntityViewBuilderTest.php b/core/modules/system/src/Tests/Entity/EntityViewBuilderTest.php
index 333dcda..bf0512d 100644
--- a/core/modules/system/src/Tests/Entity/EntityViewBuilderTest.php
+++ b/core/modules/system/src/Tests/Entity/EntityViewBuilderTest.php
@@ -63,7 +63,7 @@ public function testEntityViewBuilderCache() {
     // Get a fully built entity view render array.
     $entity_test->save();
     $build = $this->container->get('entity.manager')->getViewBuilder('entity_test')->view($entity_test, 'full');
-    $cid_parts = array_merge($build['#cache']['keys'], $cache_contexts_manager->convertTokensToKeys(['languages:' . LanguageInterface::TYPE_INTERFACE, 'theme']));
+    $cid_parts = array_merge($build['#cache']['keys'], $cache_contexts_manager->convertTokensToKeys(['languages:' . LanguageInterface::TYPE_INTERFACE, 'theme', 'user.permissions']));
     $cid = implode(':', $cid_parts);
     $bin = $build['#cache']['bin'];
 
@@ -113,7 +113,7 @@ public function testEntityViewBuilderCacheWithReferences() {
 
     // Get a fully built entity view render array for the referenced entity.
     $build = $this->container->get('entity.manager')->getViewBuilder('entity_test')->view($entity_test_reference, 'full');
-    $cid_parts = array_merge($build['#cache']['keys'], $cache_contexts_manager->convertTokensToKeys(['languages:' . LanguageInterface::TYPE_INTERFACE, 'theme']));
+    $cid_parts = array_merge($build['#cache']['keys'], $cache_contexts_manager->convertTokensToKeys(['languages:' . LanguageInterface::TYPE_INTERFACE, 'theme', 'user.permissions']));
     $cid_reference = implode(':', $cid_parts);
     $bin_reference = $build['#cache']['bin'];
 
@@ -132,7 +132,7 @@ public function testEntityViewBuilderCacheWithReferences() {
 
     // Get a fully built entity view render array.
     $build = $this->container->get('entity.manager')->getViewBuilder('entity_test')->view($entity_test, 'full');
-    $cid_parts = array_merge($build['#cache']['keys'], $cache_contexts_manager->convertTokensToKeys(['languages:' . LanguageInterface::TYPE_INTERFACE, 'theme']));
+    $cid_parts = array_merge($build['#cache']['keys'], $cache_contexts_manager->convertTokensToKeys(['languages:' . LanguageInterface::TYPE_INTERFACE, 'theme', 'user.permissions']));
     $cid = implode(':', $cid_parts);
     $bin = $build['#cache']['bin'];
 
diff --git a/core/modules/system/src/Tests/Entity/EntityWithUriCacheTagsTestBase.php b/core/modules/system/src/Tests/Entity/EntityWithUriCacheTagsTestBase.php
index 0b6f430..47b551a 100644
--- a/core/modules/system/src/Tests/Entity/EntityWithUriCacheTagsTestBase.php
+++ b/core/modules/system/src/Tests/Entity/EntityWithUriCacheTagsTestBase.php
@@ -32,7 +32,7 @@ public function testEntityUri() {
     $view_mode = $this->selectViewMode($entity_type);
 
     // The default cache contexts for rendered entities.
-    $entity_cache_contexts = ['languages:' . LanguageInterface::TYPE_INTERFACE, 'theme'];
+    $entity_cache_contexts = ['languages:' . LanguageInterface::TYPE_INTERFACE, 'theme', 'user.permissions'];
 
     // Generate the standardized entity cache tags.
     $cache_tag = $this->entity->getCacheTags();
diff --git a/core/modules/tour/src/Tests/TourCacheTagsTest.php b/core/modules/tour/src/Tests/TourCacheTagsTest.php
index 1c4c323..8d2814f 100644
--- a/core/modules/tour/src/Tests/TourCacheTagsTest.php
+++ b/core/modules/tour/src/Tests/TourCacheTagsTest.php
@@ -52,6 +52,7 @@ public function testRenderedTour() {
     // Verify a cache hit, but also the presence of the correct cache tags.
     $expected_tags = [
       'config:tour.tour.tour-test',
+      'config:user.role.anonymous',
       'rendered',
     ];
     $this->verifyPageCache($url, 'HIT', $expected_tags);
@@ -71,6 +72,7 @@ public function testRenderedTour() {
 
     // Verify a cache hit.
     $expected_tags = [
+      'config:user.role.anonymous',
       'rendered',
     ];
     $this->verifyPageCache($url, 'HIT', $expected_tags);
diff --git a/sites/default/default.services.yml b/sites/default/default.services.yml
index c44c73b..3e813fa 100644
--- a/sites/default/default.services.yml
+++ b/sites/default/default.services.yml
@@ -82,8 +82,8 @@ parameters:
     # The Renderer will automatically associate these cache contexts with every
     # render array, hence varying every render array by these cache contexts.
     #
-    # @default ['languages:language_interface', 'theme']
-    required_cache_contexts: ['languages:language_interface', 'theme']
+    # @default ['languages:language_interface', 'theme', 'user.permissions']
+    required_cache_contexts: ['languages:language_interface', 'theme', 'user.permissions']
   factory.keyvalue:
     {}
     # Default key/value storage service to use.
