Merge branch 'main' of github.com:hackademix/noscript into ctx

This commit is contained in:
hackademix 2022-02-13 17:05:14 +01:00
commit 963f728658
8 changed files with 66 additions and 37 deletions

View File

@ -736,7 +736,7 @@
"description": ""
},
"cap_unchecked_css": {
"message": "jedes CSS",
"message": "ungeprüfte CSS",
"description": ""
},
"cap_other": {

View File

@ -661,7 +661,7 @@ var RequestGuard = (() => {
policy.navigationURL = url;
let debugStatement = ns.local.debug ? `
let mark = Date.now() + ":" + Math.random();
console.debug("domPolicy", domPolicy, document.readyState, mark);` : '';
console.debug("domPolicy", domPolicy, document.readyState, location.href, mark, window.ns);` : '';
return `
let domPolicy = ${JSON.stringify(policy)};
let {ns} = window;
@ -669,9 +669,7 @@ var RequestGuard = (() => {
ns.domPolicy = domPolicy;
if (ns.setup) {
if (ns.syncSetup) ns.syncSetup(domPolicy);
else if (!ns.pendingSyncFetchPolicy) {
ns.setup(domPolicy);
}
else ns.setup(domPolicy);
} ;
} else {
window.ns = {domPolicy}

View File

@ -212,7 +212,7 @@
function onSyncMessage(msg, sender) {
switch(msg.id) {
case "fetchPolicy":
case "fetchChildPolicy":
return messageHandler.fetchChildPolicy(msg, sender);
break;
}

View File

@ -23,7 +23,7 @@
let listenersMap = new Map();
let backlog = new Set();
var ns = {
let ns = {
debug: true, // DEV_ONLY
get embeddingDocument() {
delete this.embeddingDocument;
@ -72,6 +72,14 @@
}
}
if (this.syncFetchPolicy) {
// extra hops to ensure that scripts don't run when CSP has not been set through HTTP headers
this.syncFetchPolicy();
return;
}
this.pendingSyncFetchPolicy = true;
if (!sync) {
queueMicrotask(() => this.fetchPolicy(true));
return;
@ -86,24 +94,46 @@
debug("Fetching policy for actual URL %s (was %s)", url, document.URL);
}
if (this.syncFetchPolicy) {
// extra hops to ensure that scripts don't run when CSP has not been set through HTTP headers
this.syncFetchPolicy();
} else {
let msg = {id: "fetchPolicy", url};
if (document.readyState === "complete") {
// no point fetching synchronously, since the document is already loaded (hot extension update?)
(async () => this.setup(await browser.runtime.sendMessage(msg)))();
} else {
debug(`Synchronously fetching policy for ${url}.`);
this.setup(browser.runtime.sendSyncMessage(msg));
}
if (!this.syncFetchPolicy) {
let msg = {id: "fetchChildPolicy", url};
let asyncFetch = (async () => {
let policy = null;
for (let attempts = 10; !(policy || this.policy) && attempts-- > 0;) {
try {
debug(`Retrieving policy asynchronously (${attempts} attempts left).`);
policy = await Messages.send(msg.id, msg) || this.domPolicy;
debug("Asynchronous policy", policy);
} catch (e) {
error(e, "(Asynchronous policy fetch)");
}
}
this.setup(policy);
});
debug(`Synchronously fetching policy for ${url}.`);
let policy = null;
let attempts = 100;
let refetch = () => {
policy = browser.runtime.sendSyncMessage(msg) || this.domPolicy;
if (policy) {
this.setup(policy);
} else if (attempts-- > 0) {
debug(`Couldn't retrieve policy synchronously (${attempts} attempts left).`);
if (asyncFetch) {
asyncFetch();
asyncFetch = null;
}
queueMicrotask(refetch);
}
};
refetch();
}
},
setup(policy) {
if (this.policy) return false;
debug("%s, %s, fetched %o", document.URL, document.readyState, policy);
debug("%s, %s, fetched %o", document.URL, document.readyState, policy, new Error().stack); // DEV_ONLY
if (!policy) {
policy = {permissions: {capabilities: []}, localFallback: true};
}

View File

@ -22,6 +22,9 @@
(window.ns || (window.ns = {})).syncFetchPolicy = function() {
ns.pendingSyncFetchPolicy = false;
ns.syncFetchPolicy = () => {};
let url = document.URL;
// Here we've got no CSP header yet (file: or ftp: URL), we need one
@ -32,18 +35,17 @@
if (window.wrappedJSObject) {
if (top === window) {
let persistentPolicy = null;
ns.syncSetup = policy => {
if (!ns.setup(policy)) return;
if (top === window && window.wrappedJSObject) {
let persistentPolicy = JSON.stringify(policy);
Object.freeze(persistentPolicy);
try {
Object.defineProperty(window.wrappedJSObject, "_noScriptPolicy", {value: cloneInto(persistentPolicy, window)});
} catch(e) {
error(e);
}
if (persistentPolicy) return;
ns.setup(policy);
persistentPolicy = JSON.stringify(policy);
Object.freeze(persistentPolicy);
try {
Object.defineProperty(window.wrappedJSObject, "_noScriptPolicy", {value: cloneInto(persistentPolicy, window)});
} catch(e) {
error(e);
}
ns.syncSetup = () => {};
};
} else try {
if (top.wrappedJSObject._noScriptPolicy) {
@ -239,6 +241,5 @@
};
if (ns.pendingSyncFetchPolicy) {
ns.pendingSyncFetchPolicy = false;
ns.syncFetchPolicy();
}

View File

@ -8,7 +8,7 @@
"strict_min_version": "59.0"
}
},
"version": "11.2.19",
"version": "11.2.25",
"description": "__MSG_Description__",
"incognito": "spanning",

@ -1 +1 @@
Subproject commit fa49ecb52140aa80db30a7fa834f6358acc94a13
Subproject commit 7a302d1d181f7d9ef2bbee716c6c850df8cefdad

View File

@ -20,10 +20,10 @@
ns.on("capabilities", event => {
if (ns.allows("script")) {
let name = ns.getWindowName();
if (/[<"'\`(=:]/.test(name)) {
console.log(`NoScript XSS filter sanitizing suspicious window.name "%s" on %s`, name, document.URL);
window.name = window.name.substring(0, window.name.length - name.length);
let dangerousRx = /[<"'\`(=:]/g;
if (/[<"'\`(=:]/.test(window.name)) {
console.log(`NoScript XSS filter sanitizing suspicious window.name "%s" on %s`, window.name, document.URL);
window.name = window.name.replace(dangerousRx, '');
}
}
});