laravelvue.jsvitecontent-security-policyinertiajs

Add CSP nonce in script tag


I'm actually trying to add CSP on my Laravel/Inertia project.

I install the spatie/laravel-csp package and generate the nonce with Vite::useCspNonce();

I also set csp_nonce meta property in my main blade app but I always have the same error in console after building assets :

EvalError: Refused to evaluate a string as JavaScript because 'unsafe-eval' is not an allowed source of script in the following Content Security Policy directive: "script-src 'self' 'nonce-nonceGenerated'"

Here my csp config file :

<?php

return [

    /*
     * A policy will determine which CSP headers will be set. A valid CSP policy is
     * any class that extends `Spatie\Csp\Policies\Policy`
     */
    'policy' => \App\Support\CustomPolicy::class,

    /*
     * This policy which will be put in report only mode. This is great for testing out
     * a new policy or changes to existing csp policy without breaking anything.
     */
    'report_only_policy' => '',

    /*
     * All violations against the policy will be reported to this url.
     * A great service you could use for this is https://report-uri.com/
     *
     * You can override this setting by calling `reportTo` on your policy.
     */
    'report_uri' => env('CSP_REPORT_URI', ''),

    /*
     * Headers will only be added if this setting is set to true.
     */
    'enabled' => env('CSP_ENABLED', true),

    /*
     * The class responsible for generating the nonces used in inline tags and headers.
     */
    'nonce_generator' => \App\Support\ViteNonceGenerator::class
];

In my custom policy, I just use the Basic policy and add shouldNotApplied for whoops error like shown in documentation.

And here is my app.blade.php :

<!doctype html>
<html lang="{{ str_replace("_", "-", app()->getLocale()) }}">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <meta property="csp-nonce" content="{{ csp_nonce() }}">

    @vite('resources/js/app.js')
    @vite('resources/css/app.scss')
    @inertiaHead
</head>
<body>
@inertia
</body>
</html>

I try with middleware like shown in Laravel docs and with the spatie package without success.


Solution

  • The error message is not related to the nonces, but to the fact that you are evaluating strings in your script. Evaluating strings as in eval, new Function, setInterval or setTimeout is prohibited by default when script-src/default-src is set. You will either have to rewrite these or allow them by adding 'unsafe-eval' (which is of course unsafe).