summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/_locales/en/messages.json12
-rw-r--r--src/bg/Defaults.js5
-rw-r--r--src/bg/RequestGuard.js2
-rw-r--r--src/bg/Settings.js75
-rw-r--r--src/bg/main.js4
-rw-r--r--src/ui/options.css10
-rw-r--r--src/ui/options.html22
-rw-r--r--src/ui/options.js9
-rw-r--r--src/ui/ui.js3
-rw-r--r--src/xss/XSS.js18
10 files changed, 138 insertions, 22 deletions
diff --git a/src/_locales/en/messages.json b/src/_locales/en/messages.json
index cd0fb52..13ab4c3 100644
--- a/src/_locales/en/messages.json
+++ b/src/_locales/en/messages.json
@@ -267,6 +267,18 @@
"OptFilterXPost": {
"message": "Turn cross-site POST requests into data-less GET requests"
},
+ "OptScanXUpload": {
+ "message": "Scan uploads for potential cross-site attacks"
+ },
+ "OptBlockUnscannedXPost": {
+ "message": "Ask confirmation for cross-site POST requests which could not be scanned"
+ },
+ "UnscannedXPost": {
+ "message": "This cross-site request could not be scanned for XSS.\nIt might be innocuous, but NoScript cannot tell for sure. Allow only if you trust both sites."
+ },
+ "OptOverrideTorBrowserPolicy": {
+ "message": "Override Tor Browser's Security Level preset"
+ },
"Options": {
"message": "Options…"
},
diff --git a/src/bg/Defaults.js b/src/bg/Defaults.js
index ef2311f..892ee40 100644
--- a/src/bg/Defaults.js
+++ b/src/bg/Defaults.js
@@ -12,7 +12,10 @@ var Defaults = {
sync: {
"global": false,
"xss": true,
- "clearclick": true
+ "xssScanRequestBody": true,
+ "xssBlockUnscannedPOST": false,
+ "overrideTorBrowserPolicy": false, // note: Settings.update() on reset will flip this to true
+ "clearclick": true,
}
};
let defaultsClone = JSON.parse(JSON.stringify(defaults));
diff --git a/src/bg/RequestGuard.js b/src/bg/RequestGuard.js
index a174eba..2f590dc 100644
--- a/src/bg/RequestGuard.js
+++ b/src/bg/RequestGuard.js
@@ -379,7 +379,7 @@ var RequestGuard = (() => {
if (pending) {
pending.scriptBlocked = scriptBlocked;
if (!(pending.headersProcessed &&
- (scriptBlocked || !ns.isEnforced(tabId) || ns.policy.can(url, "script", request.documentURL))
+ (scriptBlocked || !ns.requestCan(request, "script"))
)) {
debug("[WARNING] onHeadersReceived %s %o", frameId, tabId,
pending.headersProcessed ? "has been overridden on": "could not process",
diff --git a/src/bg/Settings.js b/src/bg/Settings.js
index 0a911ee..3efc4ad 100644
--- a/src/bg/Settings.js
+++ b/src/bg/Settings.js
@@ -81,8 +81,56 @@ var Settings = {
tabId,
unrestrictedTab,
reloadAffected,
+ isTorBrowser,
} = settings;
- if (xssUserChoices) await XSS.saveUserChoices(xssUserChoices);
+
+ let oldDebug = ns.local.debug;
+
+ let reloadOptionsUI = false;
+
+ if (isTorBrowser) {
+ // Tor Browser-specific settings
+ ns.defaults.local.isTorBrowser = true; // prevents reset from forgetting
+ if (!this.gotTorBrowserInit) {
+ // First initialization message from the Tor Browser
+ this.gotTorBrowserInit = true;
+ if (ns.sync.overrideTorBrowserPolicy) {
+ // If the user chose to override Tor Browser's policy we skip
+ // copying the Security Level preset on startup (only).
+ // Manually changing the security level works as usual.
+ ns.local.isTorBrowser = true;
+ await ns.save(ns.local);
+ return;
+ }
+ } else {
+ reloadOptionsUI = true;
+ }
+ if (!settings.local) settings.local = {};
+ settings.local.isTorBrowser = true;
+ if (!settings.sync) settings.sync = {};
+ settings.sync.xssScanRequestBody = false;
+ settings.sync.xssBlockUnscannedPOST = true;
+ }
+
+ if (settings.sync === null) {
+ // overriden defaults when user manually resets options
+
+ // we want the reset options to stick (otherwise it gets very confusing)
+ ns.defaults.sync.overrideTorBrowserPolicy = true;
+ reloadOptionsUI = true;
+ }
+
+ await Promise.all(["local", "sync"].map(
+ async storage => (settings[storage] || // changed or...
+ settings[storage] === null // ... needs reset to default
+ ) && await ns.save(settings[storage]
+ ? Object.assign(ns[storage], settings[storage]) : ns[storage] = ns.defaults[storage])
+ ));
+ if (ns.local.debug !== oldDebug) {
+ await include("/lib/log.js");
+ if (oldDebug) debug = () => {};
+ }
+
if (policy) {
ns.policy = new Policy(policy);
await ns.savePolicy();
@@ -95,22 +143,15 @@ var Settings = {
browser.tabs.reload(tabId);
}
- let oldDebug = ns.local.debug;
- await Promise.all(["local", "sync"].map(
- storage => (settings[storage] || // changed or...
- settings[storage] === null // ... needs reset to default
- ) && ns.save(
- ns[storage] = settings[storage] || ns.defaults[storage])
- ));
- if (ns.local.debug !== oldDebug) {
- await include("/lib/log.js");
- if (oldDebug) debug = () => {};
- }
+ if (xssUserChoices) await XSS.saveUserChoices(xssUserChoices);
+
if (ns.sync.xss) {
XSS.start();
} else {
XSS.stop();
}
+
+ if (reloadOptionsUI) await this.reloadOptionsUI();
},
export() {
@@ -125,5 +166,15 @@ var Settings = {
async enforceTabRestrictions(tabId, unrestricted = ns.unrestrictedTabs.has(tabId)) {
await ChildPolicies.storeTabInfo(tabId, unrestricted && {unrestricted: true});
return unrestricted;
+ },
+
+ async reloadOptionsUI() {
+ try {
+ for (let t of await browser.tabs.query({url: browser.runtime.getManifest().options_ui.page })) {
+ browser.tabs.reload(t.id);
+ };
+ } catch (e) {
+ error(e);
+ }
}
}
diff --git a/src/bg/main.js b/src/bg/main.js
index 18abe70..7bd72a6 100644
--- a/src/bg/main.js
+++ b/src/bg/main.js
@@ -180,6 +180,10 @@
return this.policy.enforced && (tabId === -1 || !this.unrestrictedTabs.has(tabId));
},
+ requestCan(request, capability) {
+ return !this.isEnforced(request.tabId) || this.policy.can(request.url, "script", request.documentURL);
+ },
+
start() {
if (this.running) return;
this.running = true;
diff --git a/src/ui/options.css b/src/ui/options.css
index f7db24b..6e6eec7 100644
--- a/src/ui/options.css
+++ b/src/ui/options.css
@@ -136,9 +136,19 @@ input[type="file"] {
.opt-group {
padding: 0.5em 0;
}
+
#xssFaq {
padding: 0.5em 1em;
}
+
+#tb-options {
+ display: none;
+}
+
+.tor #tb-options {
+ display: initial;
+}
+
#clearclick-options {
display: none;
}
diff --git a/src/ui/options.html b/src/ui/options.html
index 6e2ad0e..a80dece 100644
--- a/src/ui/options.html
+++ b/src/ui/options.html
@@ -99,17 +99,33 @@
<h3 class="flextabs__tab"><button class="flextabs__toggle">__MSG_SectionAdvanced__</button></h3>
<div class="flextabs__content">
- <div class="opt-group">
- <span id="xss-opts">
+ <div id="xss-options" class="opt-group">
+ <span id="xss-opt">
<input type="checkbox" id="opt-xss"><label for="opt-xss" id="lbl-xss">__MSG_OptFilterXGet__</label>
- <span id="xssFaq">(<a href="https://noscript.net/faq#xss" title="https://noscript.net/faq#xss">__MSG_XssFaq__</a>)</span>
+ <span id="xssFaq">(<a href="https://noscript.net/faq#xss" title="https://noscript.net/faq#xss">__MSG_XssFaq__</a>)</span>
</span>
<button id="btn-delete-xss-choices" disabled>__MSG_XSS_clearUserChoices__</button>
+ <br />
+ <span id="xssScanRequestBody-opt">
+ <input type="checkbox" id="opt-xssScanRequestBody">
+ <label for="opt-xssScanRequestBody" id="lbl-opt-xssScanRequestBody">__MSG_OptScanXUpload__</label>
+ </span>
+ <span id="xssBlockUnscannedPOST-opt">
+ <input type="checkbox" id="opt-xssBlockUnscannedPOST">
+ <label for="opt-xssBlockUnscannedPOST" id="lbl-opt-xssBlockUnscannedPOST">__MSG_OptBlockUnscannedXPost__</label>
+ </span>
</div>
<div id="clearclick-options" class="opt-group">
<input type="checkbox" id="opt-clearclick"><label for="opt-clearclick" id="lbl-clearclick">ClearClick</label>
</div>
+ <div id="tb-options" class="opt-group">
+ <span id="overrideTorBrowserPolicy-opt">
+ <input type="checkbox" id="opt-overrideTorBrowserPolicy">
+ <label for="opt-overrideTorBrowserPolicy" id="lbl-opt-overrideTorBrowserPolicy">__MSG_OptOverrideTorBrowserPolicy__</label>
+ </span>
+ </div>
+
<section id="debug" class="browser-style">
<div class="opt-group">
<span><input type="checkbox" id="opt-debug"><label id="label-debug" for="opt-debug">Debug</label></span>
diff --git a/src/ui/options.js b/src/ui/options.js
index 31cf5c3..7a9ca2b 100644
--- a/src/ui/options.js
+++ b/src/ui/options.js
@@ -8,9 +8,9 @@
let version = browser.runtime.getManifest().version;
document.querySelector("#version").textContent = _("Version", version);
// simple general options
-
+
let opt = UI.wireOption;
-
+
opt("global", o => {
if (o) {
policy.enforced = !o.checked;
@@ -33,6 +33,11 @@
});
opt("xss");
+ opt("xssScanRequestBody");
+ opt("xssBlockUnscannedPOST");
+
+ opt("overrideTorBrowserPolicy");
+
{
let button = document.querySelector("#btn-reset");
button.onclick = async () => {
diff --git a/src/ui/ui.js b/src/ui/ui.js
index 205d2a9..46d9d7f 100644
--- a/src/ui/ui.js
+++ b/src/ui/ui.js
@@ -41,6 +41,9 @@ var UI = (() => {
if (UI.local && !UI.local.debug) {
debug = () => {}; // be quiet!
}
+ if (UI.local) {
+ document.documentElement.classList.toggle("tor", !!UI.local.isTorBrowser);
+ }
resolve();
if (UI.onSettings) UI.onSettings();
await HighContrast.init();
diff --git a/src/xss/XSS.js b/src/xss/XSS.js
index f95ea04..b7bffce 100644
--- a/src/xss/XSS.js
+++ b/src/xss/XSS.js
@@ -114,6 +114,13 @@ var XSS = (() => {
return {
async start() {
let {onBeforeRequest} = browser.webRequest;
+ let {xssScanRequestBody} = ns.sync;
+ if (xssScanRequestBody !== this.xssScanRequestBody) {
+ this.stop();
+ this.xssScanRequestBody = xssScanRequestBody;
+ }
+ this.xssBlockUnscannedPOST = ns.sync.xssBlockUnscannedPOST;
+
if (onBeforeRequest.hasListener(requestListener)) return;
await include("/legacy/Legacy.js");
@@ -135,7 +142,9 @@ var XSS = (() => {
onBeforeRequest.addListener(requestListener, {
urls: ["*://*/*"],
types: ["main_frame", "sub_frame", "object"]
- }, ["blocking", "requestBody"]);
+ },
+ // work-around for https://bugzilla.mozilla.org/show_bug.cgi?id=1532530
+ xssScanRequestBody ? ["blocking", "requestBody"] : ["blocking"]);
},
stop() {
@@ -233,8 +242,11 @@ var XSS = (() => {
ic.reset();
let postInjection = xssReq.isPost &&
- request.requestBody && request.requestBody.formData &&
- ic.checkPost(request.requestBody.formData, skipParams);
+ (XSS.xssScanRequestBody ?
+ request.requestBody && request.requestBody.formData &&
+ ic.checkPost(request.requestBody.formData, skipParams)
+ : XSS.xssBlockUnscannedPOST && ns.requestCan(request, "script") && _("UnscannedXPost")
+ );
let protectName = ic.nameAssignment;
let urlInjection = ic.checkUrl(destUrl, skipRx);