- From: Alexia Death <notifications@github.com>
- Date: Thu, 22 Oct 2026 00:14:42 -0700
- To: whatwg/fetch <fetch@noreply.github.com>
- Cc: Subscribed <subscribed@noreply.github.com>
- Message-ID: <whatwg/fetch/issues/869/6335021417@github.com>
alexiade left a comment (whatwg/fetch#869) @mikkorantalainen I agree with your starting point: the certificate is public and is not a secret to protect. But I don't think the probing argument holds up, and I want to go through why. **The oracle isn't the certificate, it's usable key material.** Having a cert gives you nothing. The handshake only completes if the private key is available and unlocked. JS never sees the certificate, which cert was chosen, or whether the host uses mTLS at all. All it can see is whether a request completes and how long it takes. **On a cold connection, nothing happens silently.** The browser asks the user to choose a certificate *for the named host*, and for smartcards it also asks for a PIN. Cancel looks exactly like "I don't have one." A third-party page cannot quietly test for this. **The no-prompt cases are access that was already granted on purpose:** - an admin auto-select policy for specific URLs, where the host is explicitly pre-trusted; - an existing session, where the user already chose the cert and unlocked the key for that host. In both cases, all JS can learn is "this user currently has access to this host." That is the same thing it learns when the user is on a VPN to a private network. We don't strip VPN routing from preflights. Browsers handle that leak where the request starts (Private/Local Network Access) and by partitioning connection state, not by breaking the transport layer. **Prompts as a phishing tool:** this is a real UI/consent concern, but it isn't specific to preflight. A server that requires mTLS asks for a client certificate during the TLS handshake, before any HTTP is exchanged. So *any* connection to that host triggers certificate selection, whatever opened it: a form submission, an `<img>`, a script. Preflights are the only case where browsers deliberately skip that step. Leaving client certs out of preflights removes neither the prompt vector nor the "has access" signal. **So what does the exclusion actually do?** It doesn't protect anything. It breaks browser-based applications that need to talk to hosts enforcing mTLS at the transport layer. The servers are working as configured. The browser is applying an HTTP-layer concept (credentials mode) to a transport-layer decision. The result is the situation @Okeanos described: enterprises dropping mTLS at the edge, because the browser cannot get a preflight through it. In practice that weakens security rather than protecting anyone. **Proposal:** certificate presentation for a preflight should follow the same transport configuration as the actual request it guards. If the actual request would use a given client certificate (already selected, already unlocked, or auto-selected by policy), the preflight's handshake uses it too. If getting one would need a prompt, the same prompting rules apply as for the actual request, so preflights create no new prompts. Preflights stay free of HTTP-layer credentials (cookies, `Authorization`), exactly as now. They just stop interfering with TLS. -- Reply to this email directly or view it on GitHub: https://github.com/whatwg/fetch/issues/869#issuecomment-6335021417 You are receiving this because you are subscribed to this thread. Message ID: <whatwg/fetch/issues/869/6335021417@github.com>
Received on Thursday, 22 October 2026 07:14:46 UTC