diff --git a/core/modules/link/src/Plugin/Field/FieldType/LinkItem.php b/core/modules/link/src/Plugin/Field/FieldType/LinkItem.php
index 9f65cae..a552a0e 100644
--- a/core/modules/link/src/Plugin/Field/FieldType/LinkItem.php
+++ b/core/modules/link/src/Plugin/Field/FieldType/LinkItem.php
@@ -27,7 +27,7 @@
  *   description = @Translation("Stores a URL string, optional varchar link text, and optional blob of attributes to assemble a link."),
  *   default_widget = "link_default",
  *   default_formatter = "link",
- *   constraints = {"LinkType" = {}, "LinkAccess" = {}}
+ *   constraints = {"LinkType" = {}, "LinkAccess" = {}, "LinkExternalProtocols" = {}, "LinkNotExistingInternal" = {}}
  * )
  */
 class LinkItem extends FieldItemBase implements LinkItemInterface {
diff --git a/core/modules/link/src/Plugin/Field/FieldWidget/LinkWidget.php b/core/modules/link/src/Plugin/Field/FieldWidget/LinkWidget.php
index 0e8ebc2..33152aa 100644
--- a/core/modules/link/src/Plugin/Field/FieldWidget/LinkWidget.php
+++ b/core/modules/link/src/Plugin/Field/FieldWidget/LinkWidget.php
@@ -57,7 +57,7 @@ public static function defaultSettings() {
    *
    * @see static::getUserEnteredStringAsUri()
    */
-  protected static function getUriAsDisplayableString($uri) {
+  public static function getUriAsDisplayableString($uri) {
     $scheme = parse_url($uri, PHP_URL_SCHEME);
 
     // By default, the displayable string is the URI.
@@ -147,31 +147,6 @@ public static function validateUriElement($element, FormStateInterface $form_sta
       $form_state->setError($element, t('Manually entered paths should start with /, ? or #.'));
       return;
     }
-
-    // If the URI is empty or not well-formed, the link field type's validation
-    // constraint will detect it.
-    // @see \Drupal\link\Plugin\Validation\Constraint\LinkTypeConstraint::validate()
-    if (!empty($uri) && parse_url($uri)) {
-      $url = Url::fromUri($uri);
-
-      // Disallow unrouted internal URLs (i.e. disallow 'base:' URIs).
-      $disallowed  = !$url->isRouted() && !$url->isExternal();
-      // Disallow external URLs using untrusted protocols.
-      $disallowed = $disallowed || ($url->isExternal() && !in_array(parse_url($uri, PHP_URL_SCHEME), UrlHelper::getAllowedProtocols()));
-      // Disallow routed URLs that don't exist.
-      if (!$disallowed && $url->isRouted()) {
-        try {
-          $url->toString();
-        }
-        catch (RouteNotFoundException $e) {
-          $disallowed = TRUE;
-        }
-      }
-
-      if ($disallowed) {
-        $form_state->setError($element, t("The path '@link_path' is invalid.", ['@link_path' => static::getUriAsDisplayableString($uri)]));
-      }
-    }
   }
 
   /**
diff --git a/core/modules/link/src/Plugin/Validation/Constraint/LinkAccessConstraintValidator.php b/core/modules/link/src/Plugin/Validation/Constraint/LinkAccessConstraintValidator.php
index 7011ff3..7bee72d 100644
--- a/core/modules/link/src/Plugin/Validation/Constraint/LinkAccessConstraintValidator.php
+++ b/core/modules/link/src/Plugin/Validation/Constraint/LinkAccessConstraintValidator.php
@@ -9,6 +9,7 @@
 
 use Drupal\Core\Session\AccountProxyInterface;
 use Drupal\Core\DependencyInjection\ContainerInjectionInterface;
+use Drupal\link\Plugin\Field\FieldWidget\LinkWidget;
 use Symfony\Component\DependencyInjection\ContainerInterface;
 use Symfony\Component\Validator\Constraint;
 use Symfony\Component\Validator\ConstraintValidatorInterface;
@@ -75,7 +76,7 @@ public function validate($value, Constraint $constraint) {
       // permission nor can access this URI.
       $allowed = $this->current_user->hasPermission('link to any page') || $url->access();
       if (!$allowed) {
-        $this->context->addViolation($constraint->message, array('@uri' => $value->uri));
+        $this->context->addViolation($constraint->message, array('@uri' => LinkWidget::getUriAsDisplayableString($value->uri)));
       }
     }
   }
diff --git a/core/modules/link/src/Plugin/Validation/Constraint/LinkExternalProtocolsConstraint.php b/core/modules/link/src/Plugin/Validation/Constraint/LinkExternalProtocolsConstraint.php
new file mode 100644
index 0000000..4b6b7e0
--- /dev/null
+++ b/core/modules/link/src/Plugin/Validation/Constraint/LinkExternalProtocolsConstraint.php
@@ -0,0 +1,24 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\link\Plugin\Validation\Constraint\LinkExternalProtocols.
+ */
+
+namespace Drupal\link\Plugin\Validation\Constraint;
+
+use Symfony\Component\Validator\Constraint;
+
+/**
+ * Defines an protocol validation constraint for links to external URLs.
+ *
+ * @Plugin(
+ *   id = "LinkExternalProtocols",
+ *   label = @Translation("No harmful external protocols", context = "Validation"),
+ * )
+ */
+class LinkExternalProtocolsConstraint extends Constraint {
+
+  public $message = "The path '@uri' is invalid.";
+
+}
diff --git a/core/modules/link/src/Plugin/Validation/Constraint/LinkExternalProtocolsConstraintValidator.php b/core/modules/link/src/Plugin/Validation/Constraint/LinkExternalProtocolsConstraintValidator.php
new file mode 100644
index 0000000..42a0618
--- /dev/null
+++ b/core/modules/link/src/Plugin/Validation/Constraint/LinkExternalProtocolsConstraintValidator.php
@@ -0,0 +1,54 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\link\Plugin\Validation\Constraint\LinkExternalProtocolsValidator.
+ */
+
+namespace Drupal\link\Plugin\Validation\Constraint;
+
+use Drupal\Component\Utility\UrlHelper;
+use Drupal\link\Plugin\Field\FieldWidget\LinkWidget;
+use Symfony\Component\Validator\Constraint;
+use Symfony\Component\Validator\ConstraintValidatorInterface;
+use Symfony\Component\Validator\ExecutionContextInterface;
+
+/**
+ * Validates the LinkExternalProtocols constraint.
+ */
+class LinkExternalProtocolsConstraintValidator implements ConstraintValidatorInterface {
+
+  /**
+   * Stores the validator's state during validation.
+   *
+   * @var \Symfony\Component\Validator\ExecutionContextInterface
+   */
+  protected $context;
+
+  /**
+   * {@inheritdoc}
+   */
+  public function initialize(ExecutionContextInterface $context) {
+    $this->context = $context;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function validate($value, Constraint $constraint) {
+    if (isset($value)) {
+      try {
+        /** @var \Drupal\Core\Url $url */
+        $url = $value->getUrl();
+      } // If the URL is malformed this constraint cannot check further.
+      catch (\InvalidArgumentException $e) {
+        return;
+      }
+      // Disallow external URLs using untrusted protocols.
+      if ($url->isExternal() && !in_array(parse_url($url->getUri(), PHP_URL_SCHEME), UrlHelper::getAllowedProtocols())) {
+        $this->context->addViolation($constraint->message, array('@uri' => LinkWidget::getUriAsDisplayableString($value->uri)));
+      }
+    }
+  }
+
+}
diff --git a/core/modules/link/src/Plugin/Validation/Constraint/LinkNotExistingInternalConstraint.php b/core/modules/link/src/Plugin/Validation/Constraint/LinkNotExistingInternalConstraint.php
new file mode 100644
index 0000000..d21e75b
--- /dev/null
+++ b/core/modules/link/src/Plugin/Validation/Constraint/LinkNotExistingInternalConstraint.php
@@ -0,0 +1,24 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\link\Plugin\Validation\Constraint\LinkNotExistingInternal.
+ */
+
+namespace Drupal\link\Plugin\Validation\Constraint;
+
+use Symfony\Component\Validator\Constraint;
+
+/**
+ * Defines an protocol validation constraint for links to broken internal URLs.
+ *
+ * @Plugin(
+ *   id = "LinkNotExistingInternal",
+ *   label = @Translation("No broken internal links", context = "Validation"),
+ * )
+ */
+class LinkNotExistingInternalConstraint extends Constraint {
+
+  public $message = "The path '@uri' is invalid.";
+
+}
diff --git a/core/modules/link/src/Plugin/Validation/Constraint/LinkNotExistingInternalConstraintValidator.php b/core/modules/link/src/Plugin/Validation/Constraint/LinkNotExistingInternalConstraintValidator.php
new file mode 100644
index 0000000..93b56cc
--- /dev/null
+++ b/core/modules/link/src/Plugin/Validation/Constraint/LinkNotExistingInternalConstraintValidator.php
@@ -0,0 +1,63 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\link\Plugin\Validation\Constraint\LinkNotExistingInternalConstraintValidator.
+ */
+
+namespace Drupal\link\Plugin\Validation\Constraint;
+
+use Drupal\link\Plugin\Field\FieldWidget\LinkWidget;
+use Symfony\Component\Routing\Exception\RouteNotFoundException;
+use Symfony\Component\Validator\Constraint;
+use Symfony\Component\Validator\ConstraintValidatorInterface;
+use Symfony\Component\Validator\ExecutionContextInterface;
+
+/**
+ * Validates the LinkNotExistingInternal constraint.
+ */
+class LinkNotExistingInternalConstraintValidator implements ConstraintValidatorInterface {
+
+  /**
+   * Stores the validator's state during validation.
+   *
+   * @var \Symfony\Component\Validator\ExecutionContextInterface
+   */
+  protected $context;
+
+  /**
+   * {@inheritdoc}
+   */
+  public function initialize(ExecutionContextInterface $context) {
+    $this->context = $context;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function validate($value, Constraint $constraint) {
+    if (isset($value)) {
+      try {
+        /** @var \Drupal\Core\Url $url */
+        $url = $value->getUrl();
+      } // If the URL is malformed this constraint cannot check further.
+      catch (\InvalidArgumentException $e) {
+        return;
+      }
+
+      if ($url->isRouted()) {
+        $allowed = FALSE;
+        try {
+          $url->toString();
+        }
+        catch (RouteNotFoundException $e) {
+          $allowed = TRUE;
+        }
+        if (!$allowed) {
+          $this->context->addViolation($constraint->message, array('@uri' => LinkWidget::getUriAsDisplayableString($value->uri)));
+        }
+      }
+    }
+  }
+
+}
diff --git a/core/modules/link/src/Plugin/Validation/Constraint/LinkTypeConstraint.php b/core/modules/link/src/Plugin/Validation/Constraint/LinkTypeConstraint.php
index 79a6e28..a62dd62 100644
--- a/core/modules/link/src/Plugin/Validation/Constraint/LinkTypeConstraint.php
+++ b/core/modules/link/src/Plugin/Validation/Constraint/LinkTypeConstraint.php
@@ -8,6 +8,7 @@
 namespace Drupal\link\Plugin\Validation\Constraint;
 
 use Drupal\link\LinkItemInterface;
+use Drupal\link\Plugin\Field\FieldWidget\LinkWidget;
 use Symfony\Component\Validator\Constraint;
 use Symfony\Component\Validator\ConstraintValidatorInterface;
 use Symfony\Component\Validator\ExecutionContextInterface;
@@ -75,7 +76,7 @@ public function validate($value, Constraint $constraint) {
       }
 
       if (!$uri_is_valid) {
-        $this->context->addViolation($this->message, array('@uri' => $link_item->uri));
+        $this->context->addViolation($this->message, array('@uri' => LinkWidget::getUriAsDisplayableString($link_item->uri)));
       }
     }
   }
diff --git a/core/modules/link/src/Tests/LinkFieldTest.php b/core/modules/link/src/Tests/LinkFieldTest.php
index 28bd87c..b8ad326 100644
--- a/core/modules/link/src/Tests/LinkFieldTest.php
+++ b/core/modules/link/src/Tests/LinkFieldTest.php
@@ -137,18 +137,14 @@ function testURLValidation() {
     $validation_error_1 = "The path '@link_path' is invalid.";
     $validation_error_2 = 'Manually entered paths should start with /, ? or #.';
     $invalid_external_entries = array(
-      // Missing protcol
-      'not-an-url' => $validation_error_2,
       // Invalid protocol
       'invalid://not-a-valid-protocol' => $validation_error_1,
       // Missing host name
       'http://' => $validation_error_1,
     );
-    $invalid_internal_entries = array(
-      '/non/existing/path' => $validation_error_1,
-      'no-leading-slash' => $validation_error_2,
-      'entity:non_existing_entity_type/yar' => $validation_error_1,
-    );
+    // We allow URIs not pointing to Drupal (yet), so site builders can build
+    // their information architecture before they built their actual site.
+    $invalid_internal_entries = [];
 
     // Test external and internal URLs for 'link_type' = LinkItemInterface::LINK_GENERIC.
     $this->assertValidEntries($field_name, $valid_external_entries + $valid_internal_entries);
@@ -165,6 +161,14 @@ function testURLValidation() {
     $this->field->save();
     $this->assertValidEntries($field_name, $valid_internal_entries);
     $this->assertInvalidEntries($field_name, $valid_external_entries + $invalid_internal_entries);
+
+    // Ensure that users with 'link to any page', don't apply access checking.
+    $this->drupalLogin($this->drupalCreateUser([
+      'view test entity',
+      'administer entity_test content',
+    ]));
+    $this->assertValidEntries($field_name, ['entity_test/add']);
+    $this->assertInValidEntries($field_name, ['admin']);
   }
 
   /**
diff --git a/core/modules/menu_ui/src/Tests/MenuTest.php b/core/modules/menu_ui/src/Tests/MenuTest.php
index c38f25f..4d56a77 100644
--- a/core/modules/menu_ui/src/Tests/MenuTest.php
+++ b/core/modules/menu_ui/src/Tests/MenuTest.php
@@ -639,18 +639,13 @@ function addMenuLink($parent = '', $path = '/', $menu_name = 'tools', $expanded
    * Attempts to add menu link with invalid path or no access permission.
    */
   function addInvalidMenuLink() {
-    foreach (array('valid' => '/-&-', 'access' => '/admin/people/permissions') as $type => $link_path) {
+    foreach (array('access' => '/admin/people/permissions') as $type => $link_path) {
       $edit = array(
         'link[0][uri]' => $link_path,
         'title[0][value]' => 'title',
       );
       $this->drupalPostForm("admin/structure/menu/manage/{$this->menu->id()}/add", $edit, t('Save'));
-      if ($type === 'access') {
-        $this->assertRaw(t("The path '@link_path' is inaccessible.", array('@link_path' => $link_path)), 'Menu link was not created');
-      }
-      else {
-        $this->assertRaw(t("The path '@link_path' is invalid.", array('@link_path' => $link_path)), 'Menu link was not created');
-      }
+      $this->assertRaw(t("The path '@link_path' is inaccessible.", array('@link_path' => $link_path)), 'Menu link was not created');
     }
   }
 
