This method should not be called on the main thread as it may lead to
UI unresponsiveness.
I want to make sure we’re all on the same page here, so I created a tiny test project with a WKWebView
and reproduced the problem. Here’s what I see when using Xcode 14.1 running on macOS 13.0 with the iOS 16.1 simulator:
When I click the disclosure triangle associated with the issue, I see this backtrace:
#0 … SecTrustEvaluateIfNecessary ()
#1 … SecTrustCopyCertificateChain ()
#2 … WebCore::CertificateInfo::containsNonRootSHA1SignedCertificate() const ()
#3 … WebKit::WebPageProxy::didCommitLoadForFrame(WTF::ObjectIdentifier<WebCore::FrameIdentifierType>, WebKit::FrameInfoData&&, WebCore::ResourceRequest&&, unsigned long long, WTF::String const&, bool, WebCore::FrameLoadType, WebCore::CertificateInfo const&, bool, bool, std::__1::optional<WebCore::HasInsecureContent>, WebCore::MouseEventPolicy, WebKit::UserData const&) ()
#4 … WebKit::WebPageProxy::didReceiveMessage(IPC::Connection&, IPC::Decoder&) ()
#5 … IPC::MessageReceiverMap::dispatchMessage(IPC::Connection&, IPC::Decoder&) ()
#6 … WebKit::WebProcessProxy::didReceiveMessage(IPC::Connection&, IPC::Decoder&) ()
#7 … IPC::Connection::dispatchMessage(std::__1::unique_ptr<IPC::Decoder, std::__1::default_delete<IPC::Decoder> >) ()
#8 … IPC::Connection::dispatchIncomingMessages() ()
#9 … WTF::RunLoop::performWork() ()
#10 … WTF::RunLoop::performWork(void*) ()
#11 … __CFRUNLOOP_IS_CALLING_OUT_TO_A_SOURCE0_PERFORM_FUNCTION__ ()
#12 … __CFRunLoopDoSource0 ()
#13 … __CFRunLoopDoSources0 ()
#14 … __CFRunLoopRun ()
#15 … CFRunLoopRunSpecific ()
#16 … GSEventRunModal ()
#17 … -[UIApplication _run] ()
#18 … UIApplicationMain ()
#19 … UIApplicationMain(_:_:_:_:) ()
#20 … static UIApplicationDelegate.main() ()
#21 … static AppDelegate.$main() at /Users/quinn/Desktop/Test714467/Test714467/AppDelegate.swift:10
#22 … main ()
So, let’s break this down:
-
Modern versions of Xcode have a diagnostic feature that checks for potential hangs. Specifically, it looks for folks calling APIs on the main thread that might block waiting for a network request. That makes sense because, if the network is slow, such calls can cause your app to be unresponsive. In the worst case, it may even cause your app to be killed by the watchdog. See QA1693 Addressing watchdog terminations for more on that.
-
SecTrustCopyCertificateChain
is one such API. In order to build the chain of trust, the trust object may hit the network for various reasons.
-
WKWebView
calls SecTrustCopyCertificateChain
on the main thread (see frames 2 through 1 in the backtrace) and that raises this issue.
-
If you look deeper in the backtrace you’ll see that none of your code appears there, which is a strong indication that you’ve done nothing to trigger this.
-
This issue may or may not be a real problem depending on how the trust object is configured. You can configure the trust object to prevent any networking (SecTrustSetNetworkFetchAllowed
).
-
You can also use SecTrustEvaluateAsync
to avoid blocking.
-
And if you evaluate the trust object asynchronously or on a secondary thread beforehand, your call to SecTrustCopyCertificateChain
will never hit the network.
-
But none of these are relevant here because it’s not your code doing the evaluation.
-
The Security tag on this issue doesn’t mean that it’s a security problem, but rather a problem associated with the Security framework.
-
The poor interaction between WKWebView
, Security framework, and this Xcode feature is a known issue (r. 94019453). We plan to address it at some point but I don’t have any info to share as to when that’ll happen.
-
In the meantime, if you see an issue like this, look at its associate backtrace. If it’s made up entirely of system code (except for main
) it’s likely that this isn’t your problem and you should feel free to ignore the issue.
Share and Enjoy
—
Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@" + "apple.com"