LibWeb: Allow CORS requests from opaque origins to resource:// URLs

JavaScript module requests (in a non-worker context) always have CORS
enabled. However, CORS requests are only allowed for same-origin or
HTTP/S requests. This patch extends this to allow resource:// requests
from opaque origins (e.g. about: URLs).

We must also set the Access-Control-Allow-Origin header to "null" to
ensure that the response is accepted by the CORS checks. This does not
affect requesting resource:// URLs from resource:// URLs as those are
same-origin and skip CORS checks.

This ultimately enables requesting resource:// JS modules from the
about:settings page.
This commit is contained in:
Timothy Flynn 2025-04-23 11:14:15 -04:00 committed by Tim Flynn
parent 5f9b1d3cd4
commit 6539c72e7e
Notes: github-actions[bot] 2025-04-24 00:00:07 +00:00
2 changed files with 6 additions and 2 deletions

View file

@ -339,6 +339,7 @@ WebIDL::ExceptionOr<GC::Ptr<PendingResponse>> main_fetch(JS::Realm& realm, Infra
auto get_response = GC::create_function(vm.heap(), [&realm, &vm, &fetch_params, request]() -> WebIDL::ExceptionOr<GC::Ref<PendingResponse>> {
dbgln_if(WEB_FETCH_DEBUG, "Fetch: Running 'main fetch' get_response() function");
auto const* origin = request->origin().get_pointer<URL::Origin>();
// -> fetchParamss preloaded response candidate is not null
if (!fetch_params.preloaded_response_candidate().has<Empty>()) {
@ -358,7 +359,7 @@ WebIDL::ExceptionOr<GC::Ptr<PendingResponse>> main_fetch(JS::Realm& realm, Infra
// -> requests current URLs scheme is "data"
// -> requests mode is "navigate" or "websocket"
if (
(request->origin().has<URL::Origin>() && request->current_url().origin().is_same_origin(request->origin().get<URL::Origin>()) && request->response_tainting() == Infrastructure::Request::ResponseTainting::Basic)
(origin && request->current_url().origin().is_same_origin(*origin) && request->response_tainting() == Infrastructure::Request::ResponseTainting::Basic)
|| request->current_url().scheme() == "data"sv
|| (request->mode() == Infrastructure::Request::Mode::Navigate || request->mode() == Infrastructure::Request::Mode::WebSocket)) {
// 1. Set requests response tainting to "basic".
@ -391,7 +392,9 @@ WebIDL::ExceptionOr<GC::Ptr<PendingResponse>> main_fetch(JS::Realm& realm, Infra
}
// -> requests current URLs scheme is not an HTTP(S) scheme
if (!Infrastructure::is_http_or_https_scheme(request->current_url().scheme())) {
// AD-HOC: We allow CORS requests for resource:// URLs from opaque origins to enable requesting JS modules from internal pages.
if (!Infrastructure::is_http_or_https_scheme(request->current_url().scheme())
&& !(origin && origin->is_opaque() && request->current_url().scheme() == "resource"sv)) {
// NOTE: At this point all other request modes have been handled. Ensure we're not lying in the error message :^)
VERIFY(request->mode() == Infrastructure::Request::Mode::CORS);