Análise de taint é a técnica que separa achados úteis de ruído em ferramentas SAST: em vez de apontar qualquer ocorrência de função perigosa, a ferramenta rastreia dados não confiáveis da fonte até o sink e só acusa quando a contaminação sobrevive ao percurso. Times AppSec que rodam scanners no pipeline e afogam desenvolvedores em alertas imprecisos são os mais afetados pelo problema oposto, o excesso de achados sem traço de dados. A ação prioritária é modelar fontes, propagadores e sanitizadores do seu próprio código antes de ampliar a cobertura de regras — é esse ajuste, e não a troca de ferramenta, que reduz falsos positivos na origem.
Como a análise de taint funciona
Na documentação do Semgrep, a análise de taint é descrita como uma análise de fluxo de dados que acompanha dados não confiáveis ao longo do corpo de uma função ou método. Três papéis definem a regra: as fontes, de onde vem o dado controlável por fora do programa; os sinks, funções vulneráveis onde o dado contaminado causa dano; e os sanitizadores, padrões que limpam ou validam o dado no caminho, com propagadores descrevendo como a sujeira atravessa atribuições e chamadas.
Para ativar o modo, a regra em YAML recebe mode: taint e passa a aceitar os operadores pattern-sources, pattern-propagators, pattern-sanitizers e pattern-sinks. A dupla fonte–sink é o coração da regra: fontes largas demais contaminam trechos que nunca recebem entrada externa, e sinks estreitos demais deixam passar chamadas perigosas. O mesmo raciocínio vale quando o escopo do pipeline cobre mais que código próprio — o consumo de bibliotecas de terceiros também entra na superfície de análise, como no guia de maturidade no consumo de open source.
Quando uma bibliativa da linguagem propaga sujeira de um argumento para outro, o propagador customizado resolve o caso clássico: se a sujeira entra no segundo argumento de strcpy, o primeiro argumento sai contaminado. A documentação registra o limite importante: propagadores customizados funcionam apenas dentro da função ou método — atravessar fronteiras de função exige análise interprocedural.
Por que os falsos positivos aparecem
A OWASP é direta sobre o limite do estado da arte: ferramentas de análise estática servem, na prática, de apoio ao analista, e não de detector automático de falhas. Falsos positivos surgem porque a ferramenta não consegue garantir a integridade e a segurança dos dados ao longo do fluxo da aplicação, da entrada à saída — limite que piora quando o código interage com componentes fechados ou sistemas externos cujo fluxo interno não pode ser rastreado.
A lista de fraquezas da OWASP explica por que nenhum ajuste elimina todo o ruído: problemas de configuração não aparecem no código-fonte, muitos tipos de falha — autenticação, controle de acesso, uso incorreto de criptografia — são difíceis de achar automaticamente, e provar que um achado é vulnerabilidade real ainda depende de revisão humana.
A própria mecânica do casamento de padrões adiciona ruído. No Semgrep, quando um padrão de fonte como source(...) casa com uma expressão inteira, todas as subexpressões passam a contar como fontes — inclusive argumentos que nunca recebem entrada do usuário. A opção exact: true existe para restringir a fonte ao casamento exato e cortar esse tipo de achado. Há ainda o aviso da documentação: metavariáveis usadas em pattern-sources são tratadas como distintas das usadas em pattern-sinks, mesmo quando têm o mesmo nome — detalhe que derruba regras aparentemente corretas.
Ajuste de fontes e sanitizadores
O ajuste com melhor relação custo–benefício é declarar explicitamente os sanitizadores do seu domínio. Funções de escape de HTML, consultas parametrizadas e validadores de formato costumam existir no código, mas a regra genérica não sabe disso; cada sanitizador declarado remove de uma vez todos os achados em que o dado já estava limpo no ponto do sink.
Na direção oposta, fontes devem ser fechadas. A opção exact em fontes e sanitizadores controla se subexpressões do casamento contam como contaminadas ou limpas, e a recomendação da documentação é deixar o valor explícito (exact: false ou true) para que a regra não quebre se o padrão mudar. Nos sinks, o comportamento padrão já é o casamento exato — subexpressões não são sinks por padrão — e exact: false amplia o alcance quando necessário.
Um detalhe operacional da triagem: o Semgrep rastreia todos os caminhos possíveis pelos quais a contaminação chega ao sink, mas reporta apenas um traço por achado. Em revisão manual, isso significa que limpar um caminho não garante que o alerta suma — o mesmo sink pode estar contaminado por outra rota que o traço não mostrou.
Escopo entre arquivos e memória
Por padrão, a análise de taint é intraprocedural: acompanha o dado dentro da função onde nasce. A análise interprocedural, que cruza chamadas de função, é recurso do Semgrep Pro, com dois níveis práticos: --pro-intrafile cruza funções dentro do mesmo arquivo, com desempenho próximo ao intraprocedural, e --pro habilita análise entre arquivos, suportada para um subconjunto de linguagens e que exige interfile: true na própria regra.
O custo não é trivial: a documentação recomenda 8 GB de memória por núcleo ou mais para análise entre arquivos, com mínimo declarado de 4 GB. Em um runner de CI com poucos vCPUs, isso muda o dimensionamento do job e o tempo de fila do pipeline. A decisão prática em prioridades: comece intraprocedural nas regras de injeção (P1), adote --pro-intrafile quando a base concentra helpers no mesmo arquivo (P2) e reserve a análise entre arquivos para repositórios em que a entrada do usuário atravessa módulos (P3).
Checklist de triagem dos achados
Cada alerta de taint merece uma pergunta antes de virar ticket ou exceção. A tabela resume o roteiro mínimo aplicável a qualquer ferramenta com esse modo, e mantém critérios explícitos de auditoria — o mesmo princípio usado ao auditar infraestrutura com o kube-bench em clusters.
| Achado | Primeira pergunta | Ação |
|---|---|---|
| Traço simples em um sink | Existe outra rota de contaminação para o mesmo sink? | Corrigir no sink ou registrar exceção com prazo |
| Fonte que casa subexpressões | A expressão marcada recebe entrada externa de fato? | Aplicar exact: true na fonte e reexecutar |
| Chamada a helper próprio | O helper valida, escapa ou apenas repassa o dado? | Declarar o helper como sanitizador na regra |
| Regra que não casa nada | Metavariáveis de fonte e sink têm o mesmo nome? | Renomear metavariáveis e testar no playground |
Limite declarado do método: a análise de taint cobre fluxo de dados dentro do escopo configurado; ela não avalia configuração de ambiente, controle de acesso entre serviços nem decisões de produto. O scanner prioriza onde olhar — a decisão de corrigir continua sendo da equipe.