浏览代码

Add Content Security Policy

Bubka 8 月之前
父节点
当前提交
ce1692eaf4

+ 8 - 0
.env.example

@@ -274,6 +274,14 @@ TRUSTED_PROXIES=null
 PROXY_FOR_OUTGOING_REQUESTS=null
 
 
+# Set this to true to enable Content-Security-Policy (CSP).
+# CSP helps to prevent or minimize the risk of certain types of security threats.
+# This is mainly used as a defense against cross-site scripting (XSS) attacks, in which
+# an attacker is able to inject malicious code into the web app
+
+CONTENT_SECURITY_POLICY=true
+
+
 # Leave the following configuration vars as is.
 # Unless you like to tinker and know what you're doing.
 

+ 3 - 0
app/Http/Controllers/SinglePageController.php

@@ -6,6 +6,7 @@ use App\Events\ScanForNewReleaseCalled;
 use App\Facades\Settings;
 use Illuminate\Support\Facades\App;
 use Illuminate\Support\Facades\Auth;
+use Illuminate\Support\Facades\Vite;
 
 class SinglePageController extends Controller
 {
@@ -32,6 +33,7 @@ class SinglePageController extends Controller
         $installDocUrl      = config('2fauth.installDocUrl');
         $ssoDocUrl          = config('2fauth.ssoDocUrl');
         $exportSchemaUrl    = config('2fauth.exportSchemaUrl');
+        $cspNonce           = Vite::cspNonce();
 
         // if (Auth::user()->preferences)
 
@@ -57,6 +59,7 @@ class SinglePageController extends Controller
             'isTestingApp'       => $isTestingApp,
             'lang'               => $lang,
             'locales'            => $locales,
+            'cspNonce'           => $cspNonce,
         ]);
     }
 }

+ 29 - 0
app/Http/Middleware/AddContentSecurityPolicyHeaders.php

@@ -0,0 +1,29 @@
+<?php
+
+namespace App\Http\Middleware;
+
+use Closure;
+use Illuminate\Http\Request;
+use Illuminate\Support\Facades\Vite;
+use Symfony\Component\HttpFoundation\Response;
+
+class AddContentSecurityPolicyHeaders
+{
+    /**
+     * Handle an incoming request.
+     *
+     * @param  \Closure(\Illuminate\Http\Request): (\Symfony\Component\HttpFoundation\Response)  $next
+     */
+    public function handle(Request $request, Closure $next) : Response
+    {
+        if (config('2fauth.config.contentSecurityPolicy')) {
+            Vite::useCspNonce();
+
+            return $next($request)->withHeaders([
+                'Content-Security-Policy' => "script-src 'nonce-" . Vite::cspNonce() . "';style-src 'self' 'unsafe-inline';connect-src 'self';img-src 'self' data:;object-src 'none';base-uri 'none';",
+            ]);
+        }
+
+        return $next($request);
+    }
+}

+ 1 - 0
config/2fauth.php

@@ -31,6 +31,7 @@ return [
         'proxyLogoutUrl' => env('PROXY_LOGOUT_URL', null),
         'appSubdirectory' => env('APP_SUBDIRECTORY', ''),
         'authLogRetentionTime' => envUnlessEmpty('AUTHENTICATION_LOG_RETENTION', 365),
+        'contentSecurityPolicy' => envUnlessEmpty('CONTENT_SECURITY_POLICY', true),
     ],
 
     /*

+ 1 - 1
resources/views/landing.blade.php

@@ -22,7 +22,7 @@
     <div id="app">
         <app></app>
     </div>
-    <script type="text/javascript">
+    <script type="text/javascript" nonce="{{ $cspNonce }}">
         var appSettings = {!! $appSettings !!};
         var appConfig = {!! $appConfig !!};
         var urls = {!! $urls !!};

+ 2 - 1
routes/web.php

@@ -14,6 +14,7 @@ use App\Http\Controllers\Auth\WebAuthnRecoveryController;
 use App\Http\Controllers\Auth\WebAuthnRegisterController;
 use App\Http\Controllers\SinglePageController;
 use App\Http\Controllers\SystemController;
+use App\Http\Middleware\AddContentSecurityPolicyHeaders;
 use App\Http\Middleware\CustomCreateFreshApiToken;
 use App\Http\Middleware\SetLanguage;
 use Illuminate\Routing\Middleware\SubstituteBindings;
@@ -117,4 +118,4 @@ Route::withoutMiddleware([
 /**
  * Route for the main landing view
  */
-Route::get('/{any}', [SinglePageController::class, 'index'])->where('any', '.*')->name('landing');
+Route::get('/{any}', [SinglePageController::class, 'index'])->where('any', '.*')->name('landing')->middleware(AddContentSecurityPolicyHeaders::class);