Escrevemos antes sobre o fortalecimento do servidor HTTP. Este artigo é a outra metade da história. Um cliente costuma ser tratado como o lado confiável da conversa, mas não é: ele envia suas chaves de API, segue qualquer redirecionamento que o host remoto devolva, lê a resposta inteira na memória e armazena qualquer cookie que a resposta pedir para armazenar. Um endpoint hostil, ou simplesmente comprometido, consegue virar esses quatro comportamentos contra você.
O sgcWebSockets 2026.7 adiciona um conjunto de chaves no lado do cliente que fecham cada um desses buracos. Todas elas estão desativadas por padrão, de modo que atualizar não muda nada em uma aplicação existente até que você decida ativá-las. Estão disponíveis no cliente HTTP de baixo nível, em todos os clientes REST e de IA prontos para uso, e nos clientes HTTP/2 e HTTP/3.
Credenciais que seguem um redirecionamento
O vazamento clássico do lado do cliente. Você chama uma API com um cabeçalho Authorization, o servidor responde com um 302 apontando para outro host, e o cliente obedientemente repete a requisição lá, cabeçalho e cookies incluídos. Seu token bearer acabou de ser entregue a uma máquina com a qual você nunca pretendeu falar. O redirecionamento nem precisa ser malicioso, basta um atacante capaz de influenciar um redirecionamento aberto no host legítimo.
StripAuthOnCrossHostRedirect descarta os cabeçalhos Authorization e Cookie assim que um redirecionamento sai do host original. A requisição continua seguindo o redirecionamento, apenas chega sem as suas credenciais.
uses
sgcHTTP_Client;
var
oHTTP: TsgcIdHTTP;
begin
oHTTP := TsgcIdHTTP.Create(nil);
try
oHTTP.StripAuthOnCrossHostRedirect := True;
oHTTP.Request.CustomHeaders.Values['Authorization'] := 'Bearer ' + vToken;
vResponse := oHTTP.Get('https://api.example.com/v1/account');
finally
oHTTP.Free;
end;
end;
Redirecionamentos que caem para HTTP puro
O segundo problema dos redirecionamentos. Você começa em https://, o servidor responde com um Location que começa com http://, e o cliente alegremente repete a requisição em texto claro. Qualquer um no caminho pode agora ler o corpo e reescrever a resposta. Esta é exatamente a queda de segurança que o HSTS existe para evitar nos navegadores, e até agora o cliente HTTP não tinha equivalente.
NoInsecureRedirect recusa um redirecionamento que moveria a requisição de HTTPS para HTTP. O redirecionamento é rejeitado em vez de ser seguido.
oHTTP.NoInsecureRedirect := True;
// A 302 from https://api.example.com to http://api.example.com
// is now blocked instead of silently downgraded.
vResponse := oHTTP.Get('https://api.example.com/v1/data');
As duas chaves de redirecionamento são independentes, e na prática você quer as duas. Ative a primeira e um redirecionamento entre hosts deixa de carregar o seu token. Ative a segunda e um redirecionamento deixa de poder remover a sua segurança de transporte.
Respostas sem limite de tamanho
Um cliente HTTP padrão lê tudo o que o servidor enviar. Se o servidor mandar um corpo de resposta de dez gigabytes, ou uma resposta em blocos onde um único bloco anuncia um comprimento de dois gigabytes, o cliente tenta alocar espaço para isso. Isso é uma negação de serviço de uma linha contra o seu próprio processo, e nem exige que o atacante quebre nada, apenas que responda à sua requisição com mais dados do que você esperava.
Dois limites fecham isso. MaxResponseSize limita o tamanho total do corpo de uma resposta, e MaxChunkSize limita um único bloco de uma resposta em blocos. Ambos aceitam zero como "ilimitado", que é o padrão, portanto nada muda até que você os defina. Quando um limite é ultrapassado, a leitura é abortada e uma exceção é levantada, o cliente não fica aumentando o buffer.
uses
sgcHTTP_Client;
var
oHTTP: TsgcIdHTTP;
begin
oHTTP := TsgcIdHTTP.Create(nil);
try
oHTTP.MaxResponseSize := 10 * 1024 * 1024; // 10 MB total, 0 = unlimited
oHTTP.MaxChunkSize := 1024 * 1024; // 1 MB per chunk, 0 = unlimited
vResponse := oHTTP.Get('https://api.example.com/v1/report');
finally
oHTTP.Free;
end;
end;
Escolha um número que reflita o que o endpoint deveria realmente devolver. Se você está chamando uma API JSON que responde com alguns kilobytes, um limite de alguns megabytes é generoso e mesmo assim transforma uma leitura sem limites em uma leitura limitada.
Cookies reivindicados para um TLD inteiro
Uma resposta pode enviar um cookie com um atributo Domain. Nada no formato do protocolo impede que ele reivindique Domain=com ou Domain=co.uk. Um cliente que aceita isso passa a estar disposto a enviar o cookie para todos os hosts sob aquele sufixo, o que é o equivalente, em cookies, a distribuir uma chave mestra. Os navegadores recusam isso há anos, usando a Public Suffix List.
RejectPublicSuffixCookies traz a mesma regra para o componente. Um cookie cujo domínio é um sufixo público em vez de um domínio registrável de verdade é descartado. Observe que ativá-lo também liga o gerenciamento de cookies no cliente, porque é um repositório de cookies que ele filtra.
oHTTP.RejectPublicSuffixCookies := True;
// Set-Cookie: session=abc; Domain=co.uk -> rejected
// Set-Cookie: session=abc; Domain=example.co.uk -> accepted
A versão 2026.7 também corrige dois erros relacionados a cookies e redirecionamentos que estavam silenciosamente errados antes. Cabeçalhos Location relativos agora são resolvidos corretamente em URLs absolutas, um redirecionamento 307 ou 308 agora preserva o método e o corpo da requisição como a especificação exige, e um cookie cuja data de expiração não pode ser interpretada passa a ser tratado como cookie de sessão em vez de ser descartado. Max-Age continua prevalecendo sobre Expires quando ambos estão presentes.
Enviando um corpo grande: Expect: 100-continue e requisições em blocos
Nem toda opção nova é sobre ataques, duas delas são sobre não desperdiçar largura de banda. Se você faz um POST de um corpo grande para um endpoint que vai rejeitá-lo (credenciais inválidas, tipo de conteúdo errado, uma cota já esgotada), o comportamento padrão é empurrar o corpo inteiro pela rede primeiro e ler o 401 depois.
UseExpect100Continue envia os cabeçalhos da requisição com um Expect: 100-continue e espera que o servidor diga que está disposto a receber o corpo. Se o servidor responder com um status final em vez disso, você nunca envia a carga. Se nenhum sinal verde chegar, o corpo é enviado mesmo assim, então um servidor que ignora o cabeçalho continua funcionando.
UseChunkedTransferEncoding cobre o caso oposto, um envio cujo tamanho você não conhece de antemão. O corpo é enviado em blocos em vez de com um Content-Length fixo, de modo que você pode transmiti-lo a partir de um gerador, de um compressor ou de um pipe sem precisar bufferizar tudo antes.
uses
Classes, sgcHTTP_Client;
var
oHTTP: TsgcIdHTTP;
oBody: TStream;
begin
oHTTP := TsgcIdHTTP.Create(nil);
try
oHTTP.UseExpect100Continue := True; // ask before uploading
oHTTP.UseChunkedTransferEncoding := True; // size not known up front
oBody := TFileStream.Create('large_upload.bin', fmOpenRead or fmShareDenyWrite);
try
vResponse := oHTTP.Post('https://api.example.com/v1/upload', oBody);
finally
oBody.Free;
end;
finally
oHTTP.Free;
end;
end;
As mesmas chaves nos clientes de API prontos para uso
A parte interessante é onde essas propriedades vivem. Elas são reexpostas em TsgcHTTPAPI_client, a classe base de todo cliente REST pronto para uso da biblioteca. Isso significa que você as define diretamente no componente que já está usando, sem precisar recorrer ao objeto HTTP de baixo nível que está por baixo.
Isso cobre os clientes de IA e LLM (OpenAI, Anthropic, Gemini, DeepSeek, Grok, Mistral, Ollama), o cliente OAuth2, Google Cloud, WhatsApp, AWS SQS e WebPush, e as unidades de API da Amazon AWS e do Google Cloud.
uses
sgcHTTP_API_OpenAI;
var
oOpenAI: TsgcHTTP_API_OpenAI;
begin
oOpenAI := TsgcHTTP_API_OpenAI.Create(nil);
try
oOpenAI.StripAuthOnCrossHostRedirect := True; // never leak the API key
oOpenAI.NoInsecureRedirect := True; // never fall back to http
oOpenAI.RejectPublicSuffixCookies := True;
oOpenAI.MaxResponseSize := 32 * 1024 * 1024;
oOpenAI.MaxChunkSize := 1024 * 1024;
// ... use the client as usual
finally
oOpenAI.Free;
end;
end;
Uma chave de API enviada a um provedor de LLM é exatamente o tipo de credencial que você não quer que siga um redirecionamento para fora do domínio do provedor, então este é o lugar onde ligar as chaves não custa nada e traz muito.
HTTP/2 e HTTP/3
O cliente HTTP/2 ganha as mesmas proteções através do seu objeto de opções, TsgcWSHTTP2Client_Options, e o cliente HTTP/3 expõe o limite de resposta diretamente.
uses
sgcHTTP;
var
oHTTP2: TsgcHTTP2Client;
begin
oHTTP2 := TsgcHTTP2Client.Create(nil);
try
oHTTP2.HTTP2Options.StripAuthOnCrossHostRedirect := True;
oHTTP2.HTTP2Options.NoInsecureRedirect := True;
oHTTP2.HTTP2Options.MaxResponseSize := 10 * 1024 * 1024;
finally
oHTTP2.Free;
end;
end;
// HTTP/3
oHTTP3.MaxResponseSize := 10 * 1024 * 1024;
Uma linha para uma base TLS segura
Nada do que foi dito acima ajuda se a camada TLS não estiver verificando coisa alguma. O sgcWebSockets 2026.7 adiciona um preset para isso. Todo objeto de opções TLS da biblioteca, tanto nos componentes WebSocket quanto nos HTTP, publica uma propriedade Preset do tipo TsgcTLSPreset. Ela usa tlspCustom como padrão, o que mantém o que você configurou manualmente.
Defini-la como tlspSecureDefaults liga a verificação de certificado, TLS 1.2 ou superior e a verificação de nome de host em uma única linha.
uses
sgcWebSocket_Types;
begin
oHTTP.TLSOptions.Preset := tlspSecureDefaults;
// certificate verification on, TLS 1.2+, hostname verification on
end;
Combine o preset com as chaves de redirecionamento e os limites de resposta e você tem um cliente que verifica com quem está falando, recusa cair para um nível inferior, não entrega suas credenciais a terceiros e não pode ser levado a alocar memória sem limite.
.NET
A edição gerenciada traz as mesmas proteções na 2026.7. A remoção de credenciais em redirecionamentos, o bloqueio da queda de HTTPS, os limites por bloco e de resposta total, a rejeição de cookies de sufixo público, Expect: 100-continue e os corpos de requisição em blocos estão todos lá, incluindo o conjunto de clientes HTTP/2. Mesmos nomes, com a capitalização do C#.
client.StripAuthOnCrossHostRedirect = true;
client.NoInsecureRedirect = true;
client.RejectPublicSuffixCookies = true;
client.MaxResponseSize = 10 * 1024 * 1024;
client.MaxChunkSize = 1024 * 1024;
Disponibilidade
As opções de fortalecimento do cliente HTTP estão disponíveis no sgcWebSockets 2026.7 em Delphi 7 até 13 e C++Builder (Win32/Win64, Linux64, macOS, Android e iOS), e na edição .NET. Tudo o que foi descrito aqui é opcional e está desativado por padrão, portanto a atualização é direta.
Clientes com assinatura ativa podem baixar a nova versão na área de clientes. Usuários de avaliação podem obter o instalador atualizado em esegece.com/products/websockets/download.
Dúvidas, comentários ou ajuda para decidir quais dessas chaves a sua aplicação deve ligar? Entre em contato, você receberá uma resposta das pessoas que escreveram o código.
