Your first scan
This page walks you through:
- Pointing
vulkro scanat a project. - Reading the output.
- Filtering it down to actionable signal.
Run it
cd path/to/your/project
vulkro scan .
What happens:
- Vulkro walks the working tree honouring
.gitignore(same library ripgrep /fduse). - It detects your project's language and framework - Python, Node.js, or Go; Express, Fastify, Next.js, FastAPI, Django, gin, etc.
- It statically extracts every HTTP route, builds a module call graph, and runs the security pipeline (OWASP, secrets, CVEs, taint, reachability, privacy).
- It prints a colourised summary table to stdout.
Wall-clock for a mid-sized monorepo is typically 30-90s. Larger repos (Cal.com, ~2,200 modules) take ~45s on an M1.
Read the output
A typical run looks like this:
Detected: TypeScript | Next.js (App Router)
224 endpoints | 2,230 modules
Taint pass | Reachability | CVE match | Secrets | IaC
CRITICAL 33 HIGH 355 MED 1369 LOW 1063
API1 BrokenObjectLevelAuth 115 findings
API8 SecurityMisconfiguration 2292 findings
SECRETS 436 hardcoded | 19 in git history
DEPS 23 CVEs (4 KEV-listed, 7 reachable)
Completed in 42s | exit 1 (Critical/High present)
Each section is separately addressable:
- Severity counts are the headline. Critical and High block the build by default.
- OWASP categories show where your code spends its risk budget.
- SECRETS combines source-tree and git-history findings; the desktop
console (
vulkro serve) splits them. - DEPS tags the most dangerous CVEs. KEV-listed (CISA "actively exploited") and reachable (the vulnerable symbol is actually called from your code) are escalated.
Get the details
Default output is a summary. To see file paths and line numbers:
vulkro scan . --verbose
For machine-readable output:
vulkro scan . --format json | jq .findings[0]
vulkro scan . --format sarif > vulkro.sarif
vulkro scan . --format junit > vulkro-junit.xml
See the full output formats reference for the rest:
CycloneDX 1.5, SPDX 2.3, GDPR Art. 30 RoPA (markdown + HTML), executive HTML,
PDF (via wkhtmltopdf), GitHub-PR-comment, CSV.
Filter the noise
The default scan uses --min-confidence medium - Medium and High findings
only. Three knobs adjust the threshold:
# Default: medium + high. The typical day-to-day mode.
vulkro scan .
# Audit mode - surfaces every heuristic / pattern-only finding,
# including Low confidence ones on test/example code.
vulkro scan . --all-confidence
# CI-gate mode - High confidence only. Precision 0.76, recall 0.57
# on the public vuln corpus. Production-recommended for blocking gates.
vulkro scan . --min-confidence high
# Hide non-source files (Dockerfile, lockfiles, *.tf, *.md, templates,
# docker-compose). Keeps `.env*` and k8s manifests.
vulkro scan . --scope src
Confidence model -> explains the calibration table that decides which detector categories get downgraded.
Suppress a specific finding
Add a comment in the source instead of editing a config file:
# vulkro-disable-next-line BrokenAuthentication
@router.get("/health")
def health(): ...
// vulkro-disable-next-line BrokenAuthentication
app.get("/internal/ping", noAuth);
/* vulkro-disable-next-line API1 */
db.query(`SELECT * FROM ${table}`);
vulkro-disable-file at the top of a file silences all findings for it.
Suppression counts are reported in every scan summary so you can audit them.
Save the run
vulkro scan . --save
Adds the run to local scan history at ~/.vulkro/scans.db so you can:
- Compare against a previous baseline (
vulkro diff <ref>). - Track risk-debt and MTTR trends over time in the desktop console.
- Mark a scan as
baselineto gate PRs against it.
What's next
- Drop vulkro into CI -> - exit-code semantics, SARIF upload, PR comments.
- Open the desktop console -> -
vulkro servefor triage. - Reading findings -> - what each detector means.