summaryrefslogtreecommitdiff
path: root/background/policy_injector.js
diff options
context:
space:
mode:
Diffstat (limited to 'background/policy_injector.js')
-rw-r--r--background/policy_injector.js72
1 files changed, 53 insertions, 19 deletions
diff --git a/background/policy_injector.js b/background/policy_injector.js
index 9a994f8..a67b4e3 100644
--- a/background/policy_injector.js
+++ b/background/policy_injector.js
@@ -12,14 +12,13 @@
* IMPORT get_storage
* IMPORT browser
* IMPORT is_chrome
- * IMPORT is_mozilla
* IMPORT gen_unique
* IMPORT gen_nonce
* IMPORT is_privileged_url
* IMPORT url_extract_target
* IMPORT sign_policy
* IMPORT get_query_best
- * IMPORT csp_rule
+ * IMPORT parse_csp
* IMPORTS_END
*/
@@ -32,11 +31,19 @@ const csp_header_names = {
"x-content-security-policy" : true
};
+const unwanted_csp_directives = {
+ "report-to" : true,
+ "report-uri" : true,
+ "script-src" : true,
+ "script-src-elem" : true,
+ "prefetch-src": true
+};
+
const header_name = "content-security-policy";
-function is_csp_header(header)
+function not_csp_header(header)
{
- return !!csp_header_names[header.name.toLowerCase()];
+ return !csp_header_names[header.name.toLowerCase()];
}
function url_inject(details)
@@ -82,21 +89,48 @@ function headers_inject(details)
if (!targets.current)
return {cancel: true};
- const rule = csp_rule(targets.policy.nonce);
- var headers = details.responseHeaders;
-
- /*
- * Chrome doesn't have the buggy behavior of caching headers
- * we injected. Firefox does and we have to remove it there.
- */
- if (!targets.policy.allow || is_mozilla)
- headers = headers.filter(h => !is_csp_header(h));
-
- if (!targets.policy.allow) {
- headers.push({
- name : header_name,
- value : rule
- });
+ const headers = [];
+ for (let header of details.responseHeaders) {
+ if (not_csp_header(header)) {
+ /* Retain all non-snitching headers */
+ if (header.name.toLowerCase() !==
+ 'content-security-policy-report-only')
+ headers.push(header);
+
+ continue;
+ }
+
+ const csp = parse_csp(header.value);
+ const rule = `'nonce-${targets.policy.nonce}'`
+
+ /* TODO: confirm deleting non-existent things is OK everywhere */
+ /* No snitching or prefetching/rendering */
+ delete csp['report-to'];
+ delete csp['report-uri'];
+
+ if (!target.policy.allow) {
+ 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;
+
+ /* TODO: is this safe */
+ let new_policy = Object.entries(csp).map(
+ i => i[0] + ' ' + i[1].join(' ') + ';'
+ );
+
+ headers.push({name: header.name, value: new_policy.join('')});
}
return {responseHeaders: headers};