Subcommand Reference for CI

Every platform page links here rather than restating this. Read it once.

Warning Flags and default output paths change between releases. Check vulnetix <command> --help against the CLI you have installed, and open an issue if a page here is stale.

Installing in CI

One command, on every platform that has a shell:

curl -fsSL https://cli.vulnetix.com/install.sh | sh

It installs to /usr/local/bin, falling back to $HOME/.local/bin when that is not writable. Pin a release in CI:

curl -fsSL https://cli.vulnetix.com/install.sh | sh

On minimal images, install the script’s dependencies first — alpine ships without curl, bash, tar, or CA certificates:

apk add --no-cache bash ca-certificates curl tar

Via Go, note the /v3 module suffix; the module cannot be fetched without it:

go install github.com/vulnetix/cli/v3@latest
Note There is no published Vulnetix container image. The repository has a Dockerfile for local builds, but nothing is pushed to a registry. Install the CLI into a standard base image, or bake your own image once and reuse it.

Authenticating in CI

Set two environment variables from your platform’s secret store. That is the whole setup.

VariableValue
VULNETIX_ORG_IDOrganization UUID
VULNETIX_API_KEYApiKey hex digest

Then, as the first step of the job:

vulnetix auth verify

It reads the credential, calls the API, exits non-zero on failure, and writes nothing.

Do not run vulnetix auth login on an ephemeral runner. Environment variables sit at the top of the credential precedence chain, persist nothing, and disappear with the job; a login step writes a plaintext credentials file into the workspace for no benefit.

Do not store an ApiKey in VULNETIX_API_TOKEN. That variable holds a Bearer token, outranks everything else, and an ApiKey sent as a bearer credential is rejected. See Authentication in CI/CD.

What Each Subcommand Writes

Results land under .vulnetix/ in the scanned directory whether or not you ask for a copy elsewhere. Each command uploads its own findings to Vulnetix automatically when authenticated.

CommandDefault result fileFormatExits 1 when
vulnetix sca.vulnetix/sbom.cdx.jsonCycloneDXa gate flag is passed and breached
vulnetix sast.vulnetix/sast.sarifSARIF--severity is met or exceeded
vulnetix secrets.vulnetix/sast.sarifSARIF--severity is met or exceeded
vulnetix containers.vulnetix/containers.sarifSARIF--severity is met or exceeded
vulnetix iac.vulnetix/sast.sarifSARIF--severity is met or exceeded
vulnetix license.vulnetix/sbom.cdx.jsonCycloneDX--severity is met or exceeded
vulnetix cbom.vulnetix/cbom.cdx.jsonCycloneDX (CBOM)--fail-on status is found
vulnetix aibom.vulnetix/ai-bom.cdx.jsonCycloneDX (AIBOM)never
vulnetix malscan.vulnetix/malscan.sarifSARIFany malware finding
vulnetix scan.vulnetix/sbom.cdx.json + .vulnetix/sast.sarifbothany passed gate is breached
Note The SARIF-producing scans write their file only when there are findings. A clean scan deliberately leaves no empty artifact behind, so an artifact-upload step must tolerate a missing file.

Choosing the Output Flag

Three different behaviours. Getting this wrong is the most common mistake in a CI config.

FlagCommandsBehaviour
-o / --outputscan, sca, sast, secrets, containers, iacRepeatable. Takes a path ending .cdx.json or .sarif, or the literals json-cyclonedx / json-sarif for stdout
--output-filecbom, aibom, malscanSingle path. On these commands -o selects the terminal format only (pretty, json, …)
(neither)licenseWrites .vulnetix/sbom.cdx.json. -o json-spdx prints SPDX 2.3 to stdout. Copy the file out to publish it
# Two artifacts from one pass
vulnetix scan -o dist/results.sarif -o dist/sbom.cdx.json

# CBOM and AIBOM take a different flag
vulnetix cbom --output-file dist/cbom.cdx.json

# license takes neither
vulnetix license && cp .vulnetix/sbom.cdx.json dist/licenses.cdx.json

--format / -f on the scan family is deprecated; use --output.

Quality Gates

Gates are opt-in. Without a gate flag the command reports findings and exits 0.

FlagFails the build when
--severity low|medium|high|criticalany finding meets or exceeds the threshold
--block-malwarea dependency is a known malicious package, or malscan finds malware in the installed bytes
--block-eola runtime or package dependency is end-of-life
--block-unpinneda direct dependency uses a version range instead of an exact pin
--exploits poc|active|weaponizedexploit maturity reaches the threshold
--version-lag Na dependency is within the N most recently published versions
--cooldown Na dependency version was published within the last N days
vulnetix scan --severity high --block-malware --block-eol --exploits active

Most CI systems have a way to report a breach without blocking the merge — GitLab’s allow_failure: true, Jenkins’ catchError, GitHub’s continue-on-error. Prefer that to lowering the gate.

Uploading Third-Party Artifacts

The scan subcommands publish themselves. upload exists for reports produced by other tools.

vulnetix upload --file reports/semgrep.sarif
vulnetix upload --file reports/syft.spdx.json

The report is recorded under the name and version of the tool that produced it, in the category inferred from the report, with the same findings, triage and VEX records a first-party Vulnetix scan produces. The format is read from the file’s content rather than its name, because checkov and kics both write results.sarif.

FlagPurpose
--filePath to one report. Optional — without it, .vulnetix/ is auto-discovered
--dirDirectory to scan for reports
--formatOverride auto-detection
--org-idOrganization UUID, when not using stored or environment credentials
--jsonMachine-readable result: category, tool, finding counts, snapshot URL

Vulnetix accepts SARIF, CycloneDX and SPDX. Anything else is refused, naming the tool’s own SARIF flag where it has one:

$ vulnetix upload --file sonarqube-issues.json
Error: sonarqube-issues.json is not a format Vulnetix ingests (detected "json").
Vulnetix accepts SARIF, CycloneDX and SPDX.
SonarQube can emit SARIF: use its sonar.sarifReportPaths export.

Reports Vulnetix’s own scanners wrote are refused too: the subcommand that produced one published it when it ran, so republishing would record the same scan twice.

In GitHub Actions prefer vulnetix gha upload, which publishes every report a workflow run produced in one call.

Pipeline Context Is Automatic

The CLI detects GitHub Actions and GitLab CI from their environment variables and attributes findings to the right repository, commit, branch, and merge/pull request without any flags. On other platforms it falls back to reading the local git checkout.

You never pass --org-id on a machine where the environment credentials are set.