O changelog do GitHub apresenta o CodeQL 2.27.1 como uma versão de novas queries e suporte a linguagens, mas o ganho real está em outro lugar: menos alerta falso e menos ponto cego no rastreamento de dados.
Scanner estático que grita demais vira ruído. E ruído vira alerta ignorado. É assim que uma vulnerabilidade de verdade passa pelo pipeline com o selo de "já vimos esse tipo de aviso, é falso positivo".
O CodeQL 2.27.1, publicado pelo GitHub em 25 de setembro de 2026, ataca exatamente esse problema. Não é versão de manchete: não muda a linguagem de query, não reescreve o motor e não adiciona linguagem nova. É uma atualização incremental. Mas, para quem já roda code scanning no dia a dia, ela mexe nos dois pontos que definem se o time confia ou não na ferramenta: o que ela enxerga e o que ela reporta sem motivo.
Antes de tudo: o que é taint flow e por que um modelo novo importa
Boa parte das mudanças desta versão são "modelos de fluxo de dados". Vale entender o conceito antes de olhar a lista.
Taint flow é o rastreamento de um dado potencialmente contaminado, como uma entrada de usuário, desde a origem (source) até um ponto sensível (sink): execução de comando, query no banco, requisição de rede, escrita em disco. O CodeQL segue esse dado de chamada em chamada. O problema é que ele só sabe que uma função propaga o dado se alguém modelou essa função. Se não existe modelo, o rastreamento morre ali, sem erro e sem alerta.
O changelog usa dois tipos de modelo, e a diferença é sutil:
- Modelos de taint flow: dizem ao motor que aquela API participa da cadeia de contaminação.
- Flow summaries: resumem como o dado entra e sai de uma função ou tipo, sem o motor precisar analisar a implementação por dentro. Muito útil para bibliotecas externas.
Cada modelo novo é um ponto cego a menos. E é por isso que uma versão "só de modelos" pode mudar bastante o resultado do seu próximo scan.
C/C++: três APIs deixam de ser invisíveis
A mudança mais concreta para quem mantém C/C++ em produção é a cobertura de três APIs bastante usadas:
| API | O que é | Tipo de modelo adicionado |
|---|---|---|
boost::asio::ip::basic_resolver::resolve |
Resolução de endereços de rede no Boost.Asio | Taint flow |
BloombergLP::bdlbb::Blob |
Buffer de bytes segmentado do Bloomberg Development Environment | Flow summary |
google::protobuf::MessageLite |
API C++ do Protocol Buffers | Flow summary |
Na prática, se um serviço resolve endereço via Boost.Asio e repassa o resultado sem validação, essa chamada deixa de ser um buraco na análise. O mesmo vale para dados que atravessam mensagens Protobuf, algo comum em qualquer arquitetura que conversa via gRPC.
Aqui mora um efeito colateral que precisa ser comunicado ao time: modelo novo tende a gerar mais achados no primeiro scan após o upgrade, inclusive em código legado que estava lá havia anos. Não é regressão. É a ferramenta enxergando o que antes ignorava. Planeje uma rodada extra de triagem.
A nova query cpp/ambiguous-assignment-of-comparison
A versão também traz a query cpp/ambiguous-assignment-of-comparison. Ela aponta expressões que atribuem o resultado de uma comparação a uma variável e usam essa atribuição como valor de verdade. É o tipo de código que compila sem reclamar e deixa dúvida sobre a intenção de quem escreveu. Um exemplo ilustrativo:
bool encontrado;
// Atribuição ou comparação? O compilador aceita, o leitor hesita.
if (encontrado = total > 0) {
processar();
}
// Intenção explícita: separe a atribuição do teste
encontrado = (total > 0);
if (encontrado) {
processar();
}
É bug de code review: passa pelo olho humano justamente porque parece certo.
Kotlin 2.4.20 e o falso positivo do compilador K2
Para quem trabalha com Android ou back-end JVM em Kotlin, são duas mudanças: suporte oficial ao Kotlin 2.4.20 e uma correção na extração de argumentos no formato Foo::class.java quando o projeto usa o compilador K2.
O detalhe importa porque esse padrão aparece em todo lugar no Android, principalmente na criação de Intents explícitas:
// Intent explícita: o destino está definido pela classe
val intent = Intent(context, DetalheActivity::class.java)
val pending = PendingIntent.getActivity(
context, 0, intent, PendingIntent.FLAG_IMMUTABLE
)
Segundo o GitHub, a correção reduz falsos positivos em queries como java/android/implicit-pendingintents. Ou seja: se o extrator não interpreta a referência de classe corretamente, uma Intent explícita pode parecer implícita, e o alerta de PendingIntent implícito dispara onde não deveria.
Se o seu time migrou para o K2 e passou a tratar esses alertas como "sempre errados", vale rodar o scan de novo com a 2.27.1. É exatamente esse cenário que a correção resolve.
Go: a cobertura acompanhando a stdlib 1.27
No Go, o trabalho é de manutenção de cobertura. Toda API nova da biblioteca padrão nasce como ponto cego até alguém modelar o fluxo. Nesta versão entraram ou foram melhorados modelos para APIs do Go 1.27:
bytes.CutLastestrings.CutLast;database/sql.ConvertAssignedatabase/sql/driver.RowsColumnScanner.ScanColumn;net/url.URL.Cloneenet/url.Values.Clone;- o novo pacote
encoding/json/jsontext.
O pacote strings também ganhou modelos mais amplos: Clone, Cut, CutPrefix, CutSuffix, Fields, FieldsFunc, Join, Builder, Reader e Replacer.
Parece detalhe, mas pense no caminho típico de uma entrada HTTP em Go: ela é cortada, limpa, concatenada e, no fim, vira parte de uma URL ou de uma query. Se uma dessas funções de string não está modelada, a cadeia se rompe no meio e o sink final nunca é alcançado pela análise.
// Ilustrativo: o dado do usuário atravessa funções de strings
alvo := r.URL.Query().Get("destino")
_, caminho, _ := strings.Cut(alvo, "://")
url := strings.Join([]string{"https://", caminho}, "")
// Sem modelo para Cut/Join, o rastreamento poderia parar antes daqui
resp, err := http.Get(url)
[COMPLETAR: experiência minha com Go, se houver algum caso de validação de entrada ou análise estática]
JavaScript/TypeScript: Fastify no estilo encadeado
O CodeQL agora reconhece servidores Fastify configurados por métodos encadeados, como fastify().withTypeProvider() e fastify().setValidatorCompiler(...).
const app = fastify().withTypeProvider();
// Antes, rotas registradas a partir desse encadeamento
// podiam não ser atribuídas corretamente ao servidor
app.post('/login', async (request, reply) => {
// ...
});
A melhora na atribuição de rotas corta nos dois sentidos. Pode adicionar resultados em queries como js/missing-rate-limiting, porque rotas que passavam despercebidas agora são vistas. E pode remover falsos positivos quando plugins registrados globalmente já protegem essas rotas. Quem usa Express ou Koa não sente diferença aqui.
Rust: atenção se você mantém queries próprias
Três mudanças no Rust:
- modelos de fluxo de dados para
core::fmt::Write, melhorando a detecção de dado contaminado escrito em buffers de saída formatada; - correção na resolução de caminhos
m::{self}quandomé um trait; - o extrator passou a usar o
rust-analyzer0.0.347.
A terceira é a que exige cuidado. A atualização do rust-analyzer muda a AST da biblioteca Rust com novos tipos de nó e novas APIs de acesso. Se o seu time mantém queries CodeQL customizadas para Rust, leia as notas de migração no changelog completo da 2.27.1 antes de atualizar. Query que dependia da estrutura antiga pode quebrar.
C#: uma query nova e duas sugestões que deixam de errar
A query cs/linq/missed-firstordefault identifica loops foreach que só procuram o primeiro elemento correspondente e poderiam ser escritos com FirstOrDefault:
// Antes: loop manual para achar o primeiro
Pedido? pendente = null;
foreach (var p in pedidos)
{
if (p.Status == Status.Pendente)
{
pendente = p;
break;
}
}
// Depois: a intenção fica explícita
var pendente = pedidos.FirstOrDefault(p => p.Status == Status.Pendente);
Além disso:
- As queries da família
cs/linq/missed-*pararam de sugerir reescritas com lambda que capturam parâmetrosin,outouref. Essas sugestões geravam código que não compilava, já que lambdas não podem capturar esses parâmetros. - A
cs/web/missing-token-validationagora reconhece oAutoValidateAntiforgeryTokenAttributedo ASP.NET Core quando registrado como filtro MVC global viaAddControllersWithViewse métodos relacionados. Menos alerta falso em ações que já estavam protegidas.
GitHub Actions: menos barulho no pinning
A query actions/unpinned-tag, que cobra que as actions usadas no workflow estejam fixadas, ficou mais precisa em dois casos:
- não reporta mais actions fixadas por uma entrada estruturalmente válida em
.github/workflows/actions.lockpara o workflow em questão; - não reporta mais referências ao próprio repositório, como
uses: $/path/to/action, que resolvem para o mesmo commit em execução e, por isso, já são fixadas por natureza.
A mudança que passa batido: NuGet privado
Tem um item no fim do changelog que não é sobre query, mas pode afetar o build do scan. Registros NuGet privados com a opção Replaces base ativada na configuração de registro privado da organização agora substituem os feeds padrão do NuGet sempre que o CodeQL baixa dependências. Isso vale mesmo quando o projeto configura explicitamente os feeds padrão.
Para quem trabalha em .NET com registro corporativo, vale conferir se essa regra de precedência não muda a resolução de algum pacote durante a análise.
Quem recebe a atualização e quando
| Ambiente | Como chega a 2.27.1 |
|---|---|
| Code scanning no github.com | Deploy automático, sem ação do time |
| GitHub Enterprise Server 3.24 | Incluída nativamente |
| GHES em versões anteriores | Upgrade manual do CodeQL |
A última linha é a que exige atenção. Em GHES anterior à 3.24, as correções de falso positivo desta versão só chegam se alguém fizer o upgrade manual. O GitHub mantém um guia de atualização manual do CodeQL para esse cenário.
Checklist antes e depois do upgrade
- Aumento de alertas em C/C++ logo após a atualização? Provavelmente são os novos modelos de Boost.Asio, Bloomberg BDE ou Protobuf. Faça triagem antes de concluir que é regressão.
- Projeto Kotlin no K2 com alertas de PendingIntent ignorados? Rode o scan de novo e reavalie os que foram descartados em lote.
- Queries customizadas para Rust? Leia as notas de migração da AST antes de atualizar.
- API em Fastify com configuração encadeada? Espere mudanças em
js/missing-rate-limiting, para mais ou para menos. - .NET com NuGet privado e "Replaces base" ativo? Verifique se a resolução de pacotes no scan continua como esperado.
- GHES abaixo da 3.24? Coloque o upgrade manual do CodeQL no backlog com data, não com "quando der".
Nenhuma ferramenta de análise estática é útil se o time parou de ler os alertas. Versões como essa não ganham manchete, mas são elas que devolvem a confiança no scanner. E confiança, no fim, é o que faz alguém abrir o próximo alerta em vez de fechá-lo.
Fonte: GitHub Changelog
