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

Specify a nonce for all scripts #223

Merged
merged 1 commit into from
Feb 17, 2023
Merged

Conversation

humphd
Copy link
Contributor

@humphd humphd commented Feb 15, 2023

Fixes #172.

In order to protect our code from XSS attacks, we can add a cryptographically-generated, random string (i.e., a nonce) to each <script nonce="...here...">. This nonce will get recreated by the server on every reload of the page, so only scripts we send from the server can be executed (i.e., the browser will refuse to execute any others, like those injected maliciously).

Making this work in Remix wasn't obvious, and requires a few things:

  1. The Express server code needs to generate a nonce on every load, and pass it down to all the routes via res.locals
  2. The CSP headers need to include this expected nonce via helmetjs, which uses the res.locals to access the value we already generated.
  3. The Remix code needs to get access to the res.locals.nonce value via a getLoaderContext function we pass to createRequestHandler(), see https://remix.run/docs/en/v1/route/loader#context
  4. The Remix root needs to define a loader() function, which accepts the context arg. This includes the nonce value.
  5. The Remix root Document component calls useLoaderData() to access the nonce and passes it as a prop to all the various "script" components, see https://remix.run/docs/en/v1/file-conventions/root

In summary: we generate a nonce in Express, use it in helmetjs to define our CSP headers, then pass it through to Remix to render the script tags in the browser using the nonce.

To test this, try loading the page with the console open, and watch for any CSP issues.

@humphd humphd added this to the Milestone 0.3 milestone Feb 15, 2023
@humphd humphd self-assigned this Feb 15, 2023
@humphd humphd added category: front end Front end part of our web service category: back end Back end part of our web service labels Feb 15, 2023
@Genne23v
Copy link
Contributor

@humphd I don't see any issue on my console. I was expecting to see something like nonce={hexvalue} in scripts, but I see only nonce. Is this expected result?

@humphd
Copy link
Contributor Author

humphd commented Feb 17, 2023

@Genne23v interestingly, the browser hides the nonce value so that it can't be used by scripts: https://stackoverflow.com/questions/55670985/google-chrome-stripping-nonce-values-from-script-tags

Copy link
Contributor

@Genne23v Genne23v left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It works in my local without any errors.

Copy link
Contributor

@Eakam1007 Eakam1007 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good to me

@humphd humphd merged commit a1f5be6 into DevelopingSpace:main Feb 17, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
category: back end Back end part of our web service category: front end Front end part of our web service
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Chakra-UI requires 'unsafe-inline' in CSP for scripts, styles
3 participants