diff options
author | Wojtek Kosior <wk@koszkonutek-tmp.pl.eu.org> | 2021-05-13 12:32:22 +0200 |
---|---|---|
committer | Wojtek Kosior <wk@koszkonutek-tmp.pl.eu.org> | 2021-05-13 12:32:22 +0200 |
commit | c4ed1b8d44c37938aaa9b12674077274554742eb (patch) | |
tree | f51381ab7bf3bd0ec9fd9f1002081760bdd56d4a | |
parent | 57f32a269a06ec5102b08824d251afa5456d4195 (diff) | |
download | browser-extension-c4ed1b8d44c37938aaa9b12674077274554742eb.tar.gz browser-extension-c4ed1b8d44c37938aaa9b12674077274554742eb.zip |
utilize CSP for blocking
-rw-r--r-- | TODOS.org | 10 | ||||
-rw-r--r-- | content/main.js | 32 | ||||
-rw-r--r-- | content/page_actions.js | 6 |
3 files changed, 37 insertions, 11 deletions
@@ -23,18 +23,15 @@ TODO: - find some way not to require each chrome user to modify manifest.json - rename the extension to something good - port to gecko-based browsers -- CRUCIAL -- make it possible to modify CSP to suit our custom scripts' needs - - find a way to additionally block all other scripts using CSP - as an additional safety measure +- make sure page's own csp doesn't block our scripts - make blocking more torough -- CRUCIAL - - also block intrinsics -- CRUCIAL - mind the data: urls -- CRUCIAL -- find out how and make it possible to whitelist non-https urls +- find out how and make it possible to whitelist non-https urls and + whether we can inject csp to them - create a repository to host scripts - enable the extension to automatically fetch script substitutes from the repo - make it possible to inject scripts to arbitrary places in DOM - make script blocking code omit those scripts -- facilitate waiting for script injection until DOM has loaded - check if prerendering has to be blocked -- CRUCIAL - block prefetch - rearrange files in extension, add some mechanism to build the extension @@ -43,6 +40,7 @@ TODO: - perform never-ending refactoring of already-written code DONE: +- find a way to additionally block all other scripts using CSP -- DONE 2021-05-13 - only allow a single injection payload for page -- DONE 2021-05-13 - rename "bundles" to "bags" to avoid confusion with Web Bundles -- DONE 2021-05-12 - use non-predictable value in place of "myext-allow", utilizing hashes -- DONE 2021-05-12 diff --git a/content/main.js b/content/main.js index c7f57bb..507a740 100644 --- a/content/main.js +++ b/content/main.js @@ -25,6 +25,8 @@ let url = url_item(document.URL); let unique = gen_unique(url); + let nonce = unique.substring(1); + var block = true; if (first_target !== undefined && first_target === unique) { @@ -47,10 +49,20 @@ } for (let mutation of mutations) { for (let node of mutation.addedNodes) { - if (node.tagName === "SCRIPT") + /* + * Modifying <script> element doesn't always prevent its + * execution in some Mozilla browsers. Additional blocking + * through CSP meta tag injection is required. + */ + if (node.tagName === "SCRIPT") { block_script(node); - else - sanitize_attributes(node); + continue; + } + + sanitize_attributes(node); + + if (node.tagName === "HEAD") + inject_csp(node); } } } @@ -68,6 +80,18 @@ node.setAttribute("type", "application/json"); } + function inject_csp(node) + { + console.log('injecting CSP'); + let meta = document.createElement("meta"); + meta.setAttribute("http-equiv", "Content-Security-Policy"); + meta.setAttribute("content", `\ +script-src 'nonce-${nonce}'; \ +script-src-elem 'nonce-${nonce}';\ +`); + node.appendChild(meta); + } + function sanitize_attributes(node) { if (node.attributes === undefined) @@ -99,5 +123,5 @@ }); } - handle_page_actions(); + handle_page_actions(nonce); })(); diff --git a/content/page_actions.js b/content/page_actions.js index 047bf24..eee0599 100644 --- a/content/page_actions.js +++ b/content/page_actions.js @@ -17,6 +17,7 @@ var port; var loaded = false; var scripts_awaiting = []; + var nonce; function handle_message(message) { @@ -49,14 +50,17 @@ { let script = document.createElement("script"); script.textContent = script_text; + script.setAttribute("nonce", nonce); document.body.appendChild(script); } - function handle_page_actions() { + function handle_page_actions(script_nonce) { document.addEventListener("DOMContentLoaded", document_loaded); port = browser.runtime.connect({name : CONNECTION_TYPE.PAGE_ACTIONS}); port.onMessage.addListener(handle_message); port.postMessage({url: document.URL}); + + nonce = script_nonce; } window.handle_page_actions = handle_page_actions; |