Skip to main content

Vulkro vs Trivy

Trivy reads what you assembled. Vulkro reads what your team wrote.

Both tools run on your machine and neither uploads your source, so the offline argument that usually decides these pages is a tie here and this one will not pretend otherwise. The real split is the subject: Trivy scans the artifacts and manifests your build produced, while Vulkro follows a request value through the code your team wrote until it reaches something that trusted it. A lot of teams should be running both.

  • No head-to-head score exists
  • Offline posture: a tie
  • Trivy is Apache 2.0
  • Java taint is same-file

01 / The short answer

Which one your risk actually needs

High on the page because it is what you came for, and because for this pairing the honest answer is often not one of the two columns.

Choose Trivy if

Their ground

  • Your exposure is in what you ship rather than what you wrote: base images, OS packages in a layer, Kubernetes and Terraform configuration, a cluster you inherited.
  • You need dependency CVE matching across many more package ecosystems than the five manifest formats Vulkro parses.
  • You want SBOM generation and SBOM scanning, plus a licence inventory, from the same binary.
  • You want a tool that is Apache 2.0, costs nothing, and needs no account and no licence key to run in anger.
  • You do not need a call graph. Nothing in Trivy is trying to build one, and for its job it does not need to.

Choose Vulkro if

Our ground

  • The bugs that worry you are in code your team wrote: broken access control, injection, server-side request forgery, insecure direct object references, mass assignment, authentication bypass.
  • You want the path printed with the finding: where the request value entered, the hops between, and the call that trusted it.
  • Your services are Python, JavaScript, TypeScript, Go or Java, and you want the depth chart before you install rather than after.
  • You want application findings, secrets, dependency CVEs and configuration in one report with one severity model, rather than stitched together downstream.
  • You want a vendor on the hook: support, an issued licence, and someone to answer when a detector is wrong.

Run both if you can

These two are not competing for the same finding. An image with a vulnerable OS package and a handler that trusts a path parameter are different failures with different fixes, and a team with production exposure usually has both. The cost of running both is pipeline minutes and one decision about who owns the classes that overlap, which section 06 covers.

02 / The architectural difference

Facts about artifacts, or a path through your code

One tool matches things it can look up. The other builds a map of your application and walks it. Neither approach is a weaker version of the other.

Trivy answers a lookup question, and answers it well: is anything I assembled known to be vulnerable or misconfigured. An OS package in an image layer, a resolved version in a lockfile, a storage bucket left open in a Terraform resource, a credential committed by accident. Every one of those is a fact about an artifact matched against a database or a policy, which is why it is fast, why it needs no grammar for your application framework, and why it works the same on a repository nobody on your team wrote.

Vulkro answers a reachability question about code your team wrote. It parses the source, builds a call graph, maps the routes your framework registers, and follows a value from the request that carried it to the call that trusted it. That is what produces a finding no manifest could contain: this endpoint has no authorisation check, this identifier is read from the URL and used to fetch a record belonging to someone else, this parameter reaches a query string four files away. Across files it follows Python, JavaScript, TypeScript and Go for up to four hops. Java taint does not cross a file boundary at all, so a Java result set is narrower than a Python or Go one on the same codebase.

The two overlap on the perimeter, and the overlap is real rather than token: dependency CVEs, secrets, Dockerfiles and infrastructure configuration are scanned by both. On that overlap Trivy is broader, and the only thing Vulkro adds there is the reachability verdict below, which comes from the call graph it built for the application analysis anyway.

The offline posture is a tie, and it is worth saying flatly because every other comparison on this site leans on it. Trivy runs locally, uploads no source, and documents self-hosting its databases for air-gapped use. Vulkro runs locally, uploads no source, and matches against a checksummed bundle already on disk. There is one asymmetry and it runs against us: Trivy needs no account and no licence key, while Vulkro requires an account (an air-gapped machine uses a signed, machine-bound licence file, and VULKRO_OFFLINE=1 refuses every outbound call). That is a cost on our side, not a feature.

VULKRO_SCA_REACHABLE=1 vulkro scan .offline bundle
  • CRITorg.apache.commons:commons-text@1.9MavenCVE-2022-42889reachable

    pom.xmlStringSubstitutor.replace called from ReportController.render at src/main/java/com/acme/report/ReportController.java:88

  • HIGHlodash@4.17.20npmCVE-2021-23337GHSA-35jh-r3h4-6jhmreachable

    package-lock.jsontemplate() called from buildInvoice at routes/invoice.ts:47, two hops from the POST /invoices route

  • MEDurllib3@1.26.4PyPICVE-2021-33503unknown

    poetry.lockadvisory declares no vulnerable symbols, so no reachability claim is made and the severity is left as matched

  • INFOgithub.com/gin-gonic/gin@1.7.7GoCVE-2023-29401unreachable

    go.sumContext.FileAttachment is not called from the forward closure of any route, main, or plugin hookdowngraded from medium

  • INFOtime@0.1.44crates.ioCVE-2020-26235unreachable

    Cargo.lockpulled in transitively by chrono; no project function in the forward closure calls the affected symboldowngraded from high

Unreachable findings are downgraded, not dropped. Severity falls to Info, the row keeps its call-graph reason, and it stays in the report and in the JSON. A call site missed through dynamic dispatch shows up as down-ranked rather than as absent.

Five manifest formats are parsed (npm, PyPI, Go modules, crates.io, Maven), and the default published bundle currently covers npm and PyPI, with the wider bundle covering the rest. Trivy matches across many more ecosystems than that, so on breadth alone its dependency answer is the fuller one.

The overlap, and the one thing Vulkro adds to it: each dependency finding carries whether your code actually reaches the vulnerable symbol.

03 / Measured, or not measured

There is no head-to-head number here, in either direction

No scored run of Trivy against our corpus exists, and no scored run of Vulkro against container and infrastructure breadth exists either. Both gaps are stated, because only mentioning the first one would be a way of winning by omission.

Our benchmark harness has no Trivy arm. Even if it did, scoring Trivy on a corpus of application bugs would measure a tool on ground it never claimed: nothing in its documentation offers dataflow analysis of application source, so a low score would say more about the test than about the tool. Running the comparison the other way, over image and infrastructure coverage, is the test Trivy would be expected to win, and we have not built that harness either.

So the comparison here is capability and architecture, both checkable against published documentation. That is a weaker claim than a measurement and it is the claim we actually have.

What we can say
Vulkro’s own scored result on application-class bugs, published with its method: precision 0.78, recall 0.57, F1 0.66 on a corpus of real projects with independently documented bugs, at the confidence floor we recommend in CI, with 36 of the 83 catalogued bugs missed and left in the corpus. One column. A single column is a result, not a comparison.
What we cannot say
Anything of the form "more accurate than Trivy", and anything at all about Trivy’s precision or recall on any corpus. We have also not measured our own image or infrastructure coverage against theirs, which is why section 04 concedes that ground on documentation rather than pretending it is contested.

Artifactbench/comparison/scorecard-high.md · vulkro 0.18.0 · measured 2026-07-18 · Tier 1 corpus, min-confidence high, match window file + line plus or minus 5

The scoring rules, the corpus provenance and the list of what the scanner misses are on /proof and in the benchmark documentation.

04 / Where Trivy wins

The things it is simply better at

No qualifiers on the ends of these sentences. Trivy is excellent at what it is for, and a page that could not say so would not be worth reading on anything else.

Container images, end to end

OS package databases across a wide set of distributions, layer awareness, and virtual machine images and Kubernetes clusters as scan targets in their own right. Vulkro extracts packages from a built image and matches them offline, but the distribution coverage and the target list are not close.

Infrastructure as code, with a policy engine

Terraform, CloudFormation, Kubernetes manifests, Helm charts, Dockerfiles and more, checked against a rule set you can extend with policies of your own. Vulkro reads configuration for shape in the same scan, and that pass is narrower and not extensible by you.

Ecosystem breadth for dependencies

Trivy resolves and matches dependencies across many more package ecosystems than the five manifest formats Vulkro parses. If your estate has Ruby, PHP, .NET or Swift services, its dependency answer covers them and ours does not.

SBOM and licences

Generating an SBOM, scanning an SBOM someone hands you, and inventorying licences are all first-class. Vulkro emits SBOM and exploitability documents too, but licence data is a field in that inventory rather than a scanner of its own.

It is free and open source

Apache 2.0, no account, no licence key, no seat to request. Vulkro needs an account, and a licence from our team once the 14-day trial ends. On a page comparing the two that is a cost on our side of the table, and it belongs in this list rather than in a footnote.

It is already installed

Packaged nearly everywhere and present in pipelines people inherited, so adopting it is often a one-line change to a workflow file. Any second tool has to justify the pipeline minutes and the triage time it adds.

05 / Coverage

Capability against capability, with the gaps left in

Read it as two tools with different jobs rather than as a scoreboard. Ours is empty where clusters and breadth live; theirs is empty where authored code lives.

Capability comparison between Vulkro and Trivy: application dataflow, route inventory, dependency matching and reachability, container images, infrastructure as code, secrets, SBOM, Salesforce and offline operation.
CapabilityVulkroTrivy
Dataflow through code your team wroteSource to sink across files: Python, JavaScript, TypeScript and Go up to four hops. Java taint is same-file onlyNot attempted. No call graph is built, and the documentation does not describe taint analysis
Route and endpoint inventoryBuilt per framework before any rule runs, so an unauthenticated route is visible as a routeNot a scan target
Access control, object references, mass assignment, auth bypassDedicated detectors, ranked by the evidence behind each oneNot the product. Nothing in the documentation claims this class
Dependency CVE matchingOffline against a checksummed bundle on disk. Five manifest formats parsedOffline once the database is local. Many more ecosystems than five
Reachability on dependency findingsFrom the call graph. Unreachable findings are downgraded to informational and kept, never droppedNo call-graph reachability verdict from your application code
Container imagesOS packages extracted (apk, deb, and rpm where the system tool is available) and matched, with layer whiteouts appliedFlagship ground: wider distribution coverage, plus virtual machine images and clusters
Infrastructure as code and misconfigurationTerraform, Kubernetes manifests, Compose files, Helm charts and Dockerfiles, checked for shape rather than followed for dataflowFlagship ground: broader, and extensible with your own policies
SecretsYes, including the git historyYes
Kubernetes cluster as a scan targetNo. The scan reads the tree on your disk and the artifacts in itYes
SBOM and exploitability documentsCycloneDX and SPDX inventories, plus OpenVEX and CycloneDX VEX backed by reachabilitySBOM generation and SBOM scanning, plus a licence scanner
Salesforce build review (Apex, Flow, org metadata)A separate edition, Vulkro for SalesforceNot a target
Runs with no network at allYes, with a signed machine-bound licence file and VULKRO_OFFLINE=1Yes, with the databases self-hosted or pre-fetched
Capability rows, not measurements: nothing in this table is scored, and no cell is a benchmark result. The Vulkro column is read from the scanner and its own documentation. The Trivy column is read from Trivy’s published documentation and repository (2026-08-15). Two rows are marked because they are the reason the page exists, not because they were measured.
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 side of the row above, per language. There is no Trivy column here because it does not analyse application dataflow at all, and inventing one would be the like-for-like mistake this page exists to avoid.

Apex, Lightning components, Flow and org metadata are read by Vulkro for Salesforce, the same review pointed at a Salesforce build. The SBOM and exploitability documents in the table above are described in full on /sbom-and-vex.

06 / Running both

What it costs to keep the two side by side

Both emit SARIF and GitHub Code Scanning ingests either file, so the technical cost is small. The organisational cost is the part teams get wrong.

  1. 01

    Give each class one owner

    Dependency CVEs, secrets and Dockerfiles are found by both tools. Decide which report owns each class before you start, or the same package gets triaged twice and both queues get abandoned.

  2. 02

    Gate on what you can act on today

    An unfixable base-image CVE stopping every merge teaches a team to bypass the gate. Application findings with a path and a line are usually the ones a developer can close in the same pull request.

  3. 03

    Keep the two reports separate in review

    They answer different questions and they age differently: an image finding is fixed by a rebuild, an access-control finding is fixed by a change to the handler. Merging them into one number hides both.

  4. 04

    If you must pick one, pick by exposure

    A platform team shipping other people’s code should keep the artifact scanner. A product team shipping its own handlers is exposed where the artifact scanner is not looking.

# artifacts and configuration
$ trivy fs --scanners vuln,misconfig,secret . --format sarif --output trivy.sarif

# the application: routes, dataflow, and the dependency pass in the same run
$ vulkro scan . --format sarif > vulkro.sarif

# upload both to Code Scanning, and let one report own the dependency class
The supply chain and the infrastructure on one side, the application on the other. Both runs stay on the machine, and both produce SARIF.

If you only ever want one binary in the pipeline, pick the one whose flagship ground matches the risk you are most exposed to. That is the whole decision, and it does not need a scoreboard.