2026-01-20 09:55:01 -05:00
|
|
|
<?php
|
|
|
|
|
/**
|
|
|
|
|
* Security Headers Middleware
|
|
|
|
|
*
|
|
|
|
|
* Applies security-related HTTP headers to all responses.
|
|
|
|
|
*/
|
|
|
|
|
class SecurityHeadersMiddleware {
|
2026-01-29 11:04:36 -05:00
|
|
|
private static ?string $nonce = null;
|
2026-01-28 20:27:15 -05:00
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Generate or retrieve the CSP nonce for this request
|
|
|
|
|
*
|
|
|
|
|
* @return string The nonce value
|
|
|
|
|
*/
|
2026-01-29 11:04:36 -05:00
|
|
|
public static function getNonce(): string {
|
2026-01-28 20:27:15 -05:00
|
|
|
if (self::$nonce === null) {
|
|
|
|
|
self::$nonce = base64_encode(random_bytes(16));
|
|
|
|
|
}
|
|
|
|
|
return self::$nonce;
|
|
|
|
|
}
|
|
|
|
|
|
2026-01-20 09:55:01 -05:00
|
|
|
/**
|
|
|
|
|
* Apply security headers to the response
|
|
|
|
|
*/
|
2026-01-29 11:04:36 -05:00
|
|
|
public static function apply(): void {
|
2026-01-28 20:27:15 -05:00
|
|
|
$nonce = self::getNonce();
|
|
|
|
|
|
2026-01-20 09:55:01 -05:00
|
|
|
// Content Security Policy - restricts where resources can be loaded from
|
2026-01-30 13:15:55 -05:00
|
|
|
// Using nonces for scripts to prevent XSS attacks while allowing inline scripts with valid nonces
|
|
|
|
|
// All inline event handlers have been refactored to use addEventListener with data-action attributes
|
2026-04-04 17:45:02 -04:00
|
|
|
header("Content-Security-Policy: default-src 'self'; script-src 'self' 'nonce-{$nonce}' https://cdn.jsdelivr.net; style-src 'self' 'unsafe-inline' https://fonts.googleapis.com https://cdn.jsdelivr.net; img-src 'self' data:; font-src 'self' https://fonts.gstatic.com; connect-src 'self';");
|
2026-01-20 09:55:01 -05:00
|
|
|
|
|
|
|
|
// Prevent clickjacking by disallowing framing
|
|
|
|
|
header("X-Frame-Options: DENY");
|
|
|
|
|
|
|
|
|
|
// Prevent MIME type sniffing
|
|
|
|
|
header("X-Content-Type-Options: nosniff");
|
|
|
|
|
|
|
|
|
|
// Enable XSS filtering in older browsers
|
|
|
|
|
header("X-XSS-Protection: 1; mode=block");
|
|
|
|
|
|
|
|
|
|
// Control referrer information sent with requests
|
|
|
|
|
header("Referrer-Policy: strict-origin-when-cross-origin");
|
|
|
|
|
|
|
|
|
|
// Permissions Policy - disable unnecessary browser features
|
|
|
|
|
header("Permissions-Policy: geolocation=(), microphone=(), camera=()");
|
|
|
|
|
}
|
|
|
|
|
}
|