Merge branch 'main' into fix/ci-github-rate-limit
Sync GitHub / sync (push) Successful in 6s

This commit is contained in:
2026-08-20 16:27:52 -04:00
+24 -5
View File
@@ -4,6 +4,7 @@ declare(strict_types=1);
namespace App\Listener;
use App\Service\DomainInterface;
use Symfony\Component\EventDispatcher\Attribute\AsEventListener;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpKernel\Event\ResponseEvent;
@@ -15,6 +16,11 @@ use Symfony\Component\HttpKernel\Event\ResponseEvent;
*/
final readonly class SecurityHeadersListener
{
public function __construct(
private DomainInterface $domainManager,
) {
}
#[AsEventListener(priority: 0)]
public function onKernelResponse(ResponseEvent $event): void
{
@@ -36,11 +42,24 @@ final readonly class SecurityHeadersListener
/* Content-Security-Policy — the login page uses inline styles
* and scripts (via Twig includes), so we allow 'unsafe-inline'
* for those. No external resources are loaded. */
$headers->set(
'Content-Security-Policy',
"default-src 'none'; script-src 'unsafe-inline'; style-src 'unsafe-inline';"
);
* for those. No external resources are loaded.
*
* When subdomain redirection is off (or the request is not on
* the auth subdomain), the login form is served inline on the
* protected host and submission is performed via a same-origin
* fetch() call in _script.html.twig. That fetch is blocked by
* the default 'none' policy, so we add connect-src 'self' only
* in that case — the least privilege needed to make the form
* work. On the auth subdomain the form POSTs normally and no
* inline script is included, so the stricter policy applies. */
$inlineScript = $this->domainManager->getAuthSubdomain() !== $event->getRequest()->getHost();
$csp = "default-src 'none'; script-src 'unsafe-inline'; style-src 'unsafe-inline';";
if ($inlineScript) {
$csp .= " connect-src 'self';";
}
$headers->set('Content-Security-Policy', $csp);
/* HSTS — enforce HTTPS for one year (app is designed for HTTPS behind a proxy) */
$headers->set('Strict-Transport-Security', 'max-age=31536000');