diff --git a/core/lib/Drupal/Core/Url.php b/core/lib/Drupal/Core/Url.php
index 999f447..7b46129 100644
--- a/core/lib/Drupal/Core/Url.php
+++ b/core/lib/Drupal/Core/Url.php
@@ -172,6 +172,32 @@ public static function fromRoute($route_name, $route_parameters = array(), $opti
   }
 
   /**
+   * Creates a new Url object for a path, which IS controlled by Drupal.
+   *
+   * This method is to be used for generating URLs where the exact source, so
+   * route, is unknown, such as coming from user input.
+   *
+   * In general, this method should be avoided in favor of Url::fromRoute() for
+   * Drupal controlled paths, and Url::fromUri() for external paths, or paths
+   * not controlled by Drupal.
+   *
+   * Note: You can call access() on this object to do access checking.
+   *
+   * @param string $path
+   *   The path to be converted. The path may include query arguments and a
+   *   fragment.
+   *
+   * @return \Drupal\Core\Url
+   *   A new Url object for the path.
+   *
+   * @see static::fromRoute()
+   * @see static::fromUri()
+   */
+  public static function fromDrupalPath($path) {
+    return \Drupal::pathValidator()->getUrlIfValidWithoutAccessCheck($path) ?: Url::fromRoute('<invalid>');
+  }
+
+  /**
    * Creates a new URL object from a route match.
    *
    * @param \Drupal\Core\Routing\RouteMatchInterface $route_match
diff --git a/core/modules/system/system.routing.yml b/core/modules/system/system.routing.yml
index 77489f5..877cd04 100644
--- a/core/modules/system/system.routing.yml
+++ b/core/modules/system/system.routing.yml
@@ -383,6 +383,11 @@ system.theme_settings_theme:
   options:
     _only_fragment: TRUE
 
+# You can replace that route to improve UX.
+'<invalid>':
+  path: ''
+  options:
+    _only_fragment: TRUE
 
 '<current>':
   path: '<current>'
diff --git a/core/tests/Drupal/Tests/Core/UrlTest.php b/core/tests/Drupal/Tests/Core/UrlTest.php
index a93226a..ca74f67 100644
--- a/core/tests/Drupal/Tests/Core/UrlTest.php
+++ b/core/tests/Drupal/Tests/Core/UrlTest.php
@@ -51,6 +51,13 @@ class UrlTest extends UnitTestCase {
   protected $map;
 
   /**
+   * The mocked path validator.
+   *
+   * @var \Drupal\Core\Path\PathValidatorInterface|\PHPUnit_Framework_MockObject_MockObject
+   */
+  protected $pathValidator;
+
+  /**
    * {@inheritdoc}
    */
   protected function setUp() {
@@ -68,9 +75,12 @@ protected function setUp() {
       ->will($this->returnValueMap($this->map));
 
     $this->router = $this->getMock('Drupal\Tests\Core\Routing\TestRouterInterface');
+    $this->pathValidator = $this->getMock('Drupal\Core\Path\PathValidatorInterface');
+
     $this->container = new ContainerBuilder();
     $this->container->set('router.no_access_checks', $this->router);
     $this->container->set('url_generator', $this->urlGenerator);
+    $this->container->set('path.validator', $this->pathValidator);
     \Drupal::setContainer($this->container);
   }
 
@@ -137,6 +147,35 @@ public function testFromRouteFront() {
   }
 
   /**
+   * Tests fromDrupalPath() method with an invalid route.
+   *
+   * @covers ::fromDrupalPath
+   */
+  public function testFromDrupalPathWithInvalidRoute() {
+    $this->pathValidator->expects($this->once())
+      ->method('getUrlIfValidWithoutAccessCheck')
+      ->with('invalid-path')
+      ->willReturn(FALSE);
+    $url = Url::fromDrupalPath('invalid-path');
+    $this->assertSame('<invalid>', $url->getRouteName());
+  }
+
+  /**
+   * Tests fromDrupalPath() method with a valid route.
+   *
+   * @covers ::fromDrupalPath
+   */
+  public function testFromDrupalPathWithValidRoute() {
+    $url = Url::fromRoute('test_route');
+    $this->pathValidator->expects($this->once())
+      ->method('getUrlIfValidWithoutAccessCheck')
+      ->with('valid-path')
+      ->willReturn($url);
+    $result_url = Url::fromDrupalPath('valid-path');
+    $this->assertSame($url, $result_url);
+  }
+
+  /**
    * Tests the createFromRequest method.
    *
    * @covers ::createFromRequest
