Hubert Schölnast
Hubert Schölnast

Reputation: 8527

"inline-style"-Error with Content Security Policy and Javascript

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;

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:

  1. Understand why my JavaScript code produces an inline-style-error.
  2. A script that doesn't produce such an error.

Upvotes: 7

Views: 40400

Answers (1)

MiltoxBeyond
MiltoxBeyond

Reputation: 2731

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.

Upvotes: 7

Related Questions