From 4765db4d8679a3e6218c5e69ab390a1208dacf1e Mon Sep 17 00:00:00 2001 From: gorhill Date: Thu, 27 Apr 2017 10:38:22 -0400 Subject: [PATCH] code review: simplify CSP injection code --- src/js/traffic.js | 94 +++++------------------------------------------ 1 file changed, 9 insertions(+), 85 deletions(-) diff --git a/src/js/traffic.js b/src/js/traffic.js index 189abc4..f320e96 100644 --- a/src/js/traffic.js +++ b/src/js/traffic.js @@ -19,7 +19,6 @@ Home: https://github.com/gorhill/uMatrix */ -/* global chrome, µMatrix */ /* jshint boss: true */ 'use strict'; @@ -296,8 +295,6 @@ var foilRefererHeaders = function(µm, toHostname, details) { // https://github.com/gorhill/httpswitchboard/issues/35 var onHeadersReceived = function(details) { - // console.debug('onHeadersReceived()> "%s": %o', details.url, details); - // Ignore schemes other than 'http...' var requestURL = details.url; if ( requestURL.lastIndexOf('http', 0) !== 0 ) { @@ -328,96 +325,23 @@ var onHeadersReceived = function(details) { // We block only inline-script tags, all the external javascript will be // blocked by our request handler. - // https://github.com/gorhill/uMatrix/issues/129 - // https://github.com/gorhill/uMatrix/issues/320 - // Modernize CSP injection: - // - Do not overwrite blindly possibly already present CSP header - // - Add CSP directive to block inline script ONLY if needed - // - If we end up modifying the an existing CSP, strip out `report-uri` - // to prevent spurious CSP violations. - - var headers = details.responseHeaders; - - // Is there a CSP header present? - // If not, inject a script-src CSP directive to prevent inline javascript - // from executing. - var i = headerIndexFromName('content-security-policy', headers); - if ( i === -1 ) { - headers.push({ - 'name': 'Content-Security-Policy', - 'value': "script-src 'unsafe-eval' *" - }); - return { responseHeaders: headers }; + var csp = "script-src 'unsafe-eval' *", + headers = details.responseHeaders, + i = headerIndexFromName('content-security-policy', headers); + // A CSP header is already present: just add our own directive as a + // separate disposition (i.e. use comma). + if ( i !== -1 ) { + csp = headers[i].value.trim() + ', ' + csp; + headers.splice(i, 1); } - // A CSP header is already present. - // Remove the CSP header, we will re-inject it after processing it. // TODO: We are currently forced to add the CSP header at the end of the // headers array, because this is what the platform specific code // expect (Firefox). - var csp = headers.splice(i, 1)[0].value.trim(); - - // Is there a script-src directive in the CSP header? - // If not, we simply need to append our script-src directive. - // https://github.com/gorhill/uMatrix/issues/320 - // Since we are modifying an existing CSP header, we need to strip out - // 'report-uri' if it is present, to prevent spurious reporting of CSP - // violation, and thus the leakage of information to the remote site. - var matches = reScriptsrc.exec(csp); - if ( matches === null ) { - headers.push({ - 'name': 'Content-Security-Policy', - 'value': cspStripReporturi(csp + "; script-src 'unsafe-eval' *") - }); - return { responseHeaders: headers }; - } - - // A `script-src' directive is already present. Extract it. - var scriptsrc = matches[0]; - - // Is there at least one 'unsafe-inline' or 'nonce-' token in the - // script-src? - // If not we have no further processing to perform: inline scripts are - // already forbidden by the site. - if ( reUnsafeinline.test(scriptsrc) === false ) { - headers.push({ - 'name': 'Content-Security-Policy', - 'value': csp - }); - return { responseHeaders: headers }; - } - - // There are tokens enabling inline script tags in the script-src - // directive, so we have to strip them out. - // Strip out whole script-src directive, remove the offending tokens - // from it, then append the resulting script-src directive to the original - // CSP header. - // https://github.com/gorhill/uMatrix/issues/320 - // Since we are modifying an existing CSP header, we need to strip out - // 'report-uri' if it is present, to prevent spurious reporting of CSP - // violation, and thus the leakage of information to the remote site. - - // https://github.com/gorhill/uMatrix/issues/538 - // We will replace in-place the script-src directive with our own. - headers.push({ - 'name': 'Content-Security-Policy', - 'value': cspStripReporturi( - csp.slice(0, matches.index) + - scriptsrc.replace(reUnsafeinline, '') + - csp.slice(matches.index + scriptsrc.length) - ) - }); + headers.push({ name: 'Content-Security-Policy', value: csp }); return { responseHeaders: headers }; }; -var cspStripReporturi = function(csp) { - return csp.replace(reReporturi, ''); -}; - -var reReporturi = /report-uri[^;]*;?\s*/; -var reScriptsrc = /script-src[^;]*;?\s*/; -var reUnsafeinline = /'unsafe-inline'\s*|'nonce-[^']+'\s*/g; - /******************************************************************************/ var headerValue = function(headers, name) {