WebAssembly: disable some APIs under CSP
https://bugs.webkit.org/show_bug.cgi?id=173892
<rdar://problem/32914613>
Reviewed by Daniel Bates.
Source/JavaScriptCore:
We should disable parts of WebAssembly under Content Security
Policy as discussed here:
https://github.com/WebAssembly/design/issues/1092
Exactly what should be disabled isn't super clear, so we may as
well be conservative and disable many things if developers already
opted into CSP. It's easy to loosen what we disable later.
This patch disables:
- WebAssembly.Instance
- WebAssembly.instantiate
- WebAssembly.Memory
- WebAssembly.Table
And leaves:
- WebAssembly on the global object
- WebAssembly.Module
- WebAssembly.compile
- WebAssembly.CompileError
- WebAssembly.LinkError
Nothing because currently unimplmented:
- WebAssembly.compileStreaming
- WebAssembly.instantiateStreaming
That way it won't be possible to call WebAssembly-compiled code,
or create memories (which use fancy 4GiB allocations
sometimes). Table isn't really useful on its own, and eventually
we may make them shareable so without more details it seems benign
to disable them (and useless if we don't).
I haven't done anything with postMessage, so you can still
postMessage a WebAssembly.Module cross-CSP, but you can't
instantiate it so it's useless. Because of this I elected to leave
WebAssembly.Module and friends available.
I haven't added any new directives. It's still unsafe-eval. We can
add something else later, but it seems odd to add a WebAssembly as
a new capability and tell developers "you should have been using
this directive which we just implemented if you wanted to disable
WebAssembly which didn't exist when you adopted CSP". So IMO we
should keep unsafe-eval as it currently is, add WebAssembly to
what it disables, and later consider having two new directives
which do each individually or something.
In all cases I throw an EvalError *before* other WebAssembly
errors would be produced.
Note that, as for eval, reporting doesn't work and is tracked by
https://webkit.org/b/111869
- runtime/JSGlobalObject.cpp:
(JSC::JSGlobalObject::JSGlobalObject):
- runtime/JSGlobalObject.h:
(JSC::JSGlobalObject::webAssemblyEnabled):
(JSC::JSGlobalObject::webAssemblyDisabledErrorMessage):
(JSC::JSGlobalObject::setWebAssemblyEnabled):
- wasm/js/JSWebAssemblyInstance.cpp:
(JSC::JSWebAssemblyInstance::create):
- wasm/js/JSWebAssemblyMemory.cpp:
(JSC::JSWebAssemblyMemory::create):
- wasm/js/JSWebAssemblyMemory.h:
- wasm/js/JSWebAssemblyTable.cpp:
(JSC::JSWebAssemblyTable::create):
- wasm/js/WebAssemblyMemoryConstructor.cpp:
(JSC::constructJSWebAssemblyMemory):
Source/WebCore:
This does the basic separation of eval-blocked and
WebAssembly-blocked, but currently only blocks neither or both. I
think we'll eventually consider allowing one to be blocked but not
the other, so this separation makes sense and means that when we
want to do the change it'll be tiny. At a minimum we want a
different error message, which this patch provides (a lot of the
code ties blocking to the error message).
Tests: http/tests/security/contentSecurityPolicy/WebAssembly-allowed.html
http/tests/security/contentSecurityPolicy/WebAssembly-blocked-in-about-blank-iframe.html
http/tests/security/contentSecurityPolicy/WebAssembly-blocked-in-external-script.html
http/tests/security/contentSecurityPolicy/WebAssembly-blocked-in-subframe.html
http/tests/security/contentSecurityPolicy/WebAssembly-blocked.html
- bindings/js/ScriptController.cpp:
(WebCore::ScriptController::enableWebAssembly):
(WebCore::ScriptController::disableWebAssembly):
- bindings/js/ScriptController.h:
- bindings/js/WorkerScriptController.cpp:
(WebCore::WorkerScriptController::disableWebAssembly):
- bindings/js/WorkerScriptController.h:
- dom/Document.cpp:
(WebCore::Document::disableWebAssembly):
- dom/Document.h:
- dom/ScriptExecutionContext.h:
- page/csp/ContentSecurityPolicy.cpp:
(WebCore::ContentSecurityPolicy::didCreateWindowProxy):
(WebCore::ContentSecurityPolicy::applyPolicyToScriptExecutionContext):
- page/csp/ContentSecurityPolicy.h:
- page/csp/ContentSecurityPolicyDirectiveList.cpp:
(WebCore::ContentSecurityPolicyDirectiveList::create):
- page/csp/ContentSecurityPolicyDirectiveList.h:
(WebCore::ContentSecurityPolicyDirectiveList::webAssemblyDisabledErrorMessage):
(WebCore::ContentSecurityPolicyDirectiveList::setWebAssemblyDisabledErrorMessage):
- workers/WorkerGlobalScope.cpp:
(WebCore::WorkerGlobalScope::disableWebAssembly):
- workers/WorkerGlobalScope.h:
LayoutTests:
These tests are basically the same as eval-blocked, but with
WebAssembly APIs instead of eval.
Disable all of them on iOS simulator which doesn't support
WebAssembly (whereas iOS does).
- http/tests/security/contentSecurityPolicy/WebAssembly-allowed-expected.txt: Added.
- http/tests/security/contentSecurityPolicy/WebAssembly-allowed.html: Added.
- http/tests/security/contentSecurityPolicy/WebAssembly-blocked-expected.txt: Added.
- http/tests/security/contentSecurityPolicy/WebAssembly-blocked-in-about-blank-iframe-expected.txt: Added.
- http/tests/security/contentSecurityPolicy/WebAssembly-blocked-in-about-blank-iframe.html: Added.
- http/tests/security/contentSecurityPolicy/WebAssembly-blocked-in-external-script-expected.txt: Added.
- http/tests/security/contentSecurityPolicy/WebAssembly-blocked-in-external-script.html: Added.
- http/tests/security/contentSecurityPolicy/WebAssembly-blocked-in-subframe-expected.txt: Added.
- http/tests/security/contentSecurityPolicy/WebAssembly-blocked-in-subframe.html: Added.
- http/tests/security/contentSecurityPolicy/WebAssembly-blocked.html: Added.
- http/tests/security/contentSecurityPolicy/resources/WebAssembly-blocked-in-external-script.js: Added.
- platform/ios-simulator/TestExpectations: