Work-around for CSP not being honored when the HEAD element has not been inserted yet.

This commit is contained in:
hackademix 2018-09-04 19:48:07 +02:00
parent 26470b84f6
commit 1814bfa03d
3 changed files with 15 additions and 35 deletions

View File

@ -5,25 +5,33 @@ class DocumentCSP {
this.document = document;
this.builder = new CapsCSP();
}
apply(capabilities, embedding = CSP.isEmbedType(this.document.contentType)) {
let csp = this.builder;
let blocker = csp.buildFromCapabilities(capabilities, embedding);
if (!blocker) return;
let document = this.document;
let createHTMLElement =
tagName => document.createElementNS("http://www.w3.org/1999/xhtml", tagName);
let header = csp.asHeader(blocker);
let meta = document.createElementNS("http://www.w3.org/1999/xhtml", "meta");
let meta = createHTMLElement("meta");
meta.setAttribute("http-equiv", header.name);
meta.setAttribute("content", header.value);
let parent = document.head || document.documentElement;
let parent = document.head ||
document.documentElement.appendChild(createHTMLElement("head"));
try {
parent.insertBefore(meta, parent.firstChild);
debug(`Failsafe <meta> CSP inserted in the DOM: "%s"`, header.value);
if (capabilities.has("script")) meta.remove();
if (capabilities.has("script")) {
meta.remove();
if (!parent.firstChild) parent.remove();
}
} catch (e) {
error(e, "Error inserting CSP %s in the DOM", header && header.value);
}
}
}

View File

@ -83,19 +83,7 @@ ns.on("capabilities", () => {
});
if (!ns.canScript) {
addEventListener("beforescriptexecute", e => e.preventDefault());
let mo = new MutationObserver(mutations => {
for (let m of mutations) {
console.log(`Mutation `, m);
if (m.type !== "attribute") continue;
if (/^on\w+/i.test(m.attributeName)) {
m.target.removeAttribute(m.attributeName);
} else if (/^\s*(javascript|data):/i.test(m.target.attributes[m.attributeName])) {
m.target.setAttribute(m.attributeName, "#");
}
}
});
// mo.observe(document.documentElement, {attributes: true, subtree: true});
if ("serviceWorker" in navigator && navigator.serviceWorker.controller) {
(async () => {
for (let r of await navigator.serviceWorker.getRegistrations()) {

View File

@ -1,20 +1,4 @@
function onScriptDisabled() {
if (document.URL.startsWith("file:")) {
// file: documents are loaded synchronously and may not be affected by
// CSP. We already intercept onbeforeexecutescript event, let's cope with
// event and URL attributes.
for (let e of document.all) {
for (let a of e.attributes) {
if (/^on\w+/i.test(a.name)) {
debug(`Removed %s.%sevent`, e.tagName, a.name);
a.value = "";
} else if (/^\s*(?:data|javascript):/i.test(unescape(a.value))) {
debug(`Neutralized %s.%s="%s" attribute`, e.tagName, a.name, a.value);
a.value = "data:";
}
}
}
}
for (let noscript of document.querySelectorAll("noscript")) {
// force show NOSCRIPT elements content
let replacement = createHTMLElement("span");