diff --git a/src/Symfony/Component/Security/Csrf/SameOriginCsrfTokenManager.php b/src/Symfony/Component/Security/Csrf/SameOriginCsrfTokenManager.php index 9ef61964bfe1e..0c95208c0f580 100644 --- a/src/Symfony/Component/Security/Csrf/SameOriginCsrfTokenManager.php +++ b/src/Symfony/Component/Security/Csrf/SameOriginCsrfTokenManager.php @@ -227,9 +227,21 @@ public function onKernelResponse(ResponseEvent $event): void */ private function isValidOrigin(Request $request): ?bool { - $source = $request->headers->get('Origin') ?? $request->headers->get('Referer') ?? 'null'; + $target = $request->getSchemeAndHttpHost().'/'; + $source = 'null'; - return 'null' === $source ? null : str_starts_with($source.'/', $request->getSchemeAndHttpHost().'/'); + foreach (['Origin', 'Referer'] as $header) { + if (!$request->headers->has($header)) { + continue; + } + $source = $request->headers->get($header); + + if (str_starts_with($source.'/', $target)) { + return true; + } + } + + return 'null' === $source ? null : false; } /** diff --git a/src/Symfony/Component/Security/Csrf/Tests/SameOriginCsrfTokenManagerTest.php b/src/Symfony/Component/Security/Csrf/Tests/SameOriginCsrfTokenManagerTest.php index 1ad17b80e0549..eae31deee379c 100644 --- a/src/Symfony/Component/Security/Csrf/Tests/SameOriginCsrfTokenManagerTest.php +++ b/src/Symfony/Component/Security/Csrf/Tests/SameOriginCsrfTokenManagerTest.php @@ -100,6 +100,20 @@ public function testValidOrigin() $this->assertSame(1 << 8, $request->attributes->get('csrf-token')); } + public function testValidRefererInvalidOrigin() + { + $request = new Request(); + $request->headers->set('Origin', 'http://localhost:1234'); + $request->headers->set('Referer', $request->getSchemeAndHttpHost()); + $this->requestStack->push($request); + + $token = new CsrfToken('test_token', str_repeat('a', 24)); + + $this->logger->expects($this->once())->method('debug')->with('CSRF validation accepted using origin info.'); + $this->assertTrue($this->csrfTokenManager->isTokenValid($token)); + $this->assertSame(1 << 8, $request->attributes->get('csrf-token')); + } + public function testValidOriginAfterDoubleSubmit() { $session = $this->createMock(Session::class);