CloudCannon / pagefind

Static low-bandwidth search at scale
https://pagefind.app
MIT License
3.48k stars 113 forks source link

ReferenceError: url is not defined with Content-Security-Policy enabled #21

Closed vanbroup closed 2 years ago

vanbroup commented 2 years ago

I'm trying to enable pagefind with Content-Security-Policy enabled and run into the following error:

pagefind.js:1 
  Uncaught (in promise) ReferenceError: url is not defined
    at Pagefind.loadWasm (pagefind.js:1:12922)
    at async Promise.all (/blog/index 0)
    at async Pagefind.init (pagefind.js:1:12207)
loadWasm @ pagefind.js:1
await in loadWasm (async)
Pagefind @ pagefind.js:1
(anonymous) @ pagefind.js:1

Hugo config:

server:
  headers:
  - for: /**
    values:
      X-Frame-Options: DENY
      X-Content-Type-Options: nosniff
      Referrer-Policy: strict-origin-when-cross-origin
      Permissions-Policy: document-domain=()
      Content-Security-Policy: default-src 'none'; img-src 'self' data:; form-action 'self'; base-uri 'self'; 
          block-all-mixed-content;
          style-src 'unsafe-inline' 'self' https://cdn.jsdelivr.net/npm/bootstrap@5.0.2/dist/css/bootstrap.min.css https://fonts.googleapis.com/css;
          font-src https://fonts.gstatic.com/s/roboto/;
          script-src 'self' https://cdn.jsdelivr.net/npm/bootstrap@5.0.2/dist/js/bootstrap.bundle.min.js https://cdn.jsdelivr.net/npm/mermaid/dist/mermaid.min.js;
          frame-src https://www.youtube-nocookie.com/ https://player.vimeo.com/;
          media-src https://i.ytimg.com https://www.rovid.nl/def/dco/2016/def-dco-20160823-idoa9bivg-web-hd.mp4;
          connect-src ws://localhost:1313/livereload 'self';

The connect-src option of the Content-Security-Policy is set to self which permits the script to connect (without this option you would get a policy error).

** copied the /public/_pagefind directory in my static Hugo folder for testing

This error is also live on: https://pkic.org/blog/

When running without Content-Security-Policy using the build in --serve option, the search runs fine:

hugo; ../pagefind --source ./public/  --serve 
bglw commented 2 years ago

Oops. So it looks like this fetch is failing on line 55: search.js > loadWasm

Unfortunately there's a bug in the catch on line 61 trying to log url which is suppressing the actual error 🤦

I'll fix up that log locally and then see if I can reproduce the CSP error. I don't see why a connect-src 'self' would block a fetch("/_pagefind/wasm.pagefind") request — my suspicions would be it doesn't like the fetch occurring inside an ES6 module, or it doesn't like the fetch of a file without any sane content type 🤔

Keen to hear if you have any ideas on where to look, otherwise I'll keep you posted on what I dig up 🙂

Cheers!

vanbroup commented 2 years ago

I don't think the call is blocked by the CSP as that would give a clear error message, but some context/meta-data might not be provided with this CSP enabled, causing the script to fail.

Sorry, I haven't looked at it in detail yet.

bglw commented 2 years ago

Ah, I see where our issue lays. If I suppress that url error, I get:

CompileError: call to WebAssembly.instantiate() blocked by CSP

Unfortunately (I'm just now learning that) wasm broadly currently gets classified under unsafe-eval.

In the past the only path to get that working has been to allow script-src 'unsafe-eval' in your CSP. There is however a proposal to add a wasm-specific CSP to browsers, which adds a specific script src wasm-unsafe-eval. It's hard to tell how broadly this is supported, but looking at Chrome it appears this has shipped, and testing it in Firefox myself it does work.

So adding script-src 'wasm-unsafe-eval' to your CSP should allow wasm to execute without adding extra permissions to your js.

bglw commented 2 years ago

Bad news — my test site doesn't work in Safari without script-src 'unsafe-eval' ☹️ Looks like wasm-unsafe-eval is on the way for Webkit but isn't stable yet.

vanbroup commented 2 years ago

Setting script-src 'wasm-unsafe-eval' looks to 'solve' the problem for Chrome, Edge and Firefox on both desktop and mobile. It would be great if we don't have to allow any unsafe policies however, unfortunately this does currently seem to be a requirement for WebAssembly.

bglw commented 2 years ago

Agreed that it isn't great. There is some chatter around adding a wasm-src CSP and verifying these files, so I'll check on the status of that in the future. I'll also add a note to the documentation.

bglw commented 2 years ago

I have covered this point in the documentation alongside the latest release, so I'll close this issue for now and keep an eye on CSP/WASM goings on.