Merge branch 'main' of github.com:hackademix/noscript into ctx
This commit is contained in:
commit
62aac29750
|
@ -315,6 +315,16 @@
|
|||
include("/test/run.js");
|
||||
},
|
||||
|
||||
async testIC(callbackOrUrl) {
|
||||
await include("xss/InjectionChecker.js");
|
||||
let IC = await XSS.InjectionChecker;
|
||||
let ic = new IC();
|
||||
ic.logEnabled = true;
|
||||
return (typeof callbackOrUrl === "function")
|
||||
? await callbackOrUrl(ic)
|
||||
: ic.checkUrl(callbackOrUrl);
|
||||
},
|
||||
|
||||
async savePolicy() {
|
||||
if (this.policy) {
|
||||
await Storage.set("sync", {
|
||||
|
|
|
@ -86,14 +86,18 @@
|
|||
debug("Fetching policy for actual URL %s (was %s)", url, document.URL);
|
||||
}
|
||||
|
||||
debug(`Synchronously fetching policy for ${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 {
|
||||
this.setup(
|
||||
browser.runtime.sendSyncMessage({id: "fetchPolicy", url})
|
||||
);
|
||||
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));
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
|
|
|
@ -8,7 +8,7 @@
|
|||
"strict_min_version": "59.0"
|
||||
}
|
||||
},
|
||||
"version": "11.2.16rc3",
|
||||
"version": "11.2.19",
|
||||
"description": "__MSG_Description__",
|
||||
"incognito": "spanning",
|
||||
|
||||
|
@ -51,7 +51,6 @@
|
|||
"/nscl/common/Permissions.js",
|
||||
"/nscl/common/Policy.js",
|
||||
"/nscl/common/locale.js",
|
||||
"/nscl/common/SyntaxChecker.js",
|
||||
"/nscl/common/Storage.js",
|
||||
"/nscl/common/include.js",
|
||||
"/nscl/service/DocStartInjection.js",
|
||||
|
|
2
src/nscl
2
src/nscl
|
@ -1 +1 @@
|
|||
Subproject commit f04ec6afe193f59ce540f5de9e0d184bf7d8a231
|
||||
Subproject commit fa49ecb52140aa80db30a7fa834f6358acc94a13
|
|
@ -21,7 +21,7 @@
|
|||
if (UA.isMozilla) {
|
||||
let y = async (url, originUrl = '') => await XSS.test({originUrl, url, method: "GET"});
|
||||
let n = async (...args) => !await y(...args);
|
||||
Promise.all([
|
||||
let xssTest = Promise.all([
|
||||
() => y("https://noscript.net/<script"),
|
||||
() => n("https://noscript.net/<script", "https://noscript.net/"),
|
||||
() => y("https://vulnerabledoma.in/char_test?body=%80%3Cscript%3Ealert(1)%3C/script%3E"),
|
||||
|
@ -32,25 +32,25 @@ if (UA.isMozilla) {
|
|||
() => y("https://vulnerabledoma.in/xss_link?url=javascript%26colo%00n%3Balert%u00281%29"),
|
||||
() => y("https://vulnerabledoma.in/xss_link?url=javascript:\\u{%0A6e}ame"),
|
||||
].map(t => Test.run(t))
|
||||
).then(() => Test.report());
|
||||
);
|
||||
|
||||
let invalidCharsTest = async () => {
|
||||
|
||||
await include("xss/InjectionChecker.js");
|
||||
let IC = await XSS.InjectionChecker;
|
||||
let rx = new IC().invalidCharsRx;
|
||||
|
||||
console.log("Testing invalidCharsRx", rx);
|
||||
let x = n => '\\u' + ("0000" + n.toString(16)).slice(-4);
|
||||
function check(ch) {
|
||||
eval(`{let _${ch}_}`);
|
||||
Function(`let _${ch}_`);
|
||||
}
|
||||
let cur = 0x7e;
|
||||
let fail = false;
|
||||
while (cur++ < 0xffff) {
|
||||
while (cur++ < 0xffff && !fail) {
|
||||
let ch = String.fromCharCode(cur);
|
||||
try {
|
||||
check(ch);
|
||||
if (tx.test(ch)) {
|
||||
if (rx.test(ch)) {
|
||||
console.error(x(cur) + " should not test invalid!");
|
||||
fail = true;
|
||||
}
|
||||
|
@ -64,6 +64,10 @@ if (UA.isMozilla) {
|
|||
}
|
||||
return !fail;
|
||||
};
|
||||
|
||||
Test.run(invalidCharsTest, "InjectionChecker.invalidCharsRx").then(Test.report());
|
||||
(async () => {
|
||||
await xssTest;
|
||||
Test.report();
|
||||
await Test.run(invalidCharsTest, "InjectionChecker.invalidCharsRx");
|
||||
Test.report();
|
||||
})();
|
||||
}
|
||||
|
|
|
@ -526,7 +526,15 @@ XSS.InjectionChecker = (async () => {
|
|||
},
|
||||
|
||||
get invalidCharsRx() {
|
||||
let value = new RegExp("^[^\"'`/<>]*[" + this._createInvalidRanges() + "]");
|
||||
let preamble = "^[^\"'`/<>]*";
|
||||
let value;
|
||||
try {
|
||||
// see https://mathiasbynens.be/notes/javascript-identifiers-es6#acceptable-unicode-symbols
|
||||
value = new RegExp(preamble + "[^$_\\p{ID_Start}\\p{ID_Continue}\\u200c\\u200d\\u2028\\u2029]", "u");
|
||||
} catch (e) {
|
||||
// Unicode entities are not supported in Gecko <= 77
|
||||
value = new RegExp(preamble + `[${this._createInvalidRanges()}]`, "u");
|
||||
}
|
||||
Object.defineProperty(Object.getPrototypeOf(this), 'invalidCharsRx', {value});
|
||||
return value;
|
||||
},
|
||||
|
@ -886,7 +894,7 @@ XSS.InjectionChecker = (async () => {
|
|||
l = l.replace(/[^=]*=\s*/i, '').replace(/[\u0000-\u001f]/g, '');
|
||||
l = /^["']/.test(l) ? l.replace(/^(['"])([^]*?)\1[^]*/g, '$2') : l.replace(/[\s>][^]*/, '');
|
||||
|
||||
if (/^(?:javascript|data):|\[[^]+\]/i.test(l) || /[<'"(]/.test(unescape(l)) && await this.checkUrl(l)) return true;
|
||||
if (/^(?:javascript|data):/i.test(l) || /[<'"([]/.test(unescape(l)) && await this.checkUrl(l)) return true;
|
||||
}
|
||||
}
|
||||
return this._rxCheck("HTML", s) || this._rxCheck("Globals", s);
|
||||
|
|
|
@ -117,10 +117,14 @@ var XSS = (() => {
|
|||
|
||||
if (reasons.protectName) {
|
||||
await include("/nscl/service/ContentScriptOnce.js");
|
||||
await ContentScriptOnce.execute(request, {
|
||||
js: [{file: "/xss/sanitizeName.js"}],
|
||||
});
|
||||
if (!block) return ALLOW;
|
||||
try {
|
||||
await ContentScriptOnce.execute(request, {
|
||||
js: [{file: "/xss/sanitizeName.js"}],
|
||||
});
|
||||
if (!block) return ALLOW;
|
||||
} catch (e) {
|
||||
error(e, "Sanitizing name in request", request.url);
|
||||
}
|
||||
}
|
||||
if (reasons.urlInjection) data.push(`(URL) ${unescapedDest}`);
|
||||
if (reasons.postInjection) data.push(`(POST) ${reasons.postInjection}`);
|
||||
|
|
Loading…
Reference in New Issue