Description
Hi Astro-Shield Maintainers!
Thanks a lot for building and maintaining Astro-Shield! It has helped me integrating CSP into my static websites.
I recently came across a very specific issue where CSP is at odds with inline style of code syntax highlighting in Astro. Here's the breakdown:
-
Astro's code syntax highlighting (such as pre-bundled shiki or astro-expressive-code) produces the HTML output where
<span>
tokens that contains inline styles.Here is one example:
<!DOCTYPE html> <style integrity="sha256-U8bvsLpPRBV22VuGGYvK6SKOwuWuIrN5tvO8jY6oZC8=">.example{font-size:18px} </style> <div class="example">Hello!</div> <pre class="astro-code github-dark" style="background-color:#24292e;color:#e1e4e8; overflow-x: auto;" tabindex="0" data-language="python"><code><span class="line"><span style="color:#F97583">def</span><span style="color:#B392F0"> greet</span><span style="color:#E1E4E8">():</span></span> <span class="line"><span style="color:#79B8FF"> print</span><span style="color:#E1E4E8">(</span><span style="color:#9ECBFF">"Hello, World!"</span><span style="color:#E1E4E8">)</span></span> <span class="line"></span></code></pre>
-
I use Astro-Shield to generate SRI hashes and also use its Netlify integration to generate
_headers
file which, according to my understanding, contains generated CSP headers for each of the pages.For completeness, my configuration looks like the following:
shield({ securityHeaders: { enableOnStaticPages: { provider: "netlify" }, contentSecurityPolicy: { cspDirectives: { "default-src": "'none'", "script-src": "'self'", "style-src": "'self' 'unsafe-inline'", "img-src": "'self' data:", "font-src": "'self' data:", "frame-src": "'self' https://www.youtube-nocookie.com", "form-action": "'self'", "frame-ancestors": "'self'", "base-uri": "'self'", "worker-src": "'self'", "manifest-src": "'self'", "upgrade-insecure-requests": "", }, }, }, }),
and the generated
_headers
(partial):/example/index.html content-security-policy: base-uri 'self'; default-src 'none'; font-src 'self' data:; form-action 'self'; frame-ancestors 'self'; frame-src 'self' https://www.youtube-nocookie.com; img-src 'self' data:; manifest-src 'self'; script-src 'none'; style-src 'self' 'sha256-U8bvsLpPRBV22VuGGYvK6SKOwuWuIrN5tvO8jY6oZC8=' 'sha256-xYqUZvluhUpsRy3UdguVrRB9kJjgiW47MPZjSxEi6TI=' 'unsafe-inline'; worker-src 'self'
The only thing to note from the above is this part:
style-src 'self' 'sha256-U8bvsLpPRBV22VuGGYvK6SKOwuWuIrN5tvO8jY6oZC8=' 'sha256-xYqUZvluhUpsRy3UdguVrRB9kJjgiW47MPZjSxEi6TI=' 'unsafe-inline';
-
Deploying this website (minimal example) on Netlify results in syntax highlighting missing their colors. The browser tells me that
'unsafe-inline'
understyle-src
is ignored because SRI hashes (or nonce) exist. That's obvious my website contains<style>
tags in other parts of the page, thus the hash was generated.
Obviously, everything is working as intended. However, I wish that Astro-Shield provides some more granular control via config over how SRI hashes are injected into CSP headers. Particularly
An option to leave
style-src
untouched when generating CSP headers so that my website can use'unsafe-inline'
. For example:shield({ securityHeaders: { enableOnStaticPages: { provider: "netlify" }, contentSecurityPolicy: { cspDirectives: { "default-src": "'none'", "script-src": "'self'", "style-src": "'self' 'unsafe-inline'", "img-src": "'self' data:", "font-src": "'self' data:", "frame-src": "'self' https://www.youtube-nocookie.com", "form-action": "'self'", "frame-ancestors": "'self'", "base-uri": "'self'", "worker-src": "'self'", "manifest-src": "'self'", "upgrade-insecure-requests": "", }, modifyCspDirectives: { // <-- added "script-src": true, "style-src": false, } }, }, }),
I know that 'unsafe-inline'
is not the best settings to use, but using it only for style-src:
but not script-src:
is an acceptable risk for me. (HTTP Observatory also seems to strongly concern more about script-src:
.)
Any tips, suggestions, or workaround is also appreciated.
Activity