.agents/skills/codeql/SKILL.md
.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)
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-queries
Options:
-s <source_dir> (required for analysis): directory to scan-q <query_dir|query_file>: custom queries directory or single .ql file-r <results_dir>: where to store DB and SARIF (default: .codeql/)-t: run unit tests instead of analysis (use with -q, no -s needed)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).
Unit tests validate that a query flags the correct lines. Each test lives in a subdirectory named after the query.
<category>/<RuleName>/
├── <RuleName>.qlref # Reference: "category/RuleName.ql"
├── test.js # Source code with `// $ Alert` annotations
└── <RuleName>.expected # Expected output (auto-generated or hand-written)
// $ Alert on a line means the query should flag that line// $ Alert should not be flagged.expected file has pipe-delimited format: | <location> | <message> |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-queries
The codeql-pr.yml workflow automatically runs unit tests on PR. It finds all *.qlref directories and runs codeql test run against them.
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/main
Requires: GITHUB_TOKEN env var with security_events scope. Depends on @octokit/rest (already in Kibana deps).
What it does:
Create the .ql file in .github/codeql/custom-queries/<category>/:
@id js/kibana/<descriptive-id> (must be unique)@kind problem (or path-problem for taint tracking)@problem.severity and @security-severityjavascript moduleUnboundedArrayInRoute.ql for patternsCreate a unit test directory <category>/<RuleName>/:
<RuleName>.qlref containing <category>/<RuleName>.qltest.js with annotated test cases (// $ Alert for expected hits).expected — verify it matches expectationsAdd a .qhelp (XML) and/or .md for documentation
Optionally add a .qls query suite if grouping multiple queries
Test locally with quick_check.sh against real Kibana source code
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:
// codeql[js/path-injection] with no explanation"false positive", "safe", "not a vulnerability" — says nothing about the actual mitigation"sanitized" — does not explain how or by what mechanismGood justifications describe the concrete security mechanism: allowlist validation, DOMPurify escaping, shell-quote library, test-only code, etc.
| 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 |