CVE-2026-11265
Overview
Changed Functions
| Function | Change | Notes |
|---|---|---|
BindRepeatingcomponents/autofill/content/browser/email_verifier_delegate.cc |
modified | |
ifcomponents/autofill/content/browser/email_verifier_delegate.cc |
modified | |
EmailVerifierDelegatecomponents/autofill/content/browser/email_verifier_delegate.h |
modified |
Files Changed
components/autofill/content/browser/email_verifier_delegate.cccomponents/autofill/content/browser/email_verifier_delegate.hcomponents/autofill/content/browser/email_verifier_delegate_unittest.cc
Patch
From 6839541cdd55f102e18d81f73f23d0aefbc6db57 Mon Sep 17 00:00:00 2001
From: Christoph Schwering <schwering@google.com>
Date: Tue, 28 Apr 2026 02:50:14 -0700
Subject: [PATCH] [Autofill] Retrieve EmailVerifierDelegate for field's frame
This CL retrieves the content::webid::EmailVerifier for the
email field's frame rather than the form's frame.
The form's frame and the field's frame are not necessarily identical
due to frame-transcending forms.
Bug: 500262869
Change-Id: Ib52bf819181db9f409f7b523568e46353f266beb
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/7735890
Reviewed-by: Dominic Battré <battre@chromium.org>
Reviewed-by: Sam Goto <goto@chromium.org>
Commit-Queue: Christoph Schwering <schwering@google.com>
Cr-Commit-Position: refs/heads/main@{#1621631}
---
diff --git a/components/autofill/content/browser/email_verifier_delegate.cc b/components/autofill/content/browser/email_verifier_delegate.cc
index 001b0e3..75997ee9 100644
--- a/components/autofill/content/browser/email_verifier_delegate.cc
+++ b/components/autofill/content/browser/email_verifier_delegate.cc
@@ -8,6 +8,7 @@
#include "base/functional/bind.h"
#include "base/strings/utf_string_conversions.h"
#include "components/autofill/content/browser/content_autofill_driver.h"
+#include "components/autofill/content/browser/renderer_forms_from_browser_form.h"
#include "components/autofill/core/browser/autofill_field.h"
#include "components/autofill/core/browser/data_model/addresses/autofill_profile.h"
#include "components/autofill/core/browser/form_structure.h"
@@ -22,11 +23,13 @@
EmailVerifierDelegate::EmailVerifierDelegate(AutofillClient* client)
: EmailVerifierDelegate(
client,
- base::BindRepeating([](AutofillManager& manager) {
- ContentAutofillDriver& content_driver =
- static_cast<ContentAutofillDriver&>(manager.driver());
- content::RenderFrameHost* rfh = content_driver.render_frame_host();
- return content::webid::EmailVerifier::GetOrCreateForFrame(rfh);
+ base::BindRepeating([](AutofillClient& client,
+ const LocalFrameToken& frame_token) {
+ content::RenderFrameHost* rfh = FindRenderFrameHostByToken(
+ *static_cast<ContentAutofillClient&>(client).web_contents(),
+ frame_token);
+ return rfh ? content::webid::EmailVerifier::GetOrCreateForFrame(rfh)
+ : nullptr;
})) {}
EmailVerifierDelegate::EmailVerifierDelegate(AutofillClient* client,
@@ -82,7 +85,10 @@
std::u16string email = (*profile)->GetRawInfo(EMAIL_ADDRESS);
content::webid::EmailVerifier* verifier =
- email_verifier_builder_.Run(manager);
+ email_verifier_builder_.Run(manager.client(), email_field.host_frame());
+ if (!verifier) {
+ return;
+ }
verifier->Verify(
base::UTF16ToUTF8(email), base::UTF16ToUTF8(email_field.nonce()),
base::BindOnce(
diff --git a/components/autofill/content/browser/email_verifier_delegate.h b/components/autofill/content/browser/email_verifier_delegate.h
index 52c2899..f39c6ed1 100644
--- a/components/autofill/content/browser/email_verifier_delegate.h
+++ b/components/autofill/content/browser/email_verifier_delegate.h
@@ -27,8 +27,8 @@
// https://github.com/dickhardt/email-verification-protocol
class EmailVerifierDelegate : public AutofillManager::Observer {
public:
- using EmailVerifierBuilder =
- base::RepeatingCallback<content::webid::EmailVerifier*(AutofillManager&)>;
+ using EmailVerifierBuilder = base::RepeatingCallback<
+ content::webid::EmailVerifier*(AutofillClient&, const LocalFrameToken&)>;
explicit EmailVerifierDelegate(AutofillClient* client);
EmailVerifierDelegate(AutofillClient* client, EmailVerifierBuilder builder);
diff --git a/components/autofill/content/browser/email_verifier_delegate_unittest.cc b/components/autofill/content/browser/email_verifier_delegate_unittest.cc
index 357ebf8..deee7d36 100644
--- a/components/autofill/content/browser/email_verifier_delegate_unittest.cc
+++ b/components/autofill/content/browser/email_verifier_delegate_unittest.cc
@@ -76,9 +76,10 @@
email_verifier_ = std::make_unique<NiceMock<MockEmailVerifier>>();
delegate_ = std::make_unique<EmailVerifierDelegate>(
&client_,
- base::BindRepeating([](content::webid::EmailVerifier* verifier,
- AutofillManager&) { return verifier; },
- email_verifier_.get()));
+ base::BindRepeating(
+ [](content::webid::EmailVerifier* verifier, AutofillClient&,
+ const LocalFrameToken&) { return verifier; },
+ email_verifier_.get()));
}
void TearDown() override {
Regression Test / PoC
diff --git a/components/autofill/content/browser/email_verifier_delegate_unittest.cc b/components/autofill/content/browser/email_verifier_delegate_unittest.cc
index 357ebf8..deee7d36 100644
--- a/components/autofill/content/browser/email_verifier_delegate_unittest.cc
+++ b/components/autofill/content/browser/email_verifier_delegate_unittest.cc
@@ -76,9 +76,10 @@
email_verifier_ = std::make_unique<NiceMock<MockEmailVerifier>>();
delegate_ = std::make_unique<EmailVerifierDelegate>(
&client_,
- base::BindRepeating([](content::webid::EmailVerifier* verifier,
- AutofillManager&) { return verifier; },
- email_verifier_.get()));
+ base::BindRepeating(
+ [](content::webid::EmailVerifier* verifier, AutofillClient&,
+ const LocalFrameToken&) { return verifier; },
+ email_verifier_.get()));
}
void TearDown() override {
Original Bug Report
EVP Cross-Frame Origin Confusion allows SD-JWT+KB Assertion Theft
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 security team.
Overview: A potential vulnerability in the Email Verification Protocol (EVP) allows a cross-origin iframe to steal a browser-signed identity assertion bound to its parent frame’s origin. Due to missing origin checks during Autofill form merging, the browser signs the parent’s origin into the token’s audience claim but delivers it to the attacker’s subframe. This could enable cross-origin identity assertion theft and account takeover.
Affected files:
components/autofill/content/browser/email_verifier_delegate.cccontent/browser/webid/delegation/email_verification_request.cccomponents/autofill/core/browser/foundations/autofill_driver_router.cccomponents/autofill/core/browser/foundations/form_forest.cccomponents/autofill/core/browser/filling/form_filler.cccomponents/autofill/content/renderer/form_autofill_util.cc
Estimated timestamp from git blame: 2025-09-25
The Email Verification Protocol (EVP) implementation within Autofill contains a logic flaw allowing an attacker-controlled subframe to obtain a signed SD-JWT+KB identity assertion scoped to its parent frame’s origin (aud claim).
Vulnerability Details
Standard Autofill processing successfully merges cross-origin subframe fields into a single logical form handled by the root frame’s BrowserAutofillManager. When a user autofills an EVP-enabled field within this merged context, EmailVerifierDelegate::OnFillOrPreviewForm is invoked.
Rather than validating the specific field’s origin, the delegate directly constructs the EmailVerificationRequest using the root manager’s RenderFrameHost. This incorrectly binds the resulting JWT’s audience (aud) claim to the parent (victim) origin. The system then routes the DispatchEmailVerifiedEvent containing the signed presentation token back to the attacker-controlled subframe that originally hosted the input field.
Potential Reproduction Steps
Note: These are suggested/potential steps to trigger the vulnerability, as our tooling agent does not yet have the ability to run code.
- Setup: An attacker embeds a cross-origin iframe (
https://attacker.com) on a target victim site (https://victim.com). - Payload: The attacker iframe contains
<input type="email" autocomplete="email" nonce="ATTACKER_NONCE">and a JavaScript listener for theemailverifiedDOM event. - Interaction: The user autofills the email field within the attacker’s iframe.
- Exploitation: The browser signs the
ATTACKER_NONCEinto an SD-JWT+KB assertion withaud=https://victim.comand fires theemailverifiedevent in the attacker’s iframe. The attacker captures the token and replays it to the victim’s backend.
Suggested Fix
Update EmailVerifierDelegate::OnFillOrPreviewForm to either:
- Verify that the
LocalFrameTokenof the field possessing thenoncematches the frame token of theAutofillManagerprocessing the form. - Pass the specific
RenderFrameHostcorresponding to the field’sframe_tokento theEmailVerifierBuilder, ensuring theaudclaim accurately reflects the subframe’s origin.
Evaluated with Chrome root at commit: f200f57a19490707ff8bc7aa5de3cbc443a3afad
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.