diff --git a/app/Http/Middleware/SecurityHeaders.php b/app/Http/Middleware/SecurityHeaders.php new file mode 100644 index 0000000..03d96e3 --- /dev/null +++ b/app/Http/Middleware/SecurityHeaders.php @@ -0,0 +1,23 @@ +headers->set('Strict-Transport-Security', 'max-age=31536000; includeSubDomains'); + $response->headers->set('X-Content-Type-Options', 'nosniff'); + $response->headers->set('X-Frame-Options', 'DENY'); + $response->headers->set('Referrer-Policy', 'strict-origin'); + $response->headers->set('Permissions-Policy', 'geolocation=(), microphone=(), camera=()'); + + return $response; + } +} diff --git a/bootstrap/app.php b/bootstrap/app.php index 0039474..2d92cd7 100644 --- a/bootstrap/app.php +++ b/bootstrap/app.php @@ -15,6 +15,7 @@ return Application::configure(basePath: dirname(__DIR__)) ->withMiddleware(function (Middleware $middleware): void { $middleware->web(append: [ \App\Http\Middleware\LocaleFromUser::class, + \App\Http\Middleware\SecurityHeaders::class, ]); $middleware->validateCsrfTokens(except: [ diff --git a/tests/Feature/Security/SecurityHeadersTest.php b/tests/Feature/Security/SecurityHeadersTest.php new file mode 100644 index 0000000..fb3b8c6 --- /dev/null +++ b/tests/Feature/Security/SecurityHeadersTest.php @@ -0,0 +1,9 @@ +get('/'); + $response->assertHeader('Strict-Transport-Security'); + $response->assertHeader('X-Content-Type-Options', 'nosniff'); + $response->assertHeader('X-Frame-Options', 'DENY'); + $response->assertHeader('Referrer-Policy', 'strict-origin'); +});