Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add content security policy support #223

Closed
ziadoz opened this issue Dec 13, 2023 · 2 comments
Closed

Add content security policy support #223

ziadoz opened this issue Dec 13, 2023 · 2 comments
Assignees

Comments

@ziadoz
Copy link

ziadoz commented Dec 13, 2023

Hey.

I'm setting up Pulse on an app that uses Spatie's CSP package, and I've noticed a bunch of errors occur in the web inspector console:

monitor.app.example.com/:11 Refused to load the stylesheet 'https://fonts.bunny.net/css?family=figtree:300,400,500,600' because it violates the following Content Security Policy directive: "style-src 'self' fonts.googleapis.com fonts.gstatic.com 'unsafe-inline'". Note that 'style-src-elem' was not explicitly set, so 'style-src' is used as a fallback.

monitor.app.example.com/:19 Refused to execute inline script because it violates the following Content Security Policy directive: "script-src 'self' fonts.googleapis.com 'unsafe-eval' 'nonce-42GgJUDp47AMqbkHIHw1pk1Gd4ogGrRDdac2vMLo'". Either the 'unsafe-inline' keyword, a hash ('sha256-OcDI2yBWsw5gybagfotY7UuJyq4im4yX0LxmHKUDH54='), or a nonce ('nonce-...') is required to enable inline execution.

monitor.app.example.com/:77 Refused to execute inline script because it violates the following Content Security Policy directive: "script-src 'self' fonts.googleapis.com 'unsafe-eval' 'nonce-42GgJUDp47AMqbkHIHw1pk1Gd4ogGrRDdac2vMLo'". Either the 'unsafe-inline' keyword, a hash ('sha256-cMjnVnQ0rhoQz8imeajiVycyxV0MhtHJuyOrZ5YWclY='), or a nonce ('nonce-...') is required to enable inline execution.

Refused to load the image '<URL>' because it violates the following Content Security Policy directive: "img-src 'self' example.com".

livewire.js?id=8a199ab2:980 Alpine Expression Error: Chart is not defined

livewire.js?id=8a199ab2:984 Uncaught ReferenceError: Chart is not defined
    at Proxy.init (eval at safeAsyncFunction (livewire.js?id=8a199ab2:1031:21), <anonymous>:5:21)
    at livewire.js?id=8a199ab2:1017:25
    at tryCatch (livewire.js?id=8a199ab2:973:14)
    at evaluate (livewire.js?id=8a199ab2:997:34)
    at Function.<anonymous> (livewire.js?id=8a199ab2:3241:29)
    at flushHandlers (livewire.js?id=8a199ab2:1135:48)
    at stopDeferring (livewire.js?id=8a199ab2:1140:7)
    at deferHandlingDirectives (livewire.js?id=8a199ab2:1143:5)
    at initTree (livewire.js?id=8a199ab2:654:5)
    at livewire.js?id=8a199ab2:602:23

I can resolve the font and image ones by adding fonts.bunny.net and gravatar.com to our policy, but I can't resolve the inline script and style ones, as I think those require a nonce attribute adding to them.

I could tweak our policy to bypass Pulse, but this might mean I can't deploy it to staging/production in the corporate environment I want to use it in.

Would it be possible for Pulse to ship with the CSP policy headers or meta tags it needs to run? Or is there a way I can properly configure the policy on my end?

Cheers.

@valorin
Copy link

valorin commented Dec 14, 2023

@ziadoz If it helps, this is the CSP I'm using for Pulse.

report-uri ... ; 
default-src 'none' ; 
connect-src 'self' ; 
font-src 'self' https://fonts.bunny.net/figtree/files/ ; 
frame-src 'none' ; 
img-src 'self' data: https://gravatar.com/avatar/ https://unavatar.io/ ; 
manifest-src 'self' ; 
script-src 'report-sample' 'self' 'unsafe-inline' 'unsafe-eval' ; 
style-src 'self' 'unsafe-inline' https://fonts.bunny.net/css ; 
form-action 'self' ; 
frame-ancestors 'none'

I had to configure a standalone CSP for /pulse because it requires unsafe-inline and I was using nonces in my app.

@ziadoz
Copy link
Author

ziadoz commented Dec 14, 2023

@valorin Cheers, that really helps me out!

I closed the ticket because I realised I could attach my own policy to the Pulse route, I just needed to poke around and write all the directives.

I translated what you wrote into a Spatie CSP policy and it all works perfectly (thanks again):

<?php

namespace App\Csp\Policies;

use Illuminate\Http\Request;
use Illuminate\Support\Facades\Vite;
use Spatie\Csp\Directive;
use Spatie\Csp\Keyword;
use Spatie\Csp\Policies\Basic;
use Symfony\Component\HttpFoundation\Response;

class LaravelPulsePolicy extends Basic
{
    public function configure(): void
    {
        $this
            ->addDirective(Directive::DEFAULT, Keyword::NONE)
            ->addDirective(Directive::CONNECT, Keyword::SELF)
            ->addDirective(Directive::FONT, [Keyword::SELF, 'https://fonts.bunny.net/figtree/files/'])
            ->addDirective(Directive::FRAME, Keyword::NONE)
            ->addDirective(Directive::IMG, [Keyword::SELF, 'data: https://gravatar.com/avatar/ https://unavatar.io/'])
            ->addDirective(Directive::MANIFEST, Keyword::SELF)
            ->addDirective(Directive::SCRIPT, [Keyword::SELF, Keyword::UNSAFE_INLINE, Keyword::UNSAFE_EVAL])
            ->addDirective(Directive::STYLE, [Keyword::SELF, Keyword::UNSAFE_INLINE, 'https://fonts.bunny.net/css'])
            ->addDirective(Directive::FORM_ACTION, Keyword::SELF)
            ->addDirective(Directive::FRAME_ANCESTORS, Keyword::NONE);
    }
}

Then just hook it up in the config/pulse.php file:

    'middleware' => [
        'web',
        Authorize::class,
        Spatie\Csp\AddCspHeaders::class . ':' . App\Csp\Policies\LaravelPulsePolicy::class,
    ],

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

No branches or pull requests

5 participants