Chrome · WebAuthn
CVE-2026-17990
Logic Error in WebAuthn
Overview
Low
Severity
—
CVSS
No
Exploited ITW
Fixed
Fix Status
Changed Functions
| Function | Change | Notes |
|---|---|---|
TEST_Fcontent/browser/webauth/authenticator_impl_unittest.cc |
modified |
Files Changed
content/browser/bad_message.hcontent/browser/renderer_host/render_frame_host_impl.cccontent/browser/webauth/authenticator_impl_unittest.cccontent/public/test/mock_render_process_host.cccontent/public/test/mock_render_process_host.htools/metrics/histograms/metadata/stability/enums.xml
Patch
From b735f1c6c3cf93c5856057477ece834a6a3a9790 Mon Sep 17 00:00:00 2001 From: Tzarial <[email protected]> Date: Mon, 29 Jun 2026 11:59:58 -0700 Subject: [PATCH] Block WebAuthn Authenticator in PDF renderers. PDF processes are not permitted to access password or passkey-class data. Refuse to bind the blink.mojom.Authenticator interface for them, mirroring the existing protection for PasswordManagerDriver. Test: AuthenticatorImplTest.PdfProcessBlocked Change-Id: Id281ea353bccb5c0a949d424cafcdaca98916e51 Fixed: 520018012 Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/7989199 Reviewed-by: Nasko Oskov <[email protected]> Commit-Queue: Tzarial <[email protected]> Reviewed-by: Caitlin Fischer <[email protected]> Cr-Commit-Position: refs/heads/main@{#1654244} --- diff --git a/content/browser/bad_message.h b/content/browser/bad_message.h index 6304132..558608f 100644 --- a/content/browser/bad_message.h +++ b/content/browser/bad_message.h @@ -380,6 +380,7 @@ RFH_DID_COMMIT_NAVIGATION_WHILE_BFCACHED = 352, BIBI_BIND_WEBNN_CONTEXT_PROVIDER_BLOCKED_BY_PERMISSIONS_POLICY = 353, BIBI_BIND_WEBNN_WEIGHTS_FILE_CREATOR_BLOCKED_BY_PERMISSIONS_POLICY = 354, + RFH_AUTHENTICATOR_PDF_PROCESS_BLOCKED = 355, // Please add new elements here. The naming convention is abbreviated class // name (e.g. RenderFrameHost becomes RFH) plus a unique description of the diff --git a/content/browser/renderer_host/render_frame_host_impl.cc b/content/browser/renderer_host/render_frame_host_impl.cc index d0874f2..d1a9233 100644 --- a/content/browser/renderer_host/render_frame_host_impl.cc +++ b/content/browser/renderer_host/render_frame_host_impl.cc @@ -15170,6 +15170,17 @@ return; } + // PDF renderer processes are not permitted to access password/passkey-class + // data for any origin (see + // ChildProcessSecurityPolicyImpl::IsAccessAllowedForPdfProcess). Refuse to + // bind blink.mojom.Authenticator for them, mirroring the gate already present + // for blink.mojom.PasswordManagerDriver. + if (GetProcess()->IsPdf()) { + bad_message::ReceivedBadMessage( + GetProcess(), bad_message::RFH_AUTHENTICATOR_PDF_PROCESS_BLOCKED); + return; + } + #if !BUILDFLAG(IS_ANDROID) AuthenticatorImpl::Create(this, std::move(receiver)); #else diff --git a/content/browser/webauth/authenticator_impl_unittest.cc b/content/browser/webauth/authenticator_impl_unittest.cc index c3898b31..7b9d870 100644 --- a/content/browser/webauth/authenticator_impl_unittest.cc +++ b/content/browser/webauth/authenticator_impl_unittest.cc @@ -1003,6 +1003,16 @@ } } +TEST_F(AuthenticatorImplTest, PdfProcessBlocked) { + process()->SetIsPdf(true); + + mojo::Remote<blink::mojom::Authenticator> authenticator; + static_cast<RenderFrameHostImpl*>(main_rfh()) + ->GetWebAuthenticationService(authenticator.BindNewPipeAndPassReceiver()); + + EXPECT_EQ(1, process()->bad_msg_count()); +} + constexpr auto kValidAppIdCases = std::to_array<OriginClaimedAuthorityPair>({ {"https://example.com", "https://example.com", AuthenticatorStatus::SUCCESS}, diff --git a/content/public/test/mock_render_process_host.cc b/content/public/test/mock_render_process_host.cc index 37a550a..384fe2e 100644 --- a/content/public/test/mock_render_process_host.cc +++ b/content/public/test/mock_render_process_host.cc @@ -220,7 +220,11 @@ } bool MockRenderProcessHost::IsPdf() { - return false; + return is_pdf_; +} + +void MockRenderProcessHost::SetIsPdf(bool is_pdf) { + is_pdf_ = is_pdf; } void MockRenderProcessHost::OnMediaStreamAdded() {} diff --git a/content/public/test/mock_render_process_host.h b/content/public/test/mock_render_process_host.h index 79612bbc..a52cee776 100644 --- a/content/public/test/mock_render_process_host.h +++ b/content/public/test/mock_render_process_host.h @@ -99,6 +99,7 @@ bool AreV8OptimizationsDisabled() override; bool DisallowV8FeatureFlagOverrides() override; bool IsPdf() override; + void SetIsPdf(bool is_pdf); void OnMediaStreamAdded() override; void OnMediaStreamRemoved() override; void OnForegroundServiceWorkerAdded() override; @@ -349,6 +350,7 @@ bool delayed_cleanup_ = false; bool deletion_callback_called_; bool is_for_guests_only_; + bool is_pdf_ = false; base::Process::Priority priority_; bool is_unused_; bool is_for_top_chrome_web_ui_ = false; diff --git a/tools/metrics/histograms/metadata/stability/enums.xml b/tools/metrics/histograms/metadata/stability/enums.xml index d7d669f..07ba3d9df 100644 --- a/tools/metrics/histograms/metadata/stability/enums.xml +++ b/tools/metrics/histograms/metadata/stability/enums.xml @@ -526,6 +526,7 @@ label="BIBI_BIND_WEBNN_CONTEXT_PROVIDER_BLOCKED_BY_PERMISSIONS_POLICY"/> <int value="354" label="BIBI_BIND_WEBNN_WEIGHTS_FILE_CREATOR_BLOCKED_BY_PERMISSIONS_POLICY"/> + <int value="355" label="RFH_AUTHENTICATOR_PDF_PROCESS_BLOCKED"/> </enum> <enum name="BadMessageReasonExtensions">
Loading diff…
Regression Test / PoC
shipped with the fix
diff --git a/content/browser/webauth/authenticator_impl_unittest.cc b/content/browser/webauth/authenticator_impl_unittest.cc
index c3898b31..7b9d870 100644
--- a/content/browser/webauth/authenticator_impl_unittest.cc
+++ b/content/browser/webauth/authenticator_impl_unittest.cc
@@ -1003,6 +1003,16 @@
}
}
+TEST_F(AuthenticatorImplTest, PdfProcessBlocked) {
+ process()->SetIsPdf(true);
+
+ mojo::Remote<blink::mojom::Authenticator> authenticator;
+ static_cast<RenderFrameHostImpl*>(main_rfh())
+ ->GetWebAuthenticationService(authenticator.BindNewPipeAndPassReceiver());
+
+ EXPECT_EQ(1, process()->bad_msg_count());
+}
+
constexpr auto kValidAppIdCases = std::to_array<OriginClaimedAuthorityPair>({
{"https://example.com", "https://example.com",
AuthenticatorStatus::SUCCESS},
diff --git a/content/public/test/mock_render_process_host.cc b/content/public/test/mock_render_process_host.cc
index 37a550a..384fe2e 100644
--- a/content/public/test/mock_render_process_host.cc
+++ b/content/public/test/mock_render_process_host.cc
@@ -220,7 +220,11 @@
}
bool MockRenderProcessHost::IsPdf() {
- return false;
+ return is_pdf_;
+}
+
+void MockRenderProcessHost::SetIsPdf(bool is_pdf) {
+ is_pdf_ = is_pdf;
}
void MockRenderProcessHost::OnMediaStreamAdded() {}
diff --git a/content/public/test/mock_render_process_host.h b/content/public/test/mock_render_process_host.h
index 79612bbc..a52cee776 100644
--- a/content/public/test/mock_render_process_host.h
+++ b/content/public/test/mock_render_process_host.h
@@ -99,6 +99,7 @@
bool AreV8OptimizationsDisabled() override;
bool DisallowV8FeatureFlagOverrides() override;
bool IsPdf() override;
+ void SetIsPdf(bool is_pdf);
void OnMediaStreamAdded() override;
void OnMediaStreamRemoved() override;
void OnForegroundServiceWorkerAdded() override;
@@ -349,6 +350,7 @@
bool delayed_cleanup_ = false;
bool deletion_callback_called_;
bool is_for_guests_only_;
+ bool is_pdf_ = false;
base::Process::Priority priority_;
bool is_unused_;
bool is_for_top_chrome_web_ui_ = false;
Loading diff…
Original Bug Report
The reporter's bug is still restricted on the tracker. Chrome de-restricts security bugs ~30–90 days after the fix ships; a later run will backfill it here.
References
On This Page