Reputation: 8527
I turned on Content Security Policy on my server with this command in my Apache2-configuration:
Header set Content-Security-Policy-Report-Only "default-src 'self'"
(I set it to ...-Report-Only
to only report errors, without really blocking something while developing.)
This setting produces an error that I don't understand. But I can reproduce it:
This is the simplified html-code:
<!DOCTYPE HTML>
<html lang="en">
<head>
<script src="/js/test.js"></script>
<title>test</title>
</head>
<body></body>
</html>
As you see, no inline-script and no inline-style (no style at all) and a completely empty body.
And here is the Javascript-file test.js:
window.onload = function () {
//create a paragraph with a red text to have some content
//in my "real" problem, this part is very much code (more than 1000 lines)
document.body.innerHTML = '<div id="original"></div><div id="copy"></div>';
var p1 = document.createElement('p');
var t1 = document.createTextNode('some text');
p1.appendChild(t1);
document.getElementById('original').appendChild(p1);
//set some style within this content
p1.style.color = "red";
//-----------------------------------
//make a copy of this content
document.getElementById('copy').innerHTML = document.getElementById('original').innerHTML;
};
This script adds two div's to the body, and inserts a paragraph with a text into one of the divs. Then it changes the color of the text to red. At the end it makes a copy of the content of this div and insert this copy into the other div.
I think I've done all right, but when I open this document in my browser, I get this error reported in the console of Safari:
[Report Only] Refused to apply a stylesheet because its hash, its nonce, or 'unsafe-inline' appears in neither the style-src directive nor the default-src directive of the Content Security Policy.
test.js:0
(the reported line number "0" is obviously not correct)
This is what Opera and Chrome write to the console:
[Report Only] Refused to apply inline style because it violates the following Content Security Policy directive: "default-src 'self'". Either the 'unsafe-inline' keyword, a hash ('sha256-ZBTj5RHLnrF+IxdRZM2RuLfjTJQXNSi7fLQHr09onfY='), or a nonce ('nonce-...') is required to enable inline execution. Note also that 'style-src' was not explicitly set, so 'default-src' is used as a fallback.
window.onload @ test.js:15
(line 15 is the manipulation of innerHTML)
This error appears only, when I set any style to a part of the document (p1.style.color = "red";
) and then make a copy of a part that contains the styled part (copy.innerHTML = original.innerHTML
).
My questions:
I have no realistic chance to change the part where the original is manipulated. All I can change is this line:
document.getElementById('copy').innerHTML = document.getElementById('original').innerHTML;
Sorry, I wasn't clear enough about this:
I do NOT want to change the CSP-Header. There is a good reason, why inline-style has to be forbidden. See XSS attacks and style attributes and similar Questions.
I want:
Upvotes: 7
Views: 40400
Reputation: 2731
Because you are converting from a DOMElement to text(via innerHTML) any elements with modified styles get converted into inline styles. I've included an example to illustrate this.
var el = document.getElementById('sample'),
output = document.getElementById('output'),
affect = document.getElementById('affected');
affect.style.backgroundColor = "#369";
affect.style.color = "#FFF";
output.innerText+=el.innerHTML;
#sample {
margin:10px;
}
#output {
margin: 10px;
}
<div id="sample">
<div id="affected">
Sample DIV
</div>
</div>
<div id="output">
Output:
</div>
Therefore when you set the innerHTML of the copy, you are including the styles that had modified the element as inline styles which violates your policy.
You could technically make a duplicate copy of the DOM element instead, and insert it to the DOM tree directly. For that, take a look at the MDN Documentation for Cloning Nodes. My old answer is still valid in the case the DOM manipulation is not viable.
According to the MDN documentation on CSP you can solve it by sending the following header:
style-src 'unsafe-inline' 'self'; default-src 'self';
Here is the documentation for default-src.
Upvotes: 7