<?php
namespace App\EventSubscriber;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use Symfony\Component\HttpKernel\Event\ResponseEvent;
class SecurityHeadersSubscriber implements EventSubscriberInterface
{
public static function getSubscribedEvents(): array
{
return [
ResponseEvent::class => 'onResponse',
];
}
public function onResponse(ResponseEvent $event): void
{
if (!$event->isMainRequest()) {
return;
}
$response = $event->getResponse();
$csp = "default-src 'self'; img-src 'self' data: https://*.stripe.com; "
. "style-src 'self' 'unsafe-inline' https://fonts.googleapis.com; "
. "script-src 'self' 'unsafe-inline' https://js.stripe.com; "
. "font-src 'self' data: https://fonts.gstatic.com; "
. "connect-src 'self' https://api.stripe.com; "
. "frame-src https://js.stripe.com https://checkout.stripe.com https://*.stripe.com; "
. "frame-ancestors 'none'; base-uri 'self'";
if (!$response->headers->has('Content-Security-Policy')) {
$response->headers->set('Content-Security-Policy', $csp);
}
$response->headers->set('Referrer-Policy', 'strict-origin-when-cross-origin');
$response->headers->set('X-Content-Type-Options', 'nosniff');
$response->headers->set('X-Frame-Options', 'DENY');
$response->headers->set('Permissions-Policy', 'geolocation=(self), microphone=(), camera=(), payment=(), fullscreen=()');
}
}