Content Security Policy is Blocking URI in Allowed Domain - content-security-policy

I have the following content security policy set in my .htaccess file:
default-src 'none'; \
form-action 'self'; \
frame-ancestors 'none'; \
font-src 'self' data: fonts.gstatic.com *.fontawesome.com; \
img-src 'self' data: www.google-analytics.com www.facebook.com; \
script-src 'self' 'unsafe-inline' www.google-analytics.com ssl.google-analytics.com www.google.com www.gstatic.com ajax.cloudflare.com www.googletagmanager.com connect.facebook.net *.fontawesome.com; \
style-src 'self' 'unsafe-inline' fonts.googleapis.com *.fontawesome.com; \
connect-src 'self' www.google-analytics.com *.fontawesome.com; \
frame-src www.google.com; \
base-uri 'none'; \
report-uri /csp-report.php
When I visit the site, I don't get any CSP messages in the developer tools console. However, I am getting reports via my report-uri like this:
blocked-uri: https://www.google-analytics.com/analytics.js
document-uri: https://URL.com/
original-policy: default-src 'none'; form-action 'self'; frame-ancestors 'none'; font-src 'self' data: https://fonts.gstatic.com https://*.fontawesome.com; img-src 'self' data: https://www.google-analytics.com https://www.facebook.com; script-src 'self' 'unsafe-inline' https://www.google-analytics.com https://ssl.google-analytics.com https://www.google.com https://www.gstatic.com https://ajax.cloudflare.com https://www.googletagmanager.com https://connect.facebook.net https://*.fontawesome.com; style-src 'self' 'unsafe-inline' https://fonts.googleapis.com https://*.fontawesome.com; connect-src 'self' https://www.google-analytics.com https://*.fontawesome.com; frame-src https://www.google.com; base-uri 'none'; report-uri https://URL.com/csp-report.php
referrer:
violated-directive: script-src
It is always the same URI, https://www.google-analytics.com/analytics.js that is being blocked, and I can't figure out why. Is this due to something on the user's end blocking Google Analytics?

I had the same issue. I was able to trace this down to browser extensions based on this SO answer.
TL;DR; is that browser extensions load up google analytics and they get blocked by CSP but it shows as if it originated out of your site.

Related

Why can't Mozilla observatory detect the http security headers on my website anymore?

A few months ago, I added security headers to all of the pages on my website. The Mozilla Observatory detected the changes then and the score increased to B+. Though I haven't changed a thing, it now tells me there are none and I get a F score. That being said, both in Chrome and in Firefox, I do see the headers. What's wrong ? Any help is appreciated.
Here are the response headers :
cache-control: no-store, no-cache, must-revalidate
content-encoding: gzip
content-language: fr
content-security-policy: default-src 'self'; style-src 'self' 'unsafe-inline'; script-src https://mydomain/config.js 'unsafe-inline'; form-action 'self'; frame-ancestors 'none';
content-type: text/html; charset=UTF-8
date: Sun, 17 Oct 2021 11:41:27 GMT
expect-ct: enforce,max-age=2592000
expires: Thu, 19 Nov 1981 08:52:00 GMT
pragma: no-cache
referrer-policy: strict-origin
server: Apache
strict-transport-security: max-age=15768000 ; includeSubDomains ;
x-content-type-options: nosniff
x-frame-options: DENY
x-xss-protection: 1;mode=block
Edit : Here is the result of the analysis
Analysis returned by the Mozilla observatory
I was having the same problem with X-XSS in Mozilla Observatory and found this:
<IfModule mod_headers.c>
Header always set X-XSS-Protection "1; mode=block"
</IfModule>
Then, the Observatory validated properly.

Azure Staging Environment "No 'Access-Control-Allow-Origin' header is present on the requested resource"

I've inherited a web-app hosted in Azure and it appears the staging environment CORS is not functioning like all other environments.
I'm fairly new to Azure administration and I've applied the CORS configuration on the API app service (previously had no config set) which did not resolve the issue.
You can compare the different environment general/response headers below.
Local Dev...
Request URL: http://localhost:3001/api/getstarted/plans?fetchExcluded=true
Request Method: GET
Status Code: 200 OK
Remote Address: [::1]:3001
Referrer Policy: strict-origin-when-cross-origin
Access-Control-Allow-Origin: *
Connection: keep-alive
Content-Encoding: gzip
Content-Type: application/json; charset=utf-8
Date: Thu, 04 Nov 2021 21:55:22 GMT
Keep-Alive: timeout=5
Strict-Transport-Security: max-age=15552000; includeSubDomains
Transfer-Encoding: chunked
Vary: Accept-Encoding
X-Content-Type-Options: nosniff
X-DNS-Prefetch-Control: off
X-Download-Options: noopen
X-Frame-Options: SAMEORIGIN
X-XSS-Protection: 1; mode=block
Current Production...
Request URL: https://api.<webapp>.app/api/getstarted/plans?fetchExcluded=true
Request Method: OPTIONS
Status Code: 204 No Content
Remote Address: ##.###.###.###:443
Referrer Policy: strict-origin-when-cross-origin
Access-Control-Allow-Headers: authorization
Access-Control-Allow-Methods: GET,HEAD,PUT,PATCH,POST,DELETE
Access-Control-Allow-Origin: *
Date: Thu, 04 Nov 2021 22:04:19 GMT
Strict-Transport-Security: max-age=15552000; includeSubDomains
Vary: Access-Control-Request-Headers
X-Content-Type-Options: nosniff
X-DNS-Prefetch-Control: off
X-Download-Options: noopen
X-Frame-Options: SAMEORIGIN
X-XSS-Protection: 1; mode=block
However in staging...
Request URL: https://<webapp>.azurewebsites.net/api/getstarted/plans?fetchExcluded=true
Request Method: OPTIONS
Status Code: 503 Service Temporarily Unavailable
Remote Address: ##.###.###.###:443
Referrer Policy: strict-origin-when-cross-origin
Content-Length: 398
Date: Thu, 04 Nov 2021 21:56:02 GMT
Server: nginx
and from debug console in staging...
- Access to XMLHttpRequest at
'https://<webapp>.azurewebsites.net/api/getstarted/plans?fetchExcluded=true'
from origin 'https://<webapp>.z8.web.core.windows.net' has been
blocked by CORS policy: Response to preflight request doesn't pass
access control check: No 'Access-Control-Allow-Origin' header is
present on the requested resource. xhr.js:178
- GET
https://<webapp>-api-staging.azurewebsites.net/api/getstarted/plans?fetchExcluded=true
net::ERR_FAILED
I've checked the Azure Subscription usage + quotas, and the only thing nearing quota is "Network Watchers"
The API framework is ExpressJS with CORS...
app.use(cors())
In my opinion the issue has nothing to do with CORS, well, better said,...
As you can see in the staging environment you are receiving a 503, service unavailable, HTTP status error code:
Status Code: 503 Service Temporarily Unavailable
So my guess is that the staging environment is not working properly by some reason, and the associated load balancer is returning a 503 error page, of course, without any CORS indication, and your browser is complaining due to the fact your API doesn't receive a valid response.
Please, review the status of the staging environment: once healthy, it probably will offer a proper response to your application.
Unfortunately the issue was not CORS at all; rather the server image was failing to build and compile due to ESNext JS syntax (server < ESNext)
I found the logstream API which allowed me to view all errors, for posterity you might be able to find the same; https://<webapp>.scm.azurewebsites.net/api/logstream

CDN - Serve different content-type based on Accept header (Verizon/EdgeCast Premium)?

I have a server which returns a different response based on the Accept header e.g. if Accept header includes "image/webp", a webp image is served, otherwise a jpg is served.
We run Varnish at server-level and it does this correctly, as per example below:
Request (with image/webp in Accept header):
curl -s -D - -o /dev/null "https://REDACTED/media/tokinoha_bowl-4.jpg?sh=2&fmt=webp,jpg" -H "Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8"
Response (webp image served):
HTTP/2 200
date: Wed, 06 Feb 2019 08:25:05 GMT
content-type: image/webp
access-control-allow-origin: *
cache-control: public, s-maxage=31536000, max-age=31536000
x-frame-options: SAMEORIGIN
x-xss-protection: 1; mode=block
x-content-type-options: nosniff
strict-transport-security: max-age=31536000; includeSubDomains
vary: Accept-Encoding, Accept-Encoding,Origin
referrer-policy: strict-origin-when-cross-origin
accept-ranges: bytes
content-length: 60028
Request (no webp in Accept header, jpg served):
curl -s -D - -o /dev/null "https://REDACTED/media/tokinoha_bowl-4.jpg?sh=2&fmt=webp,jpg" -H "Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/apng,*/*;q=0.8"
Response:
HTTP/2 200
date: Wed, 06 Feb 2019 08:25:18 GMT
content-type: image/jpeg
access-control-allow-origin: *
cache-control: public, s-maxage=31536000, max-age=31536000
x-frame-options: SAMEORIGIN
x-xss-protection: 1; mode=block
x-content-type-options: nosniff
strict-transport-security: max-age=31536000; includeSubDomains
vary: Accept-Encoding, Accept-Encoding,Origin
referrer-policy: strict-origin-when-cross-origin
accept-ranges: bytes
content-length: 166991
We have the below options in the Rules Engine set up, however whichever content-type is cached first is served on all subsequent requests irrespective of request header.
Rules Engine settings
Does anyone know of a way to achieve this?
Thanks in advance!
We had the same problem with Verizon/Edgecast: One URL delivered two different image types (JPEG and WebP) depending on Accept header. The origin (imgix) sent correctly Vary: Accept, but Edgecast ignored that and cached what it get and so browsers without WebP support got sometimes the wrong format.
We solved it with a rule in Edgecast:
WebP rule
The query parameter auto is always part of the URL and can therefore always be removed from the cache key. With the second query parameter varyWebP we recognize the URLs definitely and prevent a collision with URLs without query parameter auto.
In this case the URL
https://[HOST]/[PATH]?a=1&b=2&c=3&auto=compress,format
creates the same cache key as:
https://[HOST]/[PATH]?a=1&b=2&c=3
That's why the query parameter varyWebP protects us.

Modifying/Adding Browser Headers (Not Working)

(I'm still new to this and I don't know how to format this properly so it looks neat, sorry about that)
I'm trying to modify my Browser Headers but they don't seem to be changing, when checking the headers with http://ip-check.info they do show up, but when checking the headers using the Developer Tools, they're the same as before? I'm using Firefox 40.0.
Example (Facebook) :
Content-Security-Policy: default-src * data: blob:;script-src *.facebook.com *.fbcdn.net *.facebook.net *.google-analytics.com *.virtualearth.net .google.com 127.0.0.1: .spotilocal.com: 'unsafe-inline' 'unsafe-eval' *.akamaihd.net *.atlassolutions.com blob:;style-src * 'unsafe-inline';connect-src *.facebook.com *.fbcdn.net *.facebook.net .spotilocal.com: .akamaihd.net wss://.facebook.com:* https://fb.scanandcleanlocal.com:* *.atlassolutions.com attachment.fbsbx.com;
Strict-Transport-Security: max-age=15552000; preload
X-Content-Type-Options: nosniff
X-Frame-Options: DENY
X-XSS-Protection: 0
I would like to modify the headers to this:
X-XSS-Protection: 1; mode=block
Strict-Transport-Security: max-age=31536000; includeSubDomains
X-WebKit-CSP: default-src 'self'
X-Content-Security-Policy: default-src 'self'
Content-Security-Policy: default-src 'self'
I have tried using these two Add-Ons (not at the same time) :
https://addons.mozilla.org/en-US/firefox/addon/modify-headers
https://addons.mozilla.org/en-US/firefox/addon/modify-header-value

CORS issue No 'Access-Control-Allow-Origin' header is present on the requested resource

I have my fonts in a subdomain like static.example.com Today the fonts aren't displayed in Chrome —and in Firefox as well— and this error appeared in the dev tools:
«Font from origin 'http://static.example.com' has been blocked from loading by Cross-Origin Resource Sharing policy: No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://example.com' is therefore not allowed access.»
I already have this code in the subdomain .htaccess file
<IfModule mod_headers.c>
<FilesMatch "\.(ttf|ttc|otf|eot|woff|font.css|css)$">
Header set Access-Control-Allow-Origin "*"
Header set Access-Control-Allow-Headers "Cache-Control, Pragma, Origin, Authorization, Content-Type, X-Requested-With"
Header set Access-Control-Allow-Methods "GET, PUT, POST"
</FilesMatch>
</IfModule>
Also if I try curl -I http://static.example.com/fonts/pfcentrosanspro-reg-webfont.eot in the terminal I get this response:
HTTP/1.1 200 OK
Server: nginx
Date: Wed, 27 Aug 2014 17:20:50 GMT
Content-Type: font/eot
Content-Length: 26403
Connection: keep-alive
X-Accel-Version: 0.01
Last-Modified: Mon, 05 Aug 2013 17:49:42 GMT
Accept-Ranges: bytes
Cache-Control: max-age=31536000
Expires: Thu, 27 Aug 2015 17:20:50 GMT
X-Powered-By: PleskLin
Access-Control-Allow-Origin: *
Access-Control-Allow-Headers: Cache-Control, Pragma, Origin, Authorization, Content-Type, X-Requested-With
Access-Control-Allow-Methods: GET, PUT, POST
But the error persists, I have moved the fonts to a bucket in Amazon S3 CDN with this code:
<CORSConfiguration xmlns="http://s3.amazonaws.com/doc/2006-03-01/">
<CORSRule>
<AllowedOrigin>http://example.com</AllowedOrigin>
<AllowedMethod>GET</AllowedMethod>
<AllowedMethod>HEAD</AllowedMethod>
<AllowedMethod>DELETE</AllowedMethod>
<AllowedMethod>PUT</AllowedMethod>
<AllowedMethod>POST</AllowedMethod>
</CORSRule>
</CORSConfiguration>
No luck, the error is still there —the fonts doesn't load and the CORS error is displayed—, I even have modified the Nginx config file without results!
Am I doing something wrong? this is driving me nuts.
The site is a Wordpress blog with W3 Total Caché plugin
Thank you for your help!
Some browsers don't like this:
Access-Control-Allow-Origin *
You should set this to the domain of the originating request. I've struggled a lot with similar issues, and finally landed on the below solution (PHP, but you'll get the idea).
$origin=isset($_SERVER['HTTP_ORIGIN'])?$_SERVER['HTTP_ORIGIN']:$_SERVER['HTTP_HOST'];
header('Access-Control-Allow-Origin: '.$origin);
header('Access-Control-Allow-Methods: POST, OPTIONS, GET, PUT');
header('Access-Control-Allow-Credentials: true');
header('Access-Control-Allow-Headers: Authorization, X-Requested-With');
header('P3P: CP="NON DSP LAW CUR ADM DEV TAI PSA PSD HIS OUR DEL IND UNI PUR COM NAV INT DEM CNT STA POL HEA PRE LOC IVD SAM IVA OTC"');
header('Access-Control-Max-Age: 1');
This code will accept all requests from all domains. This could be insecure. You'd probably want to check the requests against a whitelist of accepted domains.

Resources