RESOLVED FIXED325394
[ATSPI] Unsandboxed web process crashes with RELEASE_ASSERT(!m_isConnecting) in AccessibilityAtspi::registerObject() when it cannot own its a11y bus name (e.g. Web Inspector in Flatpak)
https://bugs.webkit.org/show_bug.cgi?id=325394
Summary [ATSPI] Unsandboxed web process crashes with RELEASE_ASSERT(!m_isConnecting) ...
Fujii Hironori
Reported 2026-09-26 20:38:20 PDT
(This report was written on my behalf by Claude Opus 5.5.) A web process that is not running in a sandbox (e.g. the Web Inspector frontend process in a Flatpak app) crashes when an element loses focus because it is removed from the DOM: ASSERTION FAILED: !m_isConnecting Source/WebCore/accessibility/atspi/AccessibilityAtspi.cpp(375) : String WebCore::AccessibilityAtspi::registerObject(...) It happens with a WPE WebKit based browser (wig) running in Flatpak. When I open Web Inspector and click around in it, the inspector process crashes almost immediately. Backtrace (WebKit 321483@main): #3 WTFCrashWithInfo(int, char const*, char const*) #4 WebCore::AccessibilityAtspi::registerObject(...) #5 WebCore::AccessibilityObjectAtspi::registerObject() #6 WebCore::AccessibilityAtspi::stateChanged(WebCore::AccessibilityObjectAtspi&, char const*, bool) #7 WebCore::AXObjectCache::platformHandleFocusedUIElementChanged(...) #8 WebCore::AXObjectCache::handleFocusedUIElementChanged(...) #9 WebCore::Document::setFocusedElement(...) #10 WebCore::Document::adjustFocusedNodeOnNodeRemoval(...) #11 WebCore::Document::nodeWillBeRemoved(WebCore::Node&) #12 WebCore::ContainerNode::removeChild(WebCore::Node&) #13 WebCore::Node::remove() #14 WebCore::jsElementPrototypeFunction_remove(...) ... #32 WebCore::JSEventListener::handleEvent(...) #38 WebCore::Element::dispatchMouseEvent(...) #40 WebCore::EventHandler::handleMousePressEvent(...) #42 WebKit::WebPage::mouseEvent(...) Analysis: 1. The UI process always passes "<app-id>.Sandboxed.WebProcess-<UUID>" as the a11y bus name (WebProcessProxy::platformGetLaunchOptions() / WebProcessPool::generateNextAccessibilityBusName()), whether or not the web process is sandboxed. 2. Only a sandboxed web process spawned by flatpak-spawn gets permission to own that name (--sandbox-a11y-own-name). The Web Inspector process pool (defaultInspectorProcessPool()) doesn't enable the sandbox (m_sandboxEnabled defaults to false), so the inspector web process is spawned directly inside the app's sandbox. It connects to the a11y bus through the app's xdg-dbus-proxy, which doesn't allow owning that name. Normal web processes can end up in the same state if they are spawned without the sandbox. 3. AccessibilityAtspi::didConnect() calls g_bus_own_name_on_connection() with G_BUS_NAME_OWNER_FLAGS_DO_NOT_QUEUE and a null name_lost handler. If the name can't be acquired, didOwnName() is never called, so m_isConnecting stays true forever and m_registry stays null. I confirmed this state in a running inspector web process with gdb: m_isConnecting == true, m_connection != null, and the name isn't on the a11y bus. 4. Because m_registry is null, shouldEmitSignal() always returns true. So the first focus change reaches AccessibilityObjectAtspi::registerObject() -> AccessibilityAtspi::registerObject(), and RELEASE_ASSERT(!m_isConnecting) fails. Why it started happening recently: The broken state in 3 has existed since the name ownership was added (284894@main, Oct 2024). It didn't cause crashes because accessibility was never enabled in the inspector process. Since 320566@main ("AX: When multiple web views share a web process, only one reports correct accessibility bounds"), the accessibility mode is global in the UI process and is broadcast to all web processes. So once accessibility is enabled for the inspected page's (sandboxed) web process, the inspector process gets an AXObjectCache too and hits the assertion. With WebKit 320133@main (before 320566@main), gAccessibilityMode was MainThread in the page process and Off in the inspector process, and the inspector worked fine. With 321483@main (after it), the inspector process crashes after a few clicks. It also crashes the same way with 321997@main (2026-09-26). Possible fixes: - Pass a name_lost handler to g_bus_own_name_on_connection() and reset m_isConnecting (and handle the pending root registrations) when the name can't be owned. In that case either continue without owning a name, or disconnect. - And/or don't try to own a "Sandboxed" name when the web process isn't sandboxed.
Attachments
Radar WebKit Bug Importer
Comment 1 2026-09-26 20:38:29 PDT
Fujii Hironori
Comment 2 2026-09-26 21:44:21 PDT
Fujii Hironori
Comment 3 2026-09-26 21:44:56 PDT
This can be reproduced without Flatpak, with a stock MiniBrowser (GTK, Release, current main), by using a private a11y bus whose policy doesn't allow owning the web process bus name. The crash needs two web processes: one that owns its name and enables accessibility (which is then broadcast to all web processes since 320566@main), and one that can't own its name. A cross-site navigation gives us both, so Web Inspector isn't needed. 1. Two dbus-daemon configs. a11y-allow.conf: <!DOCTYPE busconfig PUBLIC "-//freedesktop//DTD D-Bus Bus Configuration 1.0//EN" "http://www.freedesktop.org/standards/dbus/1.0/busconfig.dtd"> <busconfig> <type>accessibility</type> <listen>unix:tmpdir=/tmp</listen> <auth>EXTERNAL</auth> <policy context="default"> <allow send_destination="*" eavesdrop="true"/> <allow eavesdrop="true"/> <allow own="*"/> </policy> </busconfig> a11y-deny.conf is the same plus, inside <policy>: <deny own_prefix="org.webkitgtk.MiniBrowser.Sandboxed"/> 2. Serve two files with "python3 -m http.server 8765": a.html: <!DOCTYPE html><title>A</title><button>hello</button> <script>setTimeout(() => { location.href = 'http://localhost:8765/focus-remove.html'; }, 8000);</script> focus-remove.html: <!DOCTYPE html> <input id="i" autofocus> <script> const i = document.getElementById('i'); i.focus(); setTimeout(() => { document.title = 'removing'; i.remove(); document.title = 'removed'; }, 3000); setTimeout(() => { document.title = 'alive'; }, 5000); </script> 3. Run (e.g. under xvfb-run): cp a11y-allow.conf a11y-live.conf dbus-daemon --config-file=a11y-live.conf --print-address --nofork & # use the printed address below export AT_SPI_BUS_ADDRESS=<address> /usr/libexec/at-spi2-registryd & WEBKIT_DISABLE_SANDBOX_THIS_IS_DANGEROUS=1 Tools/Scripts/run-minibrowser --gtk --release http://127.0.0.1:8765/a.html & # Walk the a11y tree with any AT on the same bus (accerciser, or a pyatspi script # that iterates Atspi.get_desktop(0)) so that the first web process enables accessibility. # Within 8 seconds (before a.html navigates away): cp a11y-deny.conf a11y-live.conf gdbus call -a "$AT_SPI_BUS_ADDRESS" -d org.freedesktop.DBus -o /org/freedesktop/DBus -m org.freedesktop.DBus.ReloadConfig a.html then navigates to localhost, a new web process is spawned, it inherits the accessibility mode but can't own "org.webkitgtk.MiniBrowser.Sandboxed.WebProcess-<UUID>", and it crashes at load completion: WTFCrashWithInfo WebCore::AccessibilityAtspi::registerObject(...) WebCore::AccessibilityObjectAtspi::registerObject() WebCore::AccessibilityAtspi::stateChanged(...) WebCore::AXObjectCache::frameLoadingEventPlatformNotification(...) WebCore::AXObjectCache::frameLoadingEventNotification(...) WebCore::FrameLoader::checkLoadCompleteForThisFrame(...) It's the same RELEASE_ASSERT(!m_isConnecting) as in the Flatpak inspector case, reached from a different caller. It crashed on every run. With the fix in https://github.com/WebKit/WebKit/pull/75040, the web process instead logs "Can't own name ... on a11y bus", and focus-remove.html runs to the end without crashing (3 runs). — Written by Claude Opus 5.5
EWS
Comment 4 2026-09-27 21:35:08 PDT
Committed 322028@main (08a38d85de0f): <https://commits.webkit.org/322028@main> Reviewed commits have been landed. Closing PR #75040 and removing active labels.
Note You need to log in before you can comment on or make changes to this bug.