Files
jabali-panel/app/Http/Middleware/SecurityHeaders.php
2026-02-02 03:11:45 +02:00

49 lines
1.7 KiB
PHP

<?php
declare(strict_types=1);
namespace App\Http\Middleware;
use Closure;
use Illuminate\Http\Request;
use Symfony\Component\HttpFoundation\Response;
class SecurityHeaders
{
/**
* Security headers to add to all responses.
*/
public function handle(Request $request, Closure $next): Response
{
$response = $next($request);
// Content Security Policy
$csp = implode('; ', [
"default-src 'self'",
"script-src 'self' 'unsafe-inline' 'unsafe-eval'", // Required for Livewire/Alpine
"style-src 'self' 'unsafe-inline'", // Required for Tailwind/Filament
"img-src 'self' data: blob:",
"font-src 'self' data:",
"connect-src 'self' ws: wss:", // WebSocket for Livewire
"worker-src 'self' blob:", // Required for file upload workers
"frame-ancestors 'self'",
"form-action 'self'",
"base-uri 'self'",
]);
$response->headers->set('Content-Security-Policy', $csp);
$response->headers->set('X-Content-Type-Options', 'nosniff');
$response->headers->set('X-Frame-Options', 'SAMEORIGIN');
$response->headers->set('X-XSS-Protection', '1; mode=block');
$response->headers->set('Referrer-Policy', 'strict-origin-when-cross-origin');
$response->headers->set('Permissions-Policy', 'camera=(), microphone=(), geolocation=()');
// Only add HSTS in production with HTTPS
if ($request->secure() && app()->environment('production')) {
$response->headers->set('Strict-Transport-Security', 'max-age=31536000; includeSubDomains');
}
return $response;
}
}