vulkro respond
vulkro respond is part of Pro: Respond (respond), the incident-response workflow over a finding. On Free it stops before doing any work, prints what it needs and where to get it, and exits 1. See Pricing.
Incident-response mode for the 3am advisory-drop workflow: given a package + version, or an advisory ID, in under a second, answer "is this in my project?" Walks every lockfile and per-file import once, builds a reverse index, and reports every place the named package shows up (direct or transitive).
The pipeline is deliberately scoped: it does not run the full security scan, it does not validate signatures, and it answers the query purely from files on disk without querying any advisory service. It exists for the moment between "a new advisory just dropped" and "do we patch tonight or in the morning."
Usage
vulkro respond --package <NAME@VER> [PATH]
vulkro respond --advisory <ID> [PATH]
Exactly one of --package or --advisory must be passed.
Arguments
| Argument | Description | Default |
|---|---|---|
PATH | Path to the project root. | . |
Flags
| Flag | Description | Default |
|---|---|---|
--advisory <ID> | Curated advisory ID. Accepts SUP-COMPROMISE-001..005 (the stable rule-id family for the compromised-release catalog) and specific incident IDs (e.g. INCIDENT-2018-event-stream). | (none) |
--package <PKG@VER> | Explicit package spec. Accepts name@version for npm and Cargo, name==version for PyPI, @scope/pkg@version for scoped npm. | (none) |
--format, -f <FMT> | table (default, human-readable), json, ndjson. | table |
--no-cache | Bypass both the read and the write of the on-disk reverse-index cache. Forces a fresh walk. Useful for timing a cold start or when the cache is suspected stale. Equivalent to VULKRO_DISABLE_CACHE=1. | false |
Exit codes
| Code | Meaning |
|---|---|
0 | Target NOT found in the project: you are not exposed. |
1 | Target found in at least one place. |
2 | Error: bad argument, IO failure, or an unsupported advisory ID. |
Note the inversion vs. vulkro scan: here exit 1 means "you are
exposed", exit 0 means "you are clean". CI gates that should block
on exposure can pipe vulkro respond directly.
How it works
The reverse index is built once per project and consulted on every subsequent call:
- Lockfile walkers parse every supported lockfile in the project
tree:
- npm:
package-lock.json,npm-shrinkwrap.json - Poetry:
poetry.lock - pip:
Pipfile.lock - Cargo:
Cargo.lock - Go:
go.sum
- npm:
- Per-file import extraction runs over JavaScript, TypeScript,
Python, Go, and Rust source files to catch direct
import/require/usementions of the target package. - The merged
(package, version) -> [places]map is written to the on-disk cache.
The cache lives at:
~/.vulkro/cache/<short-blake3-of-root>/reverse-index-v1.json
The short BLAKE3 hash of the project's canonical root path scopes the cache per-project so two repos cannot collide.
Cache invalidation: the index is considered stale and rebuilt
whenever any lockfile under the project tree changes (mtime, length,
new file, or removed file). Source-file edits do not invalidate the
index by themselves: the package-membership question only changes
when lockfiles change. Pass --no-cache to bypass the cache
entirely.
Cold-start wall-clock is well under one second on a typical project.
CVE IDs
--advisory CVE-2024-... returns an actionable error:
error: CVE-* IDs are not supported by `vulkro respond`. CVE matching
uses version-range membership against the local CVE bundle; this
command only does exact-string `name@version` lookups. Try:
vulkro respond --package <name>@<version> .
or run a full scan:
vulkro scan .
vulkro respond answers an exact-version question. CVE-* advisories
have a version-range shape that vulkro scan + vulkro match-cve
already resolve.
Examples
# Specific package + version.
vulkro respond --package event-stream@3.3.6 .
# Scoped npm.
vulkro respond --package @solana/web3.js@1.95.6 .
# PyPI uses `==` instead of `@`.
vulkro respond --package requests==2.31.0 .
# Stable advisory family ID covers every catalog incident of that kind.
vulkro respond --advisory SUP-COMPROMISE-001 .
# Specific historical incident.
vulkro respond --advisory INCIDENT-2018-event-stream .
# JSON for tooling pipelines.
vulkro respond --package ua-parser-js@0.7.29 . --format json | jq '.matches[]'
# Skip the cache (fresh walk, no write).
vulkro respond --package ctx==0.2.2 . --no-cache
Related
vulkro scan- the full pipeline; SUP-COMPROMISE-* findings on the project's lockfiles emit here too.vulkro mcp-audit- MCP host config supply-chain risks (MCP-006 reuses the same catalog).vulkro extension-audit- installed extension supply-chain risks (EXT-001 reuses the same catalog).- SUP-COMPROMISE-001..006 rules - per-kind rule pages with remediation guidance.
Command reference
Generated from vulkro help respond on vulkro 0.26.0. This block is the
authoritative flag, usage, and exit-code reference for this command; the
prose above is the friendly explanation. Do not edit this block by hand;
run npm run docs:cli after a release.
Answer "is this package or advisory in my project?" in under a second.
Incident-response mode: in seconds, answer "is THIS advisory or package in my project?" Walks the project's lockfiles plus per-file imports and reports every place the named package shows up. Designed for the 3am advisory-drop workflow: cold start + run + decision, all under one second on a typical project.
Caching: the reverse index is cached at `~/.vulkro/cache/<short-blake3-of-root>/reverse-index-v1.json`. The cache invalidates when any lockfile under the project changes (mtime / len / new file / removed file). Pass `--no-cache` to bypass both the read and the write.
Exit codes (unaffected by `--ai`): `0` target NOT found - you are not exposed. `1` target FOUND - at least one match in the project. `2` error: bad arg, IO failure, or an unsupported advisory id (CVE-* lookup is not yet implemented; pass `--package <name>@<version>` instead).
Examples: `vulkro respond --package event-stream@3.3.6 .` `vulkro respond --package @solana/web3.js@1.95.6 .` `vulkro respond --package requests==2.31.0 .` `vulkro respond --advisory SUP-COMPROMISE-001 .`
Usage: vulkro respond [OPTIONS] [PATH]
Arguments:
[PATH]
Path to the project root (default: current directory)
[default: .]
Options:
--advisory <ID>
Curated advisory ID. Accepts `SUP-COMPROMISE-001`..`005` (the stable rule-id family) and specific incident IDs (`INCIDENT-2018-event-stream`). CVE-* IDs return an actionable error: pass `--package <name>@<version>` instead
--offline
Hard-disable every outbound network call for this run (sets VULKRO_OFFLINE=1). Blocks the CVE feed, the license heartbeat, the update check, webhooks, and any cloud AI endpoint; a loopback model (http://127.0.0.1, http://localhost) is still allowed. Equivalent to exporting VULKRO_OFFLINE=1, and the flag wins when both are set
--package <PKG@VER>
Explicit `name@version` (or `name==version` for PyPI, or `@scope/pkg@version` for scoped npm packages). Mutually exclusive with `--advisory`
-f, --format <FORMAT>
Output format. Default `table` for humans, `json` and `ndjson` available for tooling
Possible values:
- table
- json
- sarif
- gh-pr
- gh-pr-inline-comments: GitHub PR per-finding **inline review comments**. NDJSON, one `{path, line, side, severity, rule_id, fingerprint, body}` object per line. Designed to be piped straight to a `gh api` loop so `vulkro gate` can drop comments next to the offending line on the Files Changed tab without going through a GitHub App. See the GitHub CLI integration guide at vulkro.com/docs
- github-annotations: GitHub Actions / GitLab CI **PR annotations**. One workflow-command line per finding (`::error file=...,line=...,endLine=...,title=<rule id>::<message> (<helpUri>)`). Printed straight to a CI job's stdout, GitHub turns each line into an inline annotation pinned to `file:line` on the Files Changed tab; GitLab CI's annotation parser reads the same grammar. When run against a baseline (`--gate-vs` / a `gate` flow) only NEW findings are annotated so a first run does not paper the PR
- gitlab-mr: GitLab Merge-Request comment: GitLab-flavored Markdown with collapsible blocks
- bitbucket-pr: Bitbucket Pull-Request comment: flat Markdown (Bitbucket does not render `<details>`)
- azure-pr: Azure DevOps Pull-Request comment: flat Markdown (shared with Bitbucket)
- junit
- csv
- cyclonedx: CycloneDX 1.6 JSON SBOM (uses `ScanResult.packages`)
- cyclonedx-1.7: CycloneDX 1.7 JSON SBOM. Same component shape as `cyclonedx`; emits the newer `specVersion`. Offered alongside 1.6 (which stays default)
- spdx: SPDX 2.3 JSON SBOM
- spdx3: SPDX 3.0.1 JSON-LD SBOM (`@context` + `@graph` of typed elements). Offered alongside SPDX 2.3, which stays the default for `--format spdx`
- cbom: CycloneDX 1.6 CBOM (Cryptographic Bill of Materials): one `cryptographic-asset` component per detected weak algorithm (MD5, SHA-1, ECB, RC4, DES, static IV, insecure RNG), with file:line occurrences inlined under `evidence.occurrences`. Compliance buyers (FedRAMP, post-quantum readiness reviews) ask for this as a distinct artefact from the library SBOM
- openvex: OpenVEX 0.2.0 exploitability statements for each dependency CVE (`affected` / `not_affected` / `under_investigation`), with `not_affected` backed by reachability analysis. Pairs with an SBOM
- cyclonedx-vex: CycloneDX 1.6 VEX: the same exploitability verdicts as `openvex`, in a CycloneDX `vulnerabilities[].analysis` document
- cbom-1.7: CycloneDX 1.7 CBOM. Same crypto-asset grouping as `cbom` plus a richer post-quantum descriptor. Offered alongside 1.6 (default)
- pdf: PDF render of the executive HTML report (requires `wkhtmltopdf` on PATH)
- ropa-md: GDPR Article 30 Records-of-Processing template - Markdown
- ropa-html: GDPR Article 30 Records-of-Processing template - HTML
- ndjson: Newline-delimited JSON: one finding per line plus a trailing summary line. Designed for SIEM ingestion and `jq` filter pipelines
- evidence-graph: Evidence-graph JSON (`evidence-graph/1.0`): a stable, versioned, AI-consumable document that composes endpoints, taint source -> sink flows, reachability verdicts, findings, and the dependency SBOM into one graph. Meant to be handed to an external AI agent as deterministic ground truth (Vulkro embeds no model; the agent brings its own). Pairs with `vulkro aggregate` for cross-repo linking. See `docs/ai-tool/`
[default: table]
--no-cache
Bypass the on-disk reverse-index cache at `~/.vulkro/cache/<short-blake3-of-root>/reverse-index-v1.json`. Forces a fresh walk + suppresses the cache write. Useful when you want to time a cold start or you suspect the cache is stale
--ai
[advisory] For each matched package, add a plain-language local-model reachability / relevance judgement grounded in the project's own call sites (which source files import it directly, what pulls it in transitively). ADDITIVE and ADVISORY: the deterministic presence match is unchanged and is the source of truth; the AI text is labelled advisory / non-deterministic / excluded-from-benchmark and NEVER flips the Clean/Exposed outcome or the exit code. A loopback model is allowed under VULKRO_OFFLINE; a cloud url is refused offline. Configure with `vulkro ai`
-h, --help
Print help (see a summary with '-h')