CodeQL is widely used to identify security issues in source code as part of a development and CI workflow. For teams running CodeQL through GitHub Actions or the CodeQL CLI, changes to how the CLI is packaged can affect installation, automation, and maintenance.
One important change is the move away from the traditional all-platform CodeQL CLI bundle toward platform-specific bundles.
For teams that download or install CodeQL directly, this means the way the CLI is selected and configured in CI may need to change.
The important part is not simply replacing one download URL with another. Teams should understand which operating systems their pipelines use, how CodeQL is installed, and whether their automation assumes that one package works everywhere.
What Is CodeQL?
CodeQL is a static analysis technology used to find security vulnerabilities and other coding problems by analyzing source code.
A simplified workflow looks like this:
Source Code
|
v
CodeQL Analysis
|
v
Queries
|
v
Findings
|
v
Security ResultsInstead of looking only for known strings or patterns, CodeQL represents code in a form that can be queried.
A CI workflow can therefore include CodeQL alongside normal build and test steps:
Pull Request
|
+--> Build
|
+--> Unit Tests
|
+--> CodeQL Analysis
|
+--> Dependency Checks
|
v
ReviewWhat Is the All-Platform Bundle?
Historically, CodeQL CLI distribution could be obtained in a bundle designed to support multiple platforms.
Conceptually, that means one package could contain components needed for different environments:
CodeQL Bundle
|
+-- Linux
+-- Windows
+-- macOS
+-- CodeQL CLI
+-- Supporting ComponentsThis was convenient for environments where the same bundle needed to work across different operating systems.
The platform-specific approach changes that model.
Instead of treating one package as a universal installation, the CI environment should select the package appropriate for the operating system and architecture being used.
Why Is CodeQL Moving Toward Platform-Specific Bundles?
A multi-platform package can include components that a particular machine does not need.
For example:
Linux Runner
|
v
All-Platform Bundle
|
+--> Linux Components
+--> Windows Components
+--> macOS ComponentsThe runner may only require one platform's components.
A platform-specific bundle instead looks more like:
Linux Runner
|
v
Linux CodeQL BundleThis provides a clearer relationship between the runtime environment and the software package being installed.
The exact packaging and transition details should be checked against the current CodeQL documentation before modifying production workflows.
What Changes for CI?
The main impact is on pipelines that install or manage the CodeQL CLI themselves.
A workflow might currently depend on assumptions such as:
Download CodeQL
|
v
One Bundle
|
v
Any Supported RunnerAfter the transition, the workflow may need to identify the platform first:
CI Runner
|
+--> Linux -> Linux Bundle
|
+--> Windows -> Windows Bundle
|
+--> macOS -> macOS BundleThe actual implementation depends on how CodeQL is installed in the pipeline.
GitHub-Managed CodeQL Workflows
Teams using GitHub's managed CodeQL setup may have less installation work to perform because GitHub Actions can manage much of the CodeQL tooling.
A typical workflow might look like:
name: CodeQL
on:
push:
pull_request:
jobs:
analyze:
runs-on: ubuntu-latest
permissions:
security-events: write
packages: read
actions: read
contents: read
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Initialize CodeQL
uses: github/codeql-action/init@v3
with:
languages: csharp
- name: Build
run: dotnet build --no-restore
- name: Analyze
uses: github/codeql-action/analyze@v3The important point is that teams should distinguish between:
GitHub-managed CodeQL Actions
Direct CodeQL CLI installation
Custom CI scripts
Self-hosted runner installations
The migration impact can be different for each model.
Direct CodeQL CLI Installations Need More Attention
Some organizations download the CLI themselves.
For example, a custom pipeline may contain logic similar to:
curl -L "$CODEQL_URL" -o codeql.zip
unzip codeql.zip
./codeql/codeql versionThe exact commands vary by organization.
If the URL or package selection assumes an all-platform bundle, that logic should be reviewed.
Look for:
CODEQL_URL
CODEQL_VERSION
codeql.zip
codeql-bundle
download scripts
installation scriptsThese are common places where platform assumptions may exist.
Self-Hosted Runners Are Especially Important
Self-hosted runners deserve careful review because organizations control their operating systems and installation processes.
A company might have:
Self-Hosted Runners
|
+-- Windows
+-- Linux
+-- macOSIf the same installation script is used for all three, it may need to change to account for platform-specific CodeQL packages.
A simple architecture is:
Runner
|
v
Detect OS / Architecture
|
v
Select CodeQL Package
|
v
Install
|
v
Verify VersionThe package-selection logic should be tested separately on each runner type.
Check CPU Architecture Too
Operating system alone may not be enough.
A runner can also differ by CPU architecture.
For example:
Operating System
+
CPU Architecture
|
v
Correct CodeQL PackageTherefore, installation scripts should not blindly assume that every Linux machine or every Windows machine uses the same architecture.
This is particularly important when organizations use a mixture of hosted and self-hosted infrastructure.
Search Your CI Configuration First
Before changing anything, search the repository and CI infrastructure for CodeQL installation references.
For example:
grep -Rni "codeql" .github/On Windows PowerShell, an equivalent search can be performed with:
Get-ChildItem -Recurse .github | Select-String "codeql"You can also search for:
codeql-action
codeql-bundle
codeql-cli
CODEQL_VERSION
CODEQL_URLThe exact search command should match your operating system and repository structure.
Review Container Images
Some organizations run CodeQL inside custom containers.
For example:
FROM ubuntu:latest
COPY codeql /opt/codeql
ENV PATH="/opt/codeql:${PATH}"If the container contains a manually installed CodeQL bundle, inspect how that bundle was obtained.
A container image can hide the dependency from the repository's workflow files.
The real dependency may be in:
Dockerfile
Container build script
Base image
Installation script
CI image registryCheck Build Scripts Too
The CodeQL installation may not be defined directly in GitHub Actions.
It could exist in:
scripts/install-security-tools.sh
build.ps1
Makefile
Dockerfile
bootstrap.shFor example:
#!/usr/bin/env bash
CODEQL_VERSION="X.Y.Z"
# Download and install CodeQLIf this script is used by multiple repositories, changing one repository's workflow may not be enough.
Version Pinning Matters
Security tooling should not be upgraded blindly in production CI.
A pipeline may explicitly specify a CodeQL version:
CODEQL_VERSION=X.Y.ZThat provides reproducibility.
When changing the package format, verify:
Version
Operating System
Architecture
Checksum
Installation PathIf your organization verifies downloaded artifacts, continue applying those controls to the new package format.
Do Not Assume a Successful Download Means a Successful Migration
A common mistake is:
Download succeeds
|
v
Migration completeThere are several additional checks.
After installation, verify:
codeql versionThen run a real analysis.
For example:
Install
|
v
Version Check
|
v
Database Creation
|
v
Analysis
|
v
SARIF ResultsA CLI that starts successfully can still fail later when creating a database or executing queries.
Compare the Old and New CI Workflow
A useful migration approach is to compare both environments.
Area | Existing Workflow | Updated Workflow |
|---|---|---|
Package source | Existing bundle | Platform-specific package |
OS | Verify | Verify |
Architecture | Verify | Verify |
CodeQL version | Record | Record |
Installation path | Record | Verify |
Query packs | Test | Test |
Database creation | Test | Test |
Analysis | Test | Test |
SARIF upload | Test | Test |
Runtime permissions | Record | Preserve |
This creates a concrete migration checklist instead of treating the change as a simple download replacement.
Common CI Problems After a Packaging Change
Wrong Platform Package
The runner may receive a package intended for another operating system.
Wrong Architecture
The package may not match the runner's CPU architecture.
Broken PATH Configuration
The CLI may be installed successfully but unavailable through the expected command.
For example:
codeql versioncould fail even though the files exist.
Hard-Coded Download URLs
A script may assume the previous package naming convention.
Container Cache Problems
A CI environment may continue using an older CodeQL installation from a cached layer.
Shared Installation Scripts
One central script may be used by runners with different operating systems.
Version Mismatch
The CLI and related components may not match the expected versions.
How to Troubleshoot a Failed Migration
Start with the runner.
Step 1 - Identify the Environment
Record:
Operating system
CPU architecture
Runner type
Container or hostStep 2 - Check the Installed Version
Run:
codeql versionConfirm that the expected version is actually being used.
Step 3 - Find the Executable
On Unix-like systems:
which codeqlOn Windows:
Get-Command codeqlThis helps identify whether an old installation is still being selected.
Step 4 - Test Database Creation
Run the normal CodeQL initialization and database creation process.
Step 5 - Run Analysis
Confirm that queries execute successfully.
Step 6 - Verify Results
If your pipeline uploads SARIF results, confirm that the expected security findings reach the repository's security interface.
Query Packs Also Need Testing
Changing the CLI installation should not accidentally break query-pack resolution.
If your workflow uses custom queries:
queries/
|
+-- security.ql
+-- performance.qlor external query packs, verify that they still work after the migration.
A successful CLI installation is not enough if your organization's custom analysis depends on additional components.
Keep the Migration Small
Avoid changing multiple security controls at the same time.
For example, do not combine:
CodeQL package migration
+
New queries
+
New runner OS
+
New container
+
New permissionsin one change unless there is a clear reason.
A smaller migration makes failures easier to diagnose.
Use a Test Runner Before Production
A useful rollout looks like:
Development Runner
|
v
Migration Test
|
v
Security Analysis
|
v
Validation
|
v
Production RunnersFor organizations with many self-hosted runners, test each supported environment before rolling out the change broadly.
Best Practices for CodeQL CLI Migration
Inventory Current Installations
Find every place CodeQL is installed or referenced.
Identify Runner Platforms
Document operating systems and CPU architectures.
Prefer Supported Installation Methods
Use the installation approach recommended for your environment rather than maintaining unnecessary custom packaging logic.
Pin Versions Where Reproducibility Matters
Record the CodeQL version used by important pipelines.
Verify Download Integrity
Apply existing artifact verification controls to downloaded tooling.
Test Complete Analysis
Do not stop after checking codeql version.
Keep CI Permissions Minimal
The migration should not require broader repository permissions than necessary.
Monitor the First Production Runs
Look for failures in database creation, query execution, and result upload.
Advantages of Platform-Specific Bundles
Platform-specific packaging can provide:
A clearer relationship between package and runtime
Less unnecessary platform-specific content
Simpler environment targeting
More explicit installation behavior
Better alignment with the runner being used
The actual operational benefit depends on how your organization currently installs CodeQL.
Trade-Offs
The transition can also introduce additional maintenance work.
Teams may need to:
Update installation scripts
Detect operating systems
Detect architectures
Update container images
Review caches
Test multiple runner environments
Update internal documentation
For organizations with heterogeneous CI infrastructure, this can require more careful automation.
A Practical Migration Checklist
Before moving away from the all-platform bundle, verify:
[ ] CodeQL installation method is documented
[ ] All repositories using direct CLI installation are identified
[ ] Self-hosted runners are inventoried
[ ] Operating systems are documented
[ ] CPU architectures are documented
[ ] Installation scripts are reviewed
[ ] Container images are reviewed
[ ] CodeQL versions are recorded
[ ] Package sources are verified
[ ] Checksums or integrity controls are preserved
[ ] PATH configuration is tested
[ ] Query packs are tested
[ ] Database creation is tested
[ ] Analysis is tested
[ ] SARIF upload is tested
[ ] CI permissions remain appropriate
[ ] Production rollout is monitoredSummary of the Article
The move from an all-platform CodeQL CLI bundle toward platform-specific bundles mainly affects teams that manage CodeQL installation themselves. GitHub-managed workflows may require less direct installation work, while custom CI scripts, self-hosted runners, containers, and manually installed CodeQL environments deserve closer review.
The safest migration starts with an inventory of current installations. Identify operating systems, CPU architectures, download logic, container images, installation scripts, pinned versions, and custom query packs. Then test the new package in a controlled CI environment before rolling it out broadly.
A successful migration should verify more than the CLI version. Database creation, query execution, security analysis, and SARIF result handling should all continue to work.
The key lesson is simple: when a security tool changes its packaging model, treat the change as a CI infrastructure migration, not just a new download link.

Join the conversation! Your thoughts help the community grow.