-
-
Notifications
You must be signed in to change notification settings - Fork 1.6k
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 CSP header if available #1013
base: master
Are you sure you want to change the base?
Conversation
Also need to modify the VarDumper to inject CSP attributes.. |
Any news on? |
@savage-eagle This is merged on the php-debugbar. Still need to see how we're going to add the actual nonce though. |
@barryvdh the stylesheet needs a nonce as well. Haven't properly dug into the matter yet, but here's some first thoughts for adding the nonce. First I thought to add it to the config like this "'nonce' => csp_nonce(),". That would give flexibility to devs for implementing other packages as well. But that throws a BindingResolutionException on app('csp-nonce'). I did manage to set that config from the middleware I wrote to programmatically enable Debugbar like this "config(['debugbar.nonce' => csp_nonce()]);". Hope to find some time to dig a bit deeper later on. |
Got a working proof-of-concept. config/debugbar.php:
src/JavascriptRenderer.php > renderHead():
However, I ran into the next issue with the inline script tag of the Symfony HtmlDumper. This raises the following question: should vendor packages even implement this kind of change? Regards, PS Thanks for your awesome work! |
Addendum to my previous statement: ... unless the package injects content through middleware added by an auto-discovered ServiceProvider. I could not find a way to modify the response content after the middlewares and middlewarePriority wasn't sufficient either. |
The inline html also needs to be modified. src/JavascriptRenderer.php > renderHead():
And the render method.
But that still isn't enough. The inline script creates a style element without a nonce. And assets/javascripts creates a script element without a nonce. What a can of worms... |
Yeah now you mention it, I guess this is why I didn't merge this sooner :P |
Yeah. I managed to scotchtape the inline scipt to work as well with another preg_replace by injecting a setAttribute, but assets/javascript gave me a headache. I have to park this for now. |
@barryvdh @rdevroede Will there by any more work done on this to get it to work with a CSP header? |
Sadly, I have not made any progress. I ended up following Barry's suggestion of setting it to warnings on dev and moved on to things with higher priorities. |
It feels like this is close. Is it possible to get this working without falling back to the less ideal warnings mode in dev? Making CSP failures work in dev the same as prod are really important to help prevent issues from being accidentally released. Any thoughts, @barryvdh? |
Building up to @rdevroede codes, I've managed to put this one up:
public function renderHead()
{
$cssRoute = route('debugbar.assets.css', [
'v' => $this->getModifiedTime('css'),
'theme' => config('debugbar.theme', 'auto'),
]);
$jsRoute = route('debugbar.assets.js', [
'v' => $this->getModifiedTime('js')
]);
$cssRoute = preg_replace('/\Ahttps?:/', '', $cssRoute);
$jsRoute = preg_replace('/\Ahttps?:/', '', $jsRoute);
$cspString = '';
$cspCallback = config('debugbar.csp_callback');
if ($cspCallback) {
$this->setCspNonce(call_user_func($cspCallback));
}
$nonce = isset($this->cspNonce) ? $this->getNonceAttribute() : '';
$html = "<link{$nonce} rel='stylesheet' type='text/css' property='stylesheet' href='{$cssRoute}' data-turbolinks-eval='false' data-turbo-eval='false'>";
$html .= "<script{$nonce} src='{$jsRoute}' data-turbolinks-eval='false' data-turbo-eval='false'></script>";
if ($this->isJqueryNoConflictEnabled()) {
$html .= "<script{$nonce} data-turbo-eval='false'>jQuery.noConflict(true);</script>\n";
}
$inlineHtml = $this->getInlineHtml();
if (isset($this->cspNonce)) {
$inlineHtml = preg_replace("/(<(script|style))/", "$1 {$nonce}", $inlineHtml);
$inlineHtml = preg_replace("/(doc\.head\.appendChild\(refStyle\);)/", "refStyle.setAttribute('nonce', '{$this->cspNonce}');\n", $inlineHtml);
}
$html .= $inlineHtml;
return $html;
}
/*
|--------------------------------------------------------------------------
| CSP Setter
|--------------------------------------------------------------------------
|
| DebugBar injects scripts and styles to show the debug bar. However, this causes lots of policy violations
| when CSP is used. To prevent these violations, a callback will be identified to apply a nonce or hash to the
| elements. A good example of this would be the Laravel CSP by spatie, utilizing the `csp_nonce()` function.
*/
'csp_callback' => env('DEBUGBAR_CSP_CALLBACK', null),
CSP_ENABLED=true
DEBUGBAR_INJECT=true
DEBUGBAR_CSP_CALLBACK=csp_nonce The inline part was brute forced, but it did manage to run my debug bar with CSP on since the dumper was only injecting I also want to add that the PHP Debugbar from maximebf is using jQuery 3.3.1 which also does not support CSP when creating or appending elements. This was discussed in this jQuery 3.1.1 Issue. |
TODO; get the source of the CSP in a callable?
Counterpart of maximebf/php-debugbar#439