Work-around for CSP not being honored when the HEAD element has not been inserted yet.
This commit is contained in:
parent
26470b84f6
commit
1814bfa03d
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
|
|
@ -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()) {
|
||||
|
|
|
@ -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");
|
||||
|
|
Loading…
Reference in New Issue