Safari 13.1 refused to load Shopify embeded applications - safari

Our application was working just fine, but recent changes in Safari caused our application to break.
Safari 13.1 starts blocking applications embedded in Shopify using an iframe.
The error it throws is:
refused to load https://xxdddddd.com/admin/auth/login because it does not appear in the frame-ancestor directive of content security policy.
We tried all sorts of content security policy and chrome and Firefox works just fine but safari always breaks,
We removed that header altogether.
We even added:
header("Content-Security-Policy: frame-ancestors * 'unsafe-inline' 'unsafe-eval' img-src * data:");
header("Sec-Fetch-Dest: iframe");
header("Sec-Fetch-Mode: navigate");
header("Sec-Fetch-Site: cross-site");
We tried all sorts of combinations, but it failed every time in Safari. I can find that several of other applications work just fine in embedded mode in Shopify and Safari 13.1, so it definitely means it is possible.
One thing I noticed is that the URL needs to be changed post authorization and in our cast it is not changing as Safari blocks, but in other applications it changes the URL in the browser. However I found nothing different in their code using view-source. I tried to replicate all headers as well. They are giving, but nothing worked,

Your CSP frame-ancestors * 'unsafe-inline' 'unsafe-eval' img-src * data: is completely wrong:
directives blocks should be comma-separated
the frame-ancestors directive does not supports 'unsafe-inline' and 'unsafe-eval' tokens,
Correct syntax CSP should look like frame-ancestors *; img-src * data:;
But the paradox is that this wrong CSP does allow frame-ancestors from any sources. After removing all unsupported sources, the effective CSP is frame-ancestors * data: in your case.
In the error:
refused to load https://xxdddddd.com/admin/auth/login because it does not appear in the frame-ancestor directive of content security policy.
confuses two things:
phrase in the frame-ancestor directive contains wrong directive name (s is omitted at the end of directive name). Is this a real Safari browser error?
the /admin/auth/ part - is this really public accessible URL? Or does this error appear in the administrator script, which could have other CSP rules?
You say in Chrome and Firefox all worked fine, but frame-ancestors * 'unsafe-inline' 'unsafe-eval' img-src * data: rules disallow images loading from any sources.
So it's possible you are editing one CSP header, but the app really have another. If you are familiar with the Safari browser console, you could check real CSP HTTP header delivered to the app's page.
Anyway, here you could test does Safari 13.1 support * in frame-ancestors (I can't do that due to Safari browser absence). It will exclude a case of a current version browser bug.

Related

Strict-dynamic nonce directive breaks scripts called by other scripts in CSPv2 browsers (e.g., Safari)

In browsers like Safari that (still) only support CSPv2, when I have 'strict-dynamic' and 'nonce-AAA' directives in my Content Security Policy along with all the appropriate domains, the browser will call a script loader but not execute a 2nd script called by the script loader.
For instance, if I have a CSP like:
script-src 'self' 'unsafe-inline' 'unsafe-eval' 'strict-dynamic' 'nonce-AAA' https:;
on a site that includes googletagmanager, convertexperiments, or another script loader, the first script will execute but the second script will not, and the browser will throw a standard script-src CSP error.
I expected that Safari, etc would ignore the 'strict-dynamic' and 'nonce-' directives, but it seems to only ignore the 'strict-dynamic' directive, where the 'nonce-' directive causes script loaders to break.
Recommendations about how to craft the CSP so that it can be UA-agnostic/work with both modern browsers and CSPv2 browsers without losing 'strict-dynamic'?
Tangentially, why would a CSPv2 browser be somewhat nonce aware without being able to use it in conjunction with 'strict-dynamic'?
Please note that the question isn't about whether 'unsafe-inline' is a good idea; the example is about how permissive I'm trying to make my policy to get it to work.
For instance, if I have a CSP like: script-src 'self' 'unsafe-inline' 'unsafe-eval' 'strict-dynamic' 'nonce-AAA' https:; on a site that includes googletagmanager,
convertexperiments, or another script loader, the first script will
execute but the second script will not, and the browser will throw a
standard script-src CSP error.
GoogleTagManager propagating 'nonce-value' into child scripts except Custom HTML tags. To allow inline scripts in Custom HTML tags you can use 'hash-source'.
The convertexperiments WP plugin can be easily modified to support 'nonce-value' (minor edits in class-convert-script.php file) or just move inline script to external file.
I expected that Safari, etc would ignore the 'strict-dynamic' and
'nonce-' directives, but it seems to only ignore the 'strict-dynamic'
directive, where the 'nonce-' directive causes script loaders to
break.
Safari does not support 'strict-dynamic', but is does support 'nonce-value'. And 'nonce-value' cancells 'unsafe-inline' therefore all inline scripts became blocked.
You have to craft CSP in browsers backward compatibility mode as Google does it (you can check the CSP header in https://www.google.com/recaptcha/api2/anchor for example). Since your instance of CSP already is in this mode, you need just to modify your code for 'nonce-value' support (+ 'hash-value' where it suitable).
Yes, Safari left no easy ways to implement CSP.

Google font not loading because of content security policy

I have a progressive web app. I am using Google Fonts and I am using workbox in my service worker.
My Content Security Policy is defined as:
// Omitting all the other directives
style-src 'self' https://fonts.googleapis.com 'unsafe-inline';
font-src 'self' https://fonts.gstatic.com;
connect-src 'self';
I have set up workbox to cache the fonts by following the recipe here. The code looks like:
workbox.routing.registerRoute(
/^https:\/\/fonts\.googleapis\.com/,
new workbox.strategies.StaleWhileRevalidate({
cacheName: 'google-fonts-stylesheets',
})
);
workbox.routing.registerRoute(
/^https:\/\/fonts\.gstatic\.com/,
new workbox.strategies.CacheFirst({
cacheName: 'google-fonts-webfonts',
plugins: [
new workbox.cacheableResponse.Plugin({
statuses: [0, 200],
}),
new workbox.expiration.Plugin({
maxAgeSeconds: 60 * 60 * 24 * 365,
maxEntries: 30,
}),
],
})
);
The problem here is that when I try to load my app, in the browser (Google Chrome / Safari) or in the standalone app, the font does not load. After many hair pulling moments, Chrome finally gave me an error in the console:
Refused to connect to 'https://fonts.googleapis.com/css?family=Montserrat|Quicksand&display=swap' because it violates the following Content Security Policy directive: "connect-src 'self'".
Uncaught (in promise) no-response: no-response :: [{"url":"https://fonts.googleapis.com/css?family=Montserrat|Quicksand&display=swap","error":{}}]
at o.makeRequest (https://storage.googleapis.com/workbox-cdn/releases/4.2.0/workbox-strategies.prod.js:1:3983)
GET https://fonts.googleapis.com/css?family=Montserrat|Quicksand&display=swap net::ERR_FAILED
It appears that I need to declare google fonts under connect-src too. I did not see that mentioned anywhere (and I googled a lot) so I wanted to know if this is a bug or I indeed need to define the font in the connect-src CSP directive?
connect-src 'fonts.googleapis.com' would be required, notwithstanding your current Content-Security-Policy. If I may answer this with additional material that you did not specifically request:
The purpose of CSP is Security; having unsafe-inline set for style-src is not secure. From MDN on the page dedicated to style-src - https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Security-Policy/style-src :
Note: Disallowing inline styles and inline scripts is one of the biggest security wins CSP provides. However, if you absolutely have to use it, there are a few mechanisms that will allow them.
Focusing on this alone, Google’s fonts don’t play well with SRI (subresource integrity) which would solve the security issue. A better option if security is something to which one needs to pay respect would be using a secondary server strictly for your font (unless you choose to implement SRI-friendly web fonts loaded from, e.g., CDNJS). This would allow you to implement hashing with google fonts, just be sure to have the proper CORS settings between SERVER and font server. I’d also highly recommend locking down your default-src to 'none' and thereafter define each following fetch directive as detailed by MDN here: https://developer.mozilla.org/en-US/docs/Glossary/Fetch_directive , just be sure not to use unsafe-inline in script-src OR style-src and avoid unsafe-eval as well. frame-ancestors 'none', upgrade-insecure-requests (as well as block-all-mixed-content for anyone using I.E. or Edge) and if you do decide on implementing SRI, require-sri-for script style.
I hope I haven’t overstated my answer and that, ofc, it helps you.

Is there a way to disable Safari CSP (Content Security Policy) check?

Seems like Safari has a very strong restriction on CSP. For example, on GitHub, most of the userscripts and extension doesn't work because of that.
I got a such error from the console.
[Error] Refused to execute a script because its hash, its nonce, or 'unsafe-inline' does not appear in the script-src directive of the Content Security Policy. (pulls, line 0)
How can I stop CSP check in Safari?

CSP nonce ignored by Safari

So I implemented CSP for my web app and it works perfectly fine in Chrome. All inline scripts with nonce are executed; and the ones without it are not executed.
In Safari however, this is the message I see in the console:
The source list for Content Security Policy directive 'script-src'
contains an invalid source:
''nonce-fbe23fb21d40c38e8df7c0a16357dd3ec4be86ca233cb41206ac5f897cf9a103''.
It will be ignored.
Header:
Content-Security-Policy script-src 'nonce-cb28e5c8a2b833169bb8d1fa686f659fed9b3bf8ea52b86916bcaf20a04b3209' 'self'
None of the inline scripts are executed , even the ones with nonce.
Safari does not yet support nonces (please bug your local webkit representative to support this) but Firefox and Chrome have implemented the standard behavior which is backwards compatible. Namely, if a nonce is present then 'unsafe-inline' is ignored.
Send both 'unsafe-inline' and your nonce and you will get the desired behavior. Safari will complain about the "unknown source value" but it will work as intended.
See http://www.w3.org/TR/CSP2/#directive-script-src

Enable mixed content loading in latest Chrome and firefox with http headers

I have a website that has to be served under HTTPS
However, there is a section of the site that displays BBC news stories within an iframe which is in a popup window. Here the content is not shown as both browsers say the BBC content is insecure (i.e.mixed content).
I have tried setting the header Content-Security-Policy:
to
"default-src 'self' *.my_domian.net http://*.my_domian.net http://*.bbc.co.uk *.fonts.com 'unsafe-inline' 'unsafe-eval';"
Which has an effect on other content so it is working. I have also checked the headers are sent.
However, both Chrome and Firefox continue to tell me the BBC content is insecure and it isn't shown in the iframe.
Is it possible to allow content from bbc.co.uk on a secure site ?
Have I miss understood the purpose of Content-Security-Policy ?
I have also tried frame-src in the header with no luck.
Thanks
CSP level 2 is already being applied in Chrome, and level 2 has additional frame handling.
see here: https://www.w3.org/TR/CSP2/#directive-frame-ancestors
and here: https://www.w3.org/TR/CSP2/#directive-frame-src
frame-src is being deprecated, user frame-ancestors