O app host não consegue controlar a pilha de rede do WebView. No iOS, o WKWebView não consegue interceptar HTTPS de forma alguma — a Apple documenta que registrar um WKURLSchemeHandler para http ou https lança NSInvalidArgumentException, e a interceptação NSURLProtocol de http/https não é suportada. No Android, o shouldInterceptRequest é parcial: saltos de redirecionamento, blob: e javascript: nunca disparam. Isso significa que não há fixação de certificado forçada pelo host, nem autenticação transparente, nem reuso de conexões, nem política de requisições — cada página renegocia TLS e a exfiltração para um host desconhecido fica invisível. Um runtime próprio do host medeia a rede na camada nativa: fixação, autenticação assinada, lista branca e telemetria unificada que a página nunca pode contornar.
O host não consegue ver o fio
A rede do WKWebView roda em um processo de rede separado, e a Apple proíbe explicitamente substituir o tratamento nativo de http e https. A documentação diz que é um erro de programação registrar um handler para um esquema que o WebKit já trata, como https, e tentar isso lança NSInvalidArgumentException. A interceptação NSURLProtocol de http/https não é suportada no WKWebView — o próprio engenheiro de relações de desenvolvedores da Apple confirmou que o único caminho sancionado são esquemas de URL personalizados. Assim, o host literalmente não consegue se colocar entre a página e suas requisições HTTPS. O que a página buscar, ela busca sobre o TLS do sistema, com a política do sistema, fora do alcance do app.
O Android é parcial, não está sob controle
No Android, o shouldInterceptRequest (API 21) permite que o host retorne uma resposta para um recurso, mas não é invocado para javascript:, blob:, nem URLs android_asset, e em redirecionamentos apenas para a URL de recurso inicial — as URLs de redirecionamento subsequentes nunca são chamadas. Mesmo quando dispara, não consegue adicionar cabeçalhos de forma transparente à conexão TLS do sistema, nem pode forçar a fixação de certificado. O ponto de controle parece completo na referência da API e falha na prática: uma cadeia de redirecionamento, um blob inline ou um fetch iniciado por script contornam silenciosamente o que o host achava ter enganchado.
O que se perde sem uma camada de rede controlável
Um WebView que o host não consegue mediar tira os controles que o resto do app dá como certos:
- Fixação de certificado. O único gancho do WebView é onReceivedSslError, um erro posterior que o app pode ignorar — não é fixação real. As defesas anti-MITM que vêm no cliente HTTP nativo do app não se aplicam ao tráfego do WebView.
- Autenticação transparente. Você não consegue anexar um cabeçalho de requisição assinado ou uma atestação de dispositivo a cada requisição do WebView sem uma ponte JS que a página possa detectar ou bloquear.
- Reuso de conexões. Cada página e cada WebView renegocia TLS; não há pool de conexões no nível do host nem HTTP/3 0-RTT entre navegações.
- Política de requisições. Você não consegue, na camada da plataforma, bloquear que uma página chame um host desconhecido — a exfiltração de dados fica invisível.
- Telemetria. Você não consegue medir uniformemente a latência, as falhas e os bytes das requisições do WebView como faz com as chamadas nativas.
A solução em runtime
Um runtime próprio do host medeia cada requisição na camada nativa, abaixo da página. Ele fixa certificados contra um conjunto conhecido e falha fechado, injeta autenticação assinada e atestação de dispositivo nas requisições de saída para que a página nunca as veja, mantém um pool de conexões no nível do host e negocia HTTP/3, e aplica uma lista branca para que hosts desconhecidos sejam bloqueados antes de abrir o socket. A telemetria unificada acompanha cada requisição. A página não consegue ver nem contornar a política porque a política vive abaixo dela, no runtime — não em uma ponte que possa deixar para trás.
| Dimensão | WebView | Runtime próprio do host |
|---|---|---|
| Interceptação HTTPS | iOS impossível; Android parcial | Interceptação na camada nativa, completa |
| Fixação de certificado | apenas onReceivedSslError, contornável | Conjunto fixado, falha fechado |
| Autenticação transparente | só ponte JS, detectável | Cabeçalho assinado e atestação, invisível |
| Reuso de conexões | TLS por página, sem pool | Pool host + HTTP/3, 0-RTT |
| Política de requisições | Sem bloqueio no nível da plataforma | Lista branca, bloqueia antes de conectar |
| Telemetria | Sem visão unificada | Latência, falha e bytes por requisição |
A série volta sempre a um fato: um WebView herda as superfícies mais fracas da plataforma e adiciona uma com formato de web. A rede é a superfície mais fundamental de todas — e em um WebView padrão é a que o host menos consegue governar. Um runtime devolve o app ao fio, para que o tráfego seja do app para proteger, não do sistema para decidir.
Fontes
- Fóruns de Desenvolvedores da Apple — Quinn «The Eskimo»: WKURLSchemeHandler só permite implementar esquemas personalizados, não substitui o tratamento nativo de http e https — a afirmação autoritativa de que o WKWebView não consegue interceptar HTTPS padrão.
- WebKit Bug 138169 — WKWebView não suporta interceptação estilo NSURLProtocol de http/https — a capacidade que a plataforma se recusa a fornecer.
- Android Developers — WebViewClient.shouldInterceptRequest: não é chamado para javascript:, blob: nem assets; apenas a URL de redirecionamento inicial — os limites documentados do gancho de interceptação do Android.
- OWASP MASTG — Comunicação de rede: WebView carece da UI de segurança do navegador; política TLS e fixação devem ser forçadas na camada do app — por que o tráfego do WebView precisa de controles no nível do app.
- Web.dev — Web no Android: WebView dá ao app acesso total ao conteúdo renderizado e carece dos controles de segurança e privacidade do navegador — a lacuna estrutural entre um WebView e um navegador endurecido.