How to detect Content Security Policy (CSP)

2019-02-08 01:08发布

问题:

I noticed that GitHub and Facebook are both implementing this policy now, which restricts third party scripts from being run within their experience/site.

Is there a way to detect whether a document is running against CSP using JavaScript? I'm writing a bookmarklet, and want to give the user a message if they're on a site that doesn't support embedding a script tag.

回答1:

What about this. For slow connections, the timeout should probably be raised. Onload is what I used to detect it and it seems to work. If it loads then CSP obviously isn't enabled or it is configured improperly.

var CSP = 0;
frame = document.createElement('script');
frame.setAttribute('id', 'theiframe');
frame.setAttribute('src', location.protocol+'//example.com/');
frame.setAttribute('onload', 'CSP=1;');
document.body.appendChild(frame);
setTimeout(function(){if (0 == CSP){alert("CSP IS ENABLED");}}, 250);


回答2:

From https://github.com/angular/angular.js/blob/master/src/Angular.js#L1091, function noUnsafeEval

function noUnsafeEval() {
  try {
    /* jshint -W031, -W054 */
    new Function('');
    /* jshint +W031, +W054 */
    return false;
  } catch (e) {
    return true;
  }
}


回答3:

Currently, there is no way to do so in shipping browsers.

However, something such as the following should work, per spec, and does in Chrome with experimental web platform features enabled in chrome://flags/:

function detectCSPInUse() {
  return "securityPolicy" in document ? document.securityPolicy.isActive : false;
}

The SecurityPolicy interface (what you get from document.securityPolicy if it is implemented) has a few attributes that give more detail as to what is currently allowed.



回答4:

An easy way to detect support for CSP is just by checking if JavaScript's eval()-method can be run without throwing an error, like so:

try {
    eval("return false;");
} catch (e) {
    return true;
}

However, this only works if CSP is actually turned on (obviously), with Content-Security-Policy being set in the response headers the page loaded with, and without 'unsafe-eval' in script-src.

I came here looking for a way to detect CSP support in browsers without CSP actually being turned on. It would seem this is not possible though.

On a side note, IE does not support CSP, only the sandbox directive in IE 10+, which, by looking at the CSP standard, does not make it a conformant web browser.



回答5:

From https://hackernoon.com/im-harvesting-credit-card-numbers-and-passwords-from-your-site-here-s-how-9a8cb347c5b5:

fetch(document.location.href)
.then(resp => {
  const csp = resp.headers.get('Content-Security-Policy');
  // does this exist? Is is any good?
});

This will fail however with connect-src='none' and be reported.