Skip to main content

Output formats

Most commands (vulkro scan, vulkro discover, and others) take a --format flag (short form -f) that chooses how the results come out. Every format is built from the same scan, so they always agree with each other. Only the presentation changes.

Quick reference

FormatUse it forExtensionTier
tableThe default. A colored summary in your terminal.-Free
jsonAnything programmatic. Pipe to jq or save to a file..jsonFree
ndjsonOne finding per line plus a summary line, for SIEM ingestion and jq pipelines..ndjsonFree
sarifGitHub Code Scanning, VS Code, Azure DevOps..sarifFree
gh-prA single pull-request summary comment (Markdown)..mdPro
gh-pr-inline-commentsOne inline review comment per finding (NDJSON)..ndjsonPro
github-annotationsInline PR annotations on GitHub and GitLab.-Pro
gitlab-mr / bitbucket-pr / azure-prThe merge-request and pull-request comment for each host..mdPro
junitGitLab MR reports, Jenkins, and other test runners..xmlPro
csvA spreadsheet hand-off..csvPro
cyclonedxA CycloneDX 1.6 SBOM (software bill of materials)..jsonPro
cbomA CycloneDX 1.6 cryptographic bill of materials..jsonPro
spdxAn SPDX 2.3 SBOM..jsonPro
pdfAn executive report as a PDF (needs wkhtmltopdf)..pdfPro
ropa-md / ropa-htmlA GDPR Article 30 record of processing..md / .htmlPro
evidence-graphA machine-readable map of your attack surface, for AI tools..jsonPro

The Pro rows belong to two capabilities in the registry compiled into the scanner: Pull-request output (pr-comments), findings as review comments and CI annotations, and Evidence formats (evidence-formats), SBOM, VEX, CBOM, RoPA, PDF, CSV, JUnit and evidence-graph output. On Free a Pro format stops before doing any work, prints what it needs and exits 1. See Pricing.

Examples

vulkro scan . --format json | jq '.findings[] | select(.severity == "Critical")'
vulkro scan . --format sarif > vulkro.sarif
vulkro scan . --format gh-pr > comment.md
gh pr comment "$PR" --body-file comment.md
vulkro scan . --format cyclonedx > sbom.json
vulkro scan . --format ropa-md > ropa.md

Specification versions

The standards-based formats emit a specific version. The table below is generated from the binary (vulkro formats --format markdown), so it always matches what the tool actually produces.

Format--formatSpec versionSpecificationExtension
SARIFsarif2.1.02.1.0.sarif
CycloneDX SBOMcyclonedx1.61.6.json
CycloneDX SBOMcyclonedx-1.71.71.7.json
CycloneDX CBOMcbom1.61.6.json
CycloneDX CBOMcbom-1.71.71.7.json
SPDX SBOMspdxSPDX-2.3SPDX-2.3.json
SPDX SBOMspdx3SPDX-3.0.1SPDX-3.0.1.json
OpenVEXopenvex0.2.00.2.0.json
CycloneDX VEXcyclonedx-vex1.61.6.json
JUnit XMLjunitAnt/Surefire (de-facto)Ant/Surefire (de-facto).xml

Two extra fields in JSON output

Each finding in json output can carry two grading fields. Both are computed with no AI and no network, from what the scan already found. When Vulkro cannot make a claim, the field is left out, so "no claim" is easy to tell apart from a real value.

reachability_verdict

Is the vulnerable code actually reached from your app's entry points?

ValueMeaning
reachableYes. The vulnerable code is called from your app. The most actionable case.
unreachableThe code exists but nothing calls it. The finding is lowered, never dropped.
unknownNot enough signal to say either way. The safe default.

exploitability

How confident is Vulkro that this specific finding can be exploited as written? This is not the same as severity: severity is "how bad is this class of bug," exploitability is "how sure are we this one is real."

ValueMeaning
exploitableThere is a clear, unguarded path a user can take to the bug. The most actionable case.
likelyStrong signal, but one condition is unproven. Worth fixing, not a confirmed exploit.
theoreticalThe pattern is there but exploitation is not shown. Keep for audit, deprioritize for triage.

Both fields are lowercase, and exploitability also appears as a SARIF property.

SARIF

  • Version 2.1.0, pointing at the official OASIS schema.
  • Each finding becomes one SARIF result with its rule id, severity, message, location, and fix suggestion.
  • Findings carry a stable fingerprint, so GitHub Code Scanning, DefectDojo, and other SARIF consumers can dedupe the same finding across runs even when line numbers shift.
  • Data-flow findings include the full step-by-step path, which renders as the ladder view in GitHub Code Scanning and other SARIF viewers that show taint.
  • Works directly with GitHub's SARIF uploader.

PR comments and annotations

gh-pr gives you one summary comment. gh-pr-inline-comments gives you one comment per finding as NDJSON, ready to post with gh api:

vulkro gate --base "origin/${GITHUB_BASE_REF}" \
--format gh-pr-inline-comments \
| while IFS= read -r comment; do
path=$(echo "$comment" | jq -r .path)
line=$(echo "$comment" | jq -r .line)
body=$(echo "$comment" | jq -r .body)
gh api "repos/${GITHUB_REPOSITORY}/pulls/${PR_NUMBER}/comments" \
-f path="$path" -F line="$line" -f side=RIGHT -f body="$body" \
-f commit_id="${GITHUB_SHA}"
done

github-annotations prints one workflow-command line per finding. When a GitHub Actions or GitLab CI job prints these, each becomes an inline annotation pinned to the file and line on the Files Changed tab:

- name: vulkro PR annotations
run: vulkro scan . --format github-annotations

When any of these run through vulkro gate, only new findings are posted, so a first run does not flood the PR.

SBOMs (CycloneDX and SPDX)

  • cyclonedx emits a CycloneDX 1.6 SBOM: every resolved dependency with its purl and version, plus a vulnerabilities[] block for matched CVEs. The block is present-but-empty when nothing was found, so "scanned, none found" is distinct from "not scanned."
  • spdx emits an SPDX 2.3 SBOM with the same package inventory.
  • Vulkro records only the dependency edges it can prove and never invents the full transitive tree.
  • cbom is a separate CycloneDX document listing weak cryptography (MD5, SHA-1, ECB, RC4, DES, static IVs, insecure RNG) with file and line, for post-quantum and FedRAMP reviews.

GDPR RoPA

ropa-md and ropa-html produce a starting point for a GDPR Article 30 record of processing. Vulkro lists every endpoint that handles personal data, the categories it detected, and the controls it found in place or missing. You fill in the purpose, retention, and lawful basis. Use ropa-md for Git review and ropa-html for sending to a data protection officer.

PDF

pdf renders the executive HTML report to a PDF using wkhtmltopdf. If that tool is not installed, the format fails with a clear hint.

evidence-graph

A stable, versioned JSON view of everything a scan found, shaped for an AI agent to read as reliable ground truth. It does not reason or guess: it composes the scanner's output into one connected graph and stamps its own provenance (tool: "vulkro", deterministic: true, uses_llm: false) so an agent never mistakes it for AI-generated content.

vulkro scan . --format evidence-graph > evidence.json

It includes your endpoints, outbound calls, taint flows, findings, dependencies, and a rollup summary. Feed several of them (one per repo) to vulkro aggregate to surface cross-repo data flows. The same two steps are also available as MCP tools on vulkro mcp serve.