Current CSP policy is disabled in debug mode and uses hardcoded hashes, making the application vulnerable to XSS attacks in production.
// filepath: app/Policies/CustomCSPPolicy.php
<?php
namespace App\Policies;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Route;
use Spatie\Csp\Directive;
use Spatie\Csp\Keyword;
use Spatie\Csp\Policies\Basic;
use Symfony\Component\HttpFoundation\Response;
class CustomCSPPolicy extends Basic
{
private $excludeRoute = [
'fm.tinymce5',
'fm.initialize',
'fm.content',
'fm.tree',
'cms.statistic.summary',
'presisi.index',
'presisi.kependudukan',
'laporan-bulanan.index',
'laporan-bulanan.filter',
'laporan-bulanan.export-excel',
'laporan-bulanan.detail-penduduk',
'laporan-bulanan.export-excel-detail'
];
private $hasTinyMCE = ['articles.create', 'articles.edit'];
public function configure()
{
parent::configure();
$currentRoute = Route::getCurrentRoute()?->getName() ?? '';
// TinyMCE routes - special handling
if (in_array($currentRoute, $this->hasTinyMCE)) {
$this->addDirective(Directive::IMG, ['blob:'])
->addDirective(Directive::STYLE, ['unsafe-inline']);
}
// Base directives
$this->addDirective(Directive::IMG, [
'data:',
'https://tile.openstreetmap.org/',
'https://*.tile.openstreetmap.org/'
])
->addDirective(Directive::STYLE, [
Keyword::SELF,
'https://fonts.googleapis.com/',
'https://fonts.bunny.net/',
'https://cdn.jsdelivr.net/',
'https://unpkg.com/',
'https://cdn.datatables.net/',
'https://code.ionicframework.com/',
])
->addDirective(Directive::SCRIPT, [
Keyword::SELF,
// REMOVED: 'unsafe-eval'
'https://cdn.datatables.net/',
'https://unpkg.com/',
'https://cdn.jsdelivr.net/',
'https://cdn.jsdelivr.net/npm/sweetalert2@11',
])
->addDirective(Directive::FONT, [
Keyword::SELF,
'data:',
'https://fonts.bunny.net/',
'https://fonts.gstatic.com/',
'https://code.ionicframework.com/',
])
->addDirective(Directive::CONNECT, [
Keyword::SELF,
config('app.serverPantau'),
config('app.databaseGabunganUrl'),
'https://unpkg.com',
'https://*.openstreetmap.org',
])
->addDirective(Directive::OBJECT, [Keyword::NONE])
->addDirective(Directive::BASE, [Keyword::SELF])
->addDirective(Directive::FORM_ACTION, [Keyword::SELF])
->addDirective(Directive::FRAME_ANCESTORS, [Keyword::NONE]); // Prevent clickjacking
}
public function shouldBeApplied(Request $request, Response $response): bool
{
// ALWAYS apply CSP, even in debug mode
$currentRoute = Route::getCurrentRoute()?->getName() ?? '';
if (in_array($currentRoute, $this->excludeRoute)) {
return false;
}
// CSP enabled for all environments
return config('csp.enabled', true);
}
}
<!-- Before -->
<script>
// inline code
</script>
<!-- After -->
<script nonce="{{ csp_nonce() }}">
// inline code
</script>
📋 Description
Current CSP policy is disabled in debug mode and uses hardcoded hashes, making the application vulnerable to XSS attacks in production.
🐛 Current Behavior
APP_DEBUG=trueunsafe-evalis globally allowed✅ Expected Behavior
unsafe-evaldirective🔒 Security Impact
🛠️ Solution
1. Update CustomCSPPolicy.php
2. Update Blade Templates
Add
@cspNonceto inline scripts and styles:✅ Action Items
APP_DEBUGcheck fromshouldBeApplied()unsafe-evaldirectiveframe-ancestors 'none'directiveform-action 'self'directive@cspNoncedirective📚 References
🧪 Testing
Estimated Time: 4-6 hours
Risk Level: High if not fixed
Blocking: Production deployment