Bug 298697

Summary: REGRESSION (Safari 26): Crash in WebProcess due to checkTopOrigin called from WebSWServerConnection::registerServiceWorkerClient with blob urls
Product: WebKit Reporter: dmt021
Component: Service WorkersAssignee: youenn fablet <youennf>
Status: RESOLVED FIXED    
Severity: Normal CC: cdumez, dmt021, webkit-bug-importer, youennf
Priority: P2 Keywords: InRadar
Version: Safari 26   
Hardware: iPhone / iPad   
OS: iOS 26   
Attachments:
Description Flags
demo none

dmt021
Reported 2025-09-10 19:49:43 PDT
Created attachment 476691 [details] demo The setup for the issue is quite complex, but I've created a simplified reproducer, and I'll try to explain it step by step. The reproducer is available here: https://dmt021.github.io/webkit_sw_crash/ https://github.com/DmT021/webkit_sw_crash Steps: 1. We need to create a `text/html` document available via a `blob:` url. Click "Create Blob URL" in the reproducer. This will create a blob URL with the contents of the textarea. 2. The document should contain a lazy loaded resource. In the reproducer it's achieved with an iframe with loading="lazy". 3. Copy the URL, open a new tab and navigate. This should load the page as usual. 4. Scroll down to trigger iframe load. This will crash the WebProcess. Reason: As far as I can tell the issue is due to the combination of a recent commit - https://github.com/WebKit/WebKit/pull/45996 - that added a more sophisticated check to `WebSWServerConnection::registerServiceWorkerClient` and incorrect handling of blob URLs in `RegistrableDomain`/`WTF::URL`. The issue starts in `WebProcessPool::processForNavigation` (https://github.com/WebKit/WebKit/blob/e7c9534ffab0f18047f589e79dd05d23a25271db/Source/WebKit/UIProcess/WebProcessPool.cpp#L2065): ``` Site site { navigation.currentRequest().url() }; ``` The url here is something like "blob:https://example.com/<uuid>" The `Site` constructor calls `RegistrableDomain` constructor which in turn calls `URL::host()`. `URL::host()` returns an empty string and `RegistrableDomain` falls back to "nullOrigin". Then in `WebProcessPool::prepareProcessForNavigation` we send `AddAllowedFirstPartyForCookies` to the Network process with "nullOrigin" (https://github.com/WebKit/WebKit/blob/e7c9534ffab0f18047f589e79dd05d23a25271db/Source/WebKit/UIProcess/WebProcessPool.cpp#L2131). The message is handled by `NetworkProcess::addAllowedFirstPartyForCookies`. When the deferred resource is loaded the WebProcess sends `RegisterServiceWorkerClient` to the Network process. The full bt: ``` (lldb) bt * thread #1, queue = 'com.apple.main-thread', stop reason = breakpoint 2.1 frame #0: 0x000000018e01a69c WebKit`WebKit::WebSWClientConnection::registerServiceWorkerClient(WebCore::ClientOrigin const&, WebCore::ServiceWorkerClientData&&, std::__1::optional<WTF::ObjectIdentifierGeneric<WebCore::ServiceWorkerRegistrationIdentifierType, WTF::ObjectIdentifierThreadSafeAccessTraits<unsigned long long>, unsigned long long>> const&, WTF::String&&) frame #1: 0x0000000190112fd8 WebCore`WebCore::Document::updateServiceWorkerClientData() + 728 * frame #2: 0x00000001908575f8 WebCore`WebCore::DocumentLoader::commitData(WebCore::SharedBuffer const&) + 2768 frame #3: 0x000000018e05f0a0 WebKit`WebKit::WebLocalFrameLoaderClient::committedLoad(WebCore::DocumentLoader*, WebCore::SharedBuffer const&) + 52 frame #4: 0x000000019085f270 WebCore`WebCore::DocumentLoader::commitLoad(WebCore::SharedBuffer const&) + 228 frame #5: 0x00000001909476b8 WebCore`WebCore::CachedRawResource::notifyClientsDataWasReceived(WebCore::SharedBuffer const&) + 268 frame #6: 0x0000000190947198 WebCore`WebCore::CachedRawResource::updateBuffer(WebCore::FragmentedSharedBuffer const&) + 544 frame #7: 0x0000000190916458 WebCore`WebCore::SubresourceLoader::didReceiveBuffer(WebCore::FragmentedSharedBuffer const&, long long, WebCore::DataPayloadType) + 504 frame #8: 0x000000018dfeb0c4 WebKit`WebKit::WebResourceLoader::didReceiveData(IPC::SharedBufferReference&&, unsigned long long) + 1000 frame #9: 0x000000018d8b3040 WebKit`WebKit::WebResourceLoader::didReceiveMessage(IPC::Connection&, IPC::Decoder&) + 1780 frame #10: 0x000000018dfdef30 WebKit`WebKit::NetworkProcessConnection::dispatchMessage(IPC::Connection&, IPC::Decoder&) + 300 frame #11: 0x000000018d7b8280 WebKit`WebKit::NetworkProcessConnection::didReceiveMessage(IPC::Connection&, IPC::Decoder&) + 1064 frame #12: 0x000000018e3304f4 WebKit`IPC::Connection::dispatchMessage(WTF::UniqueRef<IPC::Decoder>) + 896 frame #13: 0x000000018e34925c WebKit`WTF::Detail::CallableWrapper<IPC::Connection::enqueueIncomingMessage(WTF::UniqueRef<IPC::Decoder>)::$_2, void>::call() + 144 frame #14: 0x0000000199880644 JavaScriptCore`WTF::RunLoop::performWork() + 472 frame #15: 0x0000000199881d9c JavaScriptCore`WTF::RunLoop::performWork(void*) + 32 frame #16: 0x000000018044d4dc CoreFoundation`__CFRUNLOOP_IS_CALLING_OUT_TO_A_SOURCE0_PERFORM_FUNCTION__ + 24 frame #17: 0x000000018044d424 CoreFoundation`__CFRunLoopDoSource0 + 168 frame #18: 0x000000018044cbb0 CoreFoundation`__CFRunLoopDoSources0 + 220 frame #19: 0x000000018044bd84 CoreFoundation`__CFRunLoopRun + 760 frame #20: 0x0000000180446e24 CoreFoundation`_CFRunLoopRunSpecificWithOptions + 496 frame #21: 0x00000001810f1cac Foundation`-[NSRunLoop(NSRunLoop) runMode:beforeDate:] + 208 frame #22: 0x00000001810f1e7c Foundation`-[NSRunLoop(NSRunLoop) run] + 60 frame #23: 0x0000000180110e78 libxpc.dylib`_xpc_objc_main + 332 frame #24: 0x0000000180113258 libxpc.dylib`_xpc_main + 60 frame #25: 0x000000018011340c libxpc.dylib`xpc_main + 60 frame #26: 0x00000001d369df6c ExtensionFoundation`ExtensionFoundation._EXRunningLibXPCServiceExtension.resume() -> () + 1148 frame #27: 0x00000001d36363f4 ExtensionFoundation`ExtensionFoundation._EXRunningExtension.start(withArguments: Swift.Optional<Swift.UnsafeMutablePointer<Swift.UnsafePointer<Swift.Int8>>>, count: Swift.Int32) -> Swift.Int32 + 72 frame #28: 0x00000001d362f2f8 ExtensionFoundation`ExtensionFoundation.EXExtensionMain(Swift.Int, Swift.Optional<Swift.UnsafeMutablePointer<Swift.UnsafePointer<Swift.Int8>>>) -> Swift.Int + 636 frame #29: 0x0000000181136ee0 Foundation`NSExtensionMain + 172 frame #30: 0x00000001045c13d0 dyld_sim`start_sim + 20 frame #31: 0x000000010477eb98 dyld`start + 6076 ``` The Network process handles the message and calls `checkTopOrigin` and `allowsFirstPartyForCookies`. At this point the domain in `RegistrableDomain` is correct: ``` (lldb) bt * thread #1, queue = 'com.apple.main-thread', stop reason = instruction step into * frame #0: 0x000000018da08380 WebKit`WebKit::NetworkProcess::allowsFirstPartyForCookies(WTF::ObjectIdentifierGeneric<WebCore::ProcessIdentifierType, WTF::ObjectIdentifierMainThreadAccessTraits<unsigned long long>, unsigned long long>, WebCore::RegistrableDomain const&) frame #1: 0x000000018e293a68 WebKit`WebKit::WebSWServerConnection::checkTopOrigin(WebCore::SecurityOriginData const&) + 164 frame #2: 0x000000018e294544 WebKit`WebKit::WebSWServerConnection::registerServiceWorkerClient(WebCore::ClientOrigin&&, WebCore::ServiceWorkerClientData&&, std::__1::optional<WTF::ObjectIdentifierGeneric<WebCore::ServiceWorkerRegistrationIdentifierType, WTF::ObjectIdentifierThreadSafeAccessTraits<unsigned long long>, unsigned long long>> const&, WTF::String&&) + 84 frame #3: 0x000000018d8b8184 WebKit`WebKit::WebSWServerConnection::didReceiveMessage(IPC::Connection&, IPC::Decoder&) + 6896 frame #4: 0x000000018d9c9f7c WebKit`WebKit::NetworkConnectionToWebProcess::dispatchMessage(IPC::Connection&, IPC::Decoder&) + 1016 frame #5: 0x000000018d7b0fc4 WebKit`WebKit::NetworkConnectionToWebProcess::didReceiveMessage(IPC::Connection&, IPC::Decoder&) + 2252 frame #6: 0x000000018e3304f4 WebKit`IPC::Connection::dispatchMessage(WTF::UniqueRef<IPC::Decoder>) + 896 frame #7: 0x000000018e34925c WebKit`WTF::Detail::CallableWrapper<IPC::Connection::enqueueIncomingMessage(WTF::UniqueRef<IPC::Decoder>)::$_2, void>::call() + 144 frame #8: 0x0000000199880644 JavaScriptCore`WTF::RunLoop::performWork() + 472 frame #9: 0x0000000199881d9c JavaScriptCore`WTF::RunLoop::performWork(void*) + 32 frame #10: 0x000000018044d4dc CoreFoundation`__CFRUNLOOP_IS_CALLING_OUT_TO_A_SOURCE0_PERFORM_FUNCTION__ + 24 frame #11: 0x000000018044d424 CoreFoundation`__CFRunLoopDoSource0 + 168 frame #12: 0x000000018044cbb0 CoreFoundation`__CFRunLoopDoSources0 + 220 frame #13: 0x000000018044bd84 CoreFoundation`__CFRunLoopRun + 760 frame #14: 0x0000000180446e24 CoreFoundation`_CFRunLoopRunSpecificWithOptions + 496 frame #15: 0x00000001810f1cac Foundation`-[NSRunLoop(NSRunLoop) runMode:beforeDate:] + 208 frame #16: 0x00000001810f1e7c Foundation`-[NSRunLoop(NSRunLoop) run] + 60 frame #17: 0x0000000180110e78 libxpc.dylib`_xpc_objc_main + 332 frame #18: 0x0000000180113258 libxpc.dylib`_xpc_main + 60 frame #19: 0x000000018011340c libxpc.dylib`xpc_main + 60 frame #20: 0x00000001d369df6c ExtensionFoundation`ExtensionFoundation._EXRunningLibXPCServiceExtension.resume() -> () + 1148 frame #21: 0x00000001d36363f4 ExtensionFoundation`ExtensionFoundation._EXRunningExtension.start(withArguments: Swift.Optional<Swift.UnsafeMutablePointer<Swift.UnsafePointer<Swift.Int8>>>, count: Swift.Int32) -> Swift.Int32 + 72 frame #22: 0x00000001d362f2f8 ExtensionFoundation`ExtensionFoundation.EXExtensionMain(Swift.Int, Swift.Optional<Swift.UnsafeMutablePointer<Swift.UnsafePointer<Swift.Int8>>>) -> Swift.Int + 636 frame #23: 0x0000000181136ee0 Foundation`NSExtensionMain + 172 frame #24: 0x00000001046d53d0 dyld_sim`start_sim + 20 frame #25: 0x000000010493eb98 dyld`start + 6076 (lldb) p *((*(char***)($x2))+1) (char *) 0x0000000118008614 "dmt021.github.io\U00000001" ``` `allowsFirstPartyForCookies` fails to verify the domain and returns `AllowCookieAccess::Terminate`. https://github.com/WebKit/WebKit/blob/b1a1e18436b5afb8f992c5860b53c5ad618b2f1d/Source/WebKit/NetworkProcess/NetworkProcess.cpp#L468-L495 This leads to the following error messages: ``` /Library/Caches/com.apple.xbs/Sources/WebKit_Sim/Source/WebKit/NetworkProcess/ServiceWorker/WebSWServerConnection.cpp 1010: Invalid message dispatched void WebKit::WebSWServerConnection::checkTopOrigin(const WebCore::SecurityOriginData &) Received an invalid message 'WebSWServerConnection_RegisterServiceWorkerClient' from WebContent process 9, requesting for it to be terminated. ``` The WebProcess revieves the termination message and crashes. I'm also attaching a video with the issue in Safari on iOS 26.0 RC 1. The issue is also reproducible in Safari Technology Preview Release 227 (WebKit 20623.1.5).
Attachments
demo (5.48 MB, video/quicktime)
2025-09-10 19:49 PDT, dmt021
no flags
Alexey Proskuryakov
Comment 1 2025-09-11 17:21:31 PDT
Thank you for the excellent report. I could reproduce the issue.
Radar WebKit Bug Importer
Comment 2 2025-09-11 17:21:42 PDT
youenn fablet
Comment 3 2025-09-16 06:46:29 PDT
EWS
Comment 4 2025-09-17 00:34:05 PDT
Committed 300071@main (6e0660770428): <https://commits.webkit.org/300071@main> Reviewed commits have been landed. Closing PR #50804 and removing active labels.
EWS
Comment 5 2025-09-26 15:23:15 PDT
Committed 297297.478@safari-7622-branch (c8ac5498c9e0): <https://commits.webkit.org/297297.478@safari-7622-branch> Reviewed commits have been landed. Closing PR #3711 and removing active labels.
Note You need to log in before you can comment on or make changes to this bug.