Dev & EngARTICLE

CodeQL 2.27.1 gets C/C++ queries and Kotlin 2.4.20 support

The version released on September 25, 2026 refines GitHub's static analysis engine with new taint flow models for C/C++, adjustments to Kotlin's K2 compiler, and fixes that reduce false positives across several languages.

GitHub released version 2.27.1 of CodeQL, the static analysis engine that runs behind GitHub Advanced Security's code scanning, on September 25, 2026. It's not a relaunch or a rewrite: it's one of those incremental updates that only really matter to those who already depend on the tool day to day and feel it firsthand when it misses the target. And here the whole package revolves around an annoying, recurring problem in any static scanner: false positives that make the team ignore the next alert.

What changes in C/C++

The most concrete news for anyone maintaining C/C++ code in production is the arrival of data flow models for three specific APIs. boost::asio::ip::basic_resolver::resolve received a proper taint flow model, while BloombergLP::bdlbb::Blob (the segmented byte buffer from the Bloomberg Development Environment) and the C++ API google::protobuf::MessageLite received flow summaries, a distinct model category according to GitHub's changelog. Taint flow, for those who don't breathe static analysis every day, is the tracking of potentially tainted data (user input, for example) through function calls to a sensitive destination (a sink), such as command execution or writing to disk. Without a specific model for an API, CodeQL simply doesn't know that function propagates taint (or, in the case of flow summaries, how the data flows through it), and the data flow dies there without an alert.

In practice: if your service resolves a network address via boost::asio and passes the result along without validation, CodeQL now has a real chance of flagging it as part of an SSRF or injection chain. Before, that specific call was a blind spot. A trade-off warning is in order: a new taint flow model tends to generate more findings in the first scan after the upgrade, including in legacy code that had been sitting there for years. This isn't a regression in the tool, it's the tool seeing what it previously ignored, but prepare the team for extra triage in the first round.

The version also adds the cpp/ambiguous-assignment-of-comparison query, which catches that classic if (x = compare(a, b)) where the result of a comparison is assigned to a variable and then used as a truth value. It's a subtle bug, the kind that goes unnoticed in code review because it compiles silently and the wrong behavior only shows up at runtime.

Kotlin 2.4.20 and the K2 compiler

For those working with Android or JVM back-end in Kotlin, the relevant update is official support for Kotlin 2.4.20 and a fix in the argument extraction for Foo::class.java-type expressions when the project uses the K2 compiler. According to GitHub's changelog, this fix "reduces false positives in queries such as java/android/implicit-pendingintents", meaning projects that migrated to K2 (the Kotlin compiler that became the default in the most recent versions) and ran CodeQL had been receiving implicit PendingIntent alerts that didn't match the actual code, because the extractor wasn't correctly interpreting this class-reference pattern under the new compiler.

If your team updated to K2 months ago and stopped trusting Android security alerts because they were "always wrong", it's worth running the scan again with 2.27.1: that's exactly the scenario this fix addresses.

Effects on Go, JavaScript/TypeScript, and Rust

Go got data flow models for standard library 1.27 APIs, including bytes.CutLast, database/sql.ConvertAssign, net/url.URL.Clone, and the new encoding/json/jsontext package, plus expanded models in the strings package (Clone, Cut, CutPrefix, CutSuffix, Fields, Builder, Reader, Replacer). It's coverage maintenance keeping up with the stdlib's evolution: without it, every new Go API becomes a temporary blind spot until someone on the CodeQL team models the flow.

In JavaScript/TypeScript, CodeQL now recognizes Fastify servers configured through method chaining, such as fastify().withTypeProvider() and fastify().setValidatorCompiler(...). This improves route attribution, which can both add new results to the js/missing-rate-limiting query (routes that previously slipped through because they weren't recognized as Fastify routes) and remove false positives when globally registered plugins already protect those routes. It's the kind of adjustment that only matters for those who use Fastify specifically with this fluent configuration style; those using Express or Koa won't notice any difference here.

Rust received taint flow models for core::fmt::Write, improving detection of tainted data written to formatted output buffers, plus a fix in path resolution for m::{self} when m is a trait. The Rust extractor also moved to rust-analyzer 0.0.347, an update that changes the Rust library's AST with new node types and access APIs; anyone maintaining custom CodeQL queries for Rust needs to check the full 2.27.1 changelog before updating, because this AST change can break custom queries that relied on the old structure.

C# and GitHub Actions also changed

The C# query list gained cs/linq/missed-firstordefault, which suggests rewriting a foreach that only searches for the first matching element using LINQ's FirstOrDefault. The cs/linq/missed-* family of queries also stopped suggesting a rewrite to lambda when the parameter is in, out, or ref, a suggestion that used to generate code that simply didn't compile, because lambdas don't accept those modifiers. And cs/web/missing-token-validation now recognizes AutoValidateAntiforgeryTokenAttribute registered as a global MVC filter via AddControllersWithViews, reducing false alerts in actions that were already protected that way.

On the GitHub Actions side, actions/unpinned-tag stopped reporting actions pinned by a valid entry in .github/workflows/actions.lock and stopped flagging references to the repository itself via $/path/to/action, which resolve to the same commit being executed and are, by definition, already pinned.

What doesn't change and where the catch is

It's worth reinforcing what this version isn't: it's not an engine rewrite, it doesn't change CodeQL's query language, it doesn't add a new language to coverage. It's incremental polish, and most of the real gain is in reducing noise (false positives) rather than in finding a new vulnerability category. For those already running CodeQL with GitHub Advanced Security directly on github.com, the deployment is automatic and transparent. Those using GitHub Enterprise Server need version 3.24 to get 2.27.1 natively; on older GHES versions, you can do a manual CodeQL upgrade, but that's an extra step many teams put off, and end up running for months with the false positives the update already fixed.

Finally, a change that slips by in the changelog but affects the build pipeline: private NuGet registries with the Replaces option enabled in the organizational configuration now replace NuGet's default feeds whenever CodeQL downloads dependencies, even when the project explicitly configures the default feeds. Anyone working in .NET with a corporate private registry should check whether this precedence change breaks any package resolution expectations in the scan.

Translated from the Brazilian Portuguese original · Read the original