Medium CVSS 4.3 webkit Bypass 🔧 Commit mapped

Overview

Medium
Severity
4.3
CVSS
No
Exploited ITW
Fixed
Fix Status
DescriptionVisiting a malicious website may lead to address bar spoofing
ComponentWebKit UIProcess
Bug ClassBypass
Tracker294374
Fix commit632a293bf775 (WebKit/WebKit) +12/-0
CWECWE-451
CVSS vectorCVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:U/C:N/I:L/A:N
CISA KEVNot listed
CreditedJaydev Ahire
Disclosed2025-07-29

Background

UIProcess
The trusted WebKit2 process that owns the browser UI, window/page lifecycle and the address bar, as opposed to the sandboxed WebContent process that renders untrusted page content.
PageClient
An abstraction the UIProcess uses to talk to platform-specific view code; concrete subclasses like PageClientImpl (iOS) bridge to the native content view.
createNewPage
The UIProcess path that instantiates and configures a new WebPageProxy in response to content requesting a new window/tab (e.g. window.open).
Picker (iOS)
A native input UI (select-option, date, credential, etc.) presented by the WKContentView and anchored over the current page.
Address bar spoofing
A UI-integrity bug where the URL shown to the user does not match the content or UI actually being displayed, enabling deception.

Root Cause Analysis

WebPageProxy::createNewPage() runs in the UIProcess when web content asks to open a new window (e.g. window.open() or a target=_blank navigation that the client accepts). On iOS, a picker UI (such as a <select> option picker, date picker, or other content-view presented UI) can be open and visually anchored over the current page’s chrome at the moment a new page is requested. Before this patch, createNewPage() proceeded to configure and swap in the new page (setOpenedByDOM(), origin/app-initiated state, etc.) without first dismissing any picker that the outgoing/current content view still owns. The invariant being violated is that transient, page-anchored UI must be torn down before another page can take over the view, so that no picker outlives the page context that spawned it. Because the picker was left presented across the page transition, an attacker could arrange for the picker (or the spacing/layout it forces) to remain on screen while the address bar and page content were replaced, producing a mismatch between the URL shown and the content/UI actually displayed — i.e. address bar spoofing.

The fix adds a call, right before newPage->setOpenedByDOM(), to obtain the current PageClient and invoke dismissAnyOpenPicker(), which on iOS forwards to the content view’s dismissPickersIfNeededWithReason: using PickerDismissalReason::ViewRemoved. A new virtual PageClient::dismissAnyOpenPicker() is introduced with an empty default (no-op on non-iOS ports), and PageClientImpl (iOS) overrides it to actually dismiss pickers. This restores the invariant that opening a new page first dismisses page-anchored picker UI, closing the window during which stale UI could be composited over a page whose URL had changed.

Key insight
Transient, page-anchored UI (an open picker) was allowed to survive a page-open transition because createNewPage() never dismissed it, letting the displayed UI drift out of sync with the address bar; the fix simply forces picker dismissal before the new page takes over the view.

Attack Path

  1. Lure victim to malicious page The victim visits an attacker-controlled origin in Mobile Safari / a WKWebView-based iOS browser.
  2. Present a picker The page triggers a native picker on iOS (e.g. focusing a <select> element or another control whose picker is presented by the content view), so a picker is open and anchored to the current view.
  3. Request a new page during picker presentation While the picker is up, script calls window.open() (or performs a target=_blank navigation) so the UIProcess enters WebPageProxy::createNewPage().
  4. Exploit the missing dismissal Because createNewPage() previously did not dismiss the open picker, the picker (and the display state it forces) persists across the transition to the new page, whose address bar now reflects a different URL.
  5. Achieve address bar spoofing The user sees a trusted-looking or benign URL in the address bar while the on-screen UI/content is controlled by the attacker, enabling phishing or misattribution of displayed content.

Impact Assessment

This is a UI-integrity (spoofing) issue confined to the iOS UIProcess presentation layer, not a memory-safety bug; there is no corruption primitive, no attacker-controlled read/write, and no path to code execution shown by the diff. The realistic impact is deceiving the user about the origin of displayed content, which strengthens phishing and social-engineering attacks but does not by itself compromise the process. Severity is medium precisely because it undermines a security-relevant UI guarantee (the address bar) without granting execution or data-theft primitives on its own.

Changed Functions

FunctionChangeNotes
WebPageProxy::createNewPage
Source/WebKit/UIProcess/WebPageProxy.cpp
modified Adds a call to pageClient()->dismissAnyOpenPicker() immediately before newPage->setOpenedByDOM(), ensuring any open picker is torn down before the new page takes over the view.
PageClient::dismissAnyOpenPicker
Source/WebKit/UIProcess/PageClient.h
added New virtual method with an empty default implementation, so non-iOS ports are unaffected and only ports that need it override the behavior.
PageClientImpl::dismissAnyOpenPicker
Source/WebKit/UIProcess/ios/PageClientImplIOS.mm
added iOS override that calls [contentView() dismissPickersIfNeededWithReason:PickerDismissalReason::ViewRemoved] to actually dismiss any presented picker.
PageClientImpl::dismissAnyOpenPicker (declaration)
Source/WebKit/UIProcess/ios/PageClientImplIOS.h
modified Declares the override of the new PageClient virtual on the iOS PageClientImpl.

Files Changed

  • Source/WebKit/UIProcess/PageClient.h
  • Source/WebKit/UIProcess/WebPageProxy.cpp
  • Source/WebKit/UIProcess/ios/PageClientImplIOS.h
  • Source/WebKit/UIProcess/ios/PageClientImplIOS.mm

Audit Directions

  • Other page-lifecycle transitions in WebPageProxy
    Grep WebPageProxy.cpp for setOpenedByDOM, swapToPage, close, and navigation-commit paths and check each transitions dismisses page-anchored UI; look for other places that should call dismissAnyOpenPicker() but do not.
  • All picker/UI presenters on iOS
    In UIProcess/ios search for dismissPickersIfNeeded, present*Picker, and PickerDismissalReason to enumerate every picker type and confirm each has a dismissal tied to view removal / page change, not only the one covered here.
  • Cross-port parity of the new virtual
    Grep for dismissAnyOpenPicker across UIProcess ports (mac, gtk, wpe) to see whether the empty default hides equivalent stale-UI issues (e.g. popup menus, color/date inputs) that also need dismissal on new-page creation.
  • Spoofing via retained overlays generally
    Look for UI elements presented by the content view (context menus, share sheets, form assistants) that are keyed to the old page and audit whether they are torn down on address-bar-changing events; grep for contentView() present/dismiss pairs.

Original Bug Report

The reporter's bug is still restricted on the tracker.