diff --git a/core/core.services.yml b/core/core.services.yml
index 10feccb1372..cd63e66afe9 100644
--- a/core/core.services.yml
+++ b/core/core.services.yml
@@ -1379,7 +1379,7 @@ services:
     class: Drupal\Core\Access\CsrfAccessCheck
     tags:
       - { name: access_check, applies_to: _csrf_token, needs_incoming_request: TRUE }
-    arguments: ['@csrf_token']
+    arguments: ['@csrf_token', '@session_configuration']
   access_check.header.csrf:
     class: Drupal\Core\Access\CsrfRequestHeaderAccessCheck
     arguments: ['@session_configuration', '@csrf_token']
@@ -1481,7 +1481,7 @@ services:
     class: Drupal\Core\Access\RouteProcessorCsrf
     tags:
       - { name: route_processor_outbound }
-    arguments: ['@csrf_token', '@request_stack']
+    arguments: ['@csrf_token', '@session_configuration', '@request_stack']
   transliteration:
     class: Drupal\Core\Transliteration\PhpTransliteration
     arguments: [null, '@module_handler']
diff --git a/core/lib/Drupal/Core/Access/CsrfAccessCheck.php b/core/lib/Drupal/Core/Access/CsrfAccessCheck.php
index bd88a31c27c..9ae91df5e2c 100644
--- a/core/lib/Drupal/Core/Access/CsrfAccessCheck.php
+++ b/core/lib/Drupal/Core/Access/CsrfAccessCheck.php
@@ -4,6 +4,7 @@

 use Drupal\Core\Routing\Access\AccessInterface as RoutingAccessInterface;
 use Drupal\Core\Routing\RouteMatchInterface;
+use Drupal\Core\Session\SessionConfigurationInterface;
 use Symfony\Component\Routing\Route;
 use Symfony\Component\HttpFoundation\Request;

@@ -31,14 +32,24 @@ class CsrfAccessCheck implements RoutingAccessInterface {
    */
   protected $csrfToken;

+  /**
+   * The session configuration.
+   *
+   * @var \Drupal\Core\Session\SessionConfigurationInterface
+   */
+  protected $sessionConfiguration;
+
   /**
    * Constructs a CsrfAccessCheck object.
    *
    * @param \Drupal\Core\Access\CsrfTokenGenerator $csrf_token
    *   The CSRF token generator.
+   * @param \Drupal\Core\Session\SessionConfigurationInterface $session_configuration
+   *   The session configuration.
    */
-  public function __construct(CsrfTokenGenerator $csrf_token) {
+  public function __construct(CsrfTokenGenerator $csrf_token, SessionConfigurationInterface $session_configuration) {
     $this->csrfToken = $csrf_token;
+    $this->sessionConfiguration = $session_configuration;
   }

   /**
@@ -62,7 +73,9 @@ public function access(Route $route, Request $request, RouteMatchInterface $rout
       $path = str_replace("{{$param}}", $value, $path);
     }

-    if ($this->csrfToken->validate($request->query->get('token', ''), $path)) {
+    // Per https://www.drupal.org/node/2319205 anonymous users do not need
+    // CSRF checking.
+    if (!$this->sessionConfiguration->hasSession($request) || $this->csrfToken->validate($request->query->get('token', ''), $path)) {
       $result = AccessResult::allowed();
     }
     else {
diff --git a/core/lib/Drupal/Core/Access/RouteProcessorCsrf.php b/core/lib/Drupal/Core/Access/RouteProcessorCsrf.php
index 79dea87a612..2d17c84e4dd 100644
--- a/core/lib/Drupal/Core/Access/RouteProcessorCsrf.php
+++ b/core/lib/Drupal/Core/Access/RouteProcessorCsrf.php
@@ -6,6 +6,7 @@
 use Drupal\Core\Render\BubbleableMetadata;
 use Drupal\Core\Security\TrustedCallbackInterface;
 use Drupal\Core\RouteProcessor\OutboundRouteProcessorInterface;
+use Drupal\Core\Session\SessionConfigurationInterface;
 use Symfony\Component\HttpFoundation\RequestStack;
 use Symfony\Component\Routing\Route;

@@ -19,11 +20,14 @@ class RouteProcessorCsrf implements OutboundRouteProcessorInterface, TrustedCall
    *
    * @param \Drupal\Core\Access\CsrfTokenGenerator $csrfToken
    *   The CSRF token generator.
+   * @param \Drupal\Core\Session\SessionConfigurationInterface $sessionConfiguration
+   *    The session configuration.
    * @param \Symfony\Component\HttpFoundation\RequestStack|null $requestStack
-   *   The request stack.
+   *    The request stack.
    */
   public function __construct(
     protected CsrfTokenGenerator $csrfToken,
+    protected SessionConfigurationInterface $sessionConfiguration,
     protected ?RequestStack $requestStack = NULL,
   ) {
     if ($requestStack === NULL) {
@@ -35,7 +39,9 @@ public function __construct(
    * {@inheritdoc}
    */
   public function processOutbound($route_name, Route $route, array &$parameters, ?BubbleableMetadata $bubbleable_metadata = NULL) {
-    if ($route->hasRequirement('_csrf_token')) {
+    // Per https://www.drupal.org/node/2319205 anonymous users do not need
+    // CSRF checking.
+    if ($route->hasRequirement('_csrf_token') && $this->sessionConfiguration->hasSession($this->requestStack->getCurrentRequest())) {
       $path = ltrim($route->getPath(), '/');
       // Replace the path parameters with values from the parameters array.
       foreach ($parameters as $param => $value) {
@@ -50,7 +56,12 @@ public function processOutbound($route_name, Route $route, array &$parameters, ?
         // Generate a placeholder and a render array to replace it.
         $placeholder = Crypt::hashBase64($path);
         $placeholder_render_array = [
-          '#lazy_builder' => ['route_processor_csrf:renderPlaceholderCsrfToken', [$path]],
+          '#lazy_builder' => [
+            'route_processor_csrf:renderPlaceholderCsrfToken',
+            [
+              $path
+            ]
+          ],
         ];
         // Instead of setting an actual CSRF token as the query string, we set
         // the placeholder, which will be replaced at the very last moment. This
@@ -62,6 +73,8 @@ public function processOutbound($route_name, Route $route, array &$parameters, ?
   }

   /**
+   * Gets a CSRF token for the given path.
+   *
    * #lazy_builder callback; gets a CSRF token for the given path.
    *
    * @param string $path
diff --git a/core/modules/menu_link_content/tests/src/Kernel/MenuLinkContentCacheabilityBubblingTest.php b/core/modules/menu_link_content/tests/src/Kernel/MenuLinkContentCacheabilityBubblingTest.php
index 7bfd96a34ae..b0990c5502a 100644
--- a/core/modules/menu_link_content/tests/src/Kernel/MenuLinkContentCacheabilityBubblingTest.php
+++ b/core/modules/menu_link_content/tests/src/Kernel/MenuLinkContentCacheabilityBubblingTest.php
@@ -67,6 +67,8 @@ public function testOutboundPathAndRouteProcessing(): void {
     $request->attributes->set(RouteObjectInterface::ROUTE_NAME, '<front>');
     $request->attributes->set(RouteObjectInterface::ROUTE_OBJECT, new Route('/'));
     $request->setSession(new Session(new MockArraySessionStorage()));
+    // Fake a started session.
+    $request->cookies->add(['SESS' . substr(hash('sha256', $this->getDatabasePrefix()), 0, 32) => '']);
     $request_stack->push($request);
     $request_context->fromRequest($request);

@@ -76,7 +78,11 @@ public function testOutboundPathAndRouteProcessing(): void {
     $default_menu_cacheability = (new BubbleableMetadata())
       ->setCacheMaxAge(Cache::PERMANENT)
       ->setCacheTags(['config:system.menu.tools'])
-      ->setCacheContexts(['languages:' . LanguageInterface::TYPE_INTERFACE, 'theme', 'user.permissions']);
+      ->setCacheContexts([
+        'languages:' . LanguageInterface::TYPE_INTERFACE,
+        'theme',
+        'user.permissions'
+      ]);

     User::create(['uid' => 1, 'name' => $this->randomString()])->save();
     User::create(['uid' => 2, 'name' => $this->randomString()])->save();
@@ -91,7 +97,8 @@ public function testOutboundPathAndRouteProcessing(): void {
     // cacheability metadata of the same type is working (two links with cache
     // tags).
     $test_cases = [
-      // \Drupal\Core\RouteProcessor\RouteProcessorCurrent: 'route' cache context.
+      // \Drupal\Core\RouteProcessor\RouteProcessorCurrent: 'route' cache
+      // context.
       [
         'uri' => 'route:<current>',
         'cacheability' => (new BubbleableMetadata())->setCacheContexts(['route']),
diff --git a/core/modules/system/tests/src/Kernel/Common/UrlTest.php b/core/modules/system/tests/src/Kernel/Common/UrlTest.php
index 56a93960526..58f8af922aa 100644
--- a/core/modules/system/tests/src/Kernel/Common/UrlTest.php
+++ b/core/modules/system/tests/src/Kernel/Common/UrlTest.php
@@ -24,6 +24,9 @@ class UrlTest extends KernelTestBase {

   /**
    * {@inheritdoc}
+   * The modules list.
+   *
+   * @var array
    */
   protected static $modules = ['common_test', 'url_alter_test'];

@@ -51,19 +54,84 @@ public function testLinkXSS(): void {
    */
   public function testLinkBubbleableMetadata(): void {
     \Drupal::service('module_installer')->install(['user']);
+    // Fake a started session.
+    \Drupal::request()->cookies->add(['SESS' . substr(hash('sha256', $this->getDatabasePrefix()), 0, 32) => '']);

     $cases = [
-      ['Regular link', 'internal:/user', [], ['contexts' => [], 'tags' => [], 'max-age' => Cache::PERMANENT], []],
-      ['Regular link, absolute', 'internal:/user', ['absolute' => TRUE], ['contexts' => ['url.site'], 'tags' => [], 'max-age' => Cache::PERMANENT], []],
-      ['Route processor link', 'route:system.run_cron', [], ['contexts' => ['session'], 'tags' => [], 'max-age' => Cache::PERMANENT], ['placeholders' => []]],
-      ['Route processor link, absolute', 'route:system.run_cron', ['absolute' => TRUE], ['contexts' => ['url.site', 'session'], 'tags' => [], 'max-age' => Cache::PERMANENT], ['placeholders' => []]],
-      ['Path processor link', 'internal:/user/1', [], ['contexts' => [], 'tags' => ['user:1'], 'max-age' => Cache::PERMANENT], []],
-      ['Path processor link, absolute', 'internal:/user/1', ['absolute' => TRUE], ['contexts' => ['url.site'], 'tags' => ['user:1'], 'max-age' => Cache::PERMANENT], []],
+      [
+        'Regular link',
+        'internal:/user',
+        [],
+        [
+          'contexts' => [],
+          'tags' => [],
+          'max-age' => Cache::PERMANENT,
+        ],
+        [],
+      ],
+      [
+        'Regular link, absolute',
+        'internal:/user',
+        ['absolute' => TRUE],
+        [
+          'contexts' => ['url.site'],
+          'tags' => [],
+          'max-age' => Cache::PERMANENT,
+        ],
+        [],
+      ],
+      [
+        'Route processor link',
+        'route:system.run_cron',
+        [],
+        [
+          'contexts' => ['session'],
+          'tags' => [],
+          'max-age' => Cache::PERMANENT,
+        ],
+        ['placeholders' => []],
+      ],
+      [
+        'Route processor link, absolute',
+        'route:system.run_cron',
+        ['absolute' => TRUE],
+        [
+          'contexts' => ['url.site', 'session'],
+          'tags' => [],
+          'max-age' => Cache::PERMANENT,
+        ],
+        ['placeholders' => []],
+      ],
+      [
+        'Path processor link',
+        'internal:/user/1',
+        [],
+        [
+          'contexts' => [],
+          'tags' => ['user:1'],
+          'max-age' => Cache::PERMANENT,
+        ],
+        [],
+      ],
+      [
+        'Path processor link, absolute',
+        'internal:/user/1',
+        ['absolute' => TRUE],
+        [
+          'contexts' => ['url.site'],
+          'tags' => ['user:1'],
+          'max-age' => Cache::PERMANENT,
+        ],
+        [],
+      ],
     ];

     foreach ($cases as $case) {
       [$title, $uri, $options, $expected_cacheability, $expected_attachments] = $case;
-      $expected_cacheability['contexts'] = Cache::mergeContexts($expected_cacheability['contexts'], ['languages:language_interface', 'theme', 'user.permissions']);
+      $expected_cacheability['contexts'] = Cache::mergeContexts(
+        $expected_cacheability['contexts'],
+        ['languages:language_interface', 'theme', 'user.permissions']
+      );
       $link = [
         '#type' => 'link',
         '#title' => $title,
@@ -140,6 +208,7 @@ public function testLinkRenderArrayText(): void {
     $l = Link::fromTextAndUrl('foo', Url::fromUri('https://www.drupal.org'))->toString();

     // Test a renderable array passed to the link generator.
+    // @codingStandardsIgnoreLine
     $renderer->executeInRenderContext(new RenderContext(), function () use ($l) {
       $renderable_text = ['#markup' => 'foo'];
       $l_renderable_text = \Drupal::service('link_generator')->generate($renderable_text, Url::fromUri('https://www.drupal.org'));
@@ -168,11 +237,11 @@ public function testLinkRenderArrayText(): void {
   /**
    * Checks for class existence in link.
    *
-   * @param $attribute
+   * @param string $attribute
    *   Attribute to be checked.
-   * @param $link
+   * @param \Drupal\Core\Render\RenderableInterface|string $link
    *   URL to search.
-   * @param $class
+   * @param string $class
    *   Element class to search for.
    *
    * @return bool
@@ -215,7 +284,12 @@ public function testDrupalGetQueryParameters(): void {
     // Multiple exclusions.
     $result = $original;
     unset($result['a'], $result['b']['e'], $result['c']);
-    $this->assertEquals(UrlHelper::filterQueryParameters($original, ['a', 'b[e]', 'c']), $result, "'a', 'b[e]', 'c' were removed.");
+    $this->assertEquals(
+      UrlHelper::filterQueryParameters(
+        $original,
+        ['a', 'b[e]', 'c']
+      ), $result, "'a', 'b[e]', 'c' were removed."
+    );
   }

   /**
@@ -247,11 +321,13 @@ public function testDrupalParseUrl(): void {
     ];
     $this->assertEquals($result, UrlHelper::parse($url), 'Relative URL parsed correctly.');

-    // Test that drupal can recognize an absolute URL. Used to prevent attack vectors.
+    // Test that drupal can recognize an absolute URL. Used to prevent attack
+    // vectors.
     $url = 'https://www.example.org/foo/bar?foo=bar&bar=baz&baz#foo';
     $this->assertTrue(UrlHelper::isExternal($url), 'Correctly identified an external URL.');

-    // Test that UrlHelper::parse() does not allow spoofing a URL to force a malicious redirect.
+    // Test that UrlHelper::parse() does not allow spoofing a URL to force a malicious
+    // redirect.
     $parts = UrlHelper::parse('forged:http://cwe.mitre.org/data/definitions/601.html');
     $this->assertFalse(UrlHelper::isValid($parts['path'], TRUE), '\Drupal\Component\Utility\UrlHelper::isValid() correctly parsed a forged URL.');
   }
diff --git a/core/tests/Drupal/Tests/Core/Access/CsrfAccessCheckTest.php b/core/tests/Drupal/Tests/Core/Access/CsrfAccessCheckTest.php
index 34bb870ef48..697c4ca0f1b 100644
--- a/core/tests/Drupal/Tests/Core/Access/CsrfAccessCheckTest.php
+++ b/core/tests/Drupal/Tests/Core/Access/CsrfAccessCheckTest.php
@@ -8,6 +8,9 @@
 use Symfony\Component\HttpFoundation\Request;
 use Symfony\Component\Routing\Route;
 use Drupal\Core\Access\CsrfAccessCheck;
+use Drupal\Core\Access\CsrfTokenGenerator;
+use Drupal\Core\Routing\RouteMatchInterface;
+use Drupal\Core\Session\SessionConfigurationInterface;
 use Drupal\Tests\UnitTestCase;

 /**
@@ -37,25 +40,36 @@ class CsrfAccessCheckTest extends UnitTestCase {
    */
   protected $routeMatch;

+  /**
+   * The session configuration.
+   *
+   * @var \Drupal\Core\Session\SessionConfigurationInterface|\PHPUnit_Framework_MockObject_MockObject
+   */
+  protected $sessionConfiguration;
   /**
    * {@inheritdoc}
    */
   protected function setUp(): void {
     parent::setUp();

-    $this->csrfToken = $this->getMockBuilder('Drupal\Core\Access\CsrfTokenGenerator')
+    $this->csrfToken = $this->getMockBuilder(CsrfTokenGenerator::class)
       ->disableOriginalConstructor()
       ->getMock();

-    $this->routeMatch = $this->createMock('Drupal\Core\Routing\RouteMatchInterface');
+    $this->routeMatch = $this->createMock(RouteMatchInterface::class);

-    $this->accessCheck = new CsrfAccessCheck($this->csrfToken);
+    $this->sessionConfiguration = $this->createMock(SessionConfigurationInterface::class);
+    $this->accessCheck = new CsrfAccessCheck($this->csrfToken, $this->sessionConfiguration);
   }

   /**
    * Tests the access() method with a valid token.
    */
   public function testAccessTokenPass(): void {
+    $this->sessionConfiguration->expects($this->once())
+      ->method('hasSession')
+      ->willReturn(TRUE);
+
     $this->csrfToken->expects($this->once())
       ->method('validate')
       ->with('test_query', 'test-path/42')
@@ -71,15 +85,41 @@ public function testAccessTokenPass(): void {
     $this->assertEquals(AccessResult::allowed()->setCacheMaxAge(0), $this->accessCheck->access($route, $request, $this->routeMatch));
   }

+  /**
+   * Tests the access() method for anonymous users.
+   */
+  public function testAccessTokenAnonymousPass() {
+   $this->sessionConfiguration->expects($this->once())
+     ->method('hasSession')
+     ->willReturn(FALSE);
+   $this->routeMatch->expects($this->once())
+     ->method('getRawParameters')
+     ->will($this->returnValue(['node' => 42]));
+
+   $route = new Route('/test-path/{node}', [], ['_csrf_token' => 'TRUE']);
+   $request = Request::create('/test-path/42?token=test_query');
+   $this->csrfToken->expects($this->never())
+     ->method('validate');
+   $this->assertEquals(AccessResult::allowed()->setCacheMaxAge(0), $this->accessCheck->access($route, $request, $this->routeMatch));
+  }
+
   /**
    * @covers ::access
    */
   public function testCsrfTokenInvalid(): void {
+    $this->sessionConfiguration->expects($this->once())
+      ->method('hasSession')
+      ->willReturn(TRUE);
+
     $this->csrfToken->expects($this->once())
       ->method('validate')
       ->with('test_query', 'test-path')
       ->willReturn(FALSE);

+    $this->sessionConfiguration->expects($this->once())
+      ->method('hasSession')
+      ->willReturn(TRUE);
+
     $this->routeMatch->expects($this->once())
       ->method('getRawParameters')
       ->willReturn([]);
diff --git a/core/tests/Drupal/Tests/Core/Access/RouteProcessorCsrfTest.php b/core/tests/Drupal/Tests/Core/Access/RouteProcessorCsrfTest.php
index c4d6d6d221c..e6d8856eefb 100644
--- a/core/tests/Drupal/Tests/Core/Access/RouteProcessorCsrfTest.php
+++ b/core/tests/Drupal/Tests/Core/Access/RouteProcessorCsrfTest.php
@@ -9,8 +9,10 @@
 use Drupal\Core\Render\BubbleableMetadata;
 use Drupal\Tests\UnitTestCase;
 use Drupal\Core\Access\RouteProcessorCsrf;
-use PHPUnit\Framework\MockObject\MockObject;
+use Drupal\Core\Session\SessionConfigurationInterface;
+use Symfony\Component\HttpFoundation\Request;
 use Symfony\Component\HttpFoundation\RequestStack;
+use PHPUnit\Framework\MockObject\MockObject;
 use Symfony\Component\Routing\Route;

 /**
@@ -34,13 +36,22 @@ class RouteProcessorCsrfTest extends UnitTestCase {
    */
   protected RouteProcessorCsrf $processor;

+  /**
+   * The session configuration.
+   *
+   * @var \Drupal\Core\Session\SessionConfigurationInterface|\PHPUnit_Framework_MockObject_MockObject
+   */
+  protected $sessionConfiguration;
+
   /**
    * {@inheritdoc}
+   *
+   * Sets up the necessary mocks.
    */
   protected function setUp(): void {
     parent::setUp();

-    $this->csrfToken = $this->getMockBuilder('Drupal\Core\Access\CsrfTokenGenerator')
+    $this->csrfToken = $this->getMockBuilder(CsrfTokenGenerator::class)
       ->disableOriginalConstructor()
       ->getMock();

@@ -57,13 +68,25 @@ protected function setUp(): void {
       ->method('getCurrentRequest')
       ->willReturn($request);

-    $this->processor = new RouteProcessorCsrf($this->csrfToken, $this->requestStack);
+    $this->sessionConfiguration = $this->createMock(SessionConfigurationInterface::class);
+    $request_stack = $this->createMock(RequestStack::class);
+    // The number this is called differs between tests and is completely
+    // irrelevant, the sessionConfiguration mock object will have the exact
+    // number of calls.
+    $request_stack->expects($this->atMost(1))
+      ->method('getCurrentRequest')
+      ->willReturn($this->createMock(Request::class));
+
+   $this->processor = new RouteProcessorCsrf($this->csrfToken, $this->sessionConfiguration, $request_stack);
   }

   /**
    * Tests the processOutbound() method with no _csrf_token route requirement.
    */
   public function testProcessOutboundNoRequirement(): void {
+    $this->sessionConfiguration->expects($this->never())
+      ->method('hasSession');
+
     $this->csrfToken->expects($this->never())
       ->method('get');

@@ -83,6 +106,10 @@ public function testProcessOutboundNoRequirement(): void {
    * Tests the processOutbound() method with a _csrf_token route requirement.
    */
   public function testProcessOutbound(): void {
+    $this->sessionConfiguration->expects($this->once())
+      ->method('hasSession')
+      ->willReturn(TRUE);
+
     $route = new Route('/test-path', [], ['_csrf_token' => 'TRUE']);
     $parameters = [];

@@ -95,16 +122,43 @@ public function testProcessOutbound(): void {
     $path = 'test-path';
     $placeholder = Crypt::hashBase64($path);
     $placeholder_render_array = [
-      '#lazy_builder' => ['route_processor_csrf:renderPlaceholderCsrfToken', [$path]],
+      '#lazy_builder' => [
+        'route_processor_csrf:renderPlaceholderCsrfToken',
+        [
+          $path
+        ],
+      ],
     ];
     $this->assertSame($parameters['token'], $placeholder);
     $this->assertEquals((new BubbleableMetadata())->setAttachments(['placeholders' => [$placeholder => $placeholder_render_array]]), $bubbleable_metadata);
   }

+  /**
+  +   * Tests the processOutbound() method for anonymous users.
+  +   */
+  public function testProcessOutboundForAnonymous() {
+    $this->sessionConfiguration->expects($this->once())
+       ->method('hasSession')
+       ->willReturn(FALSE);
+    $this->csrfToken->expects($this->never())
+      ->method('get');
+    $route = new Route('/test-path', [], ['_csrf_token' => 'TRUE']);
+    $parameters = [];
+
+    $bubbleable_metadata = new BubbleableMetadata();
+    $this->processor->processOutbound('test', $route, $parameters, $bubbleable_metadata);
+    $this->assertEmpty($parameters);
+    $this->assertEquals((new BubbleableMetadata()), $bubbleable_metadata);
+  }
+
   /**
    * Tests the processOutbound() method with a dynamic path and one replacement.
    */
   public function testProcessOutboundDynamicOne(): void {
+    $this->sessionConfiguration->expects($this->once())
+      ->method('hasSession')
+      ->willReturn(TRUE);
+
     $route = new Route('/test-path/{slug}', [], ['_csrf_token' => 'TRUE']);
     $parameters = ['slug' => 100];

@@ -115,7 +169,12 @@ public function testProcessOutboundDynamicOne(): void {
     $path = 'test-path/100';
     $placeholder = Crypt::hashBase64($path);
     $placeholder_render_array = [
-      '#lazy_builder' => ['route_processor_csrf:renderPlaceholderCsrfToken', [$path]],
+      '#lazy_builder' => [
+        'route_processor_csrf:renderPlaceholderCsrfToken',
+        [
+          $path
+        ],
+      ],
     ];
     $this->assertEquals((new BubbleableMetadata())->setAttachments(['placeholders' => [$placeholder => $placeholder_render_array]]), $bubbleable_metadata);
   }
@@ -124,6 +183,10 @@ public function testProcessOutboundDynamicOne(): void {
    * Tests the processOutbound() method with two parameter replacements.
    */
   public function testProcessOutboundDynamicTwo(): void {
+    $this->sessionConfiguration->expects($this->once())
+      ->method('hasSession')
+      ->willReturn(TRUE);
+
     $route = new Route('{slug_1}/test-path/{slug_2}', [], ['_csrf_token' => 'TRUE']);
     $parameters = ['slug_1' => 100, 'slug_2' => 'test'];

@@ -134,7 +197,12 @@ public function testProcessOutboundDynamicTwo(): void {
     $path = '100/test-path/test';
     $placeholder = Crypt::hashBase64($path);
     $placeholder_render_array = [
-      '#lazy_builder' => ['route_processor_csrf:renderPlaceholderCsrfToken', [$path]],
+      '#lazy_builder' => [
+        'route_processor_csrf:renderPlaceholderCsrfToken',
+        [
+          $path
+        ],
+      ],
     ];
     $this->assertEquals((new BubbleableMetadata())->setAttachments(['placeholders' => [$placeholder => $placeholder_render_array]]), $bubbleable_metadata);
   }
