barryvdh / laravel-debugbar

Debugbar for Laravel (Integrates PHP Debug Bar)
MIT License
17k stars 1.54k forks source link

Debugbar Not Showing Due To CSP #1317

Open sys-auditing opened 2 years ago

sys-auditing commented 2 years ago

Hi,

i'm using the laravel-debugbar and works like a charm, but when adding CSP the debugbar stop showing.

Laravel : "laravel/framework": "^8.0" "spatie/laravel-csp": "2.6.4",

Debugbar : "barryvdh/laravel-debugbar": "^3.5"

Thank's for the help

robov commented 2 years ago

This is probably a problem with a missing nounce @barryvdh did you ever find a solution for this (except for enabling unsafe-inline in debug state) ?

luckydonald commented 2 years ago

The bot marked the old ticket as stale: #1016

stale[bot] commented 1 year ago

This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. If this issue is still present on the latest version of this library on supported Laravel versions, please let us know by replying to this issue so we can investigate further. Thank you for your contribution! Apologies for any delayed response on our side.

luckydonald commented 1 year ago

.

luckydonald commented 1 year ago

I mean I could just use hashes to allow just the stuff it writes.

The problem is phpdebugbar.addDataSet({…}, "…") in the last added script tag.

Which I could work around by adding this in a middleware:

            $content = $response->content();
            $debugBarVar = 'phpdebugbar';  // this was coming from some config, but I forgot from where.
            preg_match('/(?P<openScriptTagStart><script )(?P<openScriptTagEnd>.*?>)(?P<scriptContentBefore>\n.*?)\n'.$debugBarVar.'\.addDataSet\((?P<data>.+), "(?P<param>\w+)"\);(?P<scriptContentAfter>\n.*?)(?P<closeScriptTag><\/script>)/s', $response->content(), $matches);
            $openScriptTagStart = $matches['openScriptTagStart'];
            $data = $matches['data'];
            $param = $matches['param'];
            $openScriptTagEnd = $matches['openScriptTagEnd'];
            $scriptContentBefore = $matches['scriptContentBefore'];
            $scriptContentAfter = $matches['scriptContentAfter'];
            $closeScriptTag = $matches['closeScriptTag'];
            $dataEncoded = htmlspecialchars($data);
            $paramEncoded = htmlspecialchars($param);
            $old = $matches[0];
            $new = "$openScriptTagStart data-$debugBarVar-data=\"$dataEncoded\" data-$debugBarVar-param=\"$paramEncoded\" $openScriptTagEnd{$scriptContentBefore}\n";
            $new .= "var {$debugBarVar}Data = document.querySelector('script[data-$debugBarVar-data][data-$debugBarVar-param]').attributes;\n";
            $new .= "$debugBarVar.addDataSet(JSON.parse({$debugBarVar}Data['data-$debugBarVar-data'].value), {$debugBarVar}Data['data-$debugBarVar-param'].value);\n";
            $new .= "{$scriptContentAfter}$closeScriptTag";
            $content = $content->replace($old, $new)->value();
            $original = null;
            if ($response instanceof \Illuminate\Http\Response && $response->getOriginalContent()) {
                $original = $response->getOriginalContent();
            }

            // Update the new content and reset the content length
            $response->setContent($content);
            $response->headers->remove('Content-Length');

            // Restore original response (eg. the View or Ajax data)
            if ($original) {
                $response->original = $original;
            }

What it does is using a regex (uh oh) to grab the values of that. Then those get applied as two attributes to the script tag instead: data-phpdebugbar-data="{…}" and data-phpdebugbar-param="…".

It can easily be loaded with

JSON.parse(document.querySelector('script[data-phpdebugbar-data]').attributes['data-$debugBarVar-data'].value))

Now the content of the <script> does no longer change, and a hash can be used to whitelist the occurrence in the CSP; In my case '\'sha256-Q59u6hqnWqFUgu6e2Pg5p1xxto/mrNsJbgpsZsCVVY4=\''.


The only problem remaining now, is to get the middleware in the correct order so $response->content() actually is with the debug bar already injected.

dasch88 commented 1 year ago

I am running into this too. I could really use a clean solution to setting a nonce for any styles/scripts that debugbar injects inline. This seems to be a recurring theme

ultrono commented 1 year ago

Only semi workaround for this (when using spatie/laravel-csp) is to either:

Both options will allow debug bar to display.

stale[bot] commented 1 year ago

This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. If this issue is still present on the latest version of this library on supported Laravel versions, please let us know by replying to this issue so we can investigate further. Thank you for your contribution! Apologies for any delayed response on our side.

parallels999 commented 12 months ago

What about https://github.com/barryvdh/laravel-debugbar/pull/1464?