diff --git a/core/modules/node/src/Controller/NodeViewController.php b/core/modules/node/src/Controller/NodeViewController.php index 167483cef9..628c4239f4 100644 --- a/core/modules/node/src/Controller/NodeViewController.php +++ b/core/modules/node/src/Controller/NodeViewController.php @@ -77,7 +77,7 @@ public function view(EntityInterface $node, $view_mode = 'full', $langcode = NUL // This means that the page will vary by user.permissions. We also rely on // the access checking fallback to ensure the correct cacheability // metadata if we have to check access. - if ($this->currentUser->isAuthenticated() || $url->access($this->currentUser)) { + if ($this->isValidRel($rel) && ($this->currentUser->isAuthenticated() || $url->access($this->currentUser))) { // Set the node path as the canonical URL to prevent duplicate content. $build['#attached']['html_head_link'][] = [ [ @@ -123,4 +123,42 @@ public function title(EntityInterface $node) { return $this->entityRepository->getTranslationFromContext($node)->label(); } + /** + * Checks if rel attribute is w3c.org valid + * + * @param string $rel + * The unchecked rel attribute. + * + * @return bool + * The valid state + */ + private function isValidRel($rel) { + // List of all supported rel tags. + $validRelList = [ + 'alternate', + 'author', + 'bookmark', + 'canonical', + 'external', + 'help', + 'icon', + 'shortcut icon', + 'license', + 'manifest', + 'modulepreload', + 'next', + 'nofollow', + 'noopener', + 'noreferrer', + 'pingback', + 'prefetch', + 'preload', + 'prev', + 'shortlink', + 'stylesheet', + 'tag', + ]; + return in_array($rel, $validRelList, FALSE); + } + } diff --git a/core/modules/node/tests/src/Functional/NodeViewTest.php b/core/modules/node/tests/src/Functional/NodeViewTest.php index 19bb251fd5..82d56d2bb9 100644 --- a/core/modules/node/tests/src/Functional/NodeViewTest.php +++ b/core/modules/node/tests/src/Functional/NodeViewTest.php @@ -43,31 +43,10 @@ public function testHtmlHeadLinks() { // Link relations are present regardless of access for authenticated users. $result = $this->xpath('//link[@rel = "version-history"]'); - $this->assertEqual($result[0]->getAttribute('href'), $node->toUrl('version-history')->setAbsolute()->toString()); + $this->assertEmpty($result); $result = $this->xpath('//link[@rel = "edit-form"]'); - $this->assertEqual($result[0]->getAttribute('href'), $node->toUrl('edit-form')->setAbsolute()->toString()); - - // Give anonymous users access to edit the node. Do this through the UI to - // ensure caches are handled properly. - $this->drupalLogin($this->rootUser); - $edit = [ - 'anonymous[edit own ' . $node->bundle() . ' content]' => TRUE, - ]; - $this->drupalPostForm('admin/people/permissions', $edit, 'Save permissions'); - $this->drupalLogout(); - - // Anonymous user's should now see the edit-form link but not the - // version-history link. - $this->drupalGet($node->toUrl()); - $result = $this->xpath('//link[@rel = "canonical"]'); - $this->assertEqual($result[0]->getAttribute('href'), $node->toUrl()->setAbsolute()->toString()); - - $result = $this->xpath('//link[@rel = "version-history"]'); - $this->assertEmpty($result, 'Version history not present for anonymous users without access.'); - - $result = $this->xpath('//link[@rel = "edit-form"]'); - $this->assertEqual($result[0]->getAttribute('href'), $node->toUrl('edit-form')->setAbsolute()->toString()); + $this->assertEmpty($result); } /** @@ -79,7 +58,6 @@ public function testLinkHeader() { $expected = [ '<' . Html::escape($node->toUrl('canonical')->setAbsolute()->toString()) . '>; rel="canonical"', '<' . Html::escape($node->toUrl('canonical')->setAbsolute()->toString(), ['alias' => TRUE]) . '>; rel="shortlink"', - '<' . Html::escape($node->toUrl('revision')->setAbsolute()->toString()) . '>; rel="revision"', ]; $this->drupalGet($node->toUrl());