
Codeql
- 3 installs
- 21.2k repo stars
- Updated August 5, 2026
- elastic/kibana
codeql skill documents Work with CodeQL in Kibana - write, test, and debug custom queries locally, fetch scan results from GitHub, and validate inline suppression comments.
About
codeql skill documents Work with CodeQL in Kibana - write, test, and debug custom queries locally, fetch scan results from GitHub, and validate inline suppression comments. Use when writing or debugging CodeQL queries, running CodeQL unit tests, analyzing SARIF results, fetching scan results, or checking codeql suppressio. name: codeql description: Work with CodeQL in Kibana - write, test, and debug custom queries locally, fetch scan results from GitHub, and validate inline suppression comments. Use when writing or debugging CodeQL queries, running CodeQL unit tests, analyzing SARIF results, fetching scan results, or checking codeql suppression justifications.
- Work with CodeQL in Kibana - write, test, and debug custom queries locally, fetch scan results from GitHub, and validate
- Platform-specific setup patterns for codeql.
- Evidence-backed steps from upstream SKILL.md.
- When-to-use criteria for codeql versus alternatives.
Codeql by the numbers
- 3 all-time installs (skills.sh)
- Ranked #1,752 of 2,203 Security skills by installs in the Skillselion catalog
- Data as of Aug 5, 2026 (Skillselion catalog sync)
codeql capabilities & compatibility
- Capabilities
- codeql quick start · codeql when to use guidance · codeql integration patterns
- Works with
- elasticsearch
- Use cases
- security audit
What codeql says it does
disable-model-invocation: true
├── codeql-config.yml # Main config (paths-ignore, packs, query-filters)
npx skills add https://github.com/elastic/kibana --skill codeqlAdd your badge
Show developers this skill is listed on Skillselion. Paste this into your README.
| Installs | 3 |
|---|---|
| repo stars | ★ 21.2k |
| Last updated | August 5, 2026 |
| Repository | elastic/kibana ↗ |
How do I use codeql correctly?
Work with CodeQL in Kibana - write, test, and debug custom queries locally, fetch scan results from GitHub, and validate inline suppression comments. Use when writing or debugging CodeQL queries, runn
Who is it for?
Teams implementing codeql workflows from the catalog.
Skip if: Skip when requirements clearly match a different specialized stack.
When should I use this skill?
User asks about codeql, work with codeql in kibana - write, test, and debug custom queries locally, fetch scan res.
What you get
Working codeql setup with validated configuration and next steps.
Files
CodeQL
Project Layout
.github/codeql/
├── codeql-config.yml # Main config (paths-ignore, packs, query-filters)
├── custom-queries/
│ ├── qlpack.yml # QL pack definition (name: kibana-custom-queries)
│ ├── codeql-pack.lock.yml
│ ├── suppression/ # Alert suppression logic
│ │ ├── AlertSuppression.ql
│ │ └── AlertSuppression.qll
│ └── <category>/ # e.g. dos/, xss/
│ ├── <RuleName>.ql # Query file
│ ├── <RuleName>.qhelp # Help docs (XML)
│ ├── <RuleName>.md # Human-readable docs
│ ├── <category>-security.qls # Query suite
│ └── <RuleName>/ # Unit test directory
│ ├── <RuleName>.qlref # Points to the .ql file (relative to qlpack root)
│ ├── <RuleName>.expected # Expected test output
│ └── test.js # Test source code
scripts/codeql/
├── quick_check.sh # Local analysis via Docker
└── codeql.dockerfile # Docker image (ubuntu + CodeQL CLI)Running Queries Locally (Full Analysis)
Uses Docker to create a CodeQL database and run queries against real source code.
# Analyze a source directory with custom queries
bash scripts/codeql/quick_check.sh -s <source_dir> -q .github/codeql/custom-queries
# Analyze with a single query file
bash scripts/codeql/quick_check.sh -s <source_dir> -q .github/codeql/custom-queries/dos/UnboundedArrayInRoute.ql
# Custom results directory
bash scripts/codeql/quick_check.sh -s <source_dir> -r .codeql-results -q .github/codeql/custom-queriesOptions:
-s <source_dir>(required for analysis): directory to scan-q <query_dir|query_file>: custom queries directory or single.qlfile-r <results_dir>: where to store DB and SARIF (default:.codeql/)-t: run unit tests instead of analysis (use with-q, no-sneeded)
Output: SARIF file at <results_dir>/database/results.sarif. If jq is installed, a colored summary prints automatically.
First run builds a Docker image (codeql-env) from scripts/codeql/codeql.dockerfile. On Apple Silicon, it runs with --platform linux/amd64 (emulation).
Running CodeQL Unit Tests
Unit tests validate that a query flags the correct lines. Each test lives in a subdirectory named after the query.
Test structure
<category>/<RuleName>/
├── <RuleName>.qlref # Reference: "category/RuleName.ql"
├── test.js # Source code with `// $ Alert` annotations
└── <RuleName>.expected # Expected output (auto-generated or hand-written)// $ Alerton a line means the query should flag that line- Lines without
// $ Alertshould not be flagged .expectedfile has pipe-delimited format:| <location> | <message> |
Running tests via Docker
Uses the same codeql-env Docker image built by quick_check.sh (built automatically on first run).
# Run a specific test directory
bash scripts/codeql/quick_check.sh -t -q .github/codeql/custom-queries/dos/UnboundedArrayInRoute
# Run all tests in the qlpack
bash scripts/codeql/quick_check.sh -t -q .github/codeql/custom-queriesCI workflow
The codeql-pr.yml workflow automatically runs unit tests on PR. It finds all *.qlref directories and runs codeql test run against them.
Fetching Remote SARIF / Scan Results
The scripts/fetch_sarif.mjs script (relative to this skill directory) fetches CodeQL SARIF results and alerts from GitHub for a PR or branch.
# By PR number
GITHUB_TOKEN=ghp_xxx node .agents/skills/codeql/scripts/fetch_sarif.mjs 252121
# By full ref
GITHUB_TOKEN=ghp_xxx node .agents/skills/codeql/scripts/fetch_sarif.mjs refs/heads/mainRequires: GITHUB_TOKEN env var with security_events scope. Depends on @octokit/rest (already in Kibana deps).
What it does: 1. Lists recent CodeQL analyses for the ref 2. Fetches full SARIF JSON (with rule severity cross-referencing) 3. Prints formatted results (rule, severity, message, file:line) 4. Fetches code scanning alerts for the same ref
Writing a New Query
1. Create the `.ql` file in .github/codeql/custom-queries/<category>/:
- Use
@id js/kibana/<descriptive-id>(must be unique) - Include
@kind problem(orpath-problemfor taint tracking) - Set
@problem.severityand@security-severity - Import
javascriptmodule - Refer to existing queries like
UnboundedArrayInRoute.qlfor patterns
2. Create a unit test directory <category>/<RuleName>/:
<RuleName>.qlrefcontaining<category>/<RuleName>.qltest.jswith annotated test cases (// $ Alertfor expected hits)- Run tests to generate
.expected— verify it matches expectations
3. Add a `.qhelp` (XML) and/or `.md` for documentation
4. Optionally add a `.qls` query suite if grouping multiple queries
5. Test locally with quick_check.sh against real Kibana source code
Inline Suppressions
Suppressions use the format // codeql[rule-id] justification text. Every suppression must include a specific justification explaining why it is safe.
Valid:
// codeql[js/path-injection] User input is validated against an allowlist before use
return fs.readFileSync(`/etc/${validatedPath}`, 'utf8');Invalid — flag these:
- Missing justification:
// codeql[js/path-injection]with no explanation - Generic justification:
"false positive","safe","not a vulnerability"— says nothing about the actual mitigation - Incomplete justification:
"sanitized"— does not explain how or by what mechanism
Good justifications describe the concrete security mechanism: allowlist validation, DOMPurify escaping, shell-quote library, test-only code, etc.
Troubleshooting
| Issue | Fix |
|---|---|
| Docker build fails on ARM | Ensure --platform linux/amd64 is set (script handles automatically) |
qlpack.yml not found | The script walks up from the .ql file to find it — ensure qlpack.yml exists at custom-queries/ root |
Test produces .actual file | Diff .actual vs .expected — .actual files are gitignored |
| Query finds nothing | Check codeql-config.yml paths-ignore — test/mock dirs are excluded |
jq not found for summary | Install jq: brew install jq |
References
- Writing CodeQL queries — official guide covering query structure, QL tutorials, and running queries
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the "Elastic License
* 2.0", the "GNU Affero General Public License v3.0 only", and the "Server Side
* Public License v 1"; you may not use this file except in compliance with, at
* your election, the "Elastic License 2.0", the "GNU Affero General Public
* License v3.0 only", or the "Server Side Public License, v 1".
*/
/**
* Fetches CodeQL SARIF results and alerts from GitHub for a given PR or branch.
*
* Usage:
* GITHUB_TOKEN=ghp_xxx node .cursor/skills/codeql-local-testing/scripts/fetch_sarif.mjs <pr_number|ref>
*
* Examples:
* GITHUB_TOKEN=ghp_xxx node .cursor/skills/codeql-local-testing/scripts/fetch_sarif.mjs 252121
* GITHUB_TOKEN=ghp_xxx node .cursor/skills/codeql-local-testing/scripts/fetch_sarif.mjs refs/heads/main
*
* Environment:
* GITHUB_TOKEN - required, GitHub personal access token with `security_events` scope
*/
import { Octokit } from '@octokit/rest';
const GITHUB_OWNER = 'elastic';
const GITHUB_REPO = 'kibana';
const token = process.env.GITHUB_TOKEN;
if (!token) {
console.error('Error: GITHUB_TOKEN environment variable is required.');
console.error('Create a token with `security_events` scope at https://github.com/settings/tokens');
process.exit(1);
}
const input = process.argv[2];
if (!input) {
console.error('Usage: GITHUB_TOKEN=ghp_xxx node fetch_sarif.mjs <pr_number|ref>');
console.error(' e.g. node fetch_sarif.mjs 252121');
console.error(' e.g. node fetch_sarif.mjs refs/heads/main');
process.exit(1);
}
const ref = /^\d+$/.test(input) ? `refs/pull/${input}/merge` : input;
const octokit = new Octokit({ auth: token });
const main = async () => {
// Step 1: List recent CodeQL analyses for the ref
console.log(`\n=== Fetching CodeQL analyses for ${ref} ===\n`);
const { data: analyses } = await octokit.codeScanning.listRecentAnalyses({
owner: GITHUB_OWNER,
repo: GITHUB_REPO,
tool_name: 'CodeQL',
ref,
per_page: 10,
});
if (analyses.length === 0) {
console.log('No CodeQL analyses found for this ref.');
return;
}
console.log(`Found ${analyses.length} analysis run(s):`);
for (const a of analyses) {
console.log(` - id: ${a.id} | created: ${a.created_at} | sarif_id: ${a.sarif_id}`);
}
// Step 2: Fetch SARIF data from the most recent analysis
const [recentAnalysis] = analyses;
console.log(`\n=== Fetching SARIF for analysis ${recentAnalysis.id} ===\n`);
const { data: sarifMeta } = await octokit.codeScanning.getSarif({
owner: GITHUB_OWNER,
repo: GITHUB_REPO,
sarif_id: recentAnalysis.sarif_id,
});
const { data: analysisDetails } = await octokit.request({ url: sarifMeta.analyses_url });
const { data: rawSarif } = await octokit.request({
url: analysisDetails[0].url,
headers: { Accept: 'application/sarif+json' },
});
const sarifData = typeof rawSarif === 'string'
? JSON.parse(rawSarif)
: JSON.parse(new TextDecoder('utf-8').decode(rawSarif));
if (!sarifData.runs?.length) {
console.log('No runs found in SARIF data.');
return;
}
// Step 3: Print SARIF results
for (const run of sarifData.runs) {
const results = run.results ?? [];
const rulesById = Object.fromEntries(
(run.tool?.driver?.rules ?? []).map((r) => [r.id, r])
);
console.log(`Results: ${results.length}`);
if (results.length === 0) continue;
for (const result of results) {
const rule = rulesById[result.ruleId] ?? {};
const location = result.locations?.[0]?.physicalLocation;
const severity = rule.properties?.['security-severity'] ?? 'N/A';
console.log(`\n Rule: ${result.ruleId}`);
console.log(` Severity: ${severity}`);
console.log(` Message: ${result.message?.text}`);
if (location) {
console.log(` File: ${location.artifactLocation?.uri}:${location.region?.startLine}`);
}
}
}
// Step 4: Fetch code scanning alerts for the ref
console.log(`\n=== Code Scanning Alerts ===\n`);
const { data: alerts } = await octokit.codeScanning.listAlertsForRepo({
owner: GITHUB_OWNER,
repo: GITHUB_REPO,
ref,
tool_name: 'CodeQL',
per_page: 100,
});
console.log(`Total alerts: ${alerts.length}`);
for (const alert of alerts) {
console.log({
number: alert.number,
rule: alert.rule?.id,
severity: alert.rule?.security_severity_level,
state: alert.state,
description: alert.rule?.description,
path: alert.most_recent_instance?.location?.path,
line: alert.most_recent_instance?.location?.start_line,
});
}
};
main().catch((err) => {
console.error('Failed to fetch SARIF data:', err.message);
process.exit(1);
});
Related skills
FAQ
What does codeql do?
codeql skill documents Work with CodeQL in Kibana - write, test, and debug custom queries locally, fetch scan results from GitHub, and validate inline suppression comments.
When should I use codeql?
User asks about codeql, work with codeql in kibana - write, test, and debug custom queries locally, fetch scan res.
Is this skill safe to install?
Review the Security Audits panel on this page before installing in production.