Selective handling of Tor Browser options and work-around for https://bugzilla.mozilla.org/show_bug.cgi?id=1532530
This commit is contained in:
parent
3f2453053b
commit
d1dd278a81
|
@ -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…"
|
||||
},
|
||||
|
|
|
@ -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));
|
||||
|
|
|
@ -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",
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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 () => {
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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);
|
||||
|
|
Loading…
Reference in New Issue