Skip to content

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

Open
@abhabongse

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:

  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.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Assignees

No one assigned

    Labels

    triageTracking: Needs Triage

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions