diff --git a/core/lib/Drupal/Core/Entity/Entity.php b/core/lib/Drupal/Core/Entity/Entity.php
index 5a4073f..742d361 100644
--- a/core/lib/Drupal/Core/Entity/Entity.php
+++ b/core/lib/Drupal/Core/Entity/Entity.php
@@ -494,6 +494,10 @@ protected function invalidateTagsOnSave($update) {
     // listing's filtering requirements. A newly created entity may start to
     // appear in listings because it did not exist before.)
     $tags = $this->getEntityType()->getListCacheTags();
+    if ($this->hasLinkTemplate()) {
+      // Creating or updating an entity may change a cached 403 or 404 response.
+      $tags = Cache::mergeTags($tags, ['4xx-response']);
+    }
     if ($update) {
       // An existing entity was updated, also invalidate its unique cache tag.
       $tags = Cache::mergeTags($tags, $this->getCacheTags());
diff --git a/core/lib/Drupal/Core/EventSubscriber/CacheRouterRebuildSubscriber.php b/core/lib/Drupal/Core/EventSubscriber/CacheRouterRebuildSubscriber.php
new file mode 100644
index 0000000..9589348
--- /dev/null
+++ b/core/lib/Drupal/Core/EventSubscriber/CacheRouterRebuildSubscriber.php
@@ -0,0 +1,37 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\Core\EventSubscriber\CacheRouterRebuildSubscriber.
+ */
+
+namespace Drupal\Core\EventSubscriber;
+
+use Drupal\Core\Cache\Cache;
+use Drupal\Core\Routing\RoutingEvents;
+use Symfony\Component\EventDispatcher\EventSubscriberInterface;
+
+/**
+ * Clear cache tags when the router is rebuilt.
+ */
+class CacheRouterRebuildSubscriber implements EventSubscriberInterface {
+
+  /**
+   * {@inheritdoc}
+   */
+  public function onRouterFinished() {
+    // Requested URLs that formerly gave a 403/404 may now be valid.
+    Cache::invalidateTags(['4xx-response']);
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public static function getSubscribedEvents() {
+    $events = [];
+    // Act only when the router rebuild is finished.
+    $events[RoutingEvents::FINISHED][] = ['onRouterFinished'];
+    return $events;
+  }
+
+}
diff --git a/core/lib/Drupal/Core/EventSubscriber/FinishResponseSubscriber.php b/core/lib/Drupal/Core/EventSubscriber/FinishResponseSubscriber.php
index 157454d..abdaede 100644
--- a/core/lib/Drupal/Core/EventSubscriber/FinishResponseSubscriber.php
+++ b/core/lib/Drupal/Core/EventSubscriber/FinishResponseSubscriber.php
@@ -138,6 +138,15 @@ public function onRespond(FilterResponseEvent $event) {
     if ($access_result instanceof CacheableDependencyInterface) {
       $this->updateDrupalCacheHeaders($response, $access_result);
     }
+    // Add a cache tag to any 4xx response.
+    if ($response->isClientError()) {
+      $cache_tags = ['4xx-response'];
+      if ($response->headers->has('X-Drupal-Cache-Tags')) {
+        $existing_cache_tags = explode(' ', $response->headers->get('X-Drupal-Cache-Tags'));
+        $cache_tags = Cache::mergeTags($existing_cache_tags, $cache_tags);
+      }
+      $response->headers->set('X-Drupal-Cache-Tags', implode(' ', $cache_tags));
+    }
 
     $is_cacheable = ($this->requestPolicy->check($request) === RequestPolicyInterface::ALLOW) && ($this->responsePolicy->check($response, $request) !== ResponsePolicyInterface::DENY);
 
