Skip to content

Conversation

@Debatty-Tom
Copy link
Contributor

@Debatty-Tom Debatty-Tom commented Oct 8, 2025

Cover #46 by adding csp option on default script tag.

By setting CSP_ENABLE=true in your .env file, this package provides access to a nonce in the default script tag. The CSP_ENABLE flag is also used by Spatie’s laravel-csp package.

A CSP nonce should consist of at least 16 bytes of cryptographically secure random data, and be safe for use in HTML attributes and HTTP headers. I chose to use bin2hex() instead of base64_encode() because it can generate characters that are unsafe for these contexts.

Since a csp_nonce() helper does not exist by default, I implemented a custom one.

Comment on lines 58 to 67
/*
|--------------------------------------------------------------------------
| CSP configuration
|--------------------------------------------------------------------------
|
| Most cookie notices display a link to a dedicated page explaining
| the extended cookies usage policy. If your application has such a page
| you can add its route name here.
|
*/
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please add a specific description for the CSP configuration, including:

  • What it relates to (you may add a link to Spatie's CSP package)
  • How to configure it for Spatie's CSP package: env('CSP_ENABLE', false) && env('CSP_NONCE_ENABLED', true)

|
*/

'csp_enable' => env('CSP_ENABLE', false),
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just set it to false by default. People using spatie's package should refer to the updated configuration description (see previous comment).


use Illuminate\Http\Request;
use Illuminate\Support\Facades\Cookie as CookieFacade;
use Illuminate\Support\Str;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Unused facade.

Comment on lines 202 to 216
$csp_enable = config('cookieconsent.csp_enable', false);

return '<script '
. 'src="' . route('cookieconsent.script') . '?id='
. md5(\filemtime(LCC_ROOT . '/dist/script.js')) . '" '
. ($csp_enable ? 'nonce="' . $this->generateCspNonce() . '" ' : '')
. 'defer'
. '></script>';
}

protected function generateCspNonce(): string
{
return bin2hex(random_bytes(16));
}

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Developers should be able to plug into this nonce generating behavior since their CSP setup could be completely different. For instance, when using spatie's package, one should be able to use the package's nonce_generator. In fact, I can't think of a single use case where the nonce generated by this package would be used.

@Debatty-Tom Debatty-Tom changed the base branch from main to 2.x October 21, 2025 14:05
@Debatty-Tom
Copy link
Contributor Author

Waiting for the #96 to be merged to add the csp nonce to the modal script.

@ericclaeren
Copy link

ericclaeren commented Nov 4, 2025

Just to provide some additional insights. We ran into a similar issue with not having the nonce and indeed as mentioned before, we also use the spatie CSP package, so generating a nonce through this package won't work since the nonce needs to be added to the CSP directive to match CSP header nonce to the nonce in your html output.

Furthermore, if you're using CSP the Google Analytics script also the domain needs to be whitelisted and the script that's injected with the datalayer/gtag config also should contain a nonce and here lies a difficult issue.

Because the /accept-all is executed on a separate route call, which in term generates a new nonce, because CSP package uses a singleton pattern to provide the nonce through a function app('csp-nonce'), which means every request is a receiving a new nonce.

This means the injected nonce through the accepted script is actually not being accepted since the nonce is different from the nonce provided through the initial page load with the CSP headers.

We have solved it partially by not adding the datalayer, but place this in the main html, so it does execute but since the gtag script is missing, won't submit the datalayer to analytics. But this is far from ideal, because the _ga cookie can be created without actually accepting it.

I have no clue yet on what a good solution would be. I tried to add the nonce to the accepted, but since it's in the register, it will refresh on the call to accepted. Very interested if someone finds a way to pass the nonce from the first request to the accepted (maybe setting it to static property would work?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants