Passed
Push — master ( bd753d...066495 )
by Darko
10:20
created

ContentSecurityPolicy   A

Complexity

Total Complexity 4

Size/Duplication

Total Lines 60
Duplicated Lines 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
wmc 4
eloc 32
dl 0
loc 60
rs 10
c 1
b 0
f 0

1 Method

Rating   Name   Duplication   Size   Complexity  
A handle() 0 55 4
1
<?php
2
3
namespace App\Http\Middleware;
4
5
use Closure;
6
use Illuminate\Http\Request;
7
use Symfony\Component\HttpFoundation\Response;
8
9
class ContentSecurityPolicy
10
{
11
    /**
12
     * Handle an incoming request.
13
     */
14
    public function handle(Request $request, Closure $next): Response
15
    {
16
        $response = $next($request);
17
18
        // Check if Turnstile is enabled
19
        $turnstileEnabled = config('captcha.provider') === 'turnstile'
20
            && config('captcha.turnstile.enabled') === true;
21
22
        // If Turnstile is enabled, skip CSP to avoid sandbox iframe issues
23
        // Turnstile creates sandboxed iframes that conflict with strict CSP
24
        if ($turnstileEnabled) {
25
            // Set minimal security headers only
26
            $response->headers->set('X-Frame-Options', 'SAMEORIGIN');
27
            $response->headers->set('X-Content-Type-Options', 'nosniff');
28
            $response->headers->set('Referrer-Policy', 'strict-origin-when-cross-origin');
29
30
            return $response;
31
        }
32
33
        // Generate nonce for inline scripts
34
        $nonce = function_exists('csp_nonce') ? csp_nonce() : base64_encode(random_bytes(16));
35
36
        // Build CSP directives for non-Turnstile pages
37
        $directives = [
38
            "default-src 'self'",
39
            "script-src 'self' 'nonce-{$nonce}' 'unsafe-inline' 'unsafe-eval' https://www.google.com https://www.gstatic.com https://cdn.jsdelivr.net https://unpkg.com blob:",
40
            "script-src-elem 'self' 'nonce-{$nonce}' 'unsafe-inline' https://www.google.com https://www.gstatic.com https://cdn.jsdelivr.net https://unpkg.com",
41
            "script-src-attr 'unsafe-inline'",
42
            "style-src 'self' 'unsafe-inline' https://fonts.googleapis.com",
43
            "font-src 'self' https://fonts.gstatic.com data:",
44
            "img-src 'self' data: https: blob:",
45
            "connect-src 'self' https://www.google.com",
46
            "frame-src 'self' https://www.google.com https://www.gstatic.com data: blob:",
47
            "child-src 'self' https://www.google.com blob:",
48
            "worker-src 'self' blob:",
49
            "object-src 'none'",
50
            "base-uri 'self'",
51
            "form-action 'self'",
52
            "frame-ancestors 'self'",
53
        ];
54
55
        $csp = implode('; ', $directives);
56
57
        $response->headers->set('Content-Security-Policy', $csp);
58
59
        // Also set X-Frame-Options for older browsers
60
        $response->headers->set('X-Frame-Options', 'SAMEORIGIN');
61
62
        // Set X-Content-Type-Options
63
        $response->headers->set('X-Content-Type-Options', 'nosniff');
64
65
        // Set Referrer-Policy
66
        $response->headers->set('Referrer-Policy', 'strict-origin-when-cross-origin');
67
68
        return $response;
69
    }
70
}
71