CVE-2026-11207
Overview
Changed Functions
| Function | Change | Notes |
|---|---|---|
TEST_Fcomponents/autofill/core/browser/payments/payments_requests/get_bnpl_payment_instrument_for_fetching_url_request_unittest.cc |
modified |
Files Changed
components/autofill/core/browser/payments/payments_requests/get_bnpl_payment_instrument_for_fetching_url_request.cccomponents/autofill/core/browser/payments/payments_requests/get_bnpl_payment_instrument_for_fetching_url_request_unittest.cc
Patch
From 95d627b12d7a51f8f10ed3992463332fb808359c Mon Sep 17 00:00:00 2001 From: Vinny Persky <[email protected]> Date: Fri, 01 May 2026 10:12:26 -0700 Subject: [PATCH] Update BNPL redirects to enforce HTTP/HTTPS scheme This CL ensures BNPL redirects enforce HTTP/HTTPS schemes, to prevent potential malicious usage of the popup flow. Fixed: 506127858 Change-Id: If7c275dd5cfd4debdbb6c4d1e9aec99abd1751f3 Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/7804653 Reviewed-by: Olivia Saul <[email protected]> Commit-Queue: Vinny Persky <[email protected]> Cr-Commit-Position: refs/heads/main@{#1623891} --- diff --git a/components/autofill/core/browser/payments/payments_requests/get_bnpl_payment_instrument_for_fetching_url_request.cc b/components/autofill/core/browser/payments/payments_requests/get_bnpl_payment_instrument_for_fetching_url_request.cc index 14092a48..69a457b 100644 --- a/components/autofill/core/browser/payments/payments_requests/get_bnpl_payment_instrument_for_fetching_url_request.cc +++ b/components/autofill/core/browser/payments/payments_requests/get_bnpl_payment_instrument_for_fetching_url_request.cc @@ -104,6 +104,7 @@ bool GetBnplPaymentInstrumentForFetchingUrlRequest::IsResponseComplete() { return response_details_.redirect_url.is_valid() && + response_details_.redirect_url.SchemeIsHTTPOrHTTPS() && response_details_.success_url_prefix.is_valid() && response_details_.failure_url_prefix.is_valid() && !response_details_.context_token.empty(); diff --git a/components/autofill/core/browser/payments/payments_requests/get_bnpl_payment_instrument_for_fetching_url_request_unittest.cc b/components/autofill/core/browser/payments/payments_requests/get_bnpl_payment_instrument_for_fetching_url_request_unittest.cc index 48854fe9..dc5f22a94 100644 --- a/components/autofill/core/browser/payments/payments_requests/get_bnpl_payment_instrument_for_fetching_url_request_unittest.cc +++ b/components/autofill/core/browser/payments/payments_requests/get_bnpl_payment_instrument_for_fetching_url_request_unittest.cc @@ -202,6 +202,18 @@ EXPECT_FALSE(request_->IsResponseComplete()); } +TEST_F(GetBnplPaymentInstrumentForFetchingUrlRequestTest, + IsResponseComplete_ParseResponseCalled_NonHttpRedirectUrl) { + Dict response = GetFullResponse(); + response.SetByDottedPath( + "buy_now_pay_later_info.get_redirect_url_response_" + "info.redirect_url", + "chrome://version/"); + request_->ParseResponse(response); + + EXPECT_FALSE(request_->IsResponseComplete()); +} + TEST_F(GetBnplPaymentInstrumentForFetchingUrlRequestTest, RespondToDelegate) { Dict response_dict = Dict().Set( "buy_now_pay_later_info",
Regression Test / PoC
diff --git a/components/autofill/core/browser/payments/payments_requests/get_bnpl_payment_instrument_for_fetching_url_request_unittest.cc b/components/autofill/core/browser/payments/payments_requests/get_bnpl_payment_instrument_for_fetching_url_request_unittest.cc
index 48854fe9..dc5f22a94 100644
--- a/components/autofill/core/browser/payments/payments_requests/get_bnpl_payment_instrument_for_fetching_url_request_unittest.cc
+++ b/components/autofill/core/browser/payments/payments_requests/get_bnpl_payment_instrument_for_fetching_url_request_unittest.cc
@@ -202,6 +202,18 @@
EXPECT_FALSE(request_->IsResponseComplete());
}
+TEST_F(GetBnplPaymentInstrumentForFetchingUrlRequestTest,
+ IsResponseComplete_ParseResponseCalled_NonHttpRedirectUrl) {
+ Dict response = GetFullResponse();
+ response.SetByDottedPath(
+ "buy_now_pay_later_info.get_redirect_url_response_"
+ "info.redirect_url",
+ "chrome://version/");
+ request_->ParseResponse(response);
+
+ EXPECT_FALSE(request_->IsResponseComplete());
+}
+
TEST_F(GetBnplPaymentInstrumentForFetchingUrlRequestTest, RespondToDelegate) {
Dict response_dict = Dict().Set(
"buy_now_pay_later_info",
Original Bug Report
Lack of scheme validation for BNPL redirect_url allows privileged URL navigation
Project Fortify, 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 https://chromium.googlesource.com/chromium/src/+/main/docs/security/ai-generated-security-bugs-faq.md for more information.
Overview: The Buy Now Pay Later (BNPL) flow does not validate the scheme of the redirect_url returned from the Google payments server. A compromised network process can supply a privileged URL (e.g., devtools:// or chrome://), which the browser will open as a browser-initiated navigation. This leads to a potential network-to-browser sandbox escape.
Affected files:
components/autofill/core/browser/payments/payments_requests/get_bnpl_payment_instrument_for_fetching_url_request.ccchrome/browser/ui/autofill/payments/desktop_payments_window_manager.ccchrome/browser/ui/autofill/payments/android_payments_window_manager.cccomponents/autofill/core/browser/payments/bnpl_manager.ccchrome/browser/ui/android/autofill/payments/payments_window_bridge.ccchrome/browser/ui/android/ephemeraltab/java/src/org/chromium/chrome/browser/ephemeraltab/EphemeralTabMediator.java
Estimated timestamp from git blame: 2025-02-07
Summary
A vulnerability exists in the Buy Now Pay Later (BNPL) payment flow where the redirect_url provided by the payments server is not validated against a scheme allowlist. Because the subsequent navigation is treated as browser-initiated, an attacker who can modify the network response (e.g., from a compromised sandboxed network process) can force the browser to navigate to highly privileged URL schemes like devtools://, chrome://, or file://. This provides a potential network-to-browser sandbox escape primitive.
Technical Details
- Parsing: When the user initiates a BNPL checkout, the browser sends a
GetBnplPaymentInstrumentForFetchingUrlRequest. The response is parsed inGetBnplPaymentInstrumentForFetchingUrlRequest::ParseResponse()(incomponents/autofill/core/browser/payments/payments_requests/get_bnpl_payment_instrument_for_fetching_url_request.cc). Theredirect_urlstring is extracted and converted to aGURL. - Lack of Validation: The only validation occurs in
IsResponseComplete(), which checksresponse_details_.redirect_url.is_valid().GURL::is_valid()returns true for privileged schemes likedevtools://andchrome://. There is no check to restrict the scheme tohttporhttps. - Propagation: The URL is passed back to
BnplManager::OnRedirectUrlFetched(), which places it into aPaymentsWindowManager::BnplContextand callsGetPaymentsWindowManager()->InitBnplFlow(context). - Navigation (Desktop): In
DesktopPaymentsWindowManager::CreatePopup(), aNavigateParamsobject is constructed with the malicious URL. TheNavigateParamsconstructor defaults tois_renderer_initiated = falseand provides noinitiator_origin. The navigation is executed viaNavigate(¶ms). - Navigation (Android): In
AndroidPaymentsWindowManager::CreateTab(), the flow usesPaymentsWindowBridge::OpenEphemeralTab(), which calls through JNI toPaymentsWindowCoordinator.openEphemeralTab(), explicitly passing a nullinitiatorOriginto the ephemeral tab mediator, which then callsmWebContents.getNavigationController().loadUrl(params). - Sandbox Escape: Because the navigation is browser-initiated, standard security restrictions (like
ChildProcessSecurityPolicychecks for renderer-initiated navigations) are bypassed. The browser successfully opens the privileged URL in a new popup or ephemeral tab.
Potential Attacker Steps
(Note: These are suggested steps based on static analysis.)
- The attacker compromises the Chromium network process (which is sandboxed) or establishes an enterprise MITM position.
- The user initiates a BNPL payment flow via Autofill on a merchant website.
- The attacker intercepts the response from
https://payments.google.com/payments/apis-secure/chromepaymentsservice/getpaymentinstrument. - The attacker modifies the JSON response to inject a malicious scheme into the
get_redirect_url_response_info:"redirect_url": "devtools://..."or"redirect_url": "chrome://...". - The browser parses the response and opens a new popup or tab navigating to the privileged URL, allowing the attacker to interact with powerful internal browser surfaces.
Suggested Fix
Modify GetBnplPaymentInstrumentForFetchingUrlRequest::IsResponseComplete() or ParseResponse() to explicitly require the redirect_url (as well as success_url_prefix and failure_url_prefix) to have an http or https scheme. For example:
bool IsValidBnplUrl(const GURL& url) {
return url.is_valid() && url.SchemeIsHTTPOrHTTPS();
}
Evaluated with Chrome root at commit: 3acbde3302da0cb19488c22c0eb007c791207b4b
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.