CVE-2026-9963
Overview
Files Changed
ios/chrome/common/extension_open_url.mm
Patch
From f945e4889aec111612a271adbdc6f63fc881205e Mon Sep 17 00:00:00 2001 From: Andrew Paseltiner <[email protected]> Date: Wed, 22 Apr 2026 06:56:53 -0700 Subject: [PATCH] [iOS] Initialize all arguments in ExtensionOpenURL NSInvocation This CL ensures that all arguments for the openURL:options:completionHandler: selector are explicitly initialized to nil before calling retainArguments on the NSInvocation. Previously, only the first argument (index 2) was set. Leaving the options and completionHandler arguments uninitialized caused retainArguments to dereference garbage memory when attempting to retain the object and block types specified in the method signature, potentially leading to memory corruption. Fixed: 505143241 Change-Id: Ie13f904918d55c00bbc3af604309bce1bdab08bc Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/7785776 Commit-Queue: Andrew Paseltiner <[email protected]> Reviewed-by: Gauthier Ambard <[email protected]> Cr-Commit-Position: refs/heads/main@{#1618840} --- diff --git a/ios/chrome/common/extension_open_url.mm b/ios/chrome/common/extension_open_url.mm index bc8a900..8703440 100644 --- a/ios/chrome/common/extension_open_url.mm +++ b/ios/chrome/common/extension_open_url.mm @@ -20,6 +20,10 @@ open_invocation.target = responder; open_invocation.selector = open_url_selector; [open_invocation setArgument:&url atIndex:2]; + NSDictionary* options = nil; + [open_invocation setArgument:&options atIndex:3]; + void (^completion)(BOOL) = nil; + [open_invocation setArgument:&completion atIndex:4]; [open_invocation retainArguments]; [open_invocation invoke]; return YES;
Original Bug Report
Potential Use of Uninitialized Memory in ExtensionOpenURL via NSInvocation
Flapjack, an experimental security project, has identified the following potential security issue. If you’re a feature owner CC-ed on this bug, please do your best to review these reports without the Chrome Security team. Please see go/chrome-ai-generated-security-bugs-faq for more information.
Overview: The ExtensionOpenURL function in the iOS Share Extension uses NSInvocation without initializing all required arguments. Calling retainArguments on this invocation can cause the Objective-C runtime to operate on uninitialized heap memory. This could potentially allow an attacker to achieve arbitrary code execution within the sandboxed extension process.
Affected files:
ios/chrome/common/extension_open_url.mmios/chrome/share_extension/extended_share_view_controller.mm
Estimated timestamp from git blame: 2024-07-18
Overview
A potential memory corruption vulnerability exists in the ExtensionOpenURL helper function used by Chrome’s iOS extensions. When creating an NSInvocation for the openURL:options:completionHandler: selector, the code fails to initialize the second and third arguments. Because NSInvocation allocates its argument buffer on the heap without zero-initializing it, these argument slots contain residual memory. Calling retainArguments on this invocation causes the runtime to perform objc_retain and Block_copy on garbage pointers, potentially leading to memory corruption and Arbitrary Code Execution (ACE) within the sandboxed extension process.
Code Analysis
In ios/chrome/common/extension_open_url.mm, the ExtensionOpenURL function dynamically invokes the URL opening method to bypass standard extension restrictions:
SEL open_url_selector = @selector(openURL:options:completionHandler:);
// ...
NSMethodSignature* method_signature =
[responder methodSignatureForSelector:open_url_selector];
NSInvocation* open_invocation =
[NSInvocation invocationWithMethodSignature:method_signature];
open_invocation.target = responder;
open_invocation.selector = open_url_selector;
[open_invocation setArgument:&url atIndex:2];
[open_invocation retainArguments];
[open_invocation invoke];
The selector expects three arguments after the implicit self (index 0) and _cmd (index 1):
NSURL *at index 2NSDictionary *at index 3void (^)(BOOL)at index 4
The implementation only explicitly sets the argument at index 2. The memory slots for indices 3 and 4 remain uninitialized. When [open_invocation retainArguments] is called, the Objective-C runtime inspects the method signature, identifies an object at index 3 and a block at index 4, and attempts to retain them to ensure they outlive the invocation. This operation dereferences the uninitialized pointers, passing them to objc_retain. Furthermore, [open_invocation invoke] subsequently passes these garbage pointers to the target responder, which will crash or execute attacker-controlled logic when attempting to access the options dictionary or completionHandler block.
Potential Attack Steps
Note: These are suggested steps based on static analysis, as our tooling agent does not currently have the ability to execute live code or provide a working proof-of-concept.
- An attacker creates a malicious webpage that leverages the Web Share API (
navigator.share()), or a malicious native iOS app that uses the system Share Sheet. - The attacker supplies a carefully crafted, large payload (e.g., text, URLs, or generic data) designed to groom the Share Extension’s heap memory with fake Objective-C objects and controlled pointers.
- The victim triggers the share action and selects the “Chrome” app extension from the iOS Share Sheet.
- iOS spawns the Chrome Share Extension process, allocating the attacker’s payload into the extension’s heap.
- The victim interacts with the extension UI (e.g., tapping “Open in Chrome”), which triggers
ExtendedShareViewController::didTapOpenInChromeShareExtensionSheet:gaiaID:. - This method executes the vulnerable
ExtensionOpenURL()function. The Objective-C runtime dereferences the attacker-controlled heap memory during theretainArgumentsphase, potentially hijacking the instruction pointer.
Suggested Fix
Explicitly initialize all expected arguments of the method signature to nil before calling retainArguments or invoke.
NSDictionary* options = nil;
void (^completion)(BOOL) = nil;
[open_invocation setArgument:&url atIndex:2];
[open_invocation setArgument:&options atIndex:3];
[open_invocation setArgument:&completion atIndex:4];
[open_invocation retainArguments];
[open_invocation invoke];
Evaluated with Chrome root at commit: 4a3e9db74111a3c6c4b3acfd70050a05077cf27a
Results so far have been promising, but there can be wrong deductions. If this proves to be a false positive, please close as WAI; data from false positives will be used to improve accuracy over time. And please feel free to reach out to me directly if you have concerns or feedback on the project.