O que Imposição de Código faz?
Visão Geral
Um guarda é julgado pelo que recusa quando alguém tenta contorná-lo, não pelo fato de passar em seu caminho feliz. Os dois modos de falha que sobrevivem à revisão são um controle que inspeciona uma representação do valor perigoso em vez do valor em si, e um controle que retorna sucesso porque não pôde ser executado. Ambos parecem verdes em todos os testes escritos com base nas suposições do autor.
Uso
Siga as etapas abaixo ao escrever ou alterar um hook, um guarda, um validador, uma verificação de permissão, uma regra de lint ou um portal de CI — antes de abrir o arquivo, pois a etapa 1 frequentemente muda onde o código deve ficar.
Casos típicos: "bloquear rm -rf fora do repositório" (a etapa 1 move a decisão para fora da string de comando), "reprovar CI quando uma migração não tem rollback" (as etapas 3 e 4 impedem que o portal passe quando a lista de migrações retorna vazia), "recusar um push sem um commit assinado" (a etapa 5 enumera o alias, --no-verify e o segundo remote).
Etapas
- Nomeie o sink. Escreva o valor exato que atinge o que você protege: o argv expandido, o corpo da requisição, o parâmetro SQL, o caminho resolvido. Valide esse valor.
- Verifique se você pode realmente vê-lo. Se o código tem apenas uma representação do valor — uma string de comando shell, um diff, uma linha de log, uma mensagem de commit — a decisão é uma heurística, não uma verificação. Diga isso em um comentário e na nota de entrega, e rotule essa camada como consultiva. Não deixe que uma heurística seja a única barreira para uma consequência que você não pode desfazer.
- Falhe fechado. Tempo de execução ausente, entrada ilegível, exceção do parser, variável não resolvida, resultado vazio: recuse e nomeie o que estava faltando. Um guarda que sai com 0 porque não pôde ser executado é um guarda desabilitado, e ele permanece desabilitado silenciosamente por meses.
- Mantenha a falha da sonda visível. Sem
2>/dev/nullno comando que decide se o guarda pode executar, e sem nenhum branch que transforme um resultado vazio em sucesso. Se for permitido que a sonda falhe silenciosamente, a etapa 3 se torna inexequível. - Enumere os contornos antes de escrever a correção. Liste como o controle pode ser satisfeito ou ignorado: comando composto, flags duplicadas, uma segunda invocação, um alias ou função, um interpretador ausente, outro host, um subshell, um arquivo renomeado. Mantenha a lista no corpo do commit ou no arquivo de teste.
- Transforme cada entrada dessa lista em um caso de teste conectado às verificações automatizadas do projeto. Um auto-teste manual não conta: ele desaparece com a sessão que o executou.
- Quando um contorno é barato e sua consequência real, execute uma passagem adversarial. Envie um subagente de contexto fresco cujo mandato é quebrar o guarda, não revisá-lo; sua saída é a lista de tentativas e seus resultados. Pule isso para um controle cujo pior caso é um aviso.
Pegadinhas
- Analisar um comando shell para decidir. Aspas,
$(),&&, aliases e prefixosenvtodos mudam o que é executado de fato. Tal camada é um redutor de velocidade; a verificação real pertence onde o efeito do comando é aplicado. - Guardas
command -v.if command -v ferramenta > /dev/null; then verificar; fiignora silenciosamente a verificação em qualquer máquina sem a ferramenta — exatamente a máquina que mais precisa dela. Inverta: recuse quando a ferramenta estiver ausente. - Uma etapa de descoberta que não encontra nada.
git grep -Enão suporta\b, então tal padrão corresponde a zero arquivos sem erro, e o portal passa sem ter lido nada. Proteja a etapa com um canário: um arquivo que você sabe que deve aparecer em sua saída. - Testar apenas a recusa que você implementou. O teste interessante é a entrada que você não pensou; é isso que a etapa 5 produz.
- Um guarda testado apenas manualmente. Ele passa na máquina do autor, então apodrece. Se o projeto não tem onde conectar o teste, essa estrutura ausente faz parte do trabalho.
- O contexto que escreveu o guarda não consegue quebrá-lo. Ele compartilha os pontos cegos que produziram a brecha e confirmará seu próprio design. Apenas um contexto fresco é adversarial.
Restrições
- Nunca decida sobre um proxy do valor protegido quando o valor em si estiver acessível.
- Nunca saia com 0 em um caminho onde o guarda não pôde fazer seu trabalho; recuse e nomeie a causa.
- Nunca sufoque os erros da sonda que estabelece se o guarda pode executar.
- Cada contorno enumerado deve existir como um teste automatizado antes da entrega.
- Declare claramente qual camada é consultiva e qual é impositiva; uma heurística apresentada como garantia é pior do que nenhum guarda.