Verified Commit f98362ad authored by Dave Long's avatar Dave Long
Browse files

test: #3570173 Update tests for cache poisoning protection

By: akalata
By: smustgrave
By: alexpott
By: larowlan
By: neclimdul
parent d7434b43
Loading
Loading
Loading
Loading
Loading
+60 −0
Original line number Diff line number Diff line
<?php

declare(strict_types=1);

namespace Drupal\FunctionalTests\HttpKernel;

use Drupal\Core\Url;
use Drupal\Tests\ApiRequestTrait;
use Drupal\Tests\BrowserTestBase;
use GuzzleHttp\RequestOptions;
use PHPUnit\Framework\Attributes\Group;
use PHPUnit\Framework\Attributes\IgnoreDeprecations;
use PHPUnit\Framework\Attributes\RunTestsInSeparateProcesses;

/**
 * Tests RequestSanitizerMiddleware.
 */
#[Group('Http')]
#[RunTestsInSeparateProcesses]
class RequestSanitizerTest extends BrowserTestBase {
  use ApiRequestTrait;
  /**
   * {@inheritdoc}
   */
  protected static $modules = ['system'];

  /**
   * {@inheritdoc}
   */
  protected $defaultTheme = 'stark';

  /**
   * Tests X-Http-Method-Override header handling.
   */
  #[IgnoreDeprecations]
  public function testRequestSanitizer(): void {
    $url = new Url('<front>');
    $response = $this->makeApiRequest('GET', $url, []);
    $this->assertSame(200, $response->getStatusCode());

    $response = $this->makeApiRequest('POST', $url, []);
    $this->assertSame(200, $response->getStatusCode());

    $request_options = [];
    $request_options[RequestOptions::HEADERS] = [
      'X-Http-Method-Override' => 'GET',
    ];
    $this->expectDeprecation('Since symfony/http-foundation 7.4: HTTP method override is deprecated for methods GET, HEAD, CONNECT and TRACE; it will be ignored in Symfony 8.0.');
    $response = $this->makeApiRequest('POST', $url, $request_options);
    $this->assertSame(200, $response->getStatusCode());
    $this->assertSame('HIT', $response->getHeader('X-Drupal-Cache')[0]);

    // Clear the page cache.
    $this->rebuildAll();

    $response = $this->makeApiRequest('POST', $url, $request_options);
    $this->assertSame(400, $response->getStatusCode());
  }

}
+25 −0
Original line number Diff line number Diff line
@@ -11,7 +11,9 @@
use PHPUnit\Framework\Attributes\Group;
use PHPUnit\Framework\Attributes\PreserveGlobalState;
use PHPUnit\Framework\Attributes\RunTestsInSeparateProcesses;
use PHPUnit\Framework\Attributes\TestWith;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpKernel\Exception\BadRequestHttpException;

/**
 * Tests RequestSanitizer class.
@@ -305,6 +307,29 @@ public function testSanitizedDestinationGet($destination): void {
    $this->assertError('Potentially unsafe destination removed from query parameter bag because it points to an external URL.', E_USER_NOTICE);
  }

  /**
   * Tests unacceptable destinations are removed from GET requests.
   */
  #[TestWith(["POST", FALSE])]
  #[TestWith(["GET", TRUE])]
  #[TestWith(["HEAD", TRUE])]
  #[TestWith(["PUT", FALSE])]
  #[TestWith(["DELETE", FALSE])]
  #[TestWith(["CONNECT", FALSE])]
  #[TestWith(["OPTIONS", TRUE])]
  #[TestWith(["TRACE", TRUE])]
  #[TestWith(["PATCH", FALSE])]
  public function testRequestMethodOverride(string $override, bool $exception): void {
    $request = $this->createRequestForTesting();
    $request->server->set('REQUEST_METHOD', 'POST');
    $request->headers->set('X-HTTP-Method-Override', $override);
    if ($exception) {
      $this->expectException(BadRequestHttpException::class);
    }
    $request = RequestSanitizer::sanitize($request, []);
    $this->assertEquals($override, $request->getMethod());
  }

  /**
   * Tests acceptable destinations are not removed from POST requests.
   *