For my personal website, my main page has a matrix rain canvas effect that I added in buttons to be able to change the color for more interactivity. It worked for a couple days but randomly started giving me this error despite me not changing anything on the page really. This is the error I get:
Refused to execute inline event handler because it violates the following Content Security Policy directive: "script-src-attr 'none'". Either the 'unsafe-inline' keyword, a hash ('sha256-...'), or a nonce ('nonce-...') is required to enable inline execution. Note that hashes do not apply to event handlers, style attributes and javascript: navigations unless the 'unsafe-hashes' keyword is present.
I know this is most likely due to the onclick event but strange as it worked previously. Here is the code to the html for the buttons:
<button type="button" onclick="changeColor('blueviolet')" style="background-color:blueviolet"></button>
<button type="button" onclick="changeColor('#0F0')" style="background-color:#0F0;"></button>
<button type="button" onclick="changeColor('dodgerblue')" style="background-color:dodgerblue"></button>
<button type="button" onclick="changeColor('red')" style="background-color:red"></button>
Here is the code to my javascript code for the onclick function shown above:
function changeColor(newcolor) {
color = newcolor;
let spans = document.getElementsByClassName('spanlink');
let links = document.getElementsByTagName('a');
for(span of spans){
span.style.color = color;
}
for(atag of links){
atag.style.color = color;
}
console.log(`Changed the color to ${color}`);
}
Let me know what's causing this error and how I can fix it
CodePudding user response:
Ditch the onevent attriibutes they are garbage. The example below uses an onevent property. All of the <span>
and <a>
should just share a .class
so it'll be much easier to collect them into a NodeList.
Details are commented in example
/*
If there's more than one event origin
(ie buttons to click), register the event
to an ancestor tag (like document or <main>)
*/ // This is an onevent property
document.body.onclick = changeColor;
/* This is an event listener
Either one can be used but don't use
inline event attributes.
*/
/*
document.body.addEventListener('click', changeColor);
*/
// Event handler passes Event Object
function changeColor(event) {
/*
If the tag that the user clicked (event.target)
has the .colorButton class...
*/
if (event.target.matches('.colorButton')) {
/*
...get it's background-color...
*/
let color = window.getComputedStyle(event.target, null).getPropertyValue('background-color');
/*
Find all tags with class .color and
change each of their text colors to
the same color as the clicked button
*/
let col = document.querySelectorAll('.color');
for (c of col) {
c.style.color = color;
}
}
}
<fieldset>
<legend class='color'>TEST</legend>
TEST
</fieldset>
<a href=# class='color'>TEST</a>
<section>
TEST <b class='color'>TEST</b>
</section>
<button type="button" style="background-color:blueviolet"></button>
<button type="button" style="background-color:#0F0;"></button>
<button type="button" style="background-color:dodgerblue"></button>
<button type="button" style="background-color:red"></button>
CodePudding user response:
Probably the Content-Security-Policy
HTTP header is used in the response serving the html/js you are using in your scenario and that's what changed in your environment and why the behaviour of your page changed.
You can read about it here:
- https://developer.mozilla.org/en-US/docs/Web/HTTP/CSP
- https://content-security-policy.com/script-src/
And it makes an example saying that if you have a policy like this:
script-src 'self' https://js.example.com;
It will allow things like this:
<!-- allowed by 'self' -->
<script src="/js/some-file.js"></script>
<!-- allowed by https://js.example.com -->
<script src="https://js.example.com/file.js"></script>
But it won't allow this:
<script src="https://attacker.example.com/file.js"></script>
And in general (more relevant to your case):
The execution of all JS event handlers from inline HTML markup are blocked default, onclick, onl oad, onm ouseover, onsubmit, etc. You can get them to work via a 'unsafe-hashes' source list expression, however that is only supported on CSP Level 3 browsers.
How to make things work anyway? You may try using addEventHandler via js at first using handlers defined in the same page just to cut off any (yet) unknown scenario when loading external js, just for the sake of getting rid of the noise and landing to a solution as quickly as possible before attempting to better refactor.
Or there's the chance to define that policy in the <meta>
element like the MDN doc (in the link I shared above) shows in an example:
<meta http-equiv="Content-Security-Policy"
content="default-src 'self'; img-src https://*; child-src 'none';">