Skip to main content

Vulkro vs CodeQL

Two dataflow engines, two different operating models.

CodeQL compiles your code into a database and answers questions written in a query language, most often on a hosted CI runner. Vulkro is one binary that reads the tree on your disk and returns a fixed set of security verdicts with a pass or a fail. Both follow values through code. What a team actually feels is the difference in what it costs to get the first result, and where the analysis runs. No same-corpus head-to-head run exists between the two, so nothing on this page is a score.

  • No head-to-head run exists
  • No database build step
  • No query language to learn
  • Both write SARIF

01 / The short answer

Which one fits the team you have

This is what most readers came for, so it goes first. The two are not exclusive, and section 06 covers running both.

Choose CodeQL if

You want depth you can extend yourself

  • Your repositories already run GitHub code scanning and the default query suites cover the languages you ship.
  • You want to write your own interprocedural checks, and someone on the team will learn the query language and keep those queries alive.
  • You need a language Vulkro does not read at all: C, C++, C#, Ruby, Swift or Kotlin.
  • You want variant analysis: after fixing one bug, find every other place that matches its shape, across a codebase or across many repositories.
  • You want to read the query that produced a finding before you trust it. The standard query packs are published openly.

Choose Vulkro if

You want a verdict with nothing to stand up first

  • You want a result on a laptop or a runner with no database to build and no query to author. Install one binary, run one command.
  • Your code cannot go to a hosted analysis service, or your build cannot be reproduced on a hosted runner.
  • You want the same verdict twice on the same commit, so a merge gate can be left switched on instead of being disabled the first time it flakes.
  • You want the security check in the pre-commit and pre-merge loop, where a scan measured in seconds is the difference between a gate people keep and a gate people route around.
  • You want dependency CVEs, committed secrets, infrastructure configuration and container layers in the same pass as the code review, matched against a bundle on your own disk.

Neither column is a scoreboard. They describe different budgets: CodeQL buys depth and expressiveness with setup and expertise, Vulkro buys speed and locality by fixing the question set in advance.

02 / The architectural difference

A database you build and query, against a binary you run

One structural distinction explains most of the rest. CodeQL turns your code into an artifact and asks questions of it. Vulkro reads the tree and answers a fixed set.

CodeQL works by extraction. A pass over your project produces a relational database of the code, and analysis is then a query written in QL evaluated against that database. For interpreted languages the extractor reads source directly; for compiled languages it observes a real build, which is why a CodeQL setup normally has to be able to build the project. That design is the source of its strengths. The database is a reusable artifact, queries are code you can version and review, and a query written once can be pointed at any database.

The costs are the mirror image of the strengths. There is a build and extraction step before any result exists, a query language between a security engineer and a new check, and an environment that has to run both. Most teams meet CodeQL as GitHub code scanning, which means the analysis happens wherever CI happens rather than on the machine that holds the code.

Vulkro has no database and no query language. It parses the tree with tree-sitter grammars, builds a call graph and a route inventory, then runs a fixed detector set with taint over both. The output is a list of findings that each cite a file and a line, plus an exit code CI can act on. Nothing is compiled first, nothing is uploaded, and no server sits in the path. Cross-file taint runs in Python, JavaScript, TypeScript and Go for up to four hops; Java taint is same-file only, so a Java result set is narrower than a Python or Go one on the same codebase.

The trade is expressiveness, and it is worth stating twice. If a check is not in the detector set, Vulkro cannot be asked for it the way CodeQL can. Custom rules exist and they are YAML: a regular expression over file globs, or a single AST node match. Useful for an internal token format or a banned call, and not an interprocedural query.

trust boundaryone switch closes it

Everything the scan needs stays on your machine: the code it reads, the map it builds of how your product fits together, the findings it writes, and the optional local model it can consult without leaving the machine. One line leaves.

Stays on this machine
source code, call graph + taint, findings, account layer, and the local model on 127.0.0.1
One crossing
A signed entitlement check and a usage counter, on a debounced cadence.
Never crosses
source code, file paths, file names, finding contents, project names, the hardware fingerprint
Where the analysis runs. The scan pipeline never touches the wire; the single crossing carries an entitlement check, never code.

03 / Measured, or not measured

There is no CodeQL number on this page

The scored corpus this site publishes contains no CodeQL run, so this page publishes no comparative figure at all.

No head-to-head measurement

Three tools have a committed head-to-head row against the benchmark corpus. CodeQL is not one of them, and the honest consequence is that nobody here knows how the two compare on it. Every claim below is about architecture and capability, which is a different kind of statement from a score and is labelled as one.

Running it is not a matter of adding a line to the harness. Extraction for compiled languages needs each corpus project to build, and the result depends heavily on which query suite is selected. Choosing that suite ourselves would produce a figure describing our configuration rather than the tool, and a figure like that is worse than none: it looks like evidence and is not.

What is measured is published separately, with the method, the scoring rules, the false negatives and the artifact each figure was read from. Read the result and the boundary around it and the full methodology rather than taking a comparison page’s word for anything. If a defensible run against CodeQL is ever set up, the result goes here whichever way it lands.

04 / Where CodeQL wins

What CodeQL does better

Specific, and without a recovery clause. A comparison page that cannot name the other tool's strengths is an advertisement wearing a table.

The query language
QL is a real language with a large standard library, and it is the reason a security engineer can express a project-specific interprocedural check that no fixed detector set will ever contain. Vulkro has YAML custom rules: a regular expression over file globs, or a single AST node match in one language. That is useful for an internal token format or a banned call. It is not a query language, and nothing about how it is described changes that.
Languages Vulkro does not read
CodeQL covers a broader set, including C and C++, C#, Ruby, Swift and Kotlin. Vulkro parses five languages. On a C++ codebase this comparison is not close, because Vulkro reads none of it.
Variant analysis
Fix one bug, then hunt every other instance of its shape, including across a fleet of repositories at once. Vulkro has no equivalent: it runs a fixed detector set over the tree it is pointed at.
Queries you can read
The standard query packs are public, so you can open the rule that fired and see exactly what it matches. Vulkro’s detectors are closed. What this project publishes instead is the scoring method, the misses, and the evidence behind each individual finding.
The research behind the rules
Years of security research sit behind those packs, along with a long public record of real vulnerabilities found with them. That record is not marketing; it is checkable.
It is already where your team looks
If your code is on GitHub, results land in the security tab your team already reads, with no extra plumbing. Vulkro writes SARIF into that same tab, but wiring the upload is a step you take.
Depth on a language both tools read
No ordering is claimed here. Both follow values through code by different means, and with no shared measurement any statement about which one goes deeper on Python or Java would be invented. Section 03 explains why the measurement does not exist.

05 / Coverage

Capability against capability

No measurement appears in this table. It sets out what each tool is built to do, with the gaps on both sides left visible.

Capability comparison between Vulkro and CodeQL, with no scores: where analysis runs, setup before a first result, custom checks, languages, taint depth, dependency and configuration coverage, output and offline operation.
CapabilityVulkroCodeQL
Where the analysis runsOn your machine or your own runner. Source is never uploaded.Wherever the database is built and queried. The common path is a hosted CI runner.
Before the first resultInstall one binary and run one command.Create a database, observing a real build for compiled languages, then run a query suite against it.
Writing your own checkYAML rules: a regular expression over globs, or a single AST node match.QL, a full query language with a standard library.
Languages read as codePython, JavaScript, TypeScript, Go, Java (5)A broader set, including C and C++, C#, Ruby, Swift and Kotlin.
Taint across file boundariesPython, JavaScript, TypeScript and Go, up to four hops. Java taint is same-file only.Interprocedural dataflow is the core of the engine.
Endpoint inventoryRoutes extracted per framework, then checked for missing authorization.Not handed to you as an inventory. A query can be written to build one.
Dependency CVEsIn the same scan, matched against a checksummed bundle on your disk with no network call.A different job. Dependency alerting on GitHub is handled by other features, not by CodeQL queries.
Secrets, infrastructure config, container layersIn the same pass as the code review.Separate tooling. CodeQL analyses code.
Salesforce (Apex, Lightning, Flow, org metadata)Read by Vulkro for Salesforce, which is this same review pointed at a Salesforce build.Not a supported language.
Output and gatingSARIF and other machine formats, plus an exit code that is the gate.SARIF, and code scanning alerts on GitHub.
Running with no networkSupported. A scan needs no network at all.The command-line tool runs on a machine you control. The hosted code scanning path does not.
Not a measurement. Vulkro rows are read from the scanner's own documentation and source tree; CodeQL rows are read from its public documentation, checked 2026-08-15. Where a capability depends on how the other tool is deployed or licensed, the row says so rather than guessing, and no price appears for either side.
analysis depth by language7 languages x 5 capabilities
Analysis depth for each supported language, by capability. Each cell is full, partial or none.
LanguageRoute mappingentry pointsTaint, same filesource to sinkTaint, across filesvia call graphFramework awarenessrouters, ORMsDedicated detectorslanguage rules
PythonDjango, Flask, FastAPIFullFullFullFullFull
JavaScriptExpress, Koa, Next.jsFullFullFullFullFull
TypeScriptExpress, NestJS, Next.jsFullFullFullFullFull
Gonet/http, Gin, Echo, chiFullFullFullFullFull
Javasame-file taint onlyFullFullNoneFullFull
Apexentry points, not URL routesPartialFullPartialFullFull
Terraform, Dockerfileconfiguration, not dataflowNoneNoneNoneFullFull
  • Fullruns on every scan of that language
  • Partiallimited to the cases named in the row
  • Nonenot analysed at this depth today

Cross-file taint means a source in one file reaching a sink in another through the call graph. Java is same-file today: a tainted value that leaves the method is not followed into the callee's file, so a Java result set is narrower than a Python or Go one on the same codebase.

Vulkro's own analysis depth per language. This is not the comparison: a CodeQL column would carry rows this matrix does not have, and the blank cells here are Vulkro's.

The matrix above describes one of the two tools only. It is included because the honest version of “we go deep” is a table with empty cells in it, and Java is the emptiest: taint does not cross a file boundary there. The full language page states every limit per language.

06 / Migration, or running both

There is no importer, and both sets can coexist

What it actually costs to add Vulkro next to CodeQL, and what it costs to replace it.

There is no CodeQL query importer in Vulkro, and promising one would be dishonest. QL expresses interprocedural analysis; a YAML rule matches a pattern. A converter would quietly drop the part of a query that made it worth writing, and hand back something that fires in the wrong places.

Running both is the sensible arrangement for a team that already has CodeQL working. They sit at different points in the loop: Vulkro on the developer machine and the pre-merge check, where a scan measured in seconds keeps a gate alive, and CodeQL on the schedule where a full database build is affordable. Both write SARIF, and GitHub code scanning accepts more than one SARIF upload for a commit when each upload carries its own category, so the two result sets sit beside each other instead of overwriting one another.

If the plan is to replace rather than to add, run them in parallel for a release cycle and diff the two sets before dropping anything. The categories to look at hardest are the ones only one tool reports: a check written in QL for your own codebase has no counterpart here, and dependency, secret and configuration findings have no counterpart there.

# no database to build, no query suite to choose
$ vulkro scan . --min-confidence high

  SECURITY FINDINGS

    1. [HIGH]  SQL injection in order lookup
       order_id enters at the request handler and
       reaches cursor.execute() through two files.
       db/session.py:57

# the gate is the exit code, so CI parses nothing
$ echo $?
  1

# same commit, same findings, same order, every run
$ vulkro scan . --min-confidence high --format sarif > vulkro.sarif
One binary, one command, an exit code CI can gate on, and SARIF for the same security tab CodeQL writes to.