diff --git a/core/core.services.yml b/core/core.services.yml
index 0bb13d0..46ea8e9 100644
--- a/core/core.services.yml
+++ b/core/core.services.yml
@@ -608,7 +608,7 @@ services:
     class: Drupal\Core\Access\CsrfAccessCheck
     tags:
       - { name: access_check, applies_to: _csrf_token }
-    arguments: ['@csrf_token']
+    arguments: ['@csrf_token', '@url_generator']
   maintenance_mode:
     class: Drupal\Core\Site\MaintenanceMode
     arguments: ['@state', '@current_user']
diff --git a/core/lib/Drupal/Core/Access/AccessArgumentsResolver.php b/core/lib/Drupal/Core/Access/AccessArgumentsResolver.php
index 4c61fac..14e2fc0 100644
--- a/core/lib/Drupal/Core/Access/AccessArgumentsResolver.php
+++ b/core/lib/Drupal/Core/Access/AccessArgumentsResolver.php
@@ -7,6 +7,7 @@
 
 namespace Drupal\Core\Access;
 
+use Drupal\Core\Routing\RouteMatchInterface;
 use Drupal\Core\Session\AccountInterface;
 use Symfony\Component\Routing\Route;
 use Symfony\Component\HttpFoundation\Request;
@@ -19,10 +20,10 @@ class AccessArgumentsResolver implements AccessArgumentsResolverInterface {
   /**
    * {@inheritdoc}
    */
-  public function getArguments(callable $callable, Route $route, Request $request, AccountInterface $account) {
+  public function getArguments(callable $callable, Route $route, Request $request, RouteMatchInterface $route_match, AccountInterface $account) {
     $arguments = array();
     foreach ($this->getReflector($callable)->getParameters() as $parameter) {
-      $arguments[] = $this->getArgument($parameter, $route, $request, $account);
+      $arguments[] = $this->getArgument($parameter, $route, $request, $route_match, $account);
     }
     return $arguments;
   }
@@ -36,16 +37,17 @@ public function getArguments(callable $callable, Route $route, Request $request,
    *   The access checked route.
    * @param \Symfony\Component\HttpFoundation\Request $request
    *   The current request.
+   * @param \Drupal\Core\Routing\RouteMatchInterface $route_match
+   *   The route match.
    * @param \Drupal\Core\Session\AccountInterface $account
    *   The current user.
    *
+   * @internal param $
    * @return mixed
    *   The value of the requested parameter value.
    *
-   * @throws \RuntimeException
-   *   Thrown when there is a missing parameter.
    */
-  protected function getArgument(\ReflectionParameter $parameter, Route $route, Request $request, AccountInterface $account) {
+  protected function getArgument(\ReflectionParameter $parameter, Route $route, Request $request, RouteMatchInterface $route_match, AccountInterface $account) {
     $upcasted_route_arguments = $request->attributes->all();
     $raw_route_arguments = isset($upcasted_route_arguments['_raw_variables']) ? $upcasted_route_arguments['_raw_variables']->all() : $upcasted_route_arguments;
     $parameter_type_hint = $parameter->getClass();
@@ -70,7 +72,7 @@ protected function getArgument(\ReflectionParameter $parameter, Route $route, Re
       // Otherwise, resolve $request, $route, and $account by type matching
       // only. This way, the callable may rename them in case the route
       // defines other parameters with these names.
-      foreach (array($request, $route, $account) as $special_argument) {
+      foreach (array($request, $route, $route_match, $account) as $special_argument) {
         if ($parameter_type_hint->isInstance($special_argument)) {
           return $special_argument;
         }
diff --git a/core/lib/Drupal/Core/Access/AccessArgumentsResolverInterface.php b/core/lib/Drupal/Core/Access/AccessArgumentsResolverInterface.php
index ce0ecf8..514bbd6 100644
--- a/core/lib/Drupal/Core/Access/AccessArgumentsResolverInterface.php
+++ b/core/lib/Drupal/Core/Access/AccessArgumentsResolverInterface.php
@@ -7,6 +7,7 @@
 
 namespace Drupal\Core\Access;
 
+use Drupal\Core\Routing\RouteMatchInterface;
 use Drupal\Core\Session\AccountInterface;
 use Symfony\Component\Routing\Route;
 use Symfony\Component\HttpFoundation\Request;
@@ -25,6 +26,8 @@
    *   The route to check access to.
    * @param \Symfony\Component\HttpFoundation\Request $request
    *   The request object.
+   * @param \Drupal\Core\Routing\RouteMatchInterface $route_match
+   *   The route match.
    * @param \Drupal\Core\Session\AccountInterface $account
    *   The currently logged in account.
    *
@@ -34,6 +37,6 @@
    * @throws \RuntimeException
    *   When a value for an argument given is not provided.
    */
-  public function getArguments(callable $callable, Route $route, Request $request, AccountInterface $account);
+  public function getArguments(callable $callable, Route $route, Request $request, RouteMatchInterface $route_match, AccountInterface $account);
 
 }
diff --git a/core/lib/Drupal/Core/Access/AccessManager.php b/core/lib/Drupal/Core/Access/AccessManager.php
index b40905f..6a9e4a3 100644
--- a/core/lib/Drupal/Core/Access/AccessManager.php
+++ b/core/lib/Drupal/Core/Access/AccessManager.php
@@ -10,6 +10,8 @@
 use Drupal\Core\ParamConverter\ParamConverterManagerInterface;
 use Drupal\Core\ParamConverter\ParamNotConvertedException;
 use Drupal\Core\Routing\RequestHelper;
+use Drupal\Core\Routing\RouteMatch;
+use Drupal\Core\Routing\RouteMatchInterface;
 use Drupal\Core\Routing\RouteProviderInterface;
 use Drupal\Core\Session\AccountInterface;
 use Symfony\Component\Routing\Generator\UrlGeneratorInterface;
@@ -254,12 +256,13 @@ public function checkNamedRoute($route_name, array $parameters = array(), Accoun
   public function check(Route $route, Request $request, AccountInterface $account) {
     $checks = $route->getOption('_access_checks') ?: array();
     $conjunction = $route->getOption('_access_mode') ?: 'ALL';
+    $route_match = RouteMatch::createFromRequest($request);
 
     if ($conjunction == 'ALL') {
-      return $this->checkAll($checks, $route, $request, $account);
+      return $this->checkAll($checks, $route, $request, $route_match, $account);
     }
     else {
-      return $this->checkAny($checks, $route, $request, $account);
+      return $this->checkAny($checks, $route, $request, $route_match, $account);
     }
   }
 
@@ -278,7 +281,7 @@ public function check(Route $route, Request $request, AccountInterface $account)
    * @return bool
    *  Returns TRUE if the user has access to the route, else FALSE.
    */
-  protected function checkAll(array $checks, Route $route, Request $request, AccountInterface $account) {
+  protected function checkAll(array $checks, Route $route, Request $request, RouteMatchInterface $route_match, AccountInterface $account) {
     $access = FALSE;
 
     foreach ($checks as $service_id) {
@@ -286,7 +289,7 @@ protected function checkAll(array $checks, Route $route, Request $request, Accou
         $this->loadCheck($service_id);
       }
 
-      $service_access = $this->performCheck($service_id, $route, $request, $account);
+      $service_access = $this->performCheck($service_id, $route, $request, $route_match, $account);
 
       if ($service_access === AccessInterface::ALLOW) {
         $access = TRUE;
@@ -310,13 +313,16 @@ protected function checkAll(array $checks, Route $route, Request $request, Accou
    *   The route to check access to.
    * @param \Symfony\Component\HttpFoundation\Request $request
    *   The incoming request object.
+   * @param \Drupal\Core\Routing\RouteMatchInterface $route_match
+   *   The route match.
    * @param \Drupal\Core\Session\AccountInterface $account
    *   The current user.
    *
+   * @internal param $
    * @return bool
    *  Returns TRUE if the user has access to the route, else FALSE.
    */
-  protected function checkAny(array $checks, $route, $request, AccountInterface $account) {
+  protected function checkAny(array $checks, Route $route, Request $request, RouteMatchInterface $route_match, AccountInterface $account) {
     // No checks == deny by default.
     $access = FALSE;
 
@@ -325,7 +331,7 @@ protected function checkAny(array $checks, $route, $request, AccountInterface $a
         $this->loadCheck($service_id);
       }
 
-      $service_access = $this->performCheck($service_id, $route, $request, $account);
+      $service_access = $this->performCheck($service_id, $route, $request, $route_match, $account);
 
       if ($service_access === AccessInterface::ALLOW) {
         $access = TRUE;
@@ -347,18 +353,18 @@ protected function checkAny(array $checks, $route, $request, AccountInterface $a
    *   The route to check access to.
    * @param \Symfony\Component\HttpFoundation\Request $request
    *   The incoming request object.
+   * @param \Drupal\Core\Routing\RouteMatchInterface $route_match
+   *   The route match.
    * @param \Drupal\Core\Session\AccountInterface $account
    *   The current user.
    *
-   * @throws \Drupal\Core\Access\AccessException
-   *   Thrown when the access check returns an invalid value.
-   *
+   * @internal param $
    * @return string
    *   A \Drupal\Core\Access\AccessInterface constant value.
    */
-  protected function performCheck($service_id, $route, $request, $account) {
+  protected function performCheck($service_id, Route $route, Request $request, RouteMatchInterface $route_match, $account) {
     $callable = array($this->checks[$service_id], $this->checkMethods[$service_id]);
-    $arguments = $this->argumentsResolver->getArguments($callable, $route, $request, $account);
+    $arguments = $this->argumentsResolver->getArguments($callable, $route, $request, $route_match, $account);
     $service_access = call_user_func_array($callable, $arguments);
 
     if (!in_array($service_access, array(AccessInterface::ALLOW, AccessInterface::DENY, AccessInterface::KILL), TRUE)) {
diff --git a/core/lib/Drupal/Core/Access/CsrfAccessCheck.php b/core/lib/Drupal/Core/Access/CsrfAccessCheck.php
index 64c7328..ae604eb 100644
--- a/core/lib/Drupal/Core/Access/CsrfAccessCheck.php
+++ b/core/lib/Drupal/Core/Access/CsrfAccessCheck.php
@@ -8,6 +8,8 @@
 namespace Drupal\Core\Access;
 
 use Drupal\Core\Routing\Access\AccessInterface as RoutingAccessInterface;
+use Drupal\Core\Routing\RouteMatchInterface;
+use Drupal\Core\Routing\UrlGeneratorInterface;
 use Symfony\Component\Routing\Route;
 use Symfony\Component\HttpFoundation\Request;
 
@@ -28,13 +30,23 @@ class CsrfAccessCheck implements RoutingAccessInterface {
   protected $csrfToken;
 
   /**
+   * The URL generator.
+   *
+   * @var \Drupal\Core\Routing\UrlGeneratorInterface
+   */
+  protected $urlGenerator;
+
+  /**
    * Constructs a CsrfAccessCheck object.
    *
    * @param \Drupal\Core\Access\CsrfTokenGenerator $csrf_token
    *   The CSRF token generator.
+   * @param \Drupal\Core\Routing\UrlGeneratorInterface $url_generator
+   *   The URL generator.
    */
-  function __construct(CsrfTokenGenerator $csrf_token) {
+  function __construct(CsrfTokenGenerator $csrf_token, UrlGeneratorInterface $url_generator) {
     $this->csrfToken = $csrf_token;
+    $this->urlGenerator = $url_generator;
   }
 
   /**
@@ -44,16 +56,16 @@ function __construct(CsrfTokenGenerator $csrf_token) {
    *   The route to check against.
    * @param \Symfony\Component\HttpFoundation\Request $request
    *   The request object.
+   * @param \Drupal\Core\Routing\RouteMatchInterface $route_match
+   *   The route match object.
    *
    * @return string
    *   A \Drupal\Core\Access\AccessInterface constant value.
    */
-  public function access(Route $route, Request $request) {
+  public function access(Route $route, Request $request, RouteMatchInterface $route_match) {
     // If this is the controller request, check CSRF access as normal.
     if ($request->attributes->get('_controller_request')) {
-      // @todo Remove dependency on the internal _system_path attribute:
-      //   https://www.drupal.org/node/2293501.
-      return $this->csrfToken->validate($request->query->get('token'), $request->attributes->get('_system_path')) ? static::ALLOW : static::KILL;
+      return $this->csrfToken->validate($request->query->get('token'), $this->urlGenerator->getPathFromRoute($route_match->getRouteName(), $route_match->getRawParameters()->all())) ? static::ALLOW : static::KILL;
     }
 
     // Otherwise, this could be another requested access check that we don't
diff --git a/core/tests/Drupal/Tests/Core/Access/AccessArgumentsResolverTest.php b/core/tests/Drupal/Tests/Core/Access/AccessArgumentsResolverTest.php
index 2a46556..9ff926f 100644
--- a/core/tests/Drupal/Tests/Core/Access/AccessArgumentsResolverTest.php
+++ b/core/tests/Drupal/Tests/Core/Access/AccessArgumentsResolverTest.php
@@ -8,7 +8,9 @@
 namespace Drupal\Tests\Core\Access {
 
 use Drupal\Core\Access\AccessArgumentsResolver;
-use Drupal\Core\Session\AccountInterface;
+  use Drupal\Core\Routing\RouteMatch;
+  use Drupal\Core\Routing\RouteMatchInterface;
+  use Drupal\Core\Session\AccountInterface;
 use Drupal\Tests\UnitTestCase;
 use Symfony\Component\DependencyInjection\ParameterBag\ParameterBag;
 use Symfony\Component\HttpFoundation\Request;
@@ -49,7 +51,8 @@ protected function setUp() {
    * @dataProvider providerTestGetArgument
    */
   public function testGetArgument($callable, $request, $expected) {
-    $arguments = (new AccessArgumentsResolver())->getArguments($callable, $this->route, $request, $this->account);
+    $route_match = RouteMatch::createFromRequest($request);
+    $arguments = (new AccessArgumentsResolver())->getArguments($callable, $this->route, $request, $route_match, $this->account);
     $this->assertSame($expected, $arguments);
   }
 
@@ -103,8 +106,9 @@ function($foo) {}, $request, array('baz'),
   public function testGetArgumentRoute() {
     $callable = function(Route $route) {};
     $request = new Request();
+    $route_match = RouteMatch::createFromRequest($request);
 
-    $arguments = (new AccessArgumentsResolver())->getArguments($callable, $this->route, $request, $this->account);
+    $arguments = (new AccessArgumentsResolver())->getArguments($callable, $this->route, $request, $route_match, $this->account);
     $this->assertSame(array($this->route), $arguments);
   }
 
@@ -114,27 +118,30 @@ public function testGetArgumentRoute() {
   public function testGetArgumentRouteCustomName() {
     $callable = function(Route $custom_name) {};
     $request = new Request();
+    $route_match = RouteMatch::createFromRequest($request);
 
-    $arguments = (new AccessArgumentsResolver())->getArguments($callable, $this->route, $request, $this->account);
+    $arguments = (new AccessArgumentsResolver())->getArguments($callable, $this->route, $request, $route_match, $this->account);
     $this->assertSame(array($this->route), $arguments);
   }
 
   /**
-   * Tests getArgument() with a Route, Request, and Account object.
+   * Tests getArgument() with a Route, Request, RouteMatch and Account object.
    */
-  public function testGetArgumentRouteRequestAccount() {
-    $callable = function(Route $route, Request $request, AccountInterface $account) {};
+  public function testGetArgumentRouteRequestRouteMatchAccount() {
+    $callable = function(Route $route, Request $request, AccountInterface $account, RouteMatchInterface $route_match) {};
     $request = new Request();
+    $route_match = RouteMatch::createFromRequest($request);
 
-    $arguments = (new AccessArgumentsResolver())->getArguments($callable, $this->route, $request, $this->account);
-    $this->assertSame(array($this->route, $request, $this->account), $arguments);
+    $arguments = (new AccessArgumentsResolver())->getArguments($callable, $this->route, $request, $route_match, $this->account);
+    $this->assertSame(array($this->route, $request, $this->account, $route_match), $arguments);
 
     // Test again, but with the arguments in a different order.
-    $callable = function(AccountInterface $account, Request $request, Route $route) {};
+    $callable = function(AccountInterface $account, RouteMatchInterface $route_match, Request $request, Route $route) {};
     $request = new Request();
+    $route_match = RouteMatch::createFromRequest($request);
 
-    $arguments = (new AccessArgumentsResolver())->getArguments($callable, $this->route, $request, $this->account);
-    $this->assertSame(array($this->account, $request, $this->route), $arguments);
+    $arguments = (new AccessArgumentsResolver())->getArguments($callable, $this->route, $request, $route_match, $this->account);
+    $this->assertSame(array($this->account, $route_match, $request, $this->route), $arguments);
   }
 
   /**
@@ -148,8 +155,9 @@ public function testGetArgumentRouteRequestAccount() {
   public function testGetArgumentRouteNoTypehint() {
     $callable = function($route) {};
     $request = new Request();
+    $route_match = RouteMatch::createFromRequest($request);
 
-    $arguments = (new AccessArgumentsResolver())->getArguments($callable, $this->route, $request, $this->account);
+    $arguments = (new AccessArgumentsResolver())->getArguments($callable, $this->route, $request, $route_match, $this->account);
     $this->assertNull($arguments);
   }
 
@@ -162,9 +170,10 @@ public function testGetArgumentRouteNoTypehint() {
   public function testGetArgumentRouteNoTypehintAndValue() {
     $callable = function($route) {};
     $request = new Request();
+    $route_match = RouteMatch::createFromRequest($request);
     $request->attributes->set('route', 'foo');
 
-    $arguments = (new AccessArgumentsResolver())->getArguments($callable, $this->route, $request, $this->account);
+    $arguments = (new AccessArgumentsResolver())->getArguments($callable, $this->route, $request, $route_match, $this->account);
     $this->assertSame(array('foo'), $arguments);
   }
 
@@ -175,9 +184,10 @@ public function testGetArgumentBypassUpcasting() {
     $callable = function(Route $route = NULL) {};
 
     $request = new Request();
+    $route_match = RouteMatch::createFromRequest($request);
     $request->attributes->set('route', NULL);
 
-    $arguments = (new AccessArgumentsResolver())->getArguments($callable, $this->route, $request, $this->account);
+    $arguments = (new AccessArgumentsResolver())->getArguments($callable, $this->route, $request, $route_match, $this->account);
     $this->assertSame(array(NULL), $arguments);
   }
 
@@ -191,10 +201,11 @@ public function testHandleNotUpcastedArgument() {
     $callable = function(\stdClass $foo) {};
 
     $request = new Request();
+    $route_match = RouteMatch::createFromRequest($request);
     $request->attributes->set('foo', 'bar');
     $request->attributes->set('_raw_variables', new ParameterBag(array('foo' => 'baz')));
 
-    $arguments = (new AccessArgumentsResolver())->getArguments($callable, $this->route, $request, $this->account);
+    $arguments = (new AccessArgumentsResolver())->getArguments($callable, $this->route, $request, $route_match, $this->account);
     $this->assertNull($arguments);
   }
 
@@ -208,8 +219,9 @@ public function testHandleNotUpcastedArgument() {
    */
   public function testHandleUnresolvedArgument($callable) {
     $request = new Request();
+    $route_match = RouteMatch::createFromRequest($request);
 
-    $arguments = (new AccessArgumentsResolver())->getArguments($callable, $this->route, $request, $this->account);
+    $arguments = (new AccessArgumentsResolver())->getArguments($callable, $this->route, $request, $route_match, $this->account);
     $this->assertNull($arguments);
   }
 
diff --git a/core/tests/Drupal/Tests/Core/Access/CsrfAccessCheckTest.php b/core/tests/Drupal/Tests/Core/Access/CsrfAccessCheckTest.php
index a4319db..6d65a85 100644
--- a/core/tests/Drupal/Tests/Core/Access/CsrfAccessCheckTest.php
+++ b/core/tests/Drupal/Tests/Core/Access/CsrfAccessCheckTest.php
@@ -7,6 +7,7 @@
 
 namespace Drupal\Tests\Core\Access;
 
+use Drupal\Core\Routing\RouteMatch;
 use Symfony\Component\HttpFoundation\Request;
 use Symfony\Component\Routing\Route;
 use Drupal\Core\Access\CsrfAccessCheck;
@@ -27,6 +28,13 @@ class CsrfAccessCheckTest extends UnitTestCase {
   protected $csrfToken;
 
   /**
+   * The URL generator.
+   *
+   * @var \Drupal\Core\Routing\UrlGeneratorInterface|\PHPUnit_Framework_MockObject_MockObject
+   */
+  protected $urlGenerator;
+
+  /**
    * The access checker.
    *
    * @var \Drupal\Core\Access\CsrfAccessCheck
@@ -34,20 +42,16 @@ class CsrfAccessCheckTest extends UnitTestCase {
   protected $accessCheck;
 
   /**
-   * The mock user account.
-   *
-   * @var \Drupal\Core\Session\AccountInterface|\PHPUnit_Framework_MockObject_MockObject
+   * {@inheritdoc}
    */
-  protected $account;
-
   public function setUp() {
     $this->csrfToken = $this->getMockBuilder('Drupal\Core\Access\CsrfTokenGenerator')
       ->disableOriginalConstructor()
       ->getMock();
 
-    $this->account = $this->getMock('Drupal\Core\Session\AccountInterface');
+    $this->urlGenerator = $this->getMock('Drupal\Core\Routing\UrlGeneratorInterface');
 
-    $this->accessCheck = new CsrfAccessCheck($this->csrfToken);
+    $this->accessCheck = new CsrfAccessCheck($this->csrfToken, $this->urlGenerator);
   }
 
   /**
@@ -61,11 +65,15 @@ public function testAccessTokenPass() {
 
     $route = new Route('/test-path', array(), array('_csrf_token' => 'TRUE'));
     $request = Request::create('/test-path?token=test_query');
-    $request->attributes->set('_system_path', '/test-path');
+    $route_match = new RouteMatch('test_route', $route);
+    $this->urlGenerator->expects($this->once())
+      ->method('getPathFromRoute')
+      ->with($this->equalTo('test_route'))
+      ->will($this->returnValue('/test-path'));
     // Set the _controller_request flag so tokens are validated.
     $request->attributes->set('_controller_request', TRUE);
 
-    $this->assertSame(AccessInterface::ALLOW, $this->accessCheck->access($route, $request, $this->account));
+    $this->assertSame(AccessInterface::ALLOW, $this->accessCheck->access($route, $request, $route_match));
   }
 
   /**
@@ -79,11 +87,15 @@ public function testAccessTokenFail() {
 
     $route = new Route('/test-path', array(), array('_csrf_token' => 'TRUE'));
     $request = Request::create('/test-path?token=test_query');
-    $request->attributes->set('_system_path', '/test-path');
+    $route_match = new RouteMatch('test_route', $route);
+    $this->urlGenerator->expects($this->once())
+      ->method('getPathFromRoute')
+      ->with($this->equalTo('test_route'))
+      ->will($this->returnValue('/test-path'));
     // Set the _controller_request flag so tokens are validated.
     $request->attributes->set('_controller_request', TRUE);
 
-    $this->assertSame(AccessInterface::KILL, $this->accessCheck->access($route, $request, $this->account));
+    $this->assertSame(AccessInterface::KILL, $this->accessCheck->access($route, $request, $route_match));
   }
 
   /**
@@ -96,11 +108,14 @@ public function testAccessTokenMissAny() {
       ->method('validate');
 
     $route = new Route('/test-path', array(), array('_csrf_token' => 'TRUE'));
+    $route_match = new RouteMatch('test_route', $route);
+    $this->urlGenerator->expects($this->never())
+      ->method('getPathFromRoute');
     $request = new Request(array(
       'token' => 'test_query',
     ));
 
-    $this->assertSame(AccessInterface::DENY, $this->accessCheck->access($route, $request, $this->account));
+    $this->assertSame(AccessInterface::DENY, $this->accessCheck->access($route, $request, $route_match));
   }
 
   /**
@@ -113,11 +128,14 @@ public function testAccessTokenMissAll() {
       ->method('validate');
 
     $route = new Route('/test-path', array(), array('_csrf_token' => 'TRUE'), array('_access_mode' => 'ALL'));
+    $route_match = new RouteMatch('test_route', $route);
+    $this->urlGenerator->expects($this->never())
+      ->method('getPathFromRoute');
     $request = new Request(array(
       'token' => 'test_query',
     ));
 
-    $this->assertSame(AccessInterface::ALLOW, $this->accessCheck->access($route, $request, $this->account));
+    $this->assertSame(AccessInterface::ALLOW, $this->accessCheck->access($route, $request, $route_match));
   }
 
 }
