Skip to content

Astro - CSP - Preact #13798

@NepCono

Description

@NepCono

Astro Info

Astro                    v5.4.2
Node                     v20.17.0
System                   Windows (x64)
Package Manager          unknown
Output                   server
Adapter                  @astrojs/netlify
Integrations             @astrojs/mdx
                         astro-icon
                         @astrojs/preact
                         @astrojs/tailwind

If this issue only occurs in one browser, which browser is a problem?

No response

Describe the Bug

Hi, I hope this will not be a duplicate one :-)

I am working with Astro and I am very happy with it. Build a very nice site with as latest a strict required CSP with nonce value each time generated trough middleware, which also sets the required response headers. This works great with Astro and vanilla javascript because <script nonce={Astro.locals.nonce}> ... </script> makes it an inline script, also the inline <style nonce={Astro.locals.nonce}> and that is fine with me, it works as a charm.

However recently I decided that I want to make use of PREACT to make it simplified and using typescript.
But from there things went wrong, the PREACT simple component which I called with was blocked by CSP on the strict policy, (when I am developing I use a more loose policy) so I was very supprised that the strict policy blocked the PREACT component.

After the some debugging in chrome dev tools I found out that there was Astro inline client script inserted and ofcourse without nonce. So my policy works great, but what I do not understand is why the dynamically inserted client script does not have a nonce.

I read some documentation and this is normal behaviour in Astro, why ?

_Hydration Process

During the hydration process, the initial server-rendered HTML may not include a nonce because the client-side JavaScript is expected to handle the hydration without needing additional security attributes.

The hydration process is designed to seamlessly integrate client-side interactivity without altering the server-rendered content significantly._

I totally agree but on the other hand: a inserted dynamically script tag should automatically include the nonce because we have an CSP which demands it. Or am I missing something ?_

How simple could it be to get the nonce through a meta tag or somehing ?

I am using the following policy

const policy = {
		"default-src": ["'self'"],
		"base-uri": ["'self'"],
		"frame-ancestors": ["'self'"],
		"script-src": [
			"'self'",
			`'nonce-${nonce}'`, // Use nonce for inline scripts
			"'strict-dynamic'", // Allow scripts loaded by trusted scripts
			"https:", // Allow scripts from HTTPS sources
			"http:", // Allow scripts from HTTP sources (consider removing for security)
		],
		"style-src": ["'self'", "'unsafe-inline'"], // Consider removing 'unsafe-inline' if possible
		"img-src": ["'self'", "data:", "https:"],
		"font-src": ["'self'", "data:", "https:"],
		"frame-src": ["'self'"],
		"media-src": ["'self'"],
		"form-action": ["'self'"], // Prohibit clickjacking
		"upgrade-insecure-requests": [], // Force HTTPS
		"block-all-mixed-content": [], // Prohibit mixed content
		"connect-src": [
			"'self'",
			"https://api.example.com", // Allow specific API calls
		],
	};

Hope this will bring some light ?

What's the expected result?

I expected it to work :-)

Link to Minimal Reproducible Example

Participation

  • I am willing to submit a pull request for this issue.

Metadata

Metadata

Assignees

No one assigned

    Labels

    needs triageIssue needs to be triaged

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions