Verified Commit c09fdbab authored by Booteille's avatar Booteille

More work on CSP, disable qwant CSP for now

parent 68999722
......@@ -8,7 +8,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
## Unreleased
### Added
- [Invidious] Enforce CSP for qwant.com
- [Invidious] Add `m.youtube.com` to domains to redirect.
- [Nitter] Enforce CSP for embeds
### Fixed
......@@ -18,8 +18,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
### Added
- Updated italian translation, thanks to [@Unbranched](https://gitlab.com/unbranched) for having work on this so fast!
- [Invidious] Added rule for uMatrix to allow `img.youtube.com` images. They are already redirected to Invidious so nothing changed in the code.
- [Invidious] Added `zh-TW` to available interface languages.
- [Invidious] Add rule for uMatrix to allow `img.youtube.com` images. They are already redirected to Invidious so nothing changed in the code.
- [Invidious] Add `zh-TW` to available interface languages.
### Changed
- [Invidious] Now force the display of controls when controls are hidden and autoplay is on false.
......
......@@ -39,6 +39,7 @@ export const config = {
],
toInterceptCSP: [
"www.qwant.com",
"www.youtube-nocookie.com",
],
},
instance: "invidio.us",
......
......@@ -18,32 +18,40 @@ export enum PING_ERROR {
TYPE,
}
export enum FILTER_TYPE {
export enum FILTER {
CSP,
REDIRECT
}
export enum SERVICE {
INVIDIOUS,
NITTER,
CSP,
}
/**
* Generate redirection filters from domains
*
* @param {FILTER_TYPE} type
* @param {FILTER} type
* @param {string} service
* @returns {Promise<unknown[]>}
*/
export const filterDomains = async (type: FILTER_TYPE, service?: string) => {
const domains = type === FILTER_TYPE.CSP ? await domainsToInterceptCSP() : await domainsToRedirect();
const filter = type === FILTER_TYPE.CSP ? "*://*.{d}/*" : "*://{d}/*";
export const filterDomains = async (type: FILTER, service?: SERVICE) => {
const domains = type === FILTER.CSP ? await domainsToInterceptCSP() : await domainsToRedirect();
const invidious = _.map(domains.invidious, (d: string) => filter.replace("{d}", d));
const nitter = _.map(domains.nitter, (d: string) => filter.replace("{d}", d));
const invidious = _.map(domains.invidious, (d: string) => `*://${d}/*`);
const nitter = _.map(domains.nitter, (d: string) => `*://${d}/*`);
const csp = type === FILTER.CSP ? _.map(domains.csp, (d: string) => `*://${d}/*`) : [];
if (service === "invidious") {
if (service === SERVICE.INVIDIOUS) {
return invidious;
} else if (service === "nitter") {
} else if (service === SERVICE.NITTER) {
return nitter;
} else if (service === SERVICE.CSP) {
return csp;
}
return _.concat(invidious, nitter);
return FILTER.CSP ? _.concat(invidious, nitter, csp) : _.concat(invidious, nitter);
};
/**
......@@ -53,10 +61,13 @@ export const filterDomains = async (type: FILTER_TYPE, service?: string) => {
export const domainsToInterceptCSP = async () => {
try {
const settings = await SettingsManager.load();
const iDomains = settings.invidious.appSettings.domains;
const nDomains = settings.nitter.appSettings.domains;
return {
invidious: settings.invidious.appSettings.domains.toInterceptCSP,
nitter: settings.nitter.appSettings.domains.toInterceptCSP,
invidious: _.concat(iDomains.toRedirect, settings.invidious.appSettings.instance),
nitter: _.concat(nDomains.toRedirect, settings.nitter.appSettings.instance),
csp: _.concat(iDomains.toInterceptCSP, nDomains.toInterceptCSP),
};
} catch (e) {
console.error(e);
......@@ -73,6 +84,7 @@ export const domainsToRedirect = async () => {
const domains = {
invidious: [],
nitter: [],
csp: [],
};
const settings = await SettingsManager.load();
......@@ -130,6 +142,7 @@ export const error = (message) => {
* Firefox and Icecat does not handle cookies.getAll() in the same manner so here is a workaround.
*
* @param {string} hostname
* @param name
* @returns {Promise<browser.cookies.Cookie[]>}
*/
export const getCookies = async (hostname: string, name?: string) => {
......
......@@ -6,7 +6,7 @@ import * as NitterManager from "./lib/API/nitter";
import * as BackwardCompatibilityManager from "./lib/backward_compatibility";
import {toggleIcon} from "./lib/browser_action";
import {Event} from "./lib/events";
import {canWriteToClipboard, domainToUrl, FILTER_TYPE, filterDomains, info, isEnabled} from "./lib/helpers";
import {canWriteToClipboard, domainToUrl, FILTER, filterDomains, info, isEnabled, SERVICE} from "./lib/helpers";
import {toggleCleanable} from "./lib/page_action";
import * as SettingsManager from "./lib/settings";
......@@ -15,13 +15,9 @@ import * as SettingsManager from "./lib/settings";
* Code inspired from https://github.com/ThomazPom/Moz-Ext-Ignore-X-Frame-Options/
* @param r
*/
const handleCSP = async (r) => {
const injectCSP = async (r) => {
try {
const settings = await SettingsManager.load();
if (!settings.isEnabled) {
return {};
}
info(`Injecting CSP for ${r.url}`);
const headersToDelete = ["content-security-policy", "x-frame-options"];
const sourceFilters = ["http://*", "http://*:*", "https://*", "https://*:*", "file://*"].join(" ");
......@@ -54,6 +50,35 @@ const handleCSP = async (r) => {
}
};
const listenCSP = async (service?: SERVICE) => {
if (browser.webRequest.onHeadersReceived.hasListener(injectCSP)) {
browser.webRequest.onHeadersReceived.removeListener(injectCSP);
}
const urls = await filterDomains(FILTER.CSP, service);
let types = null;
switch(service) {
case SERVICE.CSP:
types = ["main_frame"];
break;
case SERVICE.INVIDIOUS:
types = ["sub_frame", "object"];
break;
case SERVICE.NITTER:
types = ["sub_frame", "object"];
break;
}
const filter = types !== null ? {urls, types} : {urls};
browser.webRequest.onHeadersReceived.addListener(
injectCSP,
filter,
["blocking", "responseHeaders"],
);
};
/**
* Handle Invidious redirections
* @param r
......@@ -63,6 +88,8 @@ const redirectInvidious = async (r) => {
try {
info(`Trying to redirect ${r.url}`);
await listenCSP(SERVICE.INVIDIOUS);
const settings = await SettingsManager.load();
const url = new URL(r.url);
......@@ -86,6 +113,8 @@ const redirectInvidious = async (r) => {
const redirectNitter = async (r) => {
info(`Trying to redirect ${r.url}`);
listenCSP(SERVICE.NITTER);
const newUrl = await NitterManager.generateUrl(new URL(r.url));
info(`Redirecting to ${newUrl.href}`);
......@@ -102,20 +131,8 @@ const redirectNitter = async (r) => {
*/
const redirect = async (r) => {
if (await InvidiousManager.mustRedirect(r)) {
browser.webRequest.onHeadersReceived.addListener(
await handleCSP,
{urls: await filterDomains(FILTER_TYPE.CSP, "invidious"), types: ["sub_frame", "object"]},
["blocking", "responseHeaders"],
);
return await redirectInvidious(r);
} else if (await NitterManager.mustRedirect(r)) {
browser.webRequest.onHeadersReceived.addListener(
await handleCSP,
{urls: await filterDomains(FILTER_TYPE.CSP, "nitter"), types: ["sub_frame", "object"]},
["blocking", "responseHeaders"],
);
return await redirectNitter(r);
}
......@@ -123,20 +140,18 @@ const redirect = async (r) => {
};
const reload = async () => {
if (browser.webRequest.onBeforeRequest.hasListener(await run)) {
if (browser.webRequest.onBeforeRequest.hasListener(await redirect)) {
info("Reloading Invidition");
browser.webRequest.onBeforeRequest.removeListener(await run);
browser.webRequest.onBeforeRequest.removeListener(await redirect);
}
browser.webRequest.onHeadersReceived.addListener(
await handleCSP,
{urls: await filterDomains(FILTER_TYPE.CSP, "invidious"), types: ["main_frame"]},
["blocking", "responseHeaders"],
);
if (!await isEnabled()) {
return {};
}
browser.webRequest.onBeforeRequest.addListener(
await run,
{urls: await filterDomains(FILTER_TYPE.REDIRECT)},
await redirect,
{urls: await filterDomains(FILTER.REDIRECT)},
["blocking"],
);
......@@ -158,19 +173,6 @@ const replaceCSP = (csp, key: string, value: string) => {
) : `${key} ${value}; ${csp}`;
};
/**
* Run background processes
* @param r
* @returns {Promise<{} | {}>}
*/
const run = async (r) => {
if (!await isEnabled()) {
return {};
}
return await redirect(r);
};
try {
browser.runtime.onInstalled.addListener(
BackwardCompatibilityManager.updateOldConfig,
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment