diff --git a/core/lib/Drupal/Core/Menu/DefaultMenuLinkTreeManipulators.php b/core/lib/Drupal/Core/Menu/DefaultMenuLinkTreeManipulators.php
index 7eefd12754..932dadd4de 100644
--- a/core/lib/Drupal/Core/Menu/DefaultMenuLinkTreeManipulators.php
+++ b/core/lib/Drupal/Core/Menu/DefaultMenuLinkTreeManipulators.php
@@ -197,22 +197,14 @@ protected function collectNodeLinks(array &$tree, array &$node_links) {
    *   The access result.
    */
   protected function menuLinkCheckAccess(MenuLinkInterface $instance) {
-    $access_result = NULL;
-    if ($this->account->hasPermission('link to any page')) {
-      $access_result = AccessResult::allowed();
-    }
-    else {
-      $url = $instance->getUrlObject();
+    $url = $instance->getUrlObject();
 
-      // When no route name is specified, this must be an external link.
-      if (!$url->isRouted()) {
-        $access_result = AccessResult::allowed();
-      }
-      else {
-        $access_result = $this->accessManager->checkNamedRoute($url->getRouteName(), $url->getRouteParameters(), $this->account, TRUE);
-      }
+    if ($url->isRouted()) {
+      return $this->accessManager->checkNamedRoute($url->getRouteName(), $url->getRouteParameters(), $this->account, TRUE);
     }
-    return $access_result->cachePerPermissions();
+
+    // When no route name is specified, this must be an external link.
+    return AccessResult::allowed();
   }
 
   /**
diff --git a/core/modules/menu_ui/menu_ui.services.yml b/core/modules/menu_ui/menu_ui.services.yml
new file mode 100644
index 0000000000..f70f94b296
--- /dev/null
+++ b/core/modules/menu_ui/menu_ui.services.yml
@@ -0,0 +1,3 @@
+services:
+  menu_ui.menu_tree_manipulators:
+    class: Drupal\menu_ui\Menu\MenuUiMenuTreeManipulators
diff --git a/core/modules/menu_ui/src/Menu/MenuUiMenuTreeManipulators.php b/core/modules/menu_ui/src/Menu/MenuUiMenuTreeManipulators.php
new file mode 100644
index 0000000000..f2dafc5b60
--- /dev/null
+++ b/core/modules/menu_ui/src/Menu/MenuUiMenuTreeManipulators.php
@@ -0,0 +1,51 @@
+<?php
+
+namespace Drupal\menu_ui\Menu;
+
+use Drupal\Core\Access\AccessResult;
+use Drupal\Core\Menu\InaccessibleMenuLink;
+
+/**
+ * Provides a menu tree manipulators to be used when managing menu links.
+ */
+class MenuUiMenuTreeManipulators {
+
+  /**
+   * Performs access checks of a menu tree when used in menu management form.
+   *
+   * Alternative to DefaultMenuLinkTreeManipulators::checkAccess() to be used in
+   * menu tree links manage form, \Drupal\menu_ui\MenuForm. Site builders should
+   * be still able to create and manage menu links with Menu UI even the menu
+   * link route is not accessible. Here are some use cases:
+   * - A logout menu link, using the `user.logout` route, is not accessible to a
+   *   logged in user, but the site builder still needs to configure the menu
+   *   link.
+   * - A site builder wants to create a menu item for Views page that is not yet
+   *   created, thus there's no access to the route, as the route doesn't exist.
+   *
+   * NOTE: This menu tree manipulator is intended to be used only in the context
+   * of MenuForm, where the user permissions to administer links is already
+   * checked. Don't use this manipulator in other places.
+   *
+   * @param \Drupal\Core\Menu\MenuLinkTreeElement[] $tree
+   *   The menu link tree to manipulate.
+   *
+   * @return \Drupal\Core\Menu\MenuLinkTreeElement[]
+   *   The manipulated menu link tree.
+   *
+   * @internal
+   *
+   * @see \Drupal\Core\Menu\DefaultMenuLinkTreeManipulators::checkAccess()
+   * @see \Drupal\menu_ui\MenuForm
+   */
+  public function checkAccess(array $tree) {
+    foreach ($tree as $key => $element) {
+      $tree[$key]->access = AccessResult::allowed();
+      if ($tree[$key]->subtree) {
+        $tree[$key]->subtree = $this->checkAccess($tree[$key]->subtree);
+      }
+    }
+    return $tree;
+  }
+
+}
diff --git a/core/modules/menu_ui/src/MenuForm.php b/core/modules/menu_ui/src/MenuForm.php
index ccedad3133..4a915b98de 100644
--- a/core/modules/menu_ui/src/MenuForm.php
+++ b/core/modules/menu_ui/src/MenuForm.php
@@ -229,7 +229,15 @@ protected function buildOverviewForm(array &$form, FormStateInterface $form_stat
     // We indicate that a menu administrator is running the menu access check.
     $this->getRequest()->attributes->set('_menu_admin', TRUE);
     $manipulators = [
-      ['callable' => 'menu.default_tree_manipulators:checkAccess'],
+      // Using a dedicated menu tree access check manipulator as users editing
+      // this form, granted with 'administer menu' permission, should be able to
+      // access even the menu links with routes they can access. Such cases are
+      // the logout menu link, whose route is not accessible by a logged in user
+      // or a link to a page not yet created. The main menu tree manipulator
+      // only allows the access the menu links with accessible routes.
+      // @see \Drupal\Core\Menu\DefaultMenuLinkTreeManipulators::checkAccess()
+      // @see \Drupal\menu_ui\Menu\MenuUiMenuTreeManipulators::checkAccess()
+      ['callable' => 'menu_ui.menu_tree_manipulators:checkAccess'],
       ['callable' => 'menu.default_tree_manipulators:generateIndexAndSort'],
     ];
     $tree = $this->menuTree->transform($tree, $manipulators);
diff --git a/core/modules/menu_ui/tests/src/Functional/MenuUiTest.php b/core/modules/menu_ui/tests/src/Functional/MenuUiTest.php
index d04075d004..3fca494b20 100644
--- a/core/modules/menu_ui/tests/src/Functional/MenuUiTest.php
+++ b/core/modules/menu_ui/tests/src/Functional/MenuUiTest.php
@@ -571,10 +571,15 @@ public function testUnpublishedNodeMenuItem() {
     $this->drupalLogout();
     $this->drupalLogin($this->adminUser);
     $this->drupalGet('admin/structure/menu/manage/' . $item->getMenuName());
-    $this->assertNoText($item->getTitle(), "Menu link pointing to unpublished node is only visible to users with 'bypass node access' permission");
+    $this->assertSession()->linkExists($item->getTitle());
     // The cache contexts associated with the (in)accessible menu links are
     // bubbled. See DefaultMenuLinkTreeManipulators::menuLinkCheckAccess().
     $this->assertSession()->responseHeaderContains('X-Drupal-Cache-Contexts', 'user.permissions');
+
+    // The menu link admin is able to administer the link but cannot access the
+    // route as is not granted with 'bypass node access' permission.
+    $this->clickLink($item->getTitle());
+    $this->assertSession()->statusCodeEquals(403);
   }
 
   /**
@@ -1035,4 +1040,47 @@ public function testMenuUiWithPendingRevisions() {
     $this->assertSession()->elementNotExists('xpath', '//div[contains(@class, "messages--error")]');
   }
 
+  /**
+   * Tests the user login/logout links.
+   */
+  public function testUserLoginUserLogoutLinks() {
+    MenuLinkContent::create([
+      'menu' => 'tools',
+      'link' => [
+        'uri' => 'internal:/user/login',
+      ],
+      'title' => 'Login',
+    ])->save();
+    MenuLinkContent::create([
+      'menu' => 'tools',
+      'link' => [
+        'uri' => 'internal:/user/logout',
+      ],
+      'title' => 'Logout',
+    ])->save();
+
+    $assert = $this->assertSession();
+
+    $block = $this->drupalPlaceBlock('system_menu_block:tools');
+    $this->drupalGet('<front>');
+    $this->assertLink('Login');
+    $this->assertNoLink('Logout');
+
+    $this->drupalLogin($this->createUser());
+    $this->drupalGet('<front>');
+    $this->assertNoLink('Login');
+    $this->assertLink('Logout');
+
+    $block->delete();
+
+    $this->drupalLogin($this->createUser([
+      'administer menu',
+      'link to any page',
+    ]));
+    $this->drupalGet('admin/structure/menu/manage/tools');
+
+    $assert->linkExists('Login');
+    $assert->linkExists('Logout');
+  }
+
 }
diff --git a/core/modules/views_ui/tests/src/Functional/DisplayPathTest.php b/core/modules/views_ui/tests/src/Functional/DisplayPathTest.php
index cdf36704cf..5dd2f4efc1 100644
--- a/core/modules/views_ui/tests/src/Functional/DisplayPathTest.php
+++ b/core/modules/views_ui/tests/src/Functional/DisplayPathTest.php
@@ -207,6 +207,7 @@ public function testDefaultMenuTabRegression() {
       'administer menu',
       'link to any page',
       'access toolbar',
+      'access administration pages',
     ]);
     $this->drupalLogin($admin_user);
 
diff --git a/core/tests/Drupal/KernelTests/Core/Menu/MenuLinkTreeTest.php b/core/tests/Drupal/KernelTests/Core/Menu/MenuLinkTreeTest.php
index 42d8110e19..a5795aee4e 100644
--- a/core/tests/Drupal/KernelTests/Core/Menu/MenuLinkTreeTest.php
+++ b/core/tests/Drupal/KernelTests/Core/Menu/MenuLinkTreeTest.php
@@ -2,8 +2,11 @@
 
 namespace Drupal\KernelTests\Core\Menu;
 
+use Drupal\Core\Menu\InaccessibleMenuLink;
 use Drupal\Core\Menu\MenuLinkTreeElement;
 use Drupal\Core\Menu\MenuTreeParameters;
+use Drupal\Core\Session\AnonymousUserSession;
+use Drupal\Core\Session\UserSession;
 use Drupal\KernelTests\KernelTestBase;
 use Drupal\Tests\Core\Menu\MenuLinkMock;
 
@@ -132,4 +135,42 @@ public function testCreateLinksInMenu() {
     $this->assertEqual($height, 3);
   }
 
+  /**
+   * Tests user/login and user/logout links.
+   */
+  public function testUserLoginAndUserLogoutLinks() {
+    $account_switcher = $this->container->get('account_switcher');
+
+    $login_menu_link = MenuLinkMock::create(['id' => 'user_login_example', 'route_name' => 'user.login']);
+    $logout_menu_link = MenuLinkMock::create(['id' => 'user_logout_example', 'route_name' => 'user.logout']);
+
+    $this->menuLinkManager->addDefinition($login_menu_link->getPluginId(), $login_menu_link->getPluginDefinition());
+    $this->menuLinkManager->addDefinition($logout_menu_link->getPluginId(), $logout_menu_link->getPluginDefinition());
+
+    // Returns the accessible links from transformed 'mock' menu tree.
+    $get_accessible_links = function () {
+      $parameters = new MenuTreeParameters();
+      $manipulators = [
+        ['callable' => 'menu.default_tree_manipulators:checkAccess'],
+      ];
+
+      $tree = $this->linkTree->load('mock', $parameters);
+      $this->linkTree->transform($tree, $manipulators);
+
+      return array_keys(
+        array_filter($tree, function (MenuLinkTreeElement $element) {
+          return !$element->link instanceof InaccessibleMenuLink;
+        })
+      );
+    };
+
+    // Check that anonymous can only access the login link.
+    $account_switcher->switchTo(new AnonymousUserSession());
+    $this->assertSame(['user_login_example'], $get_accessible_links());
+
+    // Ensure that also user 1 does not see the login link.
+    $account_switcher->switchTo(new UserSession(['uid' => 1]));
+    $this->assertSame(['user_logout_example'], $get_accessible_links());
+  }
+
 }
diff --git a/core/tests/Drupal/Tests/Core/Menu/DefaultMenuLinkTreeManipulatorsTest.php b/core/tests/Drupal/Tests/Core/Menu/DefaultMenuLinkTreeManipulatorsTest.php
index 108236e774..3b3bb22747 100644
--- a/core/tests/Drupal/Tests/Core/Menu/DefaultMenuLinkTreeManipulatorsTest.php
+++ b/core/tests/Drupal/Tests/Core/Menu/DefaultMenuLinkTreeManipulatorsTest.php
@@ -185,7 +185,7 @@ public function testCheckAccess() {
     // Menu link 1: route without parameters, access forbidden, but at level 0,
     // hence kept.
     $element = $tree[1];
-    $this->assertEquals(AccessResult::forbidden()->cachePerPermissions(), $element->access);
+    $this->assertEquals(AccessResult::forbidden(), $element->access);
     $this->assertInstanceOf('\Drupal\Core\Menu\InaccessibleMenuLink', $element->link);
     // Menu link 2: route with parameters, access granted.
     $element = $tree[2];
@@ -196,18 +196,18 @@ public function testCheckAccess() {
     // Note that the permissions cache context is added automatically, because
     // we always check the "link to any page" permission.
     $element = $tree[2]->subtree[3];
-    $this->assertEquals(AccessResult::neutral()->cachePerPermissions(), $element->access);
+    $this->assertEquals(AccessResult::neutral(), $element->access);
     $this->assertInstanceOf('\Drupal\Core\Menu\InaccessibleMenuLink', $element->link);
     // Menu link 4: child of menu link 3, which was AccessResult::neutral(),
     // hence menu link 3's subtree is removed, of which this menu link is one.
     $this->assertFalse(array_key_exists(4, $tree[2]->subtree[3]->subtree));
     // Menu link 5: no route name, treated as external, hence access granted.
     $element = $tree[5];
-    $this->assertEquals(AccessResult::allowed()->cachePerPermissions(), $element->access);
+    $this->assertEquals(AccessResult::allowed(), $element->access);
     $this->assertNotInstanceOf('\Drupal\Core\Menu\InaccessibleMenuLink', $element->link);
     // Menu link 6: external URL, hence access granted.
     $element = $tree[6];
-    $this->assertEquals(AccessResult::allowed()->cachePerPermissions(), $element->access);
+    $this->assertEquals(AccessResult::allowed(), $element->access);
     $this->assertNotInstanceOf('\Drupal\Core\Menu\InaccessibleMenuLink', $element->link);
     // Menu link 7: 'access' already set: AccessResult::neutral(), top-level
     // inaccessible link, hence kept for its cacheability metadata.
@@ -232,15 +232,17 @@ public function testCheckAccess() {
    */
   public function testCheckAccessWithLinkToAnyPagePermission() {
     $this->mockTree();
-    $this->currentUser->expects($this->exactly(9))
-      ->method('hasPermission')
-      ->with('link to any page')
-      ->willReturn(TRUE);
+    // There are 9 checks but one is on an external link, so the route access
+    // checker should be called only 8 times.
+    // @see \Drupal\Core\Menu\DefaultMenuLinkTreeManipulators::menuLinkCheckAccess()
+    $this->accessManager->expects($this->exactly(8))
+      ->method('checkNamedRoute')
+      ->willReturn(AccessResult::allowed());
 
     $this->mockTree();
     $this->defaultMenuTreeManipulators->checkAccess($this->originalTree);
 
-    $expected_access_result = AccessResult::allowed()->cachePerPermissions();
+    $expected_access_result = AccessResult::allowed();
     $this->assertEquals($expected_access_result, $this->originalTree[1]->access);
     $this->assertEquals($expected_access_result, $this->originalTree[2]->access);
     $this->assertEquals($expected_access_result, $this->originalTree[2]->subtree[3]->access);
@@ -338,8 +340,8 @@ public function testCheckNodeAccess() {
     $this->assertEquals($node_access_result, $tree[1]->access);
     $this->assertEquals($node_access_result, $tree[2]->access);
     $this->assertEquals(AccessResult::neutral(), $tree[2]->subtree[3]->access);
-    $this->assertEquals(AccessResult::allowed()->cachePerPermissions(), $tree[5]->access);
-    $this->assertEquals(AccessResult::neutral()->cachePerPermissions(), $tree[5]->subtree[6]->access);
+    $this->assertEquals(AccessResult::allowed(), $tree[5]->access);
+    $this->assertEquals(AccessResult::neutral(), $tree[5]->subtree[6]->access);
   }
 
 }
