From the OWASP's website
https://cheatsheetseries.owasp.org/cheatsheets/Content_Security_Policy_Cheat_Sheet.html:
Send a Content-Security-Policy HTTP response header from your web server.
Content-Security-Policy: ...
Using a header is the preferred way and supports the full CSP feature set. Send it in all HTTP responses, not just the index page.
I don't understand how that could be true as it is possible to set the Content-Security-Policy by using a meta tag in the HTML.
I also don't see how the policy can apply to anything else but HTML pages.
Does anyone have idea why that statement above was made and if it is safe to only send HTTP header Content-Security-Policy for text/html responses?
By the way, the policy is too big and I would like to sent as fewer bytes as possible.
This is still something that’s not formally specified and there ai still some debate on this: https://github.com/w3c/webappsec/issues/520
In general there’s two arguments here:
On the one hand some other file types (XML, PDF, perhaps even SVGs) could benefit from CSP and any resource could become the page by right clicking and opening in a separate tab.
On the other hand CSPs can get quite big and are usually written for HTML pages. So a bit wasteful to send on other resources and most of it won’t be relevant.
The right answer (as suggested by above) is probably to have a reduced, and very strict, CSP for all non-HTML responses.
But I think for most people having it on the HTML only will be good enough and bring most of the benefits of CSP. Then again CSP is an advanced technique so if going as far as that, then why not do it properly?
Using a header is the preferred way and supports the full CSP feature set.
I don't understand how that could be true as it is possible to set the Content-Security-Policy by using a meta tag in the HTML.
Inside the meta tag are not supported the directives:
report-to and report-uri
frame-ansectors
sandox
Also meta tag does not support Content-Security-Policy-Report-Only feature, only the Content-Security-Policy.
All resources that start loading before meta tag in the HTML code are not affected by CSP. Malicious scripts can be injected as first item of the <head> section just before meta tags
The nonce-value is exposed in meta tag therefore can be easely stealing by script and reuse.
Using meta tag you can only set the CSP for HTML pages, but CSP is applied for XSLT in the XML pages, and for some other kinds of content (see below).
Therefore indeed an HTTP header is the preferred way to delivery CSP and using CSP via meta tag does not allow you to use full CSP feature set.
Send it in all HTTP responses, not just the index page.
I also don't see how the policy can apply to anything else but HTML pages.
The specification had in mind a little different - you should send CSP with any response page with HTML content, not only for 200 OK, but even for 404 Not found
403 Access Forbidden, etc.
Because these pages has access to cookie that can be steal in the page not covered by CSP.
CSP is applied not only to HTML pages, but to XSLT in XML-pages, to external javascripts files for workers (in Firefox). Also frame-ancestors directive of CSP HTTP header applies to any content (JPEG/GIF/PNG/PDF/MP4/etc) intended to be embedded into iframe, see the nitty-gritty here.
For my personal use, I'm trying to show https://maps.google.com inside an iframe. Note: I am NOT looking to use Google's Embed API.
Here's what I've done:
use a Chrome Extension to remove the following request headers: X-Frame-Options, Access-Control-Allow-Origin, Access-Control-Allow-Methods
add instead these headers: Access-Control-Allow-Methods: *, Access-Control-Allow-Origin: *, Content-Security-Policy: frame-ancestors *;
the above is done on ALL request headers on ALL urls (browser.webRequest.onHeadersReceived.addListener in my extension), it's super permissive, but for now I'm just trying to make it work.
Now I'm trying to do <iframe src=" https://maps.google.com" />.
It works half-way:
I see Google Maps showing on my iframe
But there's a permanent "Loading..." text on the bottom, and I cannot click on markers or search stuff (see screenshot).
I get the following error in the console:
Blocked autofocusing on a form control in a cross-origin subframe.
maps:13 Uncaught DOMException: Blocked a frame with origin "https://www.google.com" from accessing a cross-origin frame.
at Object._.Hr (https://www.google.com/maps/_/js/k=maps.m.en.dc5HEiFGHqQ.O/m=sc2,per,mo,lp,ti,ds,stx,bom,b/rt=j/d=1/rs=ACT90oFcxIV8Ad7kvBMCB_zNoSobKCZYEw:210:51)
at /maps/_/js/k=maps.m.en.dc5HEiFGHqQ.O/m=vwr,vd,a,owc,ob,sp,en,smi,sc,vlg,log,smr,as,wrc/rt=j/d=1/ed=1/exm=sc2,per,mo,lp,ti,ds,stx,bom,b/rs=ACT90oFcxIV8Ad7kvBMCB_zNoSobKCZYEw:3599:3
at /maps/_/js/k=maps.m.en.dc5HEiFGHqQ.O/m=vwr,vd,a,owc,ob,sp,en,smi,sc,vlg,log,smr,as,wrc/rt=j/d=1/ed=1/exm=sc2,per,mo,lp,ti,ds,stx,bom,b/rs=ACT90oFcxIV8Ad7kvBMCB_zNoSobKCZYEw:4990:3
at NLa (https://www.google.com/maps/_/js/k=maps.m.en.dc5HEiFGHqQ.O/m=sc2,per,mo,lp,ti,ds,stx,bom,b/rt=j/d=1/rs=ACT90oFcxIV8Ad7kvBMCB_zNoSobKCZYEw:1677:132)
at LLa.next (https://www.google.com/maps/_/js/k=maps.m.en.dc5HEiFGHqQ.O/m=sc2,per,mo,lp,ti,ds,stx,bom,b/rt=j/d=1/rs=ACT90oFcxIV8Ad7kvBMCB_zNoSobKCZYEw:1676:469)
at IIa.f [as H] (https://www.google.com/maps/_/js/k=maps.m.en.dc5HEiFGHqQ.O/m=sc2,per,mo,lp,ti,ds,stx,bom,b/rt=j/d=1/rs=ACT90oFcxIV8Ad7kvBMCB_zNoSobKCZYEw:1561:184)
at RIa (https://www.google.com/maps/_/js/k=maps.m.en.dc5HEiFGHqQ.O/m=sc2,per,mo,lp,ti,ds,stx,bom,b/rt=j/d=1/rs=ACT90oFcxIV8Ad7kvBMCB_zNoSobKCZYEw:1556:332)
at eJa (https://www.google.com/maps/_/js/k=maps.m.en.dc5HEiFGHqQ.O/m=sc2,per,mo,lp,ti,ds,stx,bom,b/rt=j/d=1/rs=ACT90oFcxIV8Ad7kvBMCB_zNoSobKCZYEw:1565:43)
at vA.Ma (https://www.google.com/maps/_/js/k=maps.m.en.dc5HEiFGHqQ.O/m=sc2,per,mo,lp,ti,ds,stx,bom,b/rt=j/d=1/rs=ACT90oFcxIV8Ad7kvBMCB_zNoSobKCZYEw:1564:405)
at mb (https://www.google.com/maps/_/js/k=maps.m.en.dc5HEiFGHqQ.O/m=sc2,per,mo,lp,ti,ds,stx,bom,b/rt=j/d=1/rs=ACT90oFcxIV8Ad7kvBMCB_zNoSobKCZYEw:1563:293)
Any ideas on what I could try next to make this work? Or is it just plainly not possible?
Short Answer: This can't be done.
Long Answer: X-Frame-Options is decided at the server side. What this means is, the one opening the page doesn't decide if document can be opened in iframe, instead author of document decides it. In this case, its Google.
I tried achieving the same thing way back with Google search where you type a word in text box and hitting submit will pop an iframe with Google results. I did some research and learned it can't be done since Google doesn't allow different origins to display their pages.
That's why they have APIs.
More about this - How to show google.com in an iframe?
This question is about browser behavior as well as protocol specification for linking, importing, including or ajaxing css, js, image and other resources from within html, js or css files.
While testing static files and compressed content delivery in different browsers, I found that some browsers start behaving differently if you move away from conventions. For example, IE6 creates problem if you do not send Content-Disposition: inline; header for all inline css and js etc files, and a recent version of safari does not properly handle pre-compressed gzip CSS files if you use file extension .gz like in main-styles.css.gz.
My question is about the behavior of browsers about Content-Type response header. Since <link>, <script> and <img> tags already reasonably specify the content type of the resource, can this header be safely skipped, or do some browsers require it for some historical reason?
In short, no, it's not required. But it's recommended.
Most browser that I know of will treat <link>, <script>, and <img> properly if they are not sent with headers, but there's no real good reason not to send the headers. Basically, without Content-Type headers, the browser is left to try and guess based on the content.
From RFC2616:
Content-Type specifies the media type of the underlying data.
Content-Encoding may be used to indicate any additional content
codings applied to the data, usually for the purpose of data
compression, that are a property of the requested resource. There is
no default encoding.
Any HTTP/1.1 message containing an entity-body SHOULD include a
Content-Type header field defining the media type of that body. If
and only if the media type is not given by a Content-Type field, the
recipient MAY attempt to guess the media type via inspection of its
content and/or the name extension(s) of the URI used to identify the
resource. If the media type remains unknown, the recipient SHOULD
treat it as type "application/octet-stream".
Regarding the keyword SHOULD, specified in RFC2119:
SHOULD: This word, or the adjective "RECOMMENDED", mean that there
may exist valid reasons in particular circumstances to ignore a
particular item, but the full implications must be understood and
carefully weighed before choosing a different course.
It is required for backward compatibility.
For example: Internet Explorer 10 needs Content-Type:image/svg+xml in order to render any svg file
IE10, IE9 and probably other browsers always need the Content-Type header.
I ran into a problem in java where I tried to post some data via the library chrriis.dj.nativeswing.swtimpl.components.JWebBrowser, which basically displays an internet explorer inside a java program. But the simple php script on the back-end would not parse my post-data. (Used WebBrowserNavigationParameters to set post data while navigating to a certain page) I finally found out that the Content-Type header had to be set for php to properly paste the post-data. (This was not set by default.) Setting it to Content-Type: application/x-www-form-urlencoded and everything worked fine. So, I guess setting Content-Type should allways be done when POSTing data to php.
Attempting to view my site on Google Chrome and occasionally I will get the following code displayed to me. This is a Wordpress site and it works great on other browsers, as well other users viewing in Chrome don't see this (that I know of).
Any idea what this code actually is and what might be causing it?
See a screenshot of what I'm getting here: http://s24.postimg.org/m93wtt26d/search_beauty_code.png
I'm using Google Chrome Version 26.0.1410.65 on a Mac
Your file has a wrong character encoding. The real encoding is "ascii-us" whereas the HTTP header and the meta tag declare the encoding as UTF-8.
First, you should try to set the wordpress default theme to see if the theme is the issue. If not, then try to check you apache configuration to understand why the document is encoded that way.
You could also try to change the meta tag (in you theme) to <meta http-equiv="Content-Type" content="text/html; charset=ascii-us" />, and the HTTP header Content-Type accordingly (via .htaccess).
The Content-Type header is not set in the server for that file.
Try to edit your .htaccess or PHP-code (when this content is being created/relayed by PHP) to include this header.
How can I completely supress the output of the Cache-Control Header that is returned by my custom HttpHandler in ASP.NET?
I know, I can change the header field by modifying response.Cache and response.Cache.SetCacheability, but that will only change the header field, not remove it. That is not what I want. I completely want to make no assumptions about the Cache-Control field and leave it up to the browsers policy.
EDIT: The same holds true for HttpResponse.Charset. If no charset is set, ASP.NET will always set it to "utf-8", although returning a header "Content-Type: text/html" without the charset parameter is perfectly valid html. Any idea how to supress the charset, too?
You can remove header values using
HttpContext.Current.Response.Headers.Remove("HEADER-VALUE-HERE");
If you are using a IIS7 integrated pipeline, however some header values are protected and cannot be removed (i.e they are injected after the response is dealt with on the most common page lifecycles).
What you can do if the above fails (ie its protected) is you can make a module to manually hook into the PreSendRequestHeaders and use the code above to remove the header at this point.
The majority of problems removing the header is not the inabillity to remove it, its to remove it at the correct time.
I believe using a custom http handler you should be able to remove it at the instantiation of the handler though.
I'm only guessing here, but I would think that this is configured within IIS -- on the website (or virtual directory)'s Properties dialog, there is a section called "Enable content expiration". Does unticking this box suppress the header?
If you don't have access to your IIS Manager, then I'm afraid I am not sure how you could suppress that header. Looking at the docs, response.Headers is a read-only property, so setting it to an empty string isn't going to work...