diff options
-rw-r--r-- | background/policy_injector.js | 40 | ||||
-rw-r--r-- | common/misc.js | 36 | ||||
-rw-r--r-- | content/main.js | 27 |
3 files changed, 57 insertions, 46 deletions
diff --git a/background/policy_injector.js b/background/policy_injector.js index f573d48..80a0e3b 100644 --- a/background/policy_injector.js +++ b/background/policy_injector.js @@ -19,7 +19,7 @@ * IMPORT url_extract_target * IMPORT sign_policy * IMPORT get_query_best - * IMPORT parse_csp + * IMPORT sanitize_csp_header * IMPORTS_END */ @@ -79,40 +79,6 @@ function url_inject(details) }; } -function process_csp_header(header, rule, block) -{ - const csp = parse_csp(header.value); - - - if (block) { - /* No snitching */ - delete csp['report-to']; - delete csp['report-uri']; - - delete csp['script-src']; - delete csp['script-src-elem']; - - csp['script-src-attr'] = ["'none'"]; - csp['prefetch-src'] = ["'none'"]; - } - - if ('script-src' in csp) - csp['script-src'].push(rule); - else - csp['script-src'] = [rule]; - - if ('script-src-elem' in csp) - csp['script-src-elem'].push(rule); - else - csp['script-src-elem'] = [rule]; - - const new_policy = Object.entries(csp).map( - i => `${i[0]} ${i[1].join(' ')};` - ); - - return {name: header.name, value: new_policy.join('')}; -} - function headers_inject(details) { const targets = url_extract_target(details.url); @@ -157,10 +123,10 @@ function headers_inject(details) orig_csp_headers = csp_headers = null; for (const header of data) - headers.push(process_csp_header(header, rule, block)); + headers.push(sanitize_csp_header(header, rule, block)); } } else if (is_chrome || !orig_csp_headers) { - csp_headers.push(process_csp_header(header, rule, block)); + csp_headers.push(sanitize_csp_header(header, rule, block)); if (is_mozilla) orig_csp_headers.push(header); } diff --git a/common/misc.js b/common/misc.js index 0d8466e..d046b65 100644 --- a/common/misc.js +++ b/common/misc.js @@ -173,6 +173,40 @@ function parse_csp(csp) { return directives; } +/* Make CSP headers do our bidding, not interfere */ +function sanitize_csp_header(header, rule, block) +{ + const csp = parse_csp(header.value); + + if (block) { + /* No snitching */ + delete csp['report-to']; + delete csp['report-uri']; + + delete csp['script-src']; + delete csp['script-src-elem']; + + csp['script-src-attr'] = ["'none'"]; + csp['prefetch-src'] = ["'none'"]; + } + + if ('script-src' in csp) + csp['script-src'].push(rule); + else + csp['script-src'] = [rule]; + + if ('script-src-elem' in csp) + csp['script-src-elem'].push(rule); + else + csp['script-src-elem'] = [rule]; + + const new_policy = Object.entries(csp).map( + i => `${i[0]} ${i[1].join(' ')};` + ); + + return {name: header.name, value: new_policy.join('')}; +} + /* * EXPORTS_START * EXPORT gen_nonce @@ -184,6 +218,6 @@ function parse_csp(csp) { * EXPORT nice_name * EXPORT open_in_settings * EXPORT is_privileged_url - * EXPORT parse_csp + * EXPORT sanitize_csp_header * EXPORTS_END */ diff --git a/content/main.js b/content/main.js index 9ed557c..5edb8a6 100644 --- a/content/main.js +++ b/content/main.js @@ -19,6 +19,7 @@ * IMPORT is_chrome * IMPORT is_mozilla * IMPORT start_activity_info_server + * IMPORT sanitize_csp_header * IMPORTS_END */ @@ -65,6 +66,17 @@ function block_node(node) block_script(node); return; } + + else if (node.tagName === 'META' && + node.getAttribute('http-equiv') === 'content-security-policy') { + + node.content = sanitize_csp_header( + {value: node.content}, + `'nonce-${nonce}'`, + !policy.allow + ).value; + return; + } sanitize_attributes(node); @@ -114,14 +126,13 @@ if (!is_privileged_url(document.URL)) { if (!policy.allow) { block_nodes_recursively(document.documentElement); - if (is_chrome) { - var observer = new MutationObserver(handle_mutation); - observer.observe(document.documentElement, { - attributes: true, - childList: true, - subtree: true - }); - } + /* Now needed on Mozilla as well to sanitize CSP header */ + var observer = new MutationObserver(handle_mutation); + observer.observe(document.documentElement, { + attributes: true, + childList: true, + subtree: true + }); if (is_mozilla) addEventListener('beforescriptexecute', mozilla_suppress_scripts, true); |