
Agentic Framework for Synthesizing CodeQL Queries
Agentic Framework for Synthesizing CodeQL Queries

QLCoder is a framework for using LLMs to synthesize end-to-end CodeQL queries for vulnerability detection. Given an existing CVE's metadata, LLM, and coding agent, QLCoder iteratively synthesizes a CodeQL query to detect the existing CVE. The starting query is a CodeQL path query template populated by an extracted AST of the diff. While synthesizing the query, the coding agent has access to tools to interface with a RAG database and the CodeQL language server. Afterwards, the query can be used for multivariant analysis, regression testing, or guidance for writing CodeQL queries.
Note - In the paper, CodeQL version 2.22.2 was used. However, any version (and language) can be used. QLCoder stores the local CodeQL version's QL packs in the vector database. Paths are configured in .env.
Download an appropriate version of the CodeQL Action bundle from the CodeQL Action releases page.
For the latest version: Visit the latest release and download the appropriate bundle for your OS:
codeql-bundle-osx64.tar.gz for macOScodeql-bundle-linux64.tar.gz for LinuxFor a specific version (e.g., 2.22.2):
Go to the CodeQL Action releases page, find the release tagged codeql-bundle-v2.22.2, and download the appropriate bundle for your platform.
Extract to ~/codeql (or another path — update CODEQL_HOME in .env accordingly):
tar -xzf codeql-bundle-<platform>.tar.gz -C ~/
Clone the CodeQL LSP MCP server and build it.
git clone https://github.com/neuralprogram/codeql-lsp-mcp ~/codeql-lsp-mcp
cd ~/codeql-lsp-mcp
npm install
npm run build
cp .env.example .env
echo "APP_UID=$(id -u)" >> .env
echo "APP_GID=$(id -g)" >> .env
Fill in your API key and CodeQL paths in .env:
ANTHROPIC_API_KEY=...
# QL pack paths depend on your CodeQL version.
# Find the version numbers with:
# ls ~/codeql/qlpacks/codeql/java-queries/ → use for SECURITY_QLPACK_PATH
# ls ~/codeql/qlpacks/codeql/java-all/ → use for LIBRARY_QLPACK_PATH
SECURITY_QLPACK_PATH=~/codeql/qlpacks/codeql/java-queries/<version>/Security/CWE
LIBRARY_QLPACK_PATH=~/codeql/qlpacks/codeql/java-all/<version>/semmle/code/java
Then start the QLCoder app and ChromaDB:
docker compose up -d
The CVE must be listed in data/project_info.csv. This clones the repository at the buggy commit and generates the fix diff.
docker compose run --rm app python3 scripts/get_cve_repos.py --cve CVE-2025-27818
# or multiple at once:
docker compose run --rm app python3 scripts/get_cve_repos.py --cves CVE-2025-27818,CVE-2025-0851
# process CVEs from a file (one CVE ID per line)
docker compose run --rm app python3 scripts/get_cve_repos.py --cve-file cves.txt
# process all CVEs
docker compose run --rm app python3 scripts/get_cve_repos.py --all
# force regenerate existing diffs
docker compose run --rm app python3 scripts/get_cve_repos.py --cve CVE-2018-9159 --force
Databases are created with --build-mode=none — no build toolchain required.
# to build a specific CVE's CodeQL databases
docker compose run --rm app python3 scripts/build_codeql_dbs.py --cve-id CVE-2025-27818
This creates cves/CVE-2025-27818/CVE-2025-27818-vul and cves/CVE-2025-27818/CVE-2025-27818-fix.
# to build all of the fetched CVE repos' CodeQL databases
docker compose run --rm app python3 scripts/build_codeql_dbs.py
Run these scripts to populate the vector database. codeql_docs_fetcher.py and cwe_fetcher.py are one-time setup; cves_fetcher.py should be re-run after adding new CVEs.
docker compose run --rm app python3 scripts/codeql_docs_fetcher.py
docker compose run --rm app python3 scripts/cwe_fetcher.py
docker compose run --rm app python3 scripts/cves_fetcher.py
Note - In the paper, CodeQL version 2.22.2 was used. However, any version (and language) can be used. QLCoder stores the local CodeQL version's QL packs in the vector database. Paths are configured in .env.
Download an appropriate version of the CodeQL Action bundle from the CodeQL Action releases page.
For the latest version: Visit the latest release and download the appropriate bundle for your OS:
codeql-bundle-linux64.tar.gz for LinuxFor a specific version (e.g., 2.22.2):
Go to the CodeQL Action releases page, find the release tagged codeql-bundle-v2.22.2, and download the appropriate bundle for your platform.
After downloading, extract the archive in the project root directory:
tar -xzf codeql-bundle-<platform>.tar.gz
This should create a sub-directory codeql/ with the executable codeql inside.
Add the path of this executable to your PATH environment variable:
export PATH="$PWD/codeql:$PATH"
Clone the CodeQL LSP MCP server and build it.
git clone https://github.com/neuralprogram/codeql-lsp-mcp
cd codeql-lsp-mcp
npm install
npm run build
conda env create -f environment.yml
conda activate qlcoder
.envcp .env.example .env
Fill in your API key and CodeQL paths in .env:
ANTHROPIC_API_KEY=...
CODEQL_HOME=~/codeql
CODEQL_LSP_MCP_HOME=~/codeql-lsp-mcp
# QL pack paths depend on your CodeQL version.
# Find the version numbers with:
# ls ~/codeql/qlpacks/codeql/java-queries/ → use for SECURITY_QLPACK_PATH
# ls ~/codeql/qlpacks/codeql/java-all/ → use for LIBRARY_QLPACK_PATH
SECURITY_QLPACK_PATH=~/codeql/qlpacks/codeql/java-queries/<version>/Security/CWE
LIBRARY_QLPACK_PATH=~/codeql/qlpacks/codeql/java-all/<version>/semmle/code/java
The CVE must be listed in data/project_info.csv. This clones the repository at the buggy commit and generates the fix diff.
python3 scripts/get_cve_repos.py --cve CVE-2025-27818
# or multiple at once:
python3 scripts/get_cve_repos.py --cves CVE-2025-27818,CVE-2025-0851
# process CVEs from a file (one CVE ID per line)
python3 scripts/get_cve_repos.py --cve-file cves.txt
# process all CVEs
python3 scripts/get_cve_repos.py --all
# force regenerate existing diffs
python3 scripts/get_cve_repos.py --cve CVE-2018-9159 --force
Databases are created with --build-mode=none — no build toolchain required.
# to build a specific CVE's CodeQL databases
python3 scripts/build_codeql_dbs.py --cve-id CVE-2025-27818