I created a site using the new Google sites (not Classic Sites), set up site proxying through Cloudflare, and enabled the Email Address Obfuscation feature in Cloudflare. Then I added a button that performs a simple action mailto:[email protected]
and ran into a problem: When I click on the button, I am taken to the Cloudflare "Email Protection" page with the message "You are unable to access this email address example.com".
This is for a simple reason - my browser (and it will happen with any modern browser) does not load the email-decode.min.js
script from Cloudflare. In turn, this is due to the fact that Google Sites uses CSP >= v2 and the CSP directives are configured in such a way that they do not allow the script from Cloudflare to load.
According to Cloudflare documentation, in order to use Scrape Shield you need to update CSP headers as follows:
script-src 'self' 'unsafe-inline'
This is what the new Google Sites CSP header looks like:
base-uri 'self';
object-src 'none';
report-uri /_/view/cspreport;
script-src 'report-sample' 'nonce-7+8CsMF6KihKnNmDwfM84w' 'unsafe-inline' 'unsafe-eval';
worker-src 'self';
frame-ancestors https://google-admin.corp.google.com/
* nonce-<base64-value>
is updated with every request.
When loading a page that contains email I see the following error in the browser console:
Refused to load the script 'https://example.com/cdn-cgi/scripts/6d6ddgh8/cloudflare-static/email-decode.min.js' because it violates the following Content Security Policy directive: "script-src 'report-sample' 'nonce-7+8CsMF6KihKnNmDwfM84w' 'unsafe-inline' 'unsafe-eval'". Note that 'script-src-elem' was not explicitly set, so 'script-src' is used as a fallback.
I'm not sure about the reason, but the script won't load for one of two reasons:
- The source
'self'
is not set for thescript-src
directive (I don’t think this is the case). - The source
'unsafe-inline'
is ignored because a cryptographic nonce is present.
It doesn't work anyway. I see two solutions, but I don't know how to implement them:
- For the first reason (although I don't think this is the case) this could be solved if Google added the source
'self'
to thescript-src
directive, or if I had the ability to customize this header and I would do it myself. - For the second reason, this could be solved if Cloudflare read the
'nonce-<base64-value>'
that the Google server returns when the site is requested and adds it to its scripts.
It would be grateful if someone could share a solution to this problem.
So I figured out that the reason is the missing
'self'
source in thescript-src
directive.I found a forum thread that suggests using Cloudflare Workers to change the required data in a request / response on the fly. I also found a ready-made example code for a worker that allows to replace headers in the request / response.
Inspired by this idea and given that Cloudflare provides 100,000 requests per day for free, I wrote and deployed a worker code that changes the server response headers, in fact, it updates the
script-src
directive in thecontent-security-policy
header, supplementing it with the sources specified in the variablesources
.My problem is solved, now the Cloudflare script is loading and the button is working.
* I don't promise quality code, but it works. The code could be made even more versatile, but I didn't have time for that.
Here is my worker code: