CodeQL Analysis skill for Codex
Taint tracking source to sink. This skill uses CodeQL for the bugs pattern scanners miss: deep taint and dataflow analysis that traces untrusted input to a sink across functions and files. It covers GitHub code-scanning setup, the local CLI with real builds for compiled languages, reading the dataflow path to triage alerts, and writing custom QL queries for project-specific sources and sinks.
curl -fsSL codexskills.dev/install.sh \ | sh -s -- codeql-analysis Installs to ~/.agents/skills/codeql-analysis/ for every project on this machine.
curl -fsSL codexskills.dev/cli.mjs -o codex-skills.mjsnode codex-skills.mjs install codeql-analysis The CLI also searches, updates and removes skills. Run it with no arguments to pick from a list. Needs Node 20.12+.
curl -fsSL codexskills.dev/install.sh \ | sh -s -- --project codeql-analysis Installs to .agents/skills/codeql-analysis/ in the current repository. Commit it and everyone who runs Codex there gets it.
curl -fsSLO codexskills.dev/downloads/codeql-analysis.zipunzip -o codeql-analysis.zip -d ~/.agents/skills/ The archive holds the skill folder with its generated agents/openai.yaml. Unzip into .agents/skills/ to scope it to a repo.
& ([scriptblock]::Create((irm codexskills.dev/install.ps1))) codeql-analysis PowerShell 5.1 or 7. Installs to %USERPROFILE%\.agents\skills\. Add -Project for the current repo.
104-line POSIX script. No sudo, no telemetry. Read install.sh
Use it in Codex
Start a prompt with $codeql-analysis, or pick it from /skills.
You can also just describe the task: Codex reads the description below and loads the playbook when your request matches.
What Codex reads before loading it
Sets up CodeQL to find security bugs through deep dataflow and taint analysis — build a database, run the security query packs, write custom queries, and triage alerts in GitHub code scanning. Use when asked to enable CodeQL, add code scanning to a repo, write a custom CodeQL query, or triage CodeQL alerts. Best for deep source→sink dataflow; for fast pattern rules use semgrep instead.
Use it when
- You need deep source-to-sink dataflow analysis
- Setting up GitHub code scanning for a repo
- Writing or triaging custom CodeQL queries
Use something else when
- You want fast pattern rules and quick CI: use semgrep-sast
- The target is dependency CVEs: use dependency-scanning
- You only need to find committed secrets: use secret-scanning
How to check the result
Re-run after a fix so the alert closes and the dataflow path no longer resolves; for a custom query, confirm it catches a planted bad path and not the sanitized version.
The mistake it prevents
Building the database from a failed or partial build of a compiled language, so CodeQL scans a fraction of the code and reports false confidence.
CodeQL treats code as data you query. Its strength is dataflow and taint tracking across functions and files — finding that user input reaches a sink three calls away, which pattern scanners miss. That power costs build time and query-writing effort, so use it where depth pays off and keep the alert set triaged.
When CodeQL vs a pattern scanner
- CodeQL — deep taint/dataflow (injection through layers, SSRF across helpers), whole- program reasoning, compiled languages. Slower; needs a build for compiled langs.
- Semgrep (hand off to semgrep-sast) — fast, pattern/lightweight-taint, great for style/footgun rules and quick CI. Use it for breadth and speed.
Many teams run both: Semgrep on every push, CodeQL on a schedule/PR.
Supported languages
C/C++, C#, Go, Java/Kotlin, JavaScript/TypeScript, Python, Ruby, Swift. Interpreted languages (JS/TS, Python, Ruby) need no build; compiled ones need CodeQL to observe the build.
GitHub code scanning (the easy path)
For a GitHub repo, the default setup wires everything:
# .github/workflows/codeql.yml
name: "CodeQL"
on:
push: { branches: [main] }
pull_request: { branches: [main] }
schedule: [{ cron: "0 3 * * 1" }]
jobs:
analyze:
runs-on: ubuntu-latest
permissions: { security-events: write, actions: read, contents: read }
strategy:
matrix: { language: [javascript-typescript, python] }
steps:
- uses: actions/checkout@v4
- uses: github/codeql-action/init@v3
with: { languages: ${{ matrix.language }}, queries: security-extended }
# Compiled langs: replace autobuild with your real build if autobuild fails
- uses: github/codeql-action/autobuild@v3
- uses: github/codeql-action/analyze@v3
Query suites: security-extended (more coverage, some noise) or security-and-quality
(adds maintainability). Start with security-extended.
Local CLI (when you need control or offline-ish work)
The CodeQL CLI builds a database you query directly. It is a large download and compiled- language DB builds run your toolchain — Codex’s sandbox may need approval for the install and build; call that out.
# Interpreted language: no build command needed
codeql database create db --language=python --source-root=.
# Compiled language: wrap the real build
codeql database create db --language=java --command="mvn -B clean install -DskipTests"
# Run the standard security queries, output SARIF
codeql database analyze db codeql/python-queries:codeql-suites/python-security-extended.qls \
--format=sarifv2.1.0 --output=results.sarif
Upload results.sarif to GitHub code scanning with codeql github upload-results if you
want alerts in the UI.
Triage alerts
CodeQL alerts carry a dataflow path (source → steps → sink) — read it; it tells you whether the taint is real.
- True positive → fix the sink or add a sanitizer on the path; CodeQL re-tracks on the next run.
- False positive → if a sanitizer exists that CodeQL does not recognize, model it in a custom query/sanitizer rather than blanket-dismissing. In the UI, dismiss with a reason (“false positive” / “won’t fix” / “used in tests”); the reason is auditable.
- Fix the source of a class, not one alert at a time, when many share a root cause.
Custom queries (QL basics)
Write a query when you need a project-specific source or sink the standard packs miss. CodeQL queries are written in QL and typically extend the dataflow library:
/**
* @name User input reaches our raw query helper
* @kind path-problem
* @problem.severity error
* @id js/custom/raw-query-taint
*/
import javascript
import DataFlow::PathGraph
class Config extends TaintTracking::Configuration {
Config() { this = "RawQueryTaint" }
override predicate isSource(DataFlow::Node n) { n instanceof RemoteFlowSource }
override predicate isSink(DataFlow::Node n) {
exists(DataFlow::CallNode c | c.getCalleeName() = "rawQuery" and n = c.getArgument(0))
}
}
from Config cfg, DataFlow::PathNode src, DataFlow::PathNode sink
where cfg.hasFlowPath(src, sink)
select sink.getNode(), src, sink, "Untrusted input reaches rawQuery()."
Iterate queries against your database with codeql query run or the VS Code CodeQL
extension (which gives autocomplete over the QL libraries). Start by copying a standard
query close to your target and adjusting the source/sink.
Verification
- Re-run after a fix: the alert closes and the dataflow path no longer resolves.
- For a custom query, confirm it finds a known-bad path you planted and not the sanitized version.
- PR gate: code scanning shows no new
error-severity alerts introduced by the change.
Output contract
## CodeQL analysis — <repo> (<date>)
Languages: <list>. Suite: security-extended. Mode: <GitHub Actions | CLI>.
### Alerts (triaged)
| Query | Severity | Source → Sink | Verdict | Action |
|-------|----------|---------------|---------|--------|
| js/sql-injection | error | req.body → rawQuery() | true positive | parameterize |
### Custom queries added: <ids>
### Gate: fail PR on new error-severity alerts.
Hard rules
- For compiled languages, make sure CodeQL sees the real build; a DB from a failed build misses most of the code and gives false confidence.
- Read the dataflow path before judging an alert; dismiss false positives with a reason, never silently.
- Model missing sanitizers in a query instead of mass-dismissing a true pattern.
- Use CodeQL where depth matters; for fast broad pattern rules, hand off to semgrep-sast.
What the zip contains
SKILL.md plus the interface file below. Nothing runs on install.
agents/openai.yaml
Gives the Codex app a display name, a one-line description and a starter prompt for this skill.
interface:
display_name: "CodeQL Analysis"
short_description: "Taint tracking source to sink"
default_prompt: "$codeql-analysis Enable CodeQL code scanning for this Java and TypeScript repo" About this skill
Written and maintained by the Codex Skills editors to the same editorial standard as every skill here: a selective description, a real workflow, known pitfalls and a way to verify the work. First published , last updated . MIT licensed. Something wrong or out of date? Tell us.