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

bug: Unable to set strict CSP rules from the header #27880

Closed
3 tasks done
ijsje71 opened this issue Jul 28, 2023 · 13 comments
Closed
3 tasks done

bug: Unable to set strict CSP rules from the header #27880

ijsje71 opened this issue Jul 28, 2023 · 13 comments
Labels

Comments

@ijsje71
Copy link

ijsje71 commented Jul 28, 2023

Prerequisites

Ionic Framework Version

v7.x

Current Behavior

I am currently trying to set strict CSP rules to prevent cross site scripting. One of the requirements that we have is that the CSP policy is set through the request header. I have solved this by adding a nonce in the index.html using a custom plugin in my vite config, which is then filled by the NGINX reverse proxy where the Ionic application is deployed. This eliminated a lot of the CSP errors, but a few still remain. These policy violations are preventing certain Ionic components to load properly. The problem is, however, that these violations come from injected stylesheets in the minified index.js file.

Is there a way to either remove those injected styles from the minified index.js file, or to move these injected styles to a different file, which reference I can then also add a nonce tag to?

I have added base side menu application with the used vite configuration to this URL, so you can see the violations for yourself: https://test.doemeebeslismee.online/folder/Inbox

The listed github repo contains the code of the project (without any of the deployment files)

The relevant parts of the nginx.conf looks like this:
`

server {    
sub_filter_once off;
sub_filter '**CSP_NONCE**' $request_id;

location / {
    autoindex on;
    try_files $uri /index.html; 
    add_header Content-Security-Policy "script-src 'self' 'nonce-$request_id'; style-src 'self' 'nonce-$request_id'; default-src 'self';";
}
}

`

Expected Behavior

I would expect that I am able to add strict CSP policies (so without any unsafe-eval/unsafe-inline values) through the request headers and still would be able to use an Ionic application.

Steps to Reproduce

  1. Go to https://test.doemeebeslismee.online/folder/Inbox
  2. See the CSP violations
  3. Open your console
  4. Select one of the sources of the errors that you see
  5. Notice that there is css directly injected into the index.js minified file.

Code Reproduction URL

https://github.com/ijsje71/blank-sidemenu-project-csp

Ionic Info

Ionic:

Ionic CLI : 7.1.1 (/usr/local/lib/node_modules/@ionic/cli)
Ionic Framework : @ionic/react 7.2.1

Utility:

cordova-res : not installed globally
native-run : not installed globally

System:

NodeJS : v20.3.1 (/usr/local/Cellar/node/20.3.1_1/bin/node)
npm : 9.6.7
OS : macOS Unknown

Additional Information

I found the fix for the vite config plugin here: vitejs/vite#9719 (comment)

@ionitron-bot ionitron-bot bot added the triage label Jul 28, 2023
@liamdebeasi
Copy link
Contributor

Have you tried our CSP guide? https://ionicframework.com/docs/techniques/security#ionic-and-csp

This shows how to use CSP with Ionic.

@liamdebeasi liamdebeasi added the needs: reply the issue needs a response from the user label Jul 28, 2023
@ionitron-bot ionitron-bot bot removed the triage label Jul 28, 2023
@ijsje71
Copy link
Author

ijsje71 commented Jul 31, 2023

I did read this before, but I thought this could only be used when applying the meta tag approach. When reading the method description in VS Code, however, I noticed that this is an alternative to the meta tag.

I have added the setNonce method in the main.tsx as you can see in the git repo, but it is still showing the same errors as it was before. I am having a hard time debugging this, as I cannot find if it successfully inserted the nonce and if NGINX successfully changed the string to the proper nonce value. Did I place the setNonce method in the correct file and if so, can I see the effect of the setNonce method somewhere in my deployed code (or somewhere in the output of the ionic build command)?

I have also updated the URL with the deployment that includes the setNonce method.

@ionitron-bot ionitron-bot bot added triage and removed needs: reply the issue needs a response from the user labels Jul 31, 2023
@liamdebeasi
Copy link
Contributor

The latest commit for setNonce does not actually include the setNonce usage: ijsje71/blank-sidemenu-project-csp@fac19f2

Also, I tried your reproduction and I was unable to get any CSP errors. Can you please ensure that the reproduction has the code required to reproduce the issue?

@liamdebeasi liamdebeasi added the needs: reply the issue needs a response from the user label Jul 31, 2023
@ionitron-bot ionitron-bot bot removed the triage label Jul 31, 2023
@ijsje71
Copy link
Author

ijsje71 commented Aug 1, 2023

I have committed the correct main.tsx file in the code reproduction repo. The deployed version on the test URL did have the setNonce included.

Did you set the CSP headers on the NGINX that hosts the reproduction code? I have listed the bare minimum NGINX configuration in the original issue, but I'll add the conf file to the repo as well.

@ionitron-bot ionitron-bot bot added triage and removed needs: reply the issue needs a response from the user labels Aug 1, 2023
@liamdebeasi
Copy link
Contributor

liamdebeasi commented Aug 1, 2023

If this issue only reproduces with an nginx server, then I am going to need instructions on how to get the nginx server set up so I can test this.

I would also make sure that the nonce generated by the server is being passed into the setNonce function before any Ionic components have loaded. In ijsje71/blank-sidemenu-project-csp@bd982ab#diff-1cd8b18798a1a103bfe13bef54354c1f3a3bea29a31c8eea1a0c67a3a839b811R6, that is going to set the nonce to "CSP_NONCE", not the value of the nonce provided by your server.

@liamdebeasi liamdebeasi added the needs: reply the issue needs a response from the user label Aug 1, 2023
@ionitron-bot ionitron-bot bot removed the triage label Aug 1, 2023
@ijsje71
Copy link
Author

ijsje71 commented Aug 2, 2023

I am currently letting NGINX look for the CSP_NONCE string in my code to let it replace it with the nonce string. This way, NGINX should replace the csp_nonce string with the actual string. I'm not sure if there's any other way for NGINX to communicate a request id to the setNonce method, since React cannot pick up on any of the headers set by the NGINX as far as I can tell.

To locally reproduce the issue, follow the following steps:

  1. Install nginx locally (on Mac brew install nginx)
  2. Build the Ionic app
  3. Copy the contents of the dist folder
  4. Go to the webroot directory (on Mac the default is /usr/local/var/www)
  5. Paste the dist folder contents here
  6. Go to the nginx conf location (default Mac: /usr/local/etc/nginx)
  7. Open the nginx.conf file
  8. Replace the not commented server block (the server block listening to port 8080) with the contents of the fontend.conf file
  9. Start the nginx server by executing the following command nginx -g "daemon off;"

Now, you should be able to open the app by navigating to http://localhost:8080 and you should see the remaining CSP errors.

@ionitron-bot ionitron-bot bot added triage and removed needs: reply the issue needs a response from the user labels Aug 2, 2023
@liamdebeasi
Copy link
Contributor

I tested your deployment, and it looks like the nonce value is not correct.

I received the following error in the console:

index-fc0b265e.js:33 Refused to apply inline style because it violates the following Content Security Policy directive: "style-src 'self' 'nonce-31a951da68b87120e25d8ffef648b478'". Either the 'unsafe-inline' keyword, a hash ('sha256-3ewiyoPIApyJinIIn0TnP8UgpcBBGPZRuflC7DYK6K0='), or a nonce ('nonce-...') is required to enable inline execution.

But the nonce that was passed to setNonce was "c9cbb0c3c2972c9c993045aad351b56f" which does not match the expected nonce.

@liamdebeasi liamdebeasi added the needs: reply the issue needs a response from the user label Aug 2, 2023
@ionitron-bot ionitron-bot bot removed the triage label Aug 2, 2023
@ijsje71
Copy link
Author

ijsje71 commented Aug 2, 2023

Where did you find the value that was passed to the setNonce method? I'm having a hard time debugging this because I cannot find what is passed to the setNonce method.

@ionitron-bot ionitron-bot bot added triage and removed needs: reply the issue needs a response from the user labels Aug 2, 2023
@liamdebeasi
Copy link
Contributor

The code is minified, so the function isn't called "setNonce". In index-fc0b265e.jsyou can search for hw( and see that the nonce value is provided there.

@liamdebeasi liamdebeasi added the needs: reply the issue needs a response from the user label Aug 2, 2023
@ionitron-bot ionitron-bot bot removed the triage label Aug 2, 2023
@ijsje71
Copy link
Author

ijsje71 commented Aug 2, 2023

Thanks! Really helps that I can see what's being inserted into the minified code.

It seems that it is generating another nonce for the minified index-fc0b265e.js because it is another network call to the NGINX. What I do not understand, however, is why the error message is trying to compare the nonce in the index-fc0b265e.js to the nonce in the index.html and not the one that's in the response headers coming from the NGINX.

indexHTMLNonce minifiedJSNonce

@ionitron-bot ionitron-bot bot removed the needs: reply the issue needs a response from the user label Aug 2, 2023
@ionitron-bot ionitron-bot bot added the triage label Aug 2, 2023
@liamdebeasi liamdebeasi added the needs: reply the issue needs a response from the user label Aug 2, 2023
@ionitron-bot ionitron-bot bot removed the triage label Aug 2, 2023
@liamdebeasi liamdebeasi added triage and removed needs: reply the issue needs a response from the user labels Aug 2, 2023
@liamdebeasi
Copy link
Contributor

Hey there,

I spoke with the Framework and Stencil teams a bit more about this. Our understanding is there should be a consistent nonce value per page request. Your nginx implementation is returning different nonce values per resource which will not work in this case. In other words, each resource within the same page session is going to need the same nonce.

Stencil, the tool Ionic Framework is built with, only supports two approaches for setting nonce values:

  1. Stencil can detect the nonce off a meta tag and assign it for you (i.e. <meta name="csp-nonce" content="{ your nonce value here }" />).
  2. Alternatively, developers can call setNonce and that will pass the nonce value through the platform and inject it onto the style and script tags.

Stencil has more information regarding this on their docs: https://stenciljs.com/docs/csp-nonce

At the moment, Stencil does not support any sort of automatic detection from response headers. I'm not able to see anything that would indicate this is an Ionic bug, so I am going to close this. If you need more assistance with your nginx configuration for CSP, I recommend posting on the Ionic Forum.

@liamdebeasi liamdebeasi closed this as not planned Won't fix, can't repro, duplicate, stale Aug 3, 2023
@ijsje71
Copy link
Author

ijsje71 commented Aug 4, 2023

The meta tag for the nonce did the trick! The nonce is still generated in the nginx proxy & there are no csp violation errors in the browser anymore.

Thank you for your help!

@ionitron-bot
Copy link

ionitron-bot bot commented Sep 3, 2023

Thanks for the issue! This issue is being locked to prevent comments that are not relevant to the original issue. If this is still an issue with the latest version of Ionic, please create a new issue and ensure the template is fully filled out.

@ionitron-bot ionitron-bot bot locked and limited conversation to collaborators Sep 3, 2023
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
Projects
None yet
Development

No branches or pull requests

2 participants