WebAssembly / content-security-policy

Other
38 stars 9 forks source link

No way to use WebAssembly on Chrome without 'unsafe-eval' #7

Closed hackcasual closed 3 years ago

hackcasual commented 6 years ago

To give a bit of background, I am a software engineer at Tableau, on our online data visualization tool. We have been targeting WebAssembly for improving visualization interactivity. As part of our security efforts, we have been working on being able to support a restrictive CSP.

Currently chrome disables compileStreaming/instantiateStreaming with CSP on and not allowing 'unsafe-eval'. Other implementations (FF/Safari/Edge) at least allow the streaming versions of the compile/instantiate commands. The 8/8/2017 meeting notes seems to indicate that Chrome is following the original straw proposal. Chrome has implemented 'wasm-eval', but restricted it to apps/extensions.

Either treating the Response object as an origin according to the given CSP or adopting 'wasm-eval' would allow us to move forward.

hackcasual commented 6 years ago

I've put together a quick example here: https://s3.amazonaws.com/webassembly-chrome-csp/csp_test.html

mikesamuel commented 6 years ago

I think the goal was for user-agents to become consistent in how they interpret unsafe-eval and wasm-eval directives. Issue #1 discussed how not to, and issue #2 touches on how to, but I'm not sure if consensus has been reached.

eholk commented 6 years ago

Right now Chrome restricts 'wasm-eval' to web apps because it's not part of the CSP standard. I'm going to try to put together a PR this week to move along the process of making 'wasm-eval' standard, at which point it should be pretty straightforward for Chrome to expose 'wasm-eval' to the web.

hackcasual commented 6 years ago

Awesome.

eholk commented 6 years ago

Out of curiosity, I just tried running your test case on Safari and got:

[Error] TypeError: WebAssembly.instantiateStreaming is not a function. (In 'WebAssembly.instantiateStreaming(fetch('simple.wasm'), importObject)', 'WebAssembly.instantiateStreaming' is undefined)
    Global Code (csp_test.js:3)

Does that match what you see? Based on the table on the Wasm CSP Proposal, Safari should not allow instantiate or instantiateStreaming without 'unsafe-eval'.

jfbastien commented 6 years ago

Safari currently doesn't implement streaming.

eholk commented 6 years ago

I just submitted the PR for 'wasm-eval': https://github.com/w3c/webappsec-csp/pull/293

hackcasual commented 6 years ago

Has there been any movement on this? Looks like the PR has been open for over 4 months now.

binji commented 6 years ago

The CSP proposal stalled out as @eholk has moved on to another team. However, @titzer is starting to help out now.

hackcasual commented 6 years ago

Awesome, thanks for pushing this forward.

twilco commented 6 years ago

So just for the sake of clarity, the end goal here will be to create a CSP that allows WASM without allowing unsafe-eval of everything? I'm also looking at incorporating WebAssembly into my application and ran into this issue, so was hoping unsafe-eval wasn't the only way out.

Also, unrelated question: why do I not receive this warning on Firefox?

titzer commented 6 years ago

@twilco Yes, the proposed wasm-eval (or maybe unsafe-wasm-eval) would be a separate directive that enables WASM code generation independent of JavaScript's eval.

titzer commented 6 years ago

There's a PR #17 to rename the directive. However, for Chrome apps that use extension URLs, we'll likely keep the old directive for some transition time.

uBlock-user commented 5 years ago

So has wasm-unsafe-eval been implemented in chrome and in which version ?

titzer commented 5 years ago

Hi, we've only implemented wasm-eval (preliminary name) in Chrome for extension URLs. The new name wasm-unsafe-eval (and applying to all URLs) has not yet been implemented. Given that this proposal seems to be (slowly) iterating to a decent state, I think we can begin implementation soon.

gorhill commented 5 years ago

Either treating the Response object as an origin according to the given CSP

I wish to be able to use WebAssembly from my extension -- this is already the case for the Firefox version of the extension.

However, I do not plan to use wasm-unsafe-eval if/when it becomes available, as this goes against the spirit of not executing remote code.

What is the reason Chromium can't allow loading of wasm modules from same-origin Response objects? This would solve the issue of loading/executing only same-origin wasm code (i.e. the extension's packaged files) without having to resort to relaxing the default CSP in the manifest.

feross commented 5 years ago

I opened a bug on the Chromium bug tracker for implementing wasm-unsafe-eval: https://bugs.chromium.org/p/chromium/issues/detail?id=948834&can=1&q=wasm-eval Please star it if you're interested in following updates.

robyoder commented 5 years ago

I've filed Support origins and SRI-style hashes in CSP for WebAssembly streaming APIs to address the concerns of @gorhill and myself.

kendraspock commented 5 years ago

Hi there - @hackcasual - I am running into this error when attempting to embed Google Street View in a dashboard in Tableau Online. I am new to coding and am curious if this conversation, particularly what you mentioned about Tableau, has to do with this error and if it's resolvable:

image

TYIA!

hackcasual commented 5 years ago

Hi @kendraspock , that error is a direct result of this. It's a little confusing since it doesn't actually mean Chrome refused to compile the WebAssembly module, it's reporting that if CSP were enabled, it would refuse to compile the module. It's benign.

martinberlin commented 4 years ago

I implemented successfully a compression protocol called Brotli here: http://udpx.fasani.de (It's an old fashioned Chrome app) Even if wasm-eval seems to work I see that on many Web Assembly existing libraries they use eval() so that is a big restriction to use them for me right now. The funny thing is that I had to upload the binary WASM on a server just to give it back with the right CSP:

header("Content-Type: application/wasm");
header("Access-Control-Allow-Origin: *");

otherwise it won't work, but I though apps restrict scripts from remote URLs.

FloodGames commented 3 years ago

image annoyed by this error

brycetham commented 3 years ago

Has there been any update on this? Is the only way to use WebAssembly on websites on Chrome still to add 'unsafe-eval' to the CSP?

fgmccabe commented 3 years ago

There has not been much progress on this in recent years. There is an implementation of wasm-eval for chrome but it is restricted to ChromeOS at the moment. All that being said, it is clear that the priority of this is rising and we are beginning to pick up the dusty threads :)

Poopooracoocoo commented 3 years ago

Argghhh I really want this for Ruffle as a user.

DeanHnter commented 3 years ago

Just encountered the same issues with firefox, edge and chrome whilst trying to use wasm generated by blazor. Its a real stumbling block in moving from local development to production. Im quite surprised that there has'nt been more progression on this front given the push behind languages to adopt WASM compilation. Also im not sure about the adoption rate of browser updates across multiple platforms and regions etc however I am concerned because I assume that when this feature does eventually release there will be an issue where any application you're trying to rollout safely will for a long period of time only be accessible by a minority of browser users.

hackcasual commented 3 years ago

Just encountered the same issues with firefox

Surprised you encountered this in firefox, as far as I know firefox doesn't gate wasm compilation.

hackcasual commented 3 years ago

Now there is technically a way to use WASM on Chrome without unsafe-eval, as long as you can load a worker with unsafe-eval. This bypass doesn't work in Safari. Depending on your security needs, you might want to do something like per agent CSP policy

https://github.com/hackcasual/ChromeWASMCSP

DeanHnter commented 3 years ago

Just encountered the same issues with firefox

Surprised you encountered this in firefox, as far as I know firefox doesn't gate wasm compilation.

It doesent block by default, the issue is if you deploy your application on a server with any kind of csp it seems to occur, though I suppose it's the same as enabling with a local document.

It's also unavoidable since it seems the method of using a js hash as you normally would with javascript in the csp causes it to still get blocked... And these alternative tags being discussed in the this thread when used in the csp also don't allow the execution either... In short csp equals no execution atleast in my tests (which aren't exhaustive as I mentioned).

But generally anywhere I would like to use wasm in production usually requires csps to be defined since security and reputation often are more valuable than performance gains.

whereisaaron commented 3 years ago

Update: If you ignore the Chrome errors below, include unsafe-eval but do not include the wasm-eval Chrome says it requires, and deploy the CSP in enforcing-mode, the error will disappear and the WASM will run anyway.

Am I correct that with Chrome 89 it is impossible to use CSP with WASM? For my Blazor WASM app Chrome warns if I don't add wasm-eval Chrome won't run the WASM code. But if it add wasm-eval and/or wasm-unsafe-eval (in addition to unsafe-eval) Chrome say is will both ignore all those and still won't run WASM because no wasm-eval 🤣

With script-src 'self' 'wasm-eval' 'wasm-unsafe-eval' 'unsafe-eval' 'unsafe-inline' the CSP is basically a no-op policy at this point yet it still can't support WASM.

I appear to be full Catch-22 screwed?

image

fgmccabe commented 3 years ago

Currently, wasm-eval on chrome is only enabled for chrome extensions and chrome apps. However, we are actively working on relaxing this. However (again), since this is dependent on the standards process of two separate committees within W3C, it is going to take time.

whereisaaron commented 3 years ago

Thanks for the background @fgmccabe I'll stay glued for updates!

Some browsers, certainly Firefox, currently allow WASM with unsafe-eval which keeps CSP relevant now, and provides a smooth transition to adding a slightly less 'unsafe' source specifically for WASM. Why isn't that Chrome's approach also? This current Chrome policy just forces people to not have any CSP at all. That doesn't feel like a sane interim position while the committees try to commit 😀

Refs: https://github.com/dotnet/aspnetcore/issues/31190 https://github.com/w3c/webappsec-csp/pull/293 https://github.com/WebAssembly/content-security-policy/issues/29 https://stackoverflow.com/questions/66149707/content-security-policy-blocks-eval-in-blazor-wasm-project-under-nginx https://www.aaron-powell.com/posts/2019-11-27-using-webassembly-with-csp-headers/

whereisaaron commented 3 years ago

This situation is not quite as it appeared (to me). If you include unsafe-eval in a CSP policy in report-only mode, then Chrome warns it will block WASM, as discussed above. But if you ignore the error message and deploy the CSP in enforcing mode anyway, the error disappears and Chrome lets the WASM module run anyway... So it appear unsafe-eval does currently work for Chrome, but Chrome reports some bogus errors in report-only mode, perhaps some confusion by Chrome between web pages and Chrome extensions/apps?

image

So still not the final/ideal solution @fgmccabe but the current workaround does work, just ignore the report-only error.

whereisaaron commented 3 years ago

Further information for misleading errors on Chrome 89: If you switch to enforcing mode with a CSP policy that includes script-src unsafe-eval, then the CSP 'report-only' error saying Chrome will block running WebAssembly goes away, and the WebAssembly runs anyway. However, you will still get this 'issue' in the dev tools claiming your WebAssembly was blocked, and telling you to add 'unsafe-eval' (which of course you already had). Basically all Chrome errors about WebAssembly are bogus and/or misleading. Best ignored.

TL;DR You get this 'issue' below saying your WebAssembly was blocked by CSP, when in fact your WebAssembly was not blocked.

image

whereisaaron commented 3 years ago

@coderanger tracked down a Chrome bug report for the errant behaviors above.👏 The situation remains as per the title of this issue: We have to add script-src unsafe-eval to enable WebAssembly (and that works, despite the errors displayed) until a better, wasm-specific option is available. https://bugs.chromium.org/p/chromium/issues/detail?id=915648

flosse commented 3 years ago

@coderanger tracked down a Chrome bug report for the errant behaviors above.clap The situation remains as per the title of this issue: We have to add script-src unsafe-eval to enable WebAssembly (and that works, despite the errors displayed) until a better, wasm-specific option is available. https://bugs.chromium.org/p/chromium/issues/detail?id=915648

@coderanger Unfortunately that does not work for me, no matter if I use unsafe-eval or wasm-eval. I created a repo to make the problem reproducible: https://github.com/flosse/wasm-browser-extension-test Can you identify the problem or misunderstanding?

fgmccabe commented 3 years ago

Closing

dm17 commented 2 years ago

Considering it is closed, can someone point me to which comment in this thread remedies the situation described here: The Firefox version of uBO makes use of WebAssembly code for core filtering code paths. This is not the case with Chromium-based browsers because this would require an extra permission in the extension manifest which could cause friction when publishing the extension in the Chrome Web Store. -- https://github.com/gorhill/uBlock/wiki/uBlock-Origin-works-best-on-Firefox

fgmccabe commented 2 years ago

A small follow-up. We are 'looking into this'. Not a whole lot to report yet.

rugk commented 2 years ago

@fgmccabe So you were looking into this, is there any result yet? And if you are looking into this, could you probably open this issue again to show that it is "in progress" as you say?

rugk commented 2 years ago

Ah or is not this fixed by https://github.com/w3c/webappsec-csp/pull/293?

Apparently Chrome 97 now supports a directive called wasm-eval.

abishekmuthian commented 2 years ago

@rugk wasm-eval does nothing, At least on Linux x86_64 tested with Chromium v99. Others have mentioned it earlier as well, Currently we're forced use 'unsafe-eval' if we need wasm.

fgmccabe commented 2 years ago

wasm-eval is/was always restricted to chrome extensions and chrome apps. For manifest v3, it will likely not be supported. The correct csp source keyword to use is wasm-unsafe-eval. This has been supported in chrome since m97. A patch to fix it for manifest v3 is rolling out at the moment.

abishekmuthian commented 2 years ago

Thanks for clarifying, wasm-unsafe-eval works for my web app.

naviln commented 2 years ago

wasm-eval is/was always restricted to chrome extensions and chrome apps. For manifest v3, it will likely not be supported. The correct csp source keyword to use is wasm-unsafe-eval. This has been supported in chrome since m97. A patch to fix it for manifest v3 is rolling out at the moment.

Thanks!

ivancuric commented 1 year ago

I've put together a quick example here: s3.amazonaws.com/webassembly-chrome-csp/csp_test.html

Thanks for clarifying, wasm-unsafe-eval works for my web app.

@abishekmuthian I might be missing something but switching the CSP to the following still doesn't work in either Chrome 109, Firefox 109 or Safari 16.2:

<meta http-equiv="Content-Security-Policy" content="script-src 'self' 'wasm-unsafe-eval'">
OnurGumus commented 1 year ago

I noticed lighthouse itself complains about CSP and 'wasm-unsafe-eval' fixes the problem. I wonder the security implications of wasm-unsafe-eval in particular for those who don't use wasm

fgmccabe commented 1 year ago

Can you be more specific? wasm-unsafe-eval is specified to only impact WebAssembly execution

OnurGumus commented 1 year ago

@fgmccabe Sure, I was running lighthouse from dev-tools itself with

script-src 'none';

That was mysteriously lowering the Best Practices score to 92. Then I ran CSP with report only mode and it pointed out the lighthouse tool itself was using web assembly to do its diagnosis.

So I changed it the following and now score is back to 100% :

script-src 'wasm-unsafe-eval';

P.S my page itself doesn't use WASM anywhere.

fgmccabe commented 1 year ago

Got it.