CodeQL

LanguageMulti-language
Kindtool
Readiness🟡
Detector conformance🟡
Checked2026-09-08, version CLI 2.26.4

CodeQL is GitHub’s semantic code analysis engine. It extracts a relational database from a codebase and runs queries written in the QL language against it, and it is the engine behind GitHub code scanning. In a pipeline it is the deep, slow security check rather than the on-every-edit linter, and its licence binds it tightly to GitHub: outside open-source code it may only be used with a GitHub Advanced Security licence.

How it is conformant

Bespoke queries are first class (4.1): a project writes .ql files with @id and @kind metadata in its own pack declared by qlpack.yml, per using custom queries. There is a real proving harness (4.2): codeql test run takes a .qlref beside example code and an .expected file, builds a test database from the example files alone, and reports the diff (testing custom queries). The identifier is author-chosen and stable: @id is required and unique, lowercase letters and digits with / or - (query metadata), and it appears unaltered as ruleId on every SARIF result (SARIF support). Every query in a pack runs from the CLI with no hosted service in the loop (5.4). Query help travels with the query as a .qhelp or .md file and can be rendered by codeql generate query-help or embedded with --sarif-include-query-help (generate query-help), which meets 6.3 for bundled queries, and the CLI bundle is self-contained and documented for machines without internet access (setting up the CLI), so the help is on disk wherever the pack is. The github/codeql repository checks for duplicate @id values in CI, which is part of what 4.4 and 6.4 ask for, though the check is not shipped to consumers.

How it is not conformant

Clause 5.3 is failed: database analyze writes CSV or SARIF to a mandatory --output file with no terminal text format (database analyze), so the invoked command’s own output carries neither a summary of the findings nor, beyond the path the practitioner supplied, a pointer to them. Clause 4.3 is partial because of the same command: the CSV format’s columns are name, description, severity, message and location (CSV output), so one machine-readable format prints the query’s display name and not its @id, and whether query run prints the @id is not verified. Clause 5.1 is met technically and failed in practice for most projects. No server is required, but every run needs a database built first, with a full build for most compiled languages unless --build-mode none applies (creating databases), and the CLI licence forbids use on private codebases without a paid GitHub Advanced Security licence. That licence condition is what puts the readiness grade at amber: a practitioner on private code cannot legally follow the method with this tool alone. Clause 5.2 is partial: analysis targets a whole database, and only the test harness targets a directory of snippets. Clause 6.1 is failed: no command resolves a printed @id to its help, and the query help site is online; resolution is by file path, which is a string the practitioner was never given. Clause 6.2 is partial for the same reason: the help ships in the pack but nothing keyed on the identifier reaches it. Clause 7.1 is partial: // codeql[query-id] comments suppress inline, and although suppression can be disabled by omitting the alert-suppression query from the suite, that is stated in a repository discussion rather than documentation (discussion). Nothing requires a reason on the comment (7.2).

Clause by clause

Document Clause Result Evidence
Detector 4.1 Yes Custom packs with qlpack.yml (custom queries)
Detector 4.2 Yes codeql test run with .qlref and .expected (testing)
Detector 4.3 Partial Required unique @id in SARIF ruleId; absent from CSV (CSV output)
Detector 4.4 Partial Duplicate-id CI check in github/codeql, not shipped to consumers
Detector 5.1 Partial No server, but database build required and licence limits private use (licence)
Detector 5.2 Partial Whole database; snippets only via the test harness
Detector 5.3 No database analyze writes to --output only (manual)
Detector 5.4 Yes Every query runs from the CLI
Detector 6.1 No No lookup keyed on @id; resolution is by path
Detector 6.2 Partial Help files ship in packs as markdown; nothing keyed on the identifier reaches them
Detector 6.3 Yes .qhelp/.md beside each query (generate query-help)
Detector 6.4 Partial Duplicate @id check in CI; no documented gate on missing help
Detector 7.1 Partial // codeql[id] disabled by omitting the suppression query, documented only in a discussion
Detector 7.2 No Suppression comment carries no reason (changelog 2.12.0)

Notes for a practitioner

On open-source code or with an Advanced Security licence, CodeQL can carry the method: write the query in a project pack, prove it red with codeql test run on a snippet that carries the hazard, sweep by analysing the full database, and keep the .md help beside the query. Emit SARIF and read ruleId from it, because the CLI prints no identifier to the terminal and the CSV format omits it. Omit the alert-suppression query from your suite so inline codeql[...] comments have no effect, and record exceptions in the config file’s paths-ignore with a stated reason.