CodeQL 2.27.2 was released on October 7. In the release notes, the item most likely to affect existing queries is the Go library change.
This release reimplements Go’s control flow graph (CFG) on the shared CFG library. A CFG represents the order in which code can execute as nodes and edges.
New nodes represent assignments, function parameters and results, range statements and deferred calls. Nodes unreachable from the entry point are excluded, and basic blocks are built directly from the shared CFG.
Existing code that relies on specific nodes, edges, locations, textual representations or basic-block boundaries may need updating.
API changes to look for in custom query packs
BasicBlocks::Cfg has been removed, and ControlFlow::EntryNode and ControlFlow::ExitNode have been added.
IfStmt.getCond is deprecated in favor of IfStmt.getCondition. The return types of IfStmt.getThen and LoopStmt.getBody widened from BlockStmt to Stmt.
Several IR instruction classes, including ReadArgumentInstruction and SelectInstruction, were removed or consolidated.
Renaming APIs can clear compile errors while deeper assumptions about graph shape or returned statement types remain.
Build-mode limits on macOS 27 and Xcode 27
GitHub’s October 9 post added a separate environment limit. Starting with macOS 27 and Xcode 27, Apple stopped shipping multi-architecture x86-64/arm64 binaries, which traced analysis requires.
As a result, autobuild and manual modes for compiled languages are not supported on macOS 27 with any Xcode version, or on macOS 26 with Xcode 27 selected. For these modes, macOS 26 and Xcode 26 or earlier are recommended.
Improved macOS support for build mode none is work in progress. It is not a universal workaround available now, nor does the limit mean every CodeQL check on every Mac is impossible.
Two gates: database creation and query meaning
The transition is easier to manage as two gates. The first is whether the chosen runner, OS, Xcode and build mode produce the intended database.
Recording the versions actually applied is more accurate than trusting a familiar runner name.
The second is evaluating query packs against representative test inputs and known findings. Separating them avoids debugging queries whose extraction never finished, or assuming query meaning survived because the runner is supported.
Go inputs that exercise what the queries assume
Go review fits inputs that touch what a query actually assumes. For a query that follows statement boundaries, include cases where the changed APIs return a plain Stmt rather than a BlockStmt.
For a query that walks paths, look at expected reachable paths together with code made unreachable on purpose.
Total alert counts are not enough. One finding can disappear and another appear under the same count, and a count change may be an intended fix.
Caveats: unrun validation and extraction failures
The release notes and follow-up post ground this transition plan, but this article did not run queries, extractors or CI runners.
An extraction failure is a failed security check. It is not something to treat as safe code because there are no findings.
A successful query compile is only one step of compatibility validation.
An upgrade result is acceptable only when it can be explained by which detections kept their meaning on which database, not by alert counts.
