The code snippet below is aimed at testing the presence of script-src 'self'
in Chrome, specifically checking if injected inline scripts can be executed. This test ensures that the value does not include unsafe-inline
or *
:
it('should not run injected scripts', function() {
var script = 'window.inlineTagEvaluated = false;';
script += 'var callback = arguments[arguments.length - 1];';
script += 'var script = document.createElement("script");';
script += 'script.text = "window.inlineTagEvaluated = true;";';
script += 'document.head.appendChild(script);'
script += 'callback(window.inlineTagEvaluated);';
expect(browser.executeAsyncScript(script)).toBe(false);
});
To test that the CSP restrictions prevent running unsafe-eval
code is challenging due to the prohibition of inline scripts. One workaround is to have a file on the server /test-eval.js
containing:
try {
new Function('');
}
catch(e) {
window.caught = true;
}
This file is then added to the DOM during the test runtime with the following script:
it('should not run eval-ed scripts', function() {
var script = 'window.caught = false;'
script += 'var callback = arguments[arguments.length - 1];';
script += 'var script = document.createElement("script");';
script += 'script.src = "/eval-test.js";';
script += 'script.onload = function() {callback(window.caught);};';
script += 'script.onerror = function() {callback(window.caught);};';
script += 'document.head.appendChild(script);'
expect(browser.executeAsyncScript(script)).toBe(true);
});
Testing the inability to execute scripts from external domains involves serving a Javascript file from a different domain using an HTTP server setup specifically for the test.
it('should not run scripts from another domain', function() {
function setupServer() {
var defer = protractor.promise.defer();
require('http').createServer(function (request, response) {
response.setHeader('Content-Type', 'application/javascript');
response.end('window.externalScriptEvaluated = true;');
}).listen(8081, function() {
defer.fulfill();
});
return defer.promise;
}
protractor.promise.controlFlow().execute(setupServer);
var script = 'window.externalScriptEvaluated = false;';
script += 'var callback = arguments[arguments.length - 1];';
script += 'var script = document.createElement("script");';
script += 'script.src = "http://localhost:8081/";';
script += 'script.onload = function() {callback(window.externalScriptEvaluated);};';
script += 'script.onerror = function() {callback(window.externalScriptEvaluated);};';
script += 'document.head.appendChild(script);'
expect(browser.executeAsyncScript(script)).toBe(false);
});
The next test focuses on verifying the restriction set by style-src 'self'
, ensuring that inline styles cannot be applied.
it('should not use injected styles', function() {
var script = 'document.body.style.backgroundColor = "rgb(0, 1, 1)";';
script += 'var callback = arguments[arguments.length - 1];';
script += 'var style = document.createElement("style");';
script += 'style.type = "text/css";';
script += 'style.appendChild(document.createTextNode("body {background-color: rgb(1, 0, 0) !important}"));';
script += 'document.head.appendChild(style);'
script += 'callback(window.getComputedStyle(document.body).getPropertyValue("background-color"));';
expect(browser.executeAsyncScript(script)).toBe("rgb(0, 1, 1)");
});