MarcelloTheArcane / netlify-plugin-csp-generator

Generate CSP headers from inline script hashes
GNU General Public License v3.0
27 stars 4 forks source link

Excluding paths from CSP #25

Closed danurbanowicz closed 8 months ago

danurbanowicz commented 8 months ago

The exclude property doesn't appear to exclude the CSP from a path when declared like this:

[plugins.inputs]
   buildDir = "_site"
   reportOnly = false
   exclude = ["/admin/"]

I can see in the generated Netlify _headers file that the excluded /admin/ path appears along with all my other site paths:

/admin/
  Content-Security-Policy: default-src 'self'; connect-src www.google-analytics.com identity.tinajs.io content.tinajs.io assets.tinajs.io; font-src 'self' data: fonts.gstatic.com; img-src 'self' www.google-analytics.com assets.tina.io; script-src 'sha256-32MnMqw9fgeLBnHLKAJbUr+nMlmt7DywP+m1TrkM1kk=' 'self' www.google-analytics.com www.googletagmanager.com; style-src 'self'; frame-ancestors 'none';

Am I declaring and formatting the excluded path correctly? The docs don't provide an example, only stating that the property is an array of paths.

Background: I'm trying to exclude my CSP from being applied to the Tina CMS SPA that runs on my site at /admin/*.

MarcelloTheArcane commented 8 months ago

Hey there, @danurbanowicz!

I use globby for matching paths. If you start the path with /, it gets confused and thinks you mean the root server directory.

I think this should work:

[plugins.inputs]
   buildDir = "_site"
   reportOnly = false
   exclude = ["admin/"]

Let me know if that still doesn't work. I'll add some examples as well, sorry about that.

danurbanowicz commented 8 months ago

Thanks for your help @MarcelloTheArcane !

I'd like to exclude all child paths of the /admin/ directory from the CSP i.e. my react CMS application.

I was hoping that I could set a wildcard path e.g. admin/**/* to exclude all child paths, but it doesn't work; the CSP is still applied and I see the errors reported.

As a test I've tried to exclude a specific path by declaring it fully, but again, the CSP is still applied when accessing that path:-

Path to exclude: /admin/#/collections/edit/project/Beautiful-City

[plugins.inputs]
   buildDir = "_site"
   reportOnly = false
   exclude = ["admin/#/collections/edit/project/Beautiful-City"]

And the following wildcard doesn't work either:-

[plugins.inputs]
   buildDir = "_site"
   reportOnly = false
   exclude = ["admin/**/*"]

Not sure what I'm doing wrong here.

MarcelloTheArcane commented 8 months ago

Hmm, this is a bit tricky. I'm not familiar with Tina CMS, so I'm shooting in the dark here. I've just created a Tina repository, and it looks like they use next (again, not familiar!), which uses a different buildDir.

If you go to the Deploy file browser at the bottom of the latest deploy, is the buildDir the same as the root folder?

image

In my test, this is set to .next, and seems to be working as expected with the latest build (1.6.1):

[[plugins]]
package = "netlify-plugin-csp-generator"

  [plugins.inputs]
- buildDir = "_site"
+ buildDir = ".next"
+ debug = true
  exclude = ["admin/**"]

  [plugins.inputs.policies]
    defaultSrc = "'self'"

Also, this latest version has a new debug property, which logs all the files that are matched and excluded to the console, which might help with solving this issue:

image

If this still doesn't work, and your configuration is a bit different to the default, let me know.

danurbanowicz commented 8 months ago

Thanks @MarcelloTheArcane for your help!

My output folder is not Next.js specific, it's just _site and my /admin/ folder containing the CMS is output inside there.

However, bumping the version to 1.6.1 seems to have fixed it with no other changes; my /admin/ folder and all child paths are now excluded from the CSP and no errors are shown.

Here's my config:

[[plugins]]
  package = "netlify-plugin-csp-generator"

  [plugins.inputs]
    buildDir = "_site"
    reportOnly = true
    debug = true
    exclude = ["admin/**/*"]

  [plugins.inputs.policies]
    defaultSrc = "'self'"
    styleSrc = "'self'"
    scriptSrc = "'self' www.google-analytics.com www.googletagmanager.com"
    fontSrc = "'self' data: fonts.gstatic.com"
    imgSrc = "'self' www.google-analytics.com assets.tina.io"
    connectSrc = "www.google-analytics.com identity.tinajs.io content.tinajs.io assets.tinajs.io"
    frameAncestors = "'none'"

And here's a segment from the build output with debugging turned on:

11:39:32 AM: netlify-plugin-csp-generator (onPostBuild event)              
11:39:32 AM: ────────────────────────────────────────────────────────────────
11:39:32 AM: ​
11:39:32 AM: Excluding 1 file
11:39:32 AM: Found 11 HTML files
11:39:32 AM: Lookup: [ "_site/**/**.html", "!_site/admin/**/*" ]
11:39:32 AM: Paths: [
11:39:32 AM:   "_site/404.html",
11:39:32 AM:   "_site/index.html",
11:39:32 AM:   "_site/project/beautiful-city/index.html",
11:39:32 AM:   "_site/project/black-sea-conde-nast-traveler/index.html",
11:39:32 AM:   "_site/project/british-gq/index.html",
11:39:32 AM:   "_site/project/fashion-portraits/index.html",
11:39:32 AM:   "_site/project/flower-studies/index.html",
11:39:32 AM:   "_site/project/id-magazine/index.html",
11:39:32 AM:   "_site/project/los-angeles/index.html",
11:39:32 AM:   "_site/project/portraits-teen-vogue/index.html",
11:39:32 AM:   "_site/project/still-lives-ii/index.html"
11:39:32 AM: ]
11:39:32 AM: Excluded 35 paths
11:39:32 AM: Excluded: [
11:39:32 AM:   "_site/admin/index.html",
11:39:32 AM:   "_site/admin/assets/SchemaReference.es-34f7052a.js",
11:39:32 AM:   "_site/admin/assets/brace-fold.es-f2e3735d.js",
11:39:32 AM:   "_site/admin/assets/closebrackets.es-e969742b.js",
11:39:32 AM:   "_site/admin/assets/codemirror.es-52e8b92d.js",
11:39:32 AM:   "_site/admin/assets/codemirror.es2-5884f31a.js",
11:39:32 AM:   "_site/admin/assets/comment.es-39699bae.js",
11:39:32 AM:   "_site/admin/assets/dialog.es-dffe62e7.js",
11:39:32 AM:   "_site/admin/assets/dialog.es2-02b3b4e7.js",
11:39:32 AM:   "_site/admin/assets/foldgutter.es-b6cee46a.js",
11:39:32 AM:   "_site/admin/assets/forEachState.es-b2033c2b.js",
11:39:32 AM:   "_site/admin/assets/hint.es-4b1625d1.js",
11:39:32 AM:   "_site/admin/assets/hint.es2-859b482d.js",
11:39:32 AM:   "_site/admin/assets/index-ccfb8d68.css",
11:39:32 AM:   "_site/admin/assets/index-f07ab0bc.js",
11:39:32 AM:   "_site/admin/assets/index-f49f92a0.js",
11:39:32 AM:   "_site/admin/assets/info-addon.es-c9b2027b.js",
11:39:32 AM:   "_site/admin/assets/info.es-a3e95c20.js",
11:39:32 AM:   "_site/admin/assets/javascript.es-3c6957c5.js",
11:39:32 AM:   "_site/admin/assets/jump-to-line.es-d901ea33.js",
11:39:32 AM:   "_site/admin/assets/jump.es-d04c8e98.js",
11:39:32 AM:   "_site/admin/assets/lint.es-fe7166bb.js",
11:39:32 AM:   "_site/admin/assets/lint.es2-c45d33a6.js",
11:39:32 AM:   "_site/admin/assets/lint.es3-630c6813.js",
11:39:32 AM:   "_site/admin/assets/matchbrackets.es-97d2e827.js",
11:39:32 AM:   "_site/admin/assets/matchbrackets.es2-f53f57e6.js",
11:39:32 AM:   "_site/admin/assets/mode-indent.es-057a4f6a.js",
11:39:32 AM:   "_site/admin/assets/mode.es-c7e7c57a.js",
11:39:32 AM:   "_site/admin/assets/mode.es2-be5e3cac.js",
11:39:32 AM:   "_site/admin/assets/mode.es3-654b5dcd.js",
11:39:32 AM:   "_site/admin/assets/search.es-1c15f5ea.js",
11:39:32 AM:   "_site/admin/assets/searchcursor.es-b1a352a2.js",
11:39:32 AM:   "_site/admin/assets/searchcursor.es2-cbfe7cae.js",
11:39:32 AM:   "_site/admin/assets/show-hint.es-b981493e.js",
11:39:32 AM:   "_site/admin/assets/sublime.es-e2a3eb60.js"
11:39:32 AM: ]
11:39:32 AM: Saved at _site/_headers - 0.31 seconds
11:39:32 AM: ​
11:39:32 AM: (netlify-plugin-csp-generator onPostBuild completed in 319ms)
11:39:32 AM: ​
11:39:32 AM: Deploy site

I'm closing this issue as resolved. Thanks again!