From 6539c72e7e300215ccee9cea38e0fcbaa6f94627 Mon Sep 17 00:00:00 2001 From: Timothy Flynn Date: Wed, 23 Apr 2025 11:14:15 -0400 Subject: [PATCH] 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. --- Libraries/LibWeb/Fetch/Fetching/Fetching.cpp | 7 +++++-- Libraries/LibWeb/Loader/ResourceLoader.cpp | 1 + 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/Libraries/LibWeb/Fetch/Fetching/Fetching.cpp b/Libraries/LibWeb/Fetch/Fetching/Fetching.cpp index 6b89cf63d06..d4e1adee693 100644 --- a/Libraries/LibWeb/Fetch/Fetching/Fetching.cpp +++ b/Libraries/LibWeb/Fetch/Fetching/Fetching.cpp @@ -339,6 +339,7 @@ WebIDL::ExceptionOr> main_fetch(JS::Realm& realm, Infra auto get_response = GC::create_function(vm.heap(), [&realm, &vm, &fetch_params, request]() -> WebIDL::ExceptionOr> { dbgln_if(WEB_FETCH_DEBUG, "Fetch: Running 'main fetch' get_response() function"); + auto const* origin = request->origin().get_pointer(); // -> fetchParams’s preloaded response candidate is not null if (!fetch_params.preloaded_response_candidate().has()) { @@ -358,7 +359,7 @@ WebIDL::ExceptionOr> main_fetch(JS::Realm& realm, Infra // -> request’s current URL’s scheme is "data" // -> request’s mode is "navigate" or "websocket" if ( - (request->origin().has() && request->current_url().origin().is_same_origin(request->origin().get()) && 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 request’s response tainting to "basic". @@ -391,7 +392,9 @@ WebIDL::ExceptionOr> main_fetch(JS::Realm& realm, Infra } // -> request’s current URL’s 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); diff --git a/Libraries/LibWeb/Loader/ResourceLoader.cpp b/Libraries/LibWeb/Loader/ResourceLoader.cpp index 0fd68692691..5deb0abfa38 100644 --- a/Libraries/LibWeb/Loader/ResourceLoader.cpp +++ b/Libraries/LibWeb/Loader/ResourceLoader.cpp @@ -142,6 +142,7 @@ static HTTP::HeaderMap response_headers_for_file(StringView path, Optional