Branch: refs/heads/main
Home: https://github.com/WebKit/WebKit
Commit: fc7c2fa58bb93ead23f03d5120ded2fac488bb66
https://github.com/WebKit/WebKit/commit/fc7c2fa58bb93ead23f03d5120ded2fac488bb66
Author: Basuke Suzuki <[email protected]>
Date: 2026-08-10 (Mon, 10 Aug 2026)
Changed paths:
M
Source/WebKit/NetworkProcess/Authentication/cocoa/AuthenticationManagerCocoa.mm
Log Message:
-----------
[WebKit Networking] Client certificate authentication challenge is never
completed when the SecKeyProxy identity cannot be created, hanging the page load
https://bugs.webkit.org/show_bug.cgi?id=321435
rdar://182381982
Reviewed by Alex Christensen.
WebKit does not move a client certificate's private key between processes. The
UI process wraps the
chosen SecIdentity in a SecKeyProxy and sends only the XPC endpoint plus the
certificate chain to the
network process, which rebuilds the identity with -[SecKeyProxy
createIdentityFromEndpoint:error:].
That call round-trips back to the UI process, so it fails whenever the private
key's Keychain ACL
denies access - for instance a certificate provisioned by a third-party
application whose ACL is bound
to that application's Team ID.
On failure the XPC handler only logged and returned, without completing the
challenge. The same was
true of every other early return in the handler: a missing or non-endpoint XPC
endpoint, a missing
certificate data array, a certificate that fails SecCertificateCreateWithData,
and an out-of-range
persistence value. Abandoning the challenge leaves the Challenge object, which
owns CFNetwork's
challenge completion handler, in AuthenticationManager::m_challenges forever.
There is no timeout and
no fallback, so the TLS handshake keeps waiting for a client certificate and
the page load stalls
indefinitely with no error shown to the user.
Move the credential reconstruction into
credentialFromClientCertificateMessage() so that all of those
failures collapse into a single std::nullopt, and complete the challenge with
PerformDefaultHandling
when it returns nothing. That matches the fallback
NetworkProcessProxy::processAuthenticationChallenge
already uses for non-server-trust schemes, and turns the hang into a reportable
load failure.
The remaining early return has to stay: there is no identifier to complete, and
constructing one anyway
would hit the RELEASE_ASSERT in ObjectIdentifier's constructor and crash the
network process. Validate
with ObjectIdentifier::isValidIdentifier() so the guard rejects exactly what
that constructor rejects,
which includes the hash table deleted value as well as zero. It only gets an
ASSERT_NOT_REACHED,
matching the message name check above it, since an invalid identifier means a
malformed message rather
than a challenge we could fail.
This does not make client certificate authentication succeed when the ACL
denies access; that denial
is by design and needs the certificate to be provisioned with an ACL that
permits the requesting
applications.
No new tests (the failure path needs a Keychain ACL denial, which cannot be
simulated in the test
harness). The unchanged success path stays covered by
TestWebKitAPI.Challenge.ClientCertificate.
*
Source/WebKit/NetworkProcess/Authentication/cocoa/AuthenticationManagerCocoa.mm:
(WebKit::credentialFromClientCertificateMessage):
(WebKit::AuthenticationManager::initializeConnection):
Canonical link: https://commits.webkit.org/318936@main
To unsubscribe from these emails, change your notification settings at
https://github.com/WebKit/WebKit/settings/notifications