Glimpse / Glimpse.Prototype

Glimpse v2 prototype
MIT License
184 stars 44 forks source link

Content-Security-Policy (CSP) Compatibility #88

Open RehanSaeed opened 8 years ago

RehanSaeed commented 8 years ago

Please make it easier for Glimpse to be compatible with the Content-Security-Policy (CSP) HTTP header. This HTTP header does not allow inline scripts or styles but requires them to be in separate files unless you add a nonce or hash to the tag.

Secondly, please provide a method to get hold of the URL endpoints that Glimpse is using so that they can be added to the CSP policy whitelist.

I work on the ASP.NET MVC Boilerplate project template which adds CSP by default using the NWebSec NuGet package, as well as Glimpse v1 too. The above features would be most helpful.

nikmd23 commented 8 years ago

@RehanSaeed, what CSP are you setting/is being violated?

Glimpse does not use any inline scripts. We've worked with @klings from NWebSec in the past to make sure the two were compatible - but perhaps there's been an update or regression we are unaware of?

RehanSaeed commented 8 years ago

The MVC 5 project template required a few exceptions to be made for Glimpse and BrowserLink which also has the same problems which you can see here. NWebSec does not exist for ASP.NET 5 yet but I know @klings is working on it with RC1. If you look at the above code we have the following policies in development and production.

Development Policy

Content-Security-Policy default-src: none connect-src self localhost:* ws://localhost:* script-src self localhost:* ...

Production Policy

Content-Security-Policy default-src: none connect-src self script-src self ...

The development policy allows for Browser Link and Glimpse using localhost:* and ws://localhost:*, whereas in production we do not use Glimpse and these exceptions are removed. It would be nice if Glimpse could modify the CSP header to add these exceptions itself, so something like this:

app.UseBrowserLink(options =>
    {
        options.EnableCspExceptions = true;
    });

This would also mean that you could make the CSP policy more targetted by adding the exact port that Glimpse uses. The policy might look like this:

Content-Security-Policy default-src: none connect-src self localhost:1234 ws://localhost:1234 script-src self localhost:1234 ...

FYI, I raised the same issue for Browser Link but it seems to have gone missing. Any idea where it might have dissapeared to?

avanderhoorn commented 8 years ago

So we are only making requests back to localhost... why does the default Production Policy lock down all localhost scripts, whats the idea with that as a default?

RehanSaeed commented 8 years ago

The most secure way to use CSP is to block everything using default-src none and then allow only the things you need like images, scripts, styles, ajax etc. individually.

I discussed this with @klings the creator of NWebSec, he recommended the above approach for best security (Thats the point of CSP it after all) and thats the approach I took.

klings commented 8 years ago

I do remember Glimpse was tweaked back in the days, so that it would play nicely with CSP: Glimpse/Glimpse#631 (which was awesome, not all libraries do that)

Funny enough, an issue surfaced the other day related to Glimpse and CSP: NWebsec/NWebsec#75. I'll ping @monotore and try to figure out which versions they're on and what the issue was.

@RehanSaeed The way I interpret this, you'd want Glimpse to automagically make modifications to the CSP header to ease the burden of configuration of the users? That won't play nicely with e.g. NWebsec, as NWebsec behaves as if it's the one true source of security headers for the application. Headers are calculated and overwritten potentially multiple times when generating a response, depending on the configuration.

Is there really a need for anything other than script-src: 'self' for production? Are there websockets also in play? Perhaps you could share the CSP violations you get in the console?

avanderhoorn commented 8 years ago

More than happy to see what we can do to help! Like @klings said, I'm not that keen in manually setting the header as it will probably result in us getting into a chicken and egg scenario where its difficult for us to consistently get it right. I kinda get the idea behind having everything (even localhost) locked by default, but it certainly restricts/complicates things slightly. What would be really nice is if there was some way of telling you what we need without their being a coupling from us to you or vise versa... It seems like this is going to be a problem for more than just us, I wonder how its thought that is will work for others (i.e. any lib which has endpoints like this given the chicken and egg scenario)?

klings commented 8 years ago

I agree, I think there are scenarios where this would be impossible to get right without tight coupling between libraries, and tight coupling would only cause trouble for all of us. The NWebsec middleware sets the headers before invoking the next middleware (since @nikmd23 wants to flush early), which means that other libs/middleware that need to signal changes to CSP will have to run in advance for NWebsec to pick it up. Yes, order matters for middleware, but I believe we should try to keep that to a minimum or we'll get stuck in "middleware order hell".

Perhaps the easiest approach is for Glimpse and other libs to simply be specific in the docs about which "holes" they need opened in CSP (if they have special needs)? If that's well documented, it should be straight forward to tweak the config for e.g. NWebsec accordingly.

As a final note, I'm always wary about which changes libraries might do to an application. Relaxing the security configuration for an application is particularly sensitive. Personally, I'd much more appreciate an error indicating that I'd have to relax some security settings to get things working. That way I'm in complete control of security, without any unpleasant surprises.

@RehanSaeed what would be the easiest way for us to reproduce the problem you're seeing? Simply add Glimpse to a dnx project and add a strict CSP to it?

nikmd23 commented 8 years ago

since @nikmd23 wants to flush early LOL :laughing:

RehanSaeed commented 8 years ago

To recreate the CSP violations, create a new ASP.NET 5 application and try adding the following line to the Index action:

this.HttpContext.Response.Headers.Add("Content-Security-Policy", new StringValues(
    "default-src 'none'; script-src 'self'; connect-src 'self'; img-src 'self'; style-src 'self'; font-src 'self';"));

You will get the following CSP violations in Chrome:

Refused to load the script 'http://localhost:13721/508fd336fda6422bb1adee3991b1909a/browserLink' because it violates the following Content Security Policy directive: "script-src 'self'".

Refused to apply inline style because it violates the following Content Security Policy directive: "style-src 'self'". Either the 'unsafe-inline' keyword, a hash ('sha256-47DEQpj8HBSa+/TImW+5JCeuQeRkm5NMpJWZG3hSuFU='), or a nonce ('nonce-...') is required to enable inline execution.

Refused to apply inline style because it violates the following Content Security Policy directive: "style-src 'self'". Either the 'unsafe-inline' keyword, a hash ('sha256-ydm0jeFFwgSAfjElF1vDpl1p6fRfd3CQYurZ0KiXmG4='), or a nonce ('nonce-...') is required to enable inline execution.

Refused to apply inline style because it violates the following Content Security Policy directive: "style-src 'self'". Either the 'unsafe-inline' keyword, a hash ('sha256-VBcV6Eq3YQ6EM0ZPJE7qpCE6EWC4lsO94ToO7D6cYpI='), or a nonce ('nonce-...') is required to enable inline execution.

Refused to apply inline style because it violates the following Content Security Policy directive: "style-src 'self'". Either the 'unsafe-inline' keyword, a hash ('sha256-s4xg4P9tHeF5A2+Um2V5SbmhVg8a19ML23E0EG3GVvM='), or a nonce ('nonce-...') is required to enable inline execution.

Refused to apply inline style because it violates the following Content Security Policy directive: "style-src 'self'". Either the 'unsafe-inline' keyword, a hash ('sha256-2pELPObkVv/CavBMw1unVWBdGKuDcQmI0A5xeY7P1IU='), or a nonce ('nonce-...') is required to enable inline execution.

Refused to apply inline style because it violates the following Content Security Policy directive: "style-src 'self'". Either the 'unsafe-inline' keyword, a hash ('sha256-z1YM8sokn7jmE396oydxUrDfHe6DmYgobxSc2DfZ7o8='), or a nonce ('nonce-...') is required to enable inline execution.

Refused to apply inline style because it violates the following Content Security Policy directive: "style-src 'self'". Either the 'unsafe-inline' keyword, a hash ('sha256-v6v8obZB4kfiM3A+I9Go2uwdnUdNW1VdkYWxN21L5N4='), or a nonce ('nonce-...') is required to enable inline execution.

Refused to apply inline style because it violates the following Content Security Policy directive: "style-src 'self'". Either the 'unsafe-inline' keyword, a hash ('sha256-7Ndaa0qN/7wLWzpe6MvxAz987/sW27kWbgFSMD//4Ec='), or a nonce ('nonce-...') is required to enable inline execution.

Refused to apply inline style because it violates the following Content Security Policy directive: "style-src 'self'". Either the 'unsafe-inline' keyword, a hash ('sha256-nJLRM6W2LJBjQj+Kl7pAECaOmmxMU5aSmgpdH+0fGcQ='), or a nonce ('nonce-...') is required to enable inline execution.

Refused to apply inline style because it violates the following Content Security Policy directive: "style-src 'self'". Either the 'unsafe-inline' keyword, a hash ('sha256-uWbMEOMIveASAYXWUNdszL2vfXxfS7PesCsr+vOItSc='), or a nonce ('nonce-...') is required to enable inline execution.

Refused to apply inline style because it violates the following Content Security Policy directive: "style-src 'self'". Either the 'unsafe-inline' keyword, a hash ('sha256-GXuvzIL1i0Mba1XvM+BOMSnUyxgdyvYUg4VmQqyJNsc='), or a nonce ('nonce-...') is required to enable inline execution.

Refused to apply inline style because it violates the following Content Security Policy directive: "style-src 'self'". Either the 'unsafe-inline' keyword, a hash ('sha256-Q7YdUaTOKHV2Y55rCST4iJAmggLgZCv1W/GNmgEIs1I='), or a nonce ('nonce-...') is required to enable inline execution.

Refused to apply inline style because it violates the following Content Security Policy directive: "style-src 'self'". Either the 'unsafe-inline' keyword, a hash ('sha256-UvynfRpN1WHMtbERwBasUN6GIJgiSu7Xj2Lh4TyxHCQ='), or a nonce ('nonce-...') is required to enable inline execution.

Refused to apply inline style because it violates the following Content Security Policy directive: "style-src 'self'". Either the 'unsafe-inline' keyword, a hash ('sha256-WzJV6ocKRf2S7t0whrZSsyAVoPkY7wfJtgJlRidHf9w='), or a nonce ('nonce-...') is required to enable inline execution.

Refused to apply inline style because it violates the following Content Security Policy directive: "style-src 'self'". Either the 'unsafe-inline' keyword, a hash ('sha256-k1JesVGZw2ecLBebF6NyovSeoPnbl5AOxe2F0lM7KZU='), or a nonce ('nonce-...') is required to enable inline execution.

The first one is Browser Link (It uses a different port so script-src 'self' does not work) but the others are Glimpse errors. I could add the unsafe-inline directive to fix Glimpse in development but it's not ideal.

avanderhoorn commented 8 years ago

In the case where, Glimpse runs before NWebsec, one options would be for us to modify the header manually before NWebsec. The problem is knowing whether NWebsec is in play, but we could probably have a setting which the users sets in the case they want us to add the CSP headers. Even if we did this, the thing I'm not 100% clear on is what if Glimpse modifies the CSP header and then another library like BrowserLink comes after us and blows away these changes... is there any way of reliably getting right, or at the end of the day we are better off flagging in the docs "For CSP user... PLEASE NOTE!!!..."?

RehanSaeed commented 8 years ago

I think modifying headers is going to be a problem. Ideally there needs to be communication between the Glimpse and BrowserLink teams to come up with a common approach.

I think the errors are caused by hud.js dynamically adding lots of inline styles. I still see a few solutions even with no code changes:

klings commented 8 years ago

So, I just had a look at what's going on with the 2.0.0-beta1. Similar to the old issue, Glimpse/Glimpse#631, I created a new ASP.NET 5 application based on the VS template and added Glimpse to it as well as the CSP header:

Content-Security-Policy: default-src 'self' 

This messed up the styling of the Glimpse link on the page, and gave med two CSP errors. image

It seems hud.js sets some inline styling for the Glimpse button, causing the error. If you could find a way around this and avoid inline styles, that would be awesome.

If you'd want to document the CSP needs of Glimpse, it would be useful to be a bit more specific than default-src 'self'. I had a look in Fiddler and it seems you are loading JS, making XHR requests, and receiving server-sent events. script-srcand connect-src should take care of these. You'd probably want to load some CSS too, so the header you require might end up being

Content-Security-Policy: script-src 'self'; style-src 'self'; connect-src 'self'

You could set the header by hand when testing this, but you'll need to be careful to get it right. If you'd want to use NWebsec to set it, just add the middleware and configure it there. You'll need the dependency

"NWebsec.Middleware": "1.0.0-gamma-39"

And then work from the options:

app.UseCsp(options =>
{
  options.DefaultSources(configuration => configuration.Self());
});

As for @RehanSaeed's proposals, 1 would be great and easy to work with for most users. 2 could be a bit more challenging, as things would break between releases if you made changes to the inline stuff. 3 would significantly reduce the security offered by CSP, so that would be a bit sad.

As a final note, thank you for looking at this. It's important for CSP adoption that popular libraries are CSP friendly. And TIL that the ASP.NET 5 VS template gives you an app that out-of-the-box works with a sane CSP as there's no inline scripts or styles in play. Feel free to ping me if you run into any CSP issues, I'd be happy to help in any way I can.