validateCertificate callback fires after request body is sent, so true TLS-pinning is impossible
Request Statement
IOHttpClientAdapter.validateCertificate runs only after the HTTP
request has already been flushed to the socket.
This means an attacker who can present a publicly trusted certificate for
example.com will receive the full request body (and often the
headers) before the app’s pinning code gets a chance to abort.
So while the callback can block the response from being delivered to the caller, it cannot stop leakage of sensitive outbound data.
The behavior breaks the primary use-case for validateCertificate: certificate / public-key pinning.
Solution Brainstorm
validateCertificate (or a new early-handshake hook) should be invoked
before any body bytes or HTTP headers are written:
- Open TCP socket
- Start TLS handshake
- Call validateCertificate with the server’s leaf cert
- Only if it returns true finish handshake and write request
- That is how Android’s
and iOS ATS / TrustKit hooks work, and it’s how users expect pinning to behave.
Could you make a PoC using the dio library so we can understands this correctly?