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 Results

Instead 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
Review

What 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 Components

This 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 Components

The runner may only require one platform's components.

A platform-specific bundle instead looks more like:

Linux Runner
    |
    v
Linux CodeQL Bundle

This 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 Runner

After the transition, the workflow may need to identify the platform first:

CI Runner
   |
   +--> Linux    -> Linux Bundle
   |
   +--> Windows  -> Windows Bundle
   |
   +--> macOS    -> macOS Bundle

The 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@v3

The 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 version

The 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 scripts

These 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
+-- macOS

If 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 Version

The 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 Package

Therefore, 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_URL

The 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 registry

Check 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.sh

For example:

#!/usr/bin/env bash

CODEQL_VERSION="X.Y.Z"

# Download and install CodeQL

If 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.Z

That provides reproducibility.

When changing the package format, verify:

Version
Operating System
Architecture
Checksum
Installation Path

If 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 complete

There are several additional checks.

After installation, verify:

codeql version

Then run a real analysis.

For example:

Install
   |
   v
Version Check
   |
   v
Database Creation
   |
   v
Analysis
   |
   v
SARIF Results

A 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 version

could 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 host

Step 2 - Check the Installed Version

Run:

codeql version

Confirm that the expected version is actually being used.

Step 3 - Find the Executable

On Unix-like systems:

which codeql

On Windows:

Get-Command codeql

This 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.ql

or 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 permissions

in 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 Runners

For 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 monitored

Summary 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.