I'm using nginx to set the CSP header.
I often see this in examples:
default-src 'self' http: https: data: blob: 'unsafe-inline' 'unsafe-eval' https://*.foo.com;
I understand that https://*.foo.com allows loading from the foo.com domain.
But what is the meaning of the "empty" http: and https: declarations?
It means allow content from all sites on that protocol. For example:
https://example.com
https://www.example.com
https://www.google.com
http://www.google.com
http://evilhacker.com
That policy, as it currently stands, basically allows everything and is pretty pointless!
Related
I'm building a NextJs application, and I'm trying to set a secure header in my project's next.config.js file. and every time i request to google like adsense and other default google services it is also blocked, is there a way to handle this, so that it is not blocked
this is my code
const ContentSecurityPolicy = `
default-src 'self';
script-src 'self' 'unsafe-eval' 'unsafe-inline' *.google.com *.doubleclick.net *.googleadservices.com *.googlesyndication.com *.googletagmanager.com *.google-analytics.com;
There are likely two root problems or your errors:
An error message says "Content Security Policy: Duplicate script-src directives detected. All but the first instance will be ignored." As the CSP you shown does not have duplicate script-src, it could be from another CSP. CSP can be defined in both response header and as a meta tag. Check both and see if one of them has multiple script-src defined. It is ok to have multiple CSPs with one script-src each. As content has to pass all policies, another CSP can only make it stricter.
You have not defined frame-src. There are errors due to iframes, and they fall back to default-src in your CSP, which only allows 'self'.
Refused to execute a script because its hash or 'unsafe-inline' does not appear in the script-src directive of the Content Security Policy.
This is happening with Google Ads. My Nginx has:
add_header Content-Security-Policy "frame-ancestors 'self'";
What do I add/change to fix that error so my google ads show?
There are likely multiple CSPs active, and all content needs to pass all policies. Check the response headers and meta tags for other CSPs and modify/remove them to have a single CSP.
Is there any documentation that explains what you cannot do, to make an iframe unusable?
You cannot use facebook iframe because of x-frame-options is deny
Twitter you cannot use iframe because an ancestor violates the following content security policy directive:"frame-ancestors" self
Is there anywhere I can check what can and can't be set to accept an iframe
To my knowledge, there are two HTTP Headers that can be used to prevent a website from being loaded as an iframe on other websites:
X-Frame-Options
The X-Frame-Options HTTP response header can be used to indicate whether or not a browser should be allowed to render a page in a <frame>, <iframe>, <embed> or <object>.
The possible values are:
deny
sameorigin
allow-fromuri
You can read more about what they each do on MDN.
Note that according to the specification, frame-ancestors takes precedence over X-Frame-Options:
The frame-ancestors directive obsoletes the X-Frame-Options header. If a resource has both policies, the frame-ancestors policy SHOULD be enforced and the X-Frame-Options policy SHOULD be ignored.
From the example you posted, it seems like Facebook has X-Frame-Options: deny as a response header, which prevents it from being loaded in an iframe from anywhere (in browsers that support this header).
Content-Security-Policy
Using either:
frame-ancestors which restricts what domains can embed this website in an iframe
The HTTP Content-Security-Policy (CSP) frame-ancestors directive specifies valid parents that may embed a page using <frame>, <iframe>, <object>, <embed>, or <applet>.
The main difference with X-Frame-Options is that
many user agents implement SAMEORIGIN such that it only matches against the top-level document’s location. This directive checks each ancestor. If any ancestor doesn’t match, the load is cancelled.
frame-src which restricts what domains this website can embed in an iframe
The HTTP Content-Security-Policy (CSP) frame-src directive specifies valid sources for nested browsing contexts loading using elements such as <frame> and <iframe>.
You can read more about frame-ancestors and frame-src on MDN.
From the example you posted, it seems like Twitter has Content-Security-Policy: frame-ancestors 'self', which means that that website can only be embedded on the same domain.
I am using an iframe to show a calendar on it. But I keep getting the following;
Refused to display 'https://cal.mixmax.com/user1' in a frame because
an ancestor violates the following Content Security Policy directive:
"frame-ancestors 'self' https://mail.google.com
https://inbox.google.com https://.force.com https://.mixmax.com".
I tried to have the meta for Content-Security-Policy as the following but no luck.
<meta http-equiv="Content-Security-Policy"
content="frame-ancestors 'self'
https://mail.google.com
https://inbox.google.com
https://*.force.com
https://*.mixmax.com">
Any idea how to overcome it?
The problem is not a misconfiguration on your side, it's on the CSP directive on Mixmax side. They have the following directive on their page:
content-security-policy:
frame-ancestors 'self'
https://mail.google.com
https://inbox.google.com
https://*.force.com
https://*.mixmax.com;;
frame-src:
https://*.stripe.com
https://*.facebook.com
https://*.mixmax.com;;
So you cannot frame it, unless you are from any of the listed domains.
One way to overcome that is to create a proxy on your site, access MixMax on the behalf of the client, and send the data to your frame, as CSP is client-enforced only.
I'm looking for a good way to implement a relatively strong Content-Security-Policy header for my ASP.NET WebForms application. I'm storing as much JavaScript as possible in files instead of inline, but by default, WebForms injects a lot of inline scripts—for things as simple as form submission and basic AJAX calls.
MVC has some simple ways to implement nonces, especially with the help of third party libraries like NWebsec, but I can't seem to find any methods of implementing them with WebForms. I wouldn't even have a problem using hashes if there were a way to predict and retrieve the hash for each .NET injected script tag.
I hate allowing the 'unsafe-inline' value. It feels wrong needing to turn off such a powerful security feature. Is there a reasonable way to implement it in WebForms?
I had the same problem. I'm sad to say this was the best we have done. We basically identified what we use and don't use. We even had to put unsafe-eval in some instructions because we were using third party controls that couldn't work without it. At least we avoid calls to external urls.
default-src 'self';
child-src 'self' 'unsafe-inline' 'unsafe-eval';
object-src 'none';
script-src 'self' 'unsafe-inline' 'unsafe-eval' https://www.google-analytics.com;
img-src 'self' https://www.google-analytics.com;
style-src 'self' 'unsafe-inline'
I wrote an answer here for what to do about all those injected scripts:
If you open up the dev tools in Chrome, you'll likely see a message like
Refused to execute inline script because it violates the following Content Security Policy directive: "script-src 'self'. Either the 'unsafe-inline' keyword, a hash ('sha256-2NqnatcPqy5jjBXalTpZyJMO/0fUaYUb3ePlviUP4II='), or a nonce ('nonce-...') is required to enable inline execution.
If you look carefully at that message, it's telling you what the hash would be: sha256-2NqnatcPqy5jjBXalTpZyJMO/0fUaYUb3ePlviUP4II=
So if you don't want to go the nonce route, you can instead go the hash route and add
Content-Security-Policy: script-src 'self' 'sha256-2NqnatcPqy5jjBXalTpZyJMO/0fUaYUb3ePlviUP4II=' 'unsafe-eval';
You may have to add unsafe-eval in some cases as well for this to work.
Let's start with a simple example:
<system.webServer>
<httpProtocol>
<customHeaders>
<add name="Content-Security-Policy" value="default-src 'self'" />
</customHeaders>
</httpProtocol>
</system.webServer>
The value of the Content-Security-Policy header is made up of N segments separated by a semicolon. In the example above, we only specify a single segment, saying "only load resources from 'self'". 'self' translates to the same origin as the HTML resource. With this minimum configuration, your HTML is allowed to fetch JavaScript, stylesheets etc. from the same domain that served the HTML referencing the resources. You won't be able to include external scripts from CDNs and similar.
Let's say that you host everything yourself, but want to include jQuery from cdnjs. You would need the following value to allow the browser to make requests outside your origin:
<add name="Content-Security-Policy" value="default-src 'self' https://cdnjs.cloudflare.com" />
Remember the segments I talked about? You can configure which domains to load different kind of resources from using a range of different *-src keys like this:
<add name="Content-Security-Policy" value="default-src 'self'; script-src 'self' https://cdnjs.cloudflare.com; style-src 'self' https://maxcdn.bootstrapcdn.com" />
This configuration let your web application load resources from its own domain, plus scripts from cdnjs.cloudflare.com and stylesheets from maxcdn.bootstrapcdn.com.
We also had to tighten
default-src 'none';
script-src 'self' 'unsafe-inline' 'unsafe-eval';
img-src 'self' data:;
style-src 'self' 'unsafe-inline' 'unsafe-eval';
connect-src 'self';
font-src 'self';
frame-ancestors 'none';
This solution works well with ASP.NET WebForms as it still allows inline (no need to extract everything to separate js files) as well as eval's.
Unsafe-Tags are specifically needed to provide better WebForms Functionality in my opinion.
To see if you need any additional/less Restrictions you can use:
https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Security-Policy