
The vulncheck CLI brings VulnCheck API index browsing, backup management, and SBOM-driven vulnerability scanning to the terminal, with a machine-friendly contract designed for scripts and AI agents in authorized security operations.
| Tool | vulncheck-oss/cli — official command-line client for the VulnCheck vulnerability-intelligence API, written in Go and released under Apache-2.0 |
| Category | Vulnerability intelligence / CLI client |
| Primary Use | Querying CVE data via cpe, purl, and advisory lookups, running scan over an SBOM, and syncing indices with offline during authorized assessments and triage workflows |
| Safe Use | A purely defensive intelligence tool intended for authorized professionals: vulnerability management, patch prioritization, and asset-triage work on systems and software you are authorized to assess |
| Telemetry Note | All queries hit the VulnCheck API under an authenticated token visible in auth status; defenders should note the CLI itself performs no network exploitation, but API request logs and the ~/.config/vulncheck/vulncheck.yaml credential file are observable artifacts |
vulncheck is the official command-line interface for the VulnCheck API, and the README is unusually candid about its ambition: it wants to be more than a human-facing wrapper. The project describes itself as bringing index browsing, backup management, and vulnerability scanning to the terminal, but the more interesting claim is buried in its "Agentic / scripted usage" section, which the document explicitly calls a contract — a set of surfaces the maintainers intend to keep stable across releases. That framing positions this tool squarely at the intersection of classic CLI ergonomics and modern automation pipelines, including AI agents, and it is reflected in nearly every design decision documented in the repository. The repo sits at a modest 160 stars, is written in Go, and ships under an Apache-2.0 license, which makes it easy to vendor, audit, and redistribute inside enterprise tooling.
Installation is deliberately boring in the good way. On macOS and Linux a curl-piped install.sh handles the setup, prompting for a system-wide or per-user location and supporting non-interactive --sudo / --non-sudo flags for CI contexts. Windows users get an equivalent install.ps1 PowerShell script, plus a bundled tab-completion profile snippet. Precompiled binaries for all three platforms are published on the GitHub releases page, and vulncheck version verifies the install by printing the version, build date, and a changelog URL — the kind of self-describing build metadata that matters when you need to know exactly which intelligence dataset semantics your automation is relying on.
Authentication is where the tool's operational maturity first shows. vulncheck auth login walks a browser or paste-token flow, but the CLI also honors the VULNCHECK_API_TOKEN environment variable — the same name used by VulnCheck's SDKs and MCP server — as well as the legacy VC_TOKEN alias. There is a subtle precedence trap documented here: VC_TOKEN wins over VULNCHECK_API_TOKEN when both are set, which is a deliberate backward-compatibility choice so existing setups never silently change credential. Environment tokens also override the saved config file at ~/.config/vulncheck/vulncheck.yaml, and consequently auth login and auth logout refuse to run while an environment token is set, because they would otherwise report success while changing nothing that takes effect. vulncheck auth status resolves the ambiguity by reporting the active token's source and, critically, a token_shadowed field when an env token is masking a different saved one — the canonical cause of "I logged in but nothing changed" support tickets.
The command surface is broad and maps almost one-to-one onto the VulnCheck product taxonomy. auth and token handle identity and API-token lifecycle; indices and index list and query the catalogue of intelligence indices; advisory queries v4 advisories in CVE Record Format 5.2; and a family of lookup commands — cpe, purl, tag, pdns, rule — translate identifiers into vulnerability or intelligence data. The scan command combines SBOM generation with vulnerability lookup over a local directory, and offline syncs indices locally so queries can run without touching the API at all. Rounding it out are backup, which downloads or fetches signed URLs for index and advisory-feed backups, plus version and an in-place upgrade command.
The scripted-usage contract deserves close reading because it is the clearest signal of the project's engineering philosophy. Global flags include --json for structured output with info routed to stderr, --quiet for suppressing chatter, --no-color, and --no-interactive, which refuses to block on TUI prompts and is implied by --json, by non-TTY stdin/stdout, and by any of the CI, BUILD_NUMBER, or RUN_ID environment variables. That last detail means a command that works interactively on a laptop degrades gracefully inside a CI runner with zero configuration — the classic failure mode of pretty-printed CLIs is designed out rather than documented as a caveat.
Exit codes are enumerated with the precision of a tool that expects to be dispatched on programmatically: 0 for success, 2 for validation failures, 3 for auth failures, 4 for 404-style resource misses, 5 for HTTP 429 rate limiting, 6 for network failures, and 130 for SIGINT cancellation. In --json mode, errors arrive as a structured envelope with a schema_version, a machine-readable code drawn from a closed set (auth_required, rate_limited, not_found, and so on), an optional http_status, and a hint field that surfaces remediation context — for example naming which environment variable supplied a rejected token. For anyone wiring this into a SOAR platform or an agent loop, this is the difference between parsing prose and dispatching on semantics.
Batch handling is similarly deliberate. The purl, cpe, tag, and pdns commands accept multiple inputs via positional arguments, piped stdin, or --from-file, with blank lines and #-prefixed comments ignored, and batch mode requires --json. The output envelope is a stable array with one row per input in input order, pairing each input with either a data payload or a per-row error — so a single malformed pkg:bad/string in a thousand-line PURL list degrades one row instead of failing the whole run. Pagination is handled with --limit/--page plus an --all flag that walks next_cursor end-to-end and emits one combined array, sparing script authors from cursor-chaining logic.
Security-conscious token handling appears in an easy-to-miss design choice in token create. In --json mode the command returns metadata on stdout with token_on_stderr: true, printing the actual secret on a single line to stderr, so a pipeline like vulncheck token create ci-runner --json > token.json never writes the secret into the captured file. An opt-in --allow-token-on-stdout flag exists for operators who explicitly want the token embedded, and the README is explicit that using it means taking responsibility for the redirection. This is the kind of secure-by-default ergonomics that separates tools designed for production CI from tools that merely tolerate it.
The probe commands complete the automation story. vulncheck version --json returns machine-readable build metadata; vulncheck auth status --json calls the API's /me endpoint to actually verify the token, always exits 0 regardless of authentication state so agents can dispatch on the boolean, and reports token_env_var even on failure so a rejected token can be traced to the variable holding it; and vulncheck commands dumps the entire command tree — every subcommand, flag with type and default, alias, and deprecation status — as a single JSON document, with the README explicitly advising agents to consume this rather than parse --help text. That last command is effectively a machine-readable schema endpoint built into the binary itself.
Operational niceties extend to process lifecycle. SIGINT and SIGTERM cancel in-flight HTTP requests cleanly via Go context propagation, and long-running operations — scan, offline sync, backup download — honor cancellation with partial files removed on the way out where applicable. The JSON output discipline guarantees that stdout carries only the payload, with every progress bar, spinner, prompt, and warning relegated to stderr and TUI elements (the README names bubbletea and huh) auto-suppressed, so vulncheck <cmd> --json | jq always works without tail or sed cleanup. Interactive commands like token browse and index browse degrade to their list-mode equivalents rather than erroring.
In an authorized professional workflow, vulncheck slots naturally into vulnerability management and triage: enriching cpe and purl identifiers from an SBOM with authoritative CVE data via scan, pulling initial-access-intelligence rule lookups to prioritize what attackers actually use, checking pdns and IP-intelligence tag membership during incident triage on infrastructure you are authorized to investigate, and using offline sync to keep intelligence queries working in air-gapped or bandwidth-constrained environments. Because every action is an authenticated API query rather than active probing, the tool leaves no footprint on third-party systems — it is an intelligence consumer, not a scanner that touches targets.
The overall impression from the README is of a tool built by people who have operated CLIs in automation at scale and internalized the failure modes. The precedence rules, the shadowed-token diagnostics, the stderr-secret handling, the closed error-code vocabulary, and the versioned output schemas all point to a maintainer team treating the CLI as a long-lived API surface rather than a convenience wrapper. For defenders, vulnerability analysts, and authorized assessment teams already in the VulnCheck ecosystem, vulncheck is a well-documented, well-contracted way to get that intelligence into scripts, CI pipelines, and agent loops without fighting the tooling at every step.
vulncheck-oss/cli.Educational analysis for authorized security professionals. Use only in controlled, authorized environments.
Related coverage
0 comentários:
Post a Comment
Note: Only a member of this blog may post a comment.