I employ a rather focused CSP on my website which forbids a lot of common XSS vectors like inline styling. This creates problems with multiple features in the theme, notably the Medium-like zoom effect. medium-zoom.min.js creates a style tag in code but does not set a nonce which means I cannot whitelist it without relying on a potentially flaky sha256 sum that will require changing everytime the script is updated.
The way I see we can fix this with minimal effort is this:
script tag for medium-zoom.min.js with a Hugo pipe (example] that handles minification and gives us the additional bonus of cache busting via unique URLs as well as implements SRI Thanks for pointing this out. I am totally with you, that his has to be fixed, in the light of the possible attach vectors and also the increasingly difficult maintenance the current approach causes.
I will try to change the processing of all the locally hosted js content to Hugo pipes and make the necessary changes, like you stated. Your approach looks correct to me and it shouldn't be too much effort.
If it's any help I'm more than happy to split the subtasks here to make this go faster.
Hi there, Thanks for your offer.
I'd started working on this and created a new branch for addressing this issue.
The only thing that is still really giving me headaches, is how to securely and dynamically generate the nonce. Just setting a static nonce, which would then be added to the CSP, would lead to a security almost insecure as allowing unsafe-inline.
The problematic code section seems to be this one:
function styleInject(css, ref) {
if (ref === void 0) ref = {};
var insertAt = ref.insertAt;
if (!css || typeof document === "undefined") {
return;
}
var head = document.head || document.getElementsByTagName("head")[0];
var style = document.createElement("style");
style.type = "text/css";
if (insertAt === "top") {
if (head.firstChild) {
head.insertBefore(style, head.firstChild);
} else {
head.appendChild(style);
}
} else {
head.appendChild(style);
}
if (style.styleSheet) {
style.styleSheet.cssText = css;
} else {
style.appendChild(document.createTextNode(css));
}
}
var css = ".medium-zoom-overlay{position:fixed;top:0;right:0;bottom:0;left:0;opacity:0;transition:opacity .3s;will-change:opacity}.medium-zoom--opened .medium-zoom-overlay{cursor:pointer;cursor:zoom-out;opacity:1}.medium-zoom-image{cursor:pointer;cursor:zoom-in;transition:transform .3s cubic-bezier(.2,0,.2,1)!important}.medium-zoom-image--hidden{visibility:hidden}.medium-zoom-image--opened{position:relative;cursor:pointer;cursor:zoom-out;will-change:transform}";
styleInject(css);
return mediumZoom;
As I 've already included the css anyways, I don't see a reason for dynamically injecting it once more.
What do you think? Would that resolve your CSP issue?
Hi there, Thanks for your offer.
I'd started working on this and created a new branch for addressing this issue.
The only thing that is still really giving me headaches, is how to securely and dynamically generate the nonce. Just setting a static nonce, which would then be added to the CSP, would lead to a security almost insecure as allowing
unsafe-inline.
That's true. If a secure nonce is not easy to generate then simply keeping track of the sha256 sum the browser generates upon CSP violations is a good compromise but certainly a manual effort.
The problematic code section seems to be this one:
As I 've already included the css anyways, I don't see a reason for dynamically injecting it once more.
What do you think? Would that resolve your CSP issue?
If the CSS is already included then yes there's no need to dynamically inject it. I'm pretty sure that'll also resolve the CSP problem. I'll pull your branch and confirm that in just a second.
The new branch is _almost_ perfect! The final CSP violation is here
Thanks for confirming this so quickly. We are definitely getting there! Let me check if this script tag really has to be inline.
w.r.t. https://github.com/lxndrblz/anatole/commit/8ecb2e1c1dbfa5b4619267333b7a26af776c7cbb#diff-929a8a6e57dacfcbc3ef2392954dc249R11, it's probably worthwhile to use resources.Concat for js/jquery-appear.js and js/jquery-migrate.js to avoid an extra network request. Putting all three together will make the request too large and prone to delaying the TTI metric. In the future the possibility of not using jQuery at all should probably also be considered in the interest of raw page size.
Nicely spotted. That should be easy to fix.
I've just moved this remaining code block also to the corresponding js file and also concatenated the s/jquery-appear.js and js/jquery-migrate.js. I can't think of any other CSP issues. Would you mind verifying?
I can now fully pass CSP with this policy!
Content-Security-Policy "
base-uri 'self';
connect-src 'self';
default-src 'self';
frame-ancestors 'none';
font-src 'self' stackpath.bootstrapcdn.com;
img-src 'self';
object-src 'none';
script-src 'self';
style-src 'self' stackpath.bootstrapcdn.com;
"
That's awesome. 馃 Thanks for your contribution. I'll merge the branch to the master.