[HttpKernel] Disable CSP header on exception pages

This commit is contained in:
Gabriel Ostrolucký 2017-12-17 23:51:54 +01:00
parent 62c11e5ea8
commit f33a383a1a
2 changed files with 40 additions and 0 deletions

View File

@ -13,7 +13,9 @@ namespace Symfony\Component\HttpKernel\EventListener;
use Psr\Log\LoggerInterface;
use Symfony\Component\Debug\Exception\FlattenException;
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpKernel\Event\FilterResponseEvent;
use Symfony\Component\HttpKernel\Log\DebugLoggerInterface;
use Symfony\Component\HttpKernel\Event\GetResponseForExceptionEvent;
use Symfony\Component\HttpKernel\KernelEvents;
@ -41,6 +43,7 @@ class ExceptionListener implements EventSubscriberInterface
{
$exception = $event->getException();
$request = $event->getRequest();
$eventDispatcher = func_num_args() > 2 ? func_get_arg(2) : null;
$this->logException($exception, sprintf('Uncaught PHP Exception %s: "%s" at %s line %s', get_class($exception), $exception->getMessage(), $exception->getFile(), $exception->getLine()));
@ -67,6 +70,14 @@ class ExceptionListener implements EventSubscriberInterface
}
$event->setResponse($response);
if ($eventDispatcher instanceof EventDispatcherInterface) {
$cspRemovalListener = function (FilterResponseEvent $event) use (&$cspRemovalListener, $eventDispatcher) {
$event->getResponse()->headers->remove('Content-Security-Policy');
$eventDispatcher->removeListener(KernelEvents::RESPONSE, $cspRemovalListener);
};
$eventDispatcher->addListener(KernelEvents::RESPONSE, $cspRemovalListener, -128);
}
}
public static function getSubscribedEvents()

View File

@ -12,8 +12,11 @@
namespace Symfony\Component\HttpKernel\Tests\EventListener;
use PHPUnit\Framework\TestCase;
use Symfony\Component\EventDispatcher\EventDispatcher;
use Symfony\Component\HttpKernel\Event\FilterResponseEvent;
use Symfony\Component\HttpKernel\HttpKernelInterface;
use Symfony\Component\HttpKernel\EventListener\ExceptionListener;
use Symfony\Component\HttpKernel\KernelEvents;
use Symfony\Component\HttpKernel\Log\DebugLoggerInterface;
use Symfony\Component\HttpKernel\Event\GetResponseForExceptionEvent;
use Symfony\Component\HttpFoundation\Request;
@ -122,6 +125,32 @@ class ExceptionListenerTest extends TestCase
$response = $event->getResponse();
$this->assertEquals('xml', $response->getContent());
}
public function testCSPHeaderIsRemoved()
{
$dispatcher = new EventDispatcher();
$kernel = $this->getMockBuilder('Symfony\Component\HttpKernel\HttpKernelInterface')->getMock();
$kernel->expects($this->once())->method('handle')->will($this->returnCallback(function (Request $request) {
return new Response($request->getRequestFormat());
}));
$listener = new ExceptionListener('foo', $this->getMockBuilder('Psr\Log\LoggerInterface')->getMock());
$dispatcher->addSubscriber($listener);
$request = Request::create('/');
$event = new GetResponseForExceptionEvent($kernel, $request, HttpKernelInterface::MASTER_REQUEST, new \Exception('foo'));
$dispatcher->dispatch(KernelEvents::EXCEPTION, $event);
$response = new Response('', 200, array('content-security-policy' => "style-src 'self'"));
$this->assertTrue($response->headers->has('content-security-policy'));
$event = new FilterResponseEvent($kernel, $request, HttpKernelInterface::MASTER_REQUEST, $response);
$dispatcher->dispatch(KernelEvents::RESPONSE, $event);
$this->assertFalse($response->headers->has('content-security-policy'), 'CSP header has been removed');
$this->assertFalse($dispatcher->hasListeners(KernelEvents::RESPONSE), 'CSP removal listener has been removed');
}
}
class TestLogger extends Logger implements DebugLoggerInterface