# HTTP method override vence a revisão por método

A revisão baseada no método não é segura quando o revisor vê apenas a linha da requisição. Uma requisição pode chegar como `POST`, levar `X-HTTP-Method-Override: DELETE` e alcançar um manipulador de exclusão depois que um middleware altera o método. Se uma tela de aprovação, regra de gateway, verificação de autorização ou registro de auditoria a classifica como POST comum, revisou o invólucro e perdeu a ação.

Esse comportamento não é um truque do protocolo HTTP que todo servidor entende. É uma convenção da aplicação, por isso passa despercebido com facilidade. O suporte varia conforme framework, ordem dos middlewares, rota e implantação. A resposta não é supor que todo POST seja destrutivo em segredo. É descobrir onde substituições são aceitas, resolvê-las antes de qualquer decisão de segurança e rejeitar ambiguidades.

## O método no transporte e o método efetivo são fatos distintos

Uma pilha que aceita substituições precisa registrar dois métodos: o da linha HTTP e o que a aplicação usa por fim para rotear. Eu os chamo de método de transporte e método efetivo. Eles normalmente coincidem. O caso perigoso surge quando um intermediário aprova ou filtra o primeiro e um componente posterior roteia pelo segundo.

O RFC 9110 diz que o token do método é a principal fonte da semântica da requisição. Ele define POST como processamento específico do recurso, enquanto DELETE pede ao servidor de origem que remova a associação entre o recurso e sua funcionalidade atual. O RFC não padroniza `X-HTTP-Method-Override`. Esse cabeçalho pertence a convenções de compatibilidade criadas para clientes ou intermediários limitados a GET e POST.

Software comum ainda implementa a convenção. O middleware `method-override` do Express lê por padrão `X-HTTP-Method-Override` em POST. Ao aceitar um valor, muda `req.method` e guarda o anterior em `req.originalMethod`. O ASP.NET Core oferece middleware cujo cabeçalho padrão também é esse. O `HiddenHttpMethodFilter` do Spring usa outro caminho: lê `_method` em um formulário POST e permite PUT, DELETE e PATCH.

Esses detalhes deixam clara uma distinção que as equipes confundem. “O gateway permitiu POST” descreve o transporte. “A aplicação executou DELETE” descreve o comportamento. Uma decisão de aprovação ou acesso precisa do segundo fato. Se o componente não consegue determinar o método efetivo, deve rejeitar sinais de substituição em vez de classificar silenciosamente pelo verbo externo.

O suporte no framework não prova exposição sozinho. A aplicação Express precisa instalar e ordenar o middleware, o ASP.NET Core precisa adicioná-lo e o Spring precisa ativar e posicionar o filtro. A configuração implantada, inclusive proxies reversos e middlewares de certas rotas, determina o resultado. Examinar o código aponta candidatos; um teste que verifica o estado fornece evidência.

## Um POST aprovado pode chegar ao manipulador DELETE

Uma escrita tunelada escapa quando os componentes discordam sobre qual representação da ação é oficial. Considere um agente propondo esta requisição a uma API de projetos:

```http
POST /v1/projects/42 HTTP/1.1
Host: api.example.test
Authorization: Bearer [injected outside the agent]
X-HTTP-Method-Override: DELETE
Content-Length: 0
```

A camada de aprovação mostra “POST /v1/projects/42” e aplica uma regra que permite POST na sessão. Um proxy reverso encaminha o cabeçalho desconhecido. O RFC 9110 em geral exige que proxies encaminhem campos desconhecidos, salvo bloqueio ou transformação explícita. Dentro da aplicação, o middleware muda o método antes do roteamento. O roteador escolhe DELETE e o projeto desaparece.

Essa falha não exige uma autorização DELETE quebrada. A aplicação pode autorizar corretamente a identidade a excluir. O defeito aparece antes: uma pessoa ou sistema aprovou uma ação materialmente diferente porque o classificador ignorou uma entrada aceita. A mesma divisão pode afetar firewall de aplicação, limite de frequência, controle CSRF, métricas e registros de acesso.

A ordem dos middlewares decide qual controle vê qual fato. A documentação do Express é direta: a substituição deve rodar antes de qualquer middleware que precise saber o método. O conselho é correto para roteamento e CSRF dentro de um processo. Não corrige um gateway externo que já decidiu com base na linha da requisição.

Há uma segunda falha mais silenciosa. O log da borda registra POST, o da aplicação registra DELETE e o investigador os trata como requisições separadas. Um identificador compartilhado pode uni-los, mas ambos precisam preservá-lo e a equipe precisa comparar os campos. Um registro normalizado único é menos propenso a erro.

Não deduza o impacto apenas pela palavra DELETE. O RFC 9110 observa que DELETE remove a associação entre o recurso e sua função atual; destruição e liberação de armazenamento dependem da aplicação. Um endpoint DELETE pode arquivar, desativar, enfileirar ou apagar. Revise a consequência real da rota, não uma definição genérica.

## Teste o endpoint com uma matriz controlada

O teste confiável compara o estado após métodos nativos, cabeçalhos de substituição e parâmetros sobre um recurso descartável. Execute em homologação ou contra um fixture feito para testes destrutivos. Use uma identidade com as permissões do chamador real e recrie o fixture antes de cada caso para uma exclusão não contaminar o seguinte.

Comece com POST de controle sem substituição. Registre status, corpo e estado do fixture. Depois envie DELETE nativo para confirmar que a rota existe e a identidade pode usá-la. Por fim, repita POST com cada convenção. Uma sonda mínima é:

```sh
BASE='https://staging.example.test'
ID='override-probe-17'

curl -sS \n  -D response.headers \n  -o response.body \n  -w 'case=x-http-method-override outer=POST status=%{http_code} bytes=%{size_download}
' \n  -X POST "$BASE/v1/projects/$ID" \n  -H 'Authorization: Bearer test-token' \n  -H 'X-HTTP-Method-Override: DELETE'

curl -sS \n  -o state.body \n  -w 'verify=read-after-request status=%{http_code} bytes=%{size_download}
' \n  -H 'Authorization: Bearer test-token' \n  "$BASE/v1/projects/$ID"
```

A saída tem uma forma estável para o CI analisar:

```text
case=x-http-method-override outer=POST status=204 bytes=0
verify=read-after-request status=404 bytes=71
```

O exemplo mostra uma substituição que apagou o fixture; não é um status universal. Algumas APIs retornam 200 com um documento, 202 para exclusão em fila ou uma representação ainda legível após exclusão lógica. Defina sucesso pelo contrato da aplicação.

Use uma matriz, não uma sequência improvisada. O controle é POST sem substituição e deve manter o comportamento normal. O caso nativo é DELETE sem substituição. Envie então POST com `X-HTTP-Method-Override: DELETE`, `X-HTTP-Method: DELETE` e `X-Method-Override: DELETE`. Termine com `?_method=DELETE` na consulta e `_method=DELETE` no formulário. Cada caso deve seguir seu projeto explícito ou falhar sem mudar o estado.

O guia de testes web da OWASP cita esses três cabeçalhos e recomenda repetir requisições com eles quando um método restrito é rejeitado. Eu iria além do status, pois a diferença pode vir de validação, roteamento ou intermediário. Verifique o recurso, sua versão e qualquer tarefa em fila após cada teste.

Se você controla a pilha, capture cada etapa: log da borda, evento de aprovação, log da aplicação, rota selecionada e resultado nos dados. Você procura divergência. Um resultado seguro pode ser rejeição consistente ou normalização deliberada seguida da mesma autorização e aprovação do DELETE nativo.

## O status dá pistas e a mudança de estado prova

Um status HTTP sozinho não diz se a substituição foi executada. Um 204 seguido de recurso ausente é evidência forte. Um 200 pode ser resposta POST, recibo de exclusão ou erro mal codificado. Um 405 pode vir da borda antes do middleware, enquanto outra rota ou tipo de conteúdo ainda o alcança.

Construa a asserção em torno de um recurso canário com identificador único e versão inicial conhecida. Antes da sonda, leia o recurso e guarde a versão ou resumo. Depois, leia novamente e examine qualquer registro de operação. Para atualização, escolha um campo inofensivo e evidente. Para exclusão, saiba se ela é física, lógica ou adiada.

Comparar respostas ajuda. Guarde status, cabeçalhos selecionados, tamanho e resumo do corpo. Compare a substituição com POST simples e DELETE nativo. Se resposta e estado se parecem com DELETE, a conclusão é convincente. Se a resposta parece POST e o estado segue DELETE, a camada de resposta ou log talvez use o método externo.

Redirecionamentos merecem teste separado. O cliente pode mudar ao seguir 301, 302, 303, 307 ou 308, e ferramentas preservam método e corpo de modos diferentes. Rode primeiro sem seguir e registre `Location`. Depois siga cada salto de propósito. Não misture redirecionamento e substituição em um resultado opaco.

APIs assíncronas exigem observação mais longa, não adivinhação. Se a resposta traz identificador de operação, consulte-o segundo o contrato. Sem referência durável, examine fila ou log em homologação. Marque um caso inconclusivo como inconclusivo, não como seguro.

Verifique também a ausência de efeitos. Uma substituição rejeitada não deve criar, atualizar, arquivar, enfileirar, enviar email nem emitir webhook privilegiado. Um 4xx limpo pode enganar se outro componente já confirmou um efeito. Instrumente o fixture para detectar essa ordem.

## Variantes e ambiguidades pertencem ao mesmo teste

Testar só a grafia canônica ignora código de compatibilidade e divergências de parser. Os nomes comuns são `X-HTTP-Method-Override`, `X-HTTP-Method` e `X-Method-Override`, mas uma aplicação pode definir um leitor próprio. Consultas e formulários podem levar `_method`, e integrações antigas usam nomes de fornecedor.

Maiúsculas no nome não formam outra convenção. O RFC 9110 diz que nomes de campo não diferenciam maiúsculas, então `x-http-method-override` e `X-HTTP-Method-Override` são o mesmo campo. Um filtro que reconhece só uma grafia é defeituoso mesmo que a biblioteca normalize nomes.

Valores duplicados e conflitantes revelam problema mais difícil. O RFC 9110 permite combinar linhas repetidas com vírgulas quando a definição permite e pede atenção a duplicatas mesmo em campos de valor único. Cabeçalhos de substituição não têm regra padronizada comum. O Express usa a primeira ocorrência, enquanto vários leitores podem criar precedência entre nomes.

Adicione `x-http-method-override: DELETE` e exija o mesmo resultado. Envie dois DELETE idênticos e exija resultado documentado ou rejeição. Envie PUT seguido de DELETE e depois valores diferentes em dois nomes; rejeite ambos por ambiguidade. Rejeite também `PUT, DELETE`, PATCH nativo com substituição DELETE sem contrato explícito e DELETE junto de `_method=PATCH`.

Não pare em DELETE. Teste PUT e PATCH, pois a revisão pode classificar criação, substituição, atualização parcial e exclusão de forma diferente. Use um token não aceito como controle negativo. Evite TRACE e CONNECT fora de escopo explícito; eles acionam outra infraestrutura sem melhorar a prova.

Espaços e caixa do valor podem revelar normalização incoerente. Envie `delete`, ` DELETE ` se o cliente permitir, e valor vazio. Normalize apenas formas documentadas, valide contra um conjunto explícito e rejeite o resto. Escolher silenciosamente o primeiro valor legível recria o desvio quando um proxy muda.

## Requisições de agentes facilitam o ponto cego

Agentes de IA não criam a fraqueza, mas pioram uma revisão incompleta. Eles podem compor cabeçalhos arbitrários, reutilizar exemplos e repetir um DELETE falho como túnel POST sem entender que a segunda forma cruza a aprovação. Uma pessoa diante de um cartão compacto tende a focar no verbo e caminho visíveis.

Trate cada parte gerada pelo agente como entrada não confiável, inclusive cabeçalhos que parecem metadados de compatibilidade. Injetar credenciais fora do modelo reduz exposição, mas não torna a ação inocente. Caminho, método, cabeçalhos, consulta e corpo escolhidos chegam a um sistema que pode interpretá-los juntos.

O esquema da ferramenta pode reduzir ambiguidade antes da requisição. Uma ferramenta HTTP genérica com cabeçalhos livres permite pedir substituições. Uma ferramenta específica de exclusão pode nomear a ação e omitir esses campos. É mais fácil de revisar, desde que não mantenha uma passagem oculta para cabeçalhos extras.

Se a ferramenta genérica for necessária, analise a proposta antes de exibi-la. O parser deve usar o mesmo inventário e precedência do executor. Congele a ação normalizada após aprovação. Se um intermediário mudar cabeçalhos depois, inclua sua transformação determinística na revisão ou resolva novamente e peça outra aprovação.

Tentativas repetidas também importam. POST não é seguro nem idempotente por natureza. O RFC 9110 o define de forma ampla e muitos endpoints POST alteram dados sem substituição. A ferramenta não pode concluir que uma repetição é segura só pelo verbo externo, nem tratar todo POST como destrutivo. Precisa da rota e do método efetivo.

Separe identidades de teste e produção. Uma credencial ampla fará tudo funcionar e esconderá diferenças de autorização. Use o papel limitado real, confirme decisões iguais para formas nativas e tuneladas e registre o que a aprovação mostrou. A falha fica provada quando proposta, exibição, execução e estado formam uma cadeia.

## O primeiro controle deve classificar a ação efetiva

Toda decisão baseada em método deve vir após um resolvedor único ou rejeitar todas as substituições. Isso vale para aprovação, autorização, CSRF, rotas, limites e auditoria. Repetir parsing improvisado em cada controle garante divergência.

Represente a resolução explicitamente:

```json
{
  "transport_method": "POST",
  "effective_method": "DELETE",
  "override_source": "header:x-http-method-override",
  "override_value": "DELETE",
  "target": "/v1/projects/42",
  "ambiguous": false
}
```

O resolvedor deve inventariar cabeçalhos e parâmetros, coletar valores e rejeitar mais de um candidato distinto. Só deve aceitar substituições de métodos externos permitidos, normalmente POST. Deve validar contra métodos intencionais e produzir um registro imutável para controles posteriores.

Coloque a autorização depois e vincule-a à rota e método efetivo. “Esta identidade pode fazer POST aqui?” é fraco se POST for túnel. Pergunte se pode executar DELETE no recurso. Aplique a mesma autorização ao DELETE nativo e à forma tunelada.

A tela deve mostrar primeiro a consequência e as duas formas quando diferirem. `DELETE /v1/projects/42 via POST override` expõe ação e transporte. Esconder o cabeçalho em um painel bruto obriga o revisor a descobrir o risco sob pressão.

Se o gateway não reproduz as regras da aplicação, não ensine um subconjunto. Rejeite qualquer sinal conhecido antes da aprovação ou mova a aprovação após normalização confiável. Um gateway que entende um cabeçalho diante de aplicação que entende três oferece cobertura falsa.

Separe resolução de semântica de negócio. O resolvedor conclui DELETE; a rota decide se significa arquivar, revogar, separar ou apagar. Operações de alto impacto exigem descrição ligada à rota. Normalizar método é necessário, mas um verbo não descreve todos os efeitos.

## Remover um cabeçalho não basta

Remover `X-HTTP-Method-Override` no proxy só é seguro se nenhum cliente usa túnel de propósito. É popular porque é simples e bloqueia a primeira demonstração. Falha se outro cabeçalho, `_method`, rota direta ou middleware posterior continua ativo.

O guia do YARP da Microsoft cita os três cabeçalhos, diz que são encaminhados por padrão e recomenda uma transformação de remoção para impedir desvio. É um reforço útil, mas não prova que o destino ignore parâmetros nem cobre tráfego que contorna o YARP.

Escolha um de dois projetos. Sem cliente legítimo, desative o middleware e rejeite todos os sinais na borda. Se clientes dependem dele, documente uma entrada, rejeite alternativas, normalize antes dos controles e teste formas nativas e tuneladas como a mesma ação.

Faça inventário primeiro. Busque middleware, wrappers, `_method`, os três nomes e atribuições de método. Revise grupos de rotas e módulos antigos mantidos por atualizações.

Examine depois o caminho de rede. Distribuição, balanceador, malha, proxy, servidor e framework podem normalizar e registrar de modo diferente. Confirme que nenhuma rota pública evita a rejeição. Rede interna não torna confiáveis cabeçalhos controlados pelo chamador.

Remover pode quebrar clientes, por isso é adiado. Meça uso registrando presença, sem segredos ou corpos completos. Anuncie a retirada, falhe claramente em testes e remova servidor e regra juntos. Manter compatibilidade escondida custa mais que migrar seus usuários.

## Os logs precisam dos dois métodos

Uma auditoria deve guardar método de transporte, método efetivo, fonte, valor normalizado, rota, identidade, alvo, decisão, resposta e resultado. Sem os dois métodos não se explica como POST chegou a DELETE. Sem resultado só há intenção.

Registre também rejeições ambíguas. Um conflito importa mesmo sem chegar ao manipulador. Guarde nomes e tokens normalizados, não autorização ou corpos alheios. Limite e escape valores inválidos para caracteres de controle não falsificarem linhas.

Una camadas com identificador criado no primeiro salto confiável. Substitua ou isole qualquer identificador externo. Borda, resolvedor, aprovação, aplicação e tarefa assíncrona devem carregar o mesmo.

Nomeie campos com precisão. `method` convida significados diferentes. Use `transport_method` para a linha e `effective_method` para a ação. Mapeie `originalMethod` deliberadamente, sem assumir sentido igual em todo framework.

Sallyport executa a chamada HTTP do agente sem expor a credencial e registra a chamada no Activity. Essa separação não torna uma substituição segura; a revisão ainda precisa classificar o método efetivo antes da execução.

A evidência contra adulteração importa depois de uma execução autônoma. Um registro encadeado por hash revela edições, mas não recupera semântica ausente. Registre a ação normalizada na decisão, não em tarefa posterior que tente inferi-la.

O painel deve mostrar divergências. Contar `transport_method != effective_method` por serviço e fonte revela tráfego inesperado. Alerte sobre novas fontes, ambiguidades e métodos destrutivos cuja aprovação guardou só o externo.

## Um teste de regressão deve falhar com segurança

A correção duradoura é um teste contratual no caminho implantado que falha quando substituição não aprovada muda estado. Um teste unitário não detecta regra de proxy removida, middleware reordenado ou novo acesso.

Escreva o resultado esperado de cada caso. Com túnel desativado, todo sinal deve dar 4xx documentado sem alteração. Com uma convenção aceita, seu DELETE deve coincidir com o nativo em autorização, aprovação, rota e auditoria. Conflitos e tokens desconhecidos falham antes de efeitos.

Inclua estas asserções:

- a aprovação nomeia o método efetivo;
- formas nativa e tunelada recebem a mesma autorização;
- entradas rejeitadas não mudam versão nem contadores;
- os dois métodos compartilham identificador confiável;
- acesso direto não pula a normalização.

Rode a suíte quando mudarem proxy, framework, autenticação, aprovação, rotas ou ferramentas. Execução noturna detecta desvio e bloqueio de release detecta mudanças deliberadas. Isole o fixture de dados humanos.

Trate uma nova convenção como mudança de segurança, mesmo chamada de compatibilidade. Exija responsável, necessidade, precedência, método externo, conjunto efetivo e critério de retirada. Caso contrário, uma linha de middleware amplia silenciosamente as ações que os controles entendem.

Um sistema limpo usa uma descrição de ação da entrada ao resultado. Se a rede diz POST e a aplicação DELETE, a diferença deve aparecer antes de alguém ou algum componente dizer sim. Depois, resta reconstruir o incidente.
