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 <zork@google.com>
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 <nasko@chromium.org>
Commit-Queue: Tzarial <zork@chromium.org>
Reviewed-by: Caitlin Fischer <caitlinfischer@google.com>
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