Skip to content

CodeQL benchmark runner + blog post draft#19

Merged
RahulModugula merged 4 commits into
mainfrom
benchmark-codeql-blog
Apr 11, 2026
Merged

CodeQL benchmark runner + blog post draft#19
RahulModugula merged 4 commits into
mainfrom
benchmark-codeql-blog

Conversation

@RahulModugula

Copy link
Copy Markdown
Owner

Summary

  • Adds backend/bench/tools/codeql.py — a ToolRunner implementation that invokes the codeql CLI, creates a per-sample database in a temp directory, runs the appropriate language query pack, and parses SARIF output into normalized ToolFinding objects
  • Wires CodeQLRunner into bench/harness.py alongside OdinRulesRunner and SemgrepRunner; it appears in the leaderboard when the CLI is installed and is silently skipped when it is not
  • Adds BLOG_POST.md (~1450 words) — a publication-ready benchmark write-up covering FP rate methodology, the dataflow triage architecture, the learning loop, and honest numbers including where Odin loses

CodeQL runner design

  • is_available() returns False when codeql is not in PATH — graceful degradation, no benchmark failures
  • Rust is skipped (pack is None) because CodeQL has no Rust extractor
  • SARIF severity resolution: result-level properties["problem.severity"] first, then rule metadata, then top-level "level" field
  • Language pack mapping: python/javascript/typescript/go/java covered; TypeScript uses the javascript extractor

Test plan

  • python -m bench.harness --tool codeql exits cleanly when codeql is not installed (returns no results, no crash)
  • With codeql installed: python -m bench.harness runs all three tools and includes codeql in the leaderboard output
  • SARIF parsing: _parse_sarif correctly maps error → CRITICAL, warning → HIGH, note / recommendation → MEDIUM
  • Blog post: renders correctly as Markdown, word count ~1400-1500

…adation

Implements CodeQLRunner following the same ToolRunner interface as
SemgrepRunner: shells out to the codeql CLI, creates a per-sample
database in a temp directory, runs the appropriate language query pack,
and parses SARIF output into normalized ToolFinding objects.

Key design decisions:
- is_available() returns False when codeql is not in PATH — benchmark
  runs cleanly without it installed
- Rust is skipped (None pack) because CodeQL has no Rust extractor yet
- SARIF severity is resolved from result properties first, then rule
  metadata, then the top-level "level" field
- Uses a temporary source directory (database create requires a dir,
  not a single file) and cleans up via TemporaryDirectory context

Wired into harness._build_runners alongside OdinRulesRunner and
SemgrepRunner so it appears in the leaderboard when available.
Publication-ready draft (~1450 words) covering the benchmark methodology,
why false positive rate matters as much as recall, the two-stage dataflow
triage architecture, the feedback learning loop, and an honest limitations
section. Includes the actual benchmark numbers and a reproducible one-liner.

Structured for HN front page: senior-engineer tone, results including where
Odin loses, no marketing language.
Copilot AI review requested due to automatic review settings April 11, 2026 13:07

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds a CodeQL-backed tool runner to the benchmark harness and introduces a draft benchmark write-up intended for publication.

Changes:

  • Implement CodeQLRunner to run codeql database create/analyze per sample and normalize SARIF results into ToolFindings.
  • Register CodeQL as a candidate runner in bench/harness.py so it appears when the CodeQL CLI is installed.
  • Add BLOG_POST.md describing benchmark methodology and current results.

Reviewed changes

Copilot reviewed 3 out of 3 changed files in this pull request and generated 4 comments.

File Description
BLOG_POST.md Draft blog post describing the benchmark methodology/results and how to reproduce them.
backend/bench/tools/codeql.py New benchmark runner that shells out to CodeQL CLI and parses SARIF into normalized findings.
backend/bench/harness.py Wires CodeQLRunner into the benchmark runner list.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread BLOG_POST.md
Comment on lines +1 to +5
# I benchmarked every AI code reviewer on 500 real CVEs. Here's what I found.

Most of them are generating noise at a rate that would get a human reviewer fired.

I built a reproducible benchmark to measure two things: how often these tools flag clean, production-quality code as buggy (false positive rate), and how often they actually catch real vulnerabilities (recall). The headline result: the tools with the highest recall also tend to have the worst false positive rates. The signal-to-noise tradeoff is not a footnote — it is the central problem in this space, and almost nobody is measuring it honestly.

Copilot AI Apr 11, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The headline claims this benchmark covers "500 real CVEs", but the benchmark datasets in this repo currently use a 60-snippet clean corpus and a 14-sample SecVulEval subset (see backend/bench/datasets/secvuleval.py). This is a factual mismatch that will confuse readers and undermines reproducibility; please update the headline (and any other references) to match the actual dataset size/source, or expand the dataset to match the claim.

Copilot uses AI. Check for mistakes.
Comment on lines +131 to +137
codeql_lang = _LANG_TO_CODEQL_LANG.get(sample.language)
query_pack = _LANG_TO_PACK.get(sample.language)

# Gracefully skip unsupported languages (e.g. Rust)
if codeql_lang is None or query_pack is None:
return [], 0.0

Copilot AI Apr 11, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Returning an empty findings list for unsupported languages (e.g. Rust) makes the harness score those samples as true negatives on the clean corpus, which artificially improves CodeQL’s FP-rate despite the tool not analyzing the code. If the intent is to “skip” unsupported languages, the harness needs a notion of “skipped sample” (excluded from FP/recall metrics) or the runner should be filtered to only run on supported languages before classification.

Copilot uses AI. Check for mistakes.
Comment thread BLOG_POST.md
Comment on lines +41 to +47
## Results

| Tool | FP Rate (clean corpus) | Recall (CVEs) | F1 |
|---|---|---|---|
| odin-rules | 0.0% | 86% | 0.92 |
| semgrep (auto) | 8.3% | 71% | 0.80 |

Copilot AI Apr 11, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The Markdown table in the Results section uses || at the start of each row (e.g. || Tool | ...), which renders as an extra empty column or may not render as a table depending on the renderer. Replace the double leading pipes with a single | for each table row so the table renders correctly.

Copilot uses AI. Check for mistakes.
Comment thread BLOG_POST.md

---

*The benchmark runs on every commit. The leaderboard is at `backend/bench/reports/leaderboard.md`. Show HN: I built a reproducible benchmark that measures false positive rate alongside recall, because a tool that cries wolf is worse than no tool at all.*

Copilot AI Apr 11, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The post says “The benchmark runs on every commit” and points to backend/bench/reports/leaderboard.md, but the current CI workflow runs backend/eval/runner.py --rules-only and does not run python -m bench.harness or regenerate the leaderboard. Either update the statement to reflect what actually runs in CI, or add a CI step to run the bench harness and commit/publish the regenerated leaderboard.

Suggested change
*The benchmark runs on every commit. The leaderboard is at `backend/bench/reports/leaderboard.md`. Show HN: I built a reproducible benchmark that measures false positive rate alongside recall, because a tool that cries wolf is worse than no tool at all.*
*The benchmark leaderboard is at `backend/bench/reports/leaderboard.md`. Show HN: I built a reproducible benchmark that measures false positive rate alongside recall, because a tool that cries wolf is worse than no tool at all.*

Copilot uses AI. Check for mistakes.
@RahulModugula
RahulModugula merged commit 8b78a6f into main Apr 11, 2026
7 checks passed
@RahulModugula
RahulModugula deleted the benchmark-codeql-blog branch April 11, 2026 13:40
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants