问题
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:
- Why does this error appear? (I want to understand why it reports "inline style" although there is no inline styling)
- How can I avoid this error?
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;
Addendum
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:
- Understand why my JavaScript code produces an inline-style-error.
- A script that doesn't produce such an error.
回答1:
Updated:
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.
Old Answer:
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.
来源:https://stackoverflow.com/questions/42401952/inline-style-error-with-content-security-policy-and-javascript