fix: Content Security Policy patching (#1814)

Co-authored-by: Vendicated <vendicated@riseup.net>
This commit is contained in:
Ryan Cao 2023-10-19 05:44:29 +08:00 committed by GitHub
parent 998ce72f3b
commit e3e5da10a9
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -62,6 +62,10 @@ if (IS_VESKTOP || !IS_VANILLA) {
} catch { } } catch { }
const findHeader = (headers: Record<string, string[]>, headerName: Lowercase<string>) => {
return Object.keys(headers).find(h => h.toLowerCase() === headerName);
};
// Remove CSP // Remove CSP
type PolicyResult = Record<string, string[]>; type PolicyResult = Record<string, string[]>;
@ -73,6 +77,7 @@ if (IS_VESKTOP || !IS_VANILLA) {
result[directiveKey] = directiveValue; result[directiveKey] = directiveValue;
} }
}); });
return result; return result;
}; };
const stringifyPolicy = (policy: PolicyResult): string => const stringifyPolicy = (policy: PolicyResult): string =>
@ -81,31 +86,39 @@ if (IS_VESKTOP || !IS_VANILLA) {
.map(directive => directive.flat().join(" ")) .map(directive => directive.flat().join(" "))
.join("; "); .join("; ");
function patchCsp(headers: Record<string, string[]>, header: string) { const patchCsp = (headers: Record<string, string[]>) => {
if (header in headers) { const header = findHeader(headers, "content-security-policy");
if (header) {
const csp = parsePolicy(headers[header][0]); const csp = parsePolicy(headers[header][0]);
for (const directive of ["style-src", "connect-src", "img-src", "font-src", "media-src", "worker-src"]) { for (const directive of ["style-src", "connect-src", "img-src", "font-src", "media-src", "worker-src"]) {
csp[directive] = ["*", "blob:", "data:", "vencord:", "'unsafe-inline'"]; csp[directive] ??= [];
csp[directive].push("*", "blob:", "data:", "vencord:", "'unsafe-inline'");
} }
// TODO: Restrict this to only imported packages with fixed version. // TODO: Restrict this to only imported packages with fixed version.
// Perhaps auto generate with esbuild // Perhaps auto generate with esbuild
csp["script-src"] ??= []; csp["script-src"] ??= [];
csp["script-src"].push("'unsafe-eval'", "https://unpkg.com", "https://cdnjs.cloudflare.com"); csp["script-src"].push("'unsafe-eval'", "https://unpkg.com", "https://cdnjs.cloudflare.com");
headers[header] = [stringifyPolicy(csp)]; headers[header] = [stringifyPolicy(csp)];
} }
} };
session.defaultSession.webRequest.onHeadersReceived(({ responseHeaders, resourceType }, cb) => { session.defaultSession.webRequest.onHeadersReceived(({ responseHeaders, resourceType }, cb) => {
if (responseHeaders) { if (responseHeaders) {
if (resourceType === "mainFrame") if (resourceType === "mainFrame")
patchCsp(responseHeaders, "content-security-policy"); patchCsp(responseHeaders);
// Fix hosts that don't properly set the css content type, such as // Fix hosts that don't properly set the css content type, such as
// raw.githubusercontent.com // raw.githubusercontent.com
if (resourceType === "stylesheet") if (resourceType === "stylesheet") {
responseHeaders["content-type"] = ["text/css"]; const header = findHeader(responseHeaders, "content-type");
if (header)
responseHeaders[header] = ["text/css"];
} }
}
cb({ cancel: false, responseHeaders }); cb({ cancel: false, responseHeaders });
}); });