Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

CSP configuration from astro-shield blocks inline styles of syntax highlighting #140

Open
abhabongse opened this issue Oct 6, 2024 · 0 comments
Labels
triage Tracking: Needs Triage

Comments

@abhabongse
Copy link

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:

  1. 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>
  2. 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'; 
    
  3. Deploying this website (minimal example) on Netlify results in syntax highlighting missing their colors. The browser tells me that 'unsafe-inline' under style-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.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
triage Tracking: Needs Triage
Projects
None yet
Development

No branches or pull requests

2 participants