Touffy / client-zip

A client-side streaming ZIP generator
MIT License
349 stars 22 forks source link

[FEATURE] Document CSP Policy required to use Client-Zip #35

Closed mangelozzi closed 2 years ago

mangelozzi commented 2 years ago

Firstly great lib!

Just downloaded the latest version of client-Zip, and using Chrome 100.

Is your feature request related to a problem? Please describe. I can only use the code on local host. When hosted, the problem is the code is blocked by the latest version of Chrome. Researching the problem I added the following to the Content-Secutiry-Policy header:

script-src 'self' 'unsafe-inline' 'wasm-eval'; object-src 'self';

I can see in the headers of the network tab in Chrome the header has been set corretly, however I still get:

Uncaught CompileError: WebAssembly.Module(): Wasm code generation disallowed by embedder
    at client-zip.min.js:1:1840

Why is your feature relevant to client-zip? Many people intend to use this lib with Chrome

Describe the solution you'd like Some documented step in the already grear README about the CSP policy required to use client-zip.

Additional context Thanks!

NOTE: This works but feels a bit over the top:

script-src 'self' 'unsafe-inline' 'wasm-eval' 'unsafe-eval'; object-src 'self';
Touffy commented 2 years ago

It sucks that all these rules are needed to instantiate the WASM module synchronously. I can't store binary code as-is in a JS file, so the binary has to go through a decoding function, and that makes Chrome paranoid because the string appears dynamic. Even though WASM can't do anything nearly as dangerous as dynamic JavaScript.

Obviously, if I put the binary in a separate .wasm file, Chrome would be fine with a basic policy. But then, calling downloadZip straight from the import would require a little more code on my part, because of the asynchronous loading of the WASM. Too bad we don't have async ES modules yet.

Also, it would mean that client-zip is no longer a single-file distribution (indeed, you wouldn't be able to use a bundler to make it single-file without sacrificing the sensible CSP). And you'd probably have to configure your HTTP server to serve WASM with the correct content-type, which could be tricky for beginners — and for cloud platforms that still think IIS is a reasonable component to use in a serverless Node.js stack…

So… yeah, I'm going to think about it a little, see if I can find a smart way to keep things simple, but if those are the two choices, I'd probably recommend using the scary CSP.

Touffy commented 2 years ago

I was wrong about the decoding thing. Since there is not, currently, a way to import a WASM module natively, Chrome considers any use of WASM "unsafe" — even when the HTTP Response is passed directly to instantiateStreaming.

However, Chrome 100 (and a few versions below) should support the less scary wasm-unsafe-eval policy. Try that.