Scan Command Reference
The scan command walks your project directory, parses package manifests locally, and queries the Vulnetix VDB API to identify vulnerable dependencies. No file contents are ever uploaded to any server. Results are saved to .vulnetix/ and printed to your terminal.
Credentials are optional. When no credentials are configured the community fallback is used automatically.
Usage
vulnetix scan [flags]
vulnetix scan status <scan-id> [flags]
Flags
| Flag | Type | Default | Description |
|---|
--path | string | . | Directory to scan |
--depth | int | 3 | Maximum recursion depth for file discovery |
--exclude | stringArray | - | Exclude paths matching glob pattern (repeatable) |
-o, --output | stringArray | - | Output target (repeatable): json-cyclonedx or json-sarif for stdout; file path (.cdx.json, .cdx, .bom.json, .sbom.json) for CycloneDX to file; file path (.sarif, .sarif.json) for SARIF to file. Multiple flags combine file outputs with pretty display. |
-f, --format | string | - | Deprecated — maps to --output json-cyclonedx. Use --output instead. |
--concurrency | int | 5 | Max concurrent VDB queries |
--no-progress | bool | false | Suppress progress indicators |
--paths | bool | false | Show full transitive dependency paths (npm, Python, Rust, Ruby, PHP, Go). Edges are built from locally installed packages (node_modules/, venv, vendor/, cargo metadata). |
--no-exploits | bool | false | Suppress the detailed exploit intelligence section |
--no-remediation | bool | false | Suppress the detailed remediation section |
--no-licenses | bool | false | Skip license analysis during scan (license analysis runs by default) |
--severity | string | - | Exit with code 1 if any vulnerability meets or exceeds this level: low, medium, high, critical. Severity is coerced from all available scoring sources (CVSS, EPSS, Coalition ESS, SSVC). Also gates on SAST findings. |
--block-malware | bool | false | Exit with code 1 when any dependency is a known malicious package. |
--block-eol | bool | false | Exit with code 1 when a runtime or package dependency is end-of-life. Runtimes: Go, Node.js, Python, Ruby. Package-level checks activate when VDB has EOL data (404s are silently skipped). |
--block-unpinned | bool | false | Exit with code 1 when any direct dependency uses a version range (^, ~, >=) instead of an exact pin. |
--exploits | string | - | Exit with code 1 when exploit maturity reaches the threshold: poc (any public exploit), active (CISA/EU KEV / actively exploited), weaponized (in-the-wild only). |
--results-only | bool | false | Only output when findings exist; completely silent when the scan is clean. Also suppresses exploit and remediation detail sections. |
--version-lag | int | 0 | Exit with code 1 when any dependency is within the N most recently published versions of that package (0 = disabled). |
--cooldown | int | 0 | Exit with code 1 when any dependency version was published within the last N days (0 = disabled, best-effort). |
--sca-autofix | bool | false | Apply validated SCA fixes with the project package manager, then rescan to confirm. See SCA Autofix. |
--sca-autofix-strategy | string | stable | Target strategy for --sca-autofix: stable, safest, or latest. |
--sca-autofix-manifest | string | - | Restrict autofix edits to one manifest file; implies non-interactive manifest selection. |
--sca-autofix-max-major-bump | int | 0 | Refuse autofix targets crossing more than N major versions. |
--yes | bool | false | Non-interactive autofix mode: auto-pick safe defaults and never prompt. |
--evaluate-sast | bool | false | Enable SAST analysis (exclusive mode — disables all other features not explicitly enabled) |
--no-sast | bool | false | Skip SAST (sast-kind) rules |
--evaluate-sca | bool | false | Enable SCA — package manifest analysis (exclusive mode) |
--no-sca | bool | false | Skip SCA — skip ordinary package manifests |
--evaluate-licenses | bool | false | Enable license analysis (exclusive mode) |
--no-licenses | bool | false | Skip license analysis |
--evaluate-secrets | bool | false | Enable secret detection rules (exclusive mode) |
--no-secrets | bool | false | Skip secret-detection SAST rules |
--enable-containers | bool | false | Enable container file analysis (exclusive mode) |
--no-containers | bool | false | Skip Dockerfile/OCI manifests and container SAST rules |
--evaluate-iac | bool | false | Enable IaC analysis (exclusive mode) |
--no-iac | bool | false | Skip HCL/Nix manifests and IaC SAST rules |
--disable-default-rules | bool | false | Skip built-in default SAST rules (external --rule repos still loaded) |
--list-default-rules | bool | false | Print built-in SAST rules and exit |
-R, --rule | stringArray | - | External SAST rule repo in org/repo format (repeatable); fetched from GitHub or --rule-registry — see Custom Rule Repositories |
--rule-registry | string | https://github.com | Override default registry URL for all --rule repos |
--dry-run | bool | false | Detect files and parse packages locally, check memory, then exit — zero API calls |
--from-memory | bool | false | Reconstruct scan pretty output from .vulnetix/sbom.cdx.json without API calls |
--fresh-exploits | bool | false | With --from-memory: fetch latest exploit intel from API |
--fresh-advisories | bool | false | With --from-memory: fetch latest remediation plans from API |
--fresh-vulns | bool | false | With --from-memory: re-fetch affected version checks and latest scoring from API |
--reachability | string | both | Tree-sitter reachability mode: direct, transitive, both, or off. Per-finding source-level reachability analysis runs against every produced CVE. Disable globally with off for large monorepos. See the Reachability Analysis section. |
Output Files
After every scan the following files are written under your project root:
| Path | Description |
|---|
.vulnetix/sbom.cdx.json | CycloneDX 1.7 SBOM for all scanned packages |
.vulnetix/sast.sarif | SARIF 2.1.0 report from SAST analysis (written when any SAST sub-category runs) |
.vulnetix/memory.yaml | Scan state record (timestamp, counts, git context) |
Scan Status
Check the status of a previously submitted (legacy) remote scan.
vulnetix scan status <scan-id> [flags]
| Flag | Type | Default | Description |
|---|
--poll | bool | false | Poll until scan completes |
--poll-interval | int | 5 | Polling interval in seconds |
-o, --output | string | pretty | Output format: json, pretty |
Package Scope Support
Vulnerabilities and packages are organised by dependency scope where the package manager provides that information:
| Package Manager | Scopes |
|---|
| npm | production, development, peer, optional |
| Python (Pipfile) | production, development |
| Python (requirements.txt) | production |
| Go | production (no scope distinction in go.mod / go.sum) |
| Rust | production (no scope distinction in Cargo.lock) |
| Ruby | production (group info requires Gemfile) |
| Maven / Gradle | production, test, provided, runtime, system |
| Composer | production, development |
| Yarn / pnpm | production (scope requires correlation with package.json) |
| NuGet | production |
| Swift | production |
| Pub (Dart) | production, development |
| Hex (Elixir) | production |
| sbt (Scala) | production |
| CocoaPods | production |
| Conan (C/C++) | production |
| vcpkg (C/C++) | production |
Supported Manifest Files
The scanner recognizes these package manager manifest and lock files:
JavaScript / TypeScript
| Filename | Ecosystem | Lock file? |
|---|
package.json | npm | No |
package-lock.json | npm | Yes |
yarn.lock | npm | Yes |
pnpm-lock.yaml | npm | Yes |
Python
| Filename | Ecosystem | Lock file? |
|---|
pyproject.toml | PyPI | No |
requirements.txt | PyPI | No |
requirements.in | PyPI | No |
Pipfile | PyPI | No |
Pipfile.lock | PyPI | Yes |
poetry.lock | PyPI | Yes |
uv.lock | PyPI | Yes |
Go
| Filename | Ecosystem | Lock file? |
|---|
go.mod | Go | No |
go.sum | Go | Yes |
Rust
| Filename | Ecosystem | Lock file? |
|---|
Cargo.toml | Cargo | No |
Cargo.lock | Cargo | Yes |
Deno
| Filename | Ecosystem | Lock file? |
|---|
deno.json | Deno | No |
deno.lock | Deno | Yes |
Ruby
| Filename | Ecosystem | Lock file? |
|---|
Gemfile | RubyGems | No |
Gemfile.lock | RubyGems | Yes |
Java / Kotlin / Scala
| Filename | Ecosystem | Lock file? |
|---|
pom.xml | Maven | No |
build.gradle | Maven | No |
build.gradle.kts | Maven | No |
gradle.lockfile | Maven | Yes |
build.sbt | Maven | No |
build.lock | Maven | Yes |
C# / .NET
| Filename | Ecosystem | Lock file? |
|---|
*.csproj | NuGet | No |
packages.lock.json | NuGet | Yes |
paket.dependencies | NuGet | No |
paket.lock | NuGet | Yes |
PHP
| Filename | Ecosystem | Lock file? |
|---|
composer.json | Composer | No |
composer.lock | Composer | Yes |
Swift / iOS
| Filename | Ecosystem | Lock file? |
|---|
Package.swift | Swift | No |
Package.resolved | Swift | Yes |
Podfile | CocoaPods | No |
Podfile.lock | CocoaPods | Yes |
Cartfile | Carthage | No |
Cartfile.resolved | Carthage | Yes |
Dart
| Filename | Ecosystem | Lock file? |
|---|
pubspec.yaml | Pub | No |
pubspec.lock | Pub | Yes |
Elixir
| Filename | Ecosystem | Lock file? |
|---|
mix.exs | Hex | No |
mix.lock | Hex | Yes |
Erlang
| Filename | Ecosystem | Lock file? |
|---|
rebar.config | Hex | No |
rebar.lock | Hex | Yes |
C / C++
| Filename | Ecosystem | Lock file? |
|---|
vcpkg.json | vcpkg | No |
conanfile.txt | Conan | No |
conanfile.py | Conan | No |
conan.lock | Conan | Yes |
CMakeLists.txt | CPM | No |
CPM.cmake | CPM | No |
meson.build | Meson | No |
CMakeLists.txt is only recognized when the file contains CPMAddPackage.
Haskell
| Filename | Ecosystem | Lock file? |
|---|
*.cabal | Cabal | No |
cabal.project.freeze | Cabal | Yes |
stack.yaml | Stack | No |
OCaml
| Filename | Ecosystem | Lock file? |
|---|
opam | opam | No |
*.opam | opam | No |
Nix
| Filename | Ecosystem | Lock file? |
|---|
flake.nix | Nix | No |
flake.lock | Nix | Yes |
Julia
| Filename | Ecosystem | Lock file? |
|---|
Project.toml | Julia | No |
Manifest.toml | Julia | Yes |
Crystal
| Filename | Ecosystem | Lock file? |
|---|
shard.yml | Crystal | No |
shard.lock | Crystal | Yes |
R
| Filename | Ecosystem | Lock file? |
|---|
DESCRIPTION | CRAN | No |
renv.lock | CRAN | Yes |
Zig
| Filename | Ecosystem | Lock file? |
|---|
build.zig.zon | Zig | No |
Bazel / Buck
| Filename | Ecosystem | Lock file? |
|---|
MODULE.bazel | Bazel | No |
WORKSPACE | Bazel | No |
WORKSPACE.bazel | Bazel | No |
BUCK | Buck | No |
BUCK2 | Buck | No |
Containers
| Filename | Ecosystem | Lock file? |
|---|
Dockerfile | Docker | No |
Containerfile | Docker | No |
*.dockerfile | Docker | No |
*.containerfile | Docker | No |
Infrastructure as Code
| Filename | Ecosystem | Lock file? |
|---|
*.tf | Terraform | No |
CI/CD
| Filename | Ecosystem | Lock file? |
|---|
.github/workflows/*.yml | GitHub Actions | No |
.github/workflows/*.yaml | GitHub Actions | No |
Existing SBOMs
The scanner also detects and ingests existing SBOM documents:
- SPDX JSON documents (identified by
spdxVersion and SPDXID fields) - CycloneDX JSON documents (identified by
bomFormat: "CycloneDX" and specVersion)
License Analysis
By default, vulnetix scan also runs license analysis on all discovered packages. License findings appear in the pretty output after the vulnerability summary and are stored in the CycloneDX BOM with source vulnetix-license-analyzer.
License resolution uses a multi-source pipeline (manifests, filesystem, container metadata, deps.dev, GitHub). See the License Command Reference for full details on resolution sources, evaluation rules, and conflict detection.
To skip license analysis:
vulnetix scan --no-licenses
Feature Control
By default, vulnetix scan runs all analysis categories: SCA, SAST (including secret detection, container rules, and IaC rules), and license analysis.
Enabling individual features (exclusive mode)
When any --evaluate-X flag is set, only the explicitly enabled categories run — everything else is disabled. This makes it easy to scope a scan to a single concern:
# SCA only (vulnerability analysis on package manifests)
vulnetix scan --evaluate-sca
# SAST only (general static analysis rules)
vulnetix scan --evaluate-sast
# Secret detection only
vulnetix scan --evaluate-secrets
# Container analysis only (Dockerfile/OCI rules)
vulnetix scan --enable-containers
# IaC analysis only (Terraform, Nix)
vulnetix scan --evaluate-iac
# License analysis only
vulnetix scan --evaluate-licenses
Disabling individual features
--no-X flags disable a specific category while leaving all others enabled:
# Run everything except license analysis
vulnetix scan --no-licenses
# Run everything except secret-detection rules
vulnetix scan --no-secrets
# Skip IaC files and rules
vulnetix scan --no-iac
# Skip containers
vulnetix scan --no-containers
# Skip all SAST-kind rules (but still run secrets/containers/IaC rules)
vulnetix scan --no-sast
Specialized scan commands
For convenience, dedicated top-level commands wrap common single-category scans:
| Command | Equivalent |
|---|
vulnetix sca | vulnetix scan --evaluate-sca --no-sast --no-secrets --no-containers --no-iac --no-licenses |
vulnetix sast | vulnetix scan --evaluate-sast --no-sca --no-secrets --no-containers --no-iac --no-licenses |
vulnetix secrets | vulnetix scan --evaluate-secrets --no-sast --no-sca --no-containers --no-iac --no-licenses |
vulnetix containers | vulnetix scan --enable-containers --no-sast --no-sca --no-secrets --no-iac --no-licenses |
vulnetix iac | vulnetix scan --evaluate-iac --no-sast --no-sca --no-secrets --no-containers --no-licenses |
SAST (Static Application Security Testing)
By default, vulnetix scan also runs SAST analysis alongside SCA. SAST evaluates Rego-based rules against your source files to detect code-level security issues — weak cryptography, hardcoded credentials, missing lock files, insecure deserialization, and more.
SAST findings appear in the pretty output after the SCA summary and are written to .vulnetix/sast.sarif in SARIF 2.1.0 format. Each finding includes CWE, CAPEC, and MITRE ATT&CK technique mappings, plus stable fingerprints for tracking results across runs.
SAST rules are organized into four sub-categories that can be toggled independently:
| Sub-category | Flag to disable | Rule kind | Applies to |
|---|
| Static analysis | --no-sast | sast | General code security rules |
| Secret detection | --no-secrets | secrets | Hardcoded credentials, API keys, tokens |
| Container rules | --no-containers | oci | Dockerfile / Containerfile analysis |
| IaC rules | --no-iac | iac | Terraform HCL, Nix files |
Disabling SAST
# Skip all SAST-kind rules (secrets/containers/IaC still run)
vulnetix scan --no-sast
# Skip secret-detection rules specifically
vulnetix scan --no-secrets
# Skip all SAST entirely (all four sub-categories)
vulnetix scan --no-sast --no-secrets --no-containers --no-iac
# Skip built-in rules only (external rule repos still loaded)
vulnetix scan --disable-default-rules --rule myorg/my-rules
Listing Built-in Rules
Prints all all built-in rules with their IDs, names, severities, and language targets, then exit:
vulnetix scan --list-default-rules
External Rule Repos
Load additional Rego rules from Git repositories. See the Custom Rule Repositories guide for a full walkthrough including repository setup, rule authoring, and all flag combinations. Rules are fetched from GitHub by default or from a custom registry.
# Load rules from a GitHub repo
vulnetix scan --rule myorg/custom-rules
# Load multiple external rule repos
vulnetix scan --rule myorg/rules-a --rule myorg/rules-b
# Use a custom registry (e.g. GitLab or self-hosted Gitea)
vulnetix scan --rule myorg/rules --rule-registry https://gitlab.example.com
SAST Severity Gating
SAST findings participate in --severity gating alongside SCA vulnerabilities. When any SAST finding meets or exceeds the threshold, the scan exits with code 1:
# Exit 1 on high or critical SAST findings (or SCA vulnerabilities)
vulnetix scan --severity high
Built-in Rules
27 rules ship with the CLI. Run vulnetix scan --list-default-rules for full descriptions and CWE/CAPEC/ATT&CK mappings.
Cryptography
| Rule ID | Severity | Name | Languages |
|---|
VNX-CRYPTO-001 | medium | MD5 usage detected | Python, Node, Go, Java, Ruby, PHP |
VNX-CRYPTO-002 | medium | SHA-1 usage detected | Python, Node, Go, Java, Ruby, PHP |
Container Security
| Rule ID | Severity | Name | Applies to |
|---|
VNX-DOCKER-001 | medium | Dockerfile missing USER directive | Dockerfile, Containerfile |
VNX-DOCKER-002 | medium | Dockerfile FROM :latest tag | Dockerfile, Containerfile |
Go
| Rule ID | Severity | Name |
|---|
VNX-GO-001 | high | Missing go.sum |
VNX-GO-002 | high | Command injection via exec.Command |
Java
| Rule ID | Severity | Name |
|---|
VNX-JAVA-001 | high | Command injection via Runtime.exec() |
VNX-JAVA-002 | medium | Spring actuator endpoints exposed |
Node.js
| Rule ID | Severity | Name |
|---|
VNX-NODE-001 | high | Missing npm lock file |
VNX-NODE-002 | high | eval() or new Function() in JavaScript |
VNX-NODE-003 | high | Command injection via child_process |
VNX-NODE-004 | medium | Express app without helmet |
VNX-NODE-005 | medium | innerHTML or dangerouslySetInnerHTML usage |
PHP
| Rule ID | Severity | Name |
|---|
VNX-PHP-001 | high | Missing composer.lock |
VNX-PHP-002 | high | Dangerous function in PHP |
Python
| Rule ID | Severity | Name |
|---|
VNX-PY-001 | high | Missing Python lock file |
VNX-PY-002 | high | eval()/exec() usage in Python |
VNX-PY-003 | high | Insecure deserialization with pickle |
VNX-PY-004 | high | yaml.load() without SafeLoader |
VNX-PY-005 | medium | Weak PRNG for security operations |
VNX-PY-006 | medium | Django DEBUG=True |
Ruby
| Rule ID | Severity | Name |
|---|
VNX-RUBY-001 | high | Missing Gemfile.lock |
VNX-RUBY-002 | high | eval() or system() in Ruby |
Rust
| Rule ID | Severity | Name |
|---|
VNX-RUST-001 | high | Missing Cargo.lock |
Secrets & Credentials
| Rule ID | Severity | Name |
|---|
VNX-SEC-001 | critical | AWS access key ID |
VNX-SEC-002 | critical | Private key committed |
VNX-SEC-004 | critical | GitHub or GitLab token |
SARIF Output
SAST results are always written to .vulnetix/sast.sarif. To write a combined SARIF report (SCA + SAST) to a custom path, use --output:
# Write combined SARIF to a file; pretty summary still goes to stdout
vulnetix scan --output results.sarif
# Write both CycloneDX and SARIF files alongside pretty output
vulnetix scan --output sbom.cdx.json --output results.sarif
The auto-written .vulnetix/sast.sarif contains SAST-only findings. The --output *.sarif file contains all scan findings (SCA + SAST) in SARIF format.
Auto-Discovery
The scanner walks the directory tree starting from --path up to --depth levels deep. It automatically skips common non-project directories:
node_modules, .git, .hg__pycache__, .tox, .venvvendor, .cargo
Use --exclude to skip additional paths by glob pattern.
Dependency graph from installed packages
After parsing manifests, the scanner also reads locally installed package directories to build a complete transitive dependency graph. This improves SBOM dependencies section accuracy and powers --paths output — no extra flags required.
| Ecosystem | Install directory |
|---|
| npm | node_modules/ (follows symlinks for pnpm) |
| Python | venv site-packages/*.dist-info/METADATA |
| Rust | cargo metadata subprocess |
| Ruby | vendor/bundle/ or GEM_HOME gemspec files |
| PHP | vendor/*/composer.json |
| Go | go mod graph subprocess |
If the install directory is not present, the scanner falls back to lock-file edge parsing where available.
Examples
Auto-discover and scan the current directory
Scan a specific project directory
vulnetix scan --path /path/to/project --depth 5
Exclude test fixtures and vendor directories
vulnetix scan --exclude "test/**" --exclude "vendor/**"
Emit CycloneDX JSON to stdout
vulnetix scan --output json-cyclonedx
Emit SARIF JSON to stdout
vulnetix scan --output json-sarif
Write CycloneDX to a file (pretty output still goes to stdout)
vulnetix scan --output /tmp/sbom.cdx.json
Write SARIF to a file (pretty output still goes to stdout)
vulnetix scan --output /tmp/results.sarif
Write both CycloneDX and SARIF files alongside pretty output
vulnetix scan --output /tmp/sbom.cdx.json --output /tmp/results.sarif
Raw CycloneDX JSON for scripting
vulnetix scan -o json-cyclonedx | jq '.components'
Suppress progress indicators (useful in CI without a TTY)
vulnetix scan --no-progress
Break the build on high or critical vulnerabilities
# Exit 1 if any high or critical vulnerability is found
vulnetix scan --severity high
# Exit 1 on any scored severity and emit a CycloneDX BOM
vulnetix scan --severity low -f cdx17
Gate on EOL runtimes and packages
# Exit 1 when a runtime or package dependency is end-of-life
vulnetix scan --block-eol
# Combine with severity gating
vulnetix scan --block-eol --severity high
Gate on version lag (supply chain freshness)
# Exit 1 if using the very latest published version of any dependency
vulnetix scan --version-lag 1
# Exit 1 if any dependency is within the 3 most recent releases
vulnetix scan --version-lag 3
Gate on recently published dependencies (cooldown period)
# Exit 1 if any dependency was published in the last 3 days
vulnetix scan --cooldown 3
# Combine multiple supply chain gates
vulnetix scan --block-malware --block-unpinned --version-lag 1 --cooldown 3 --severity high
Suppress output when clean (results-only mode)
# No output when scan is clean; table appears only when findings exist
vulnetix scan --results-only
SAST — list, disable, and load custom rules
# List all built-in SAST rules and exit
vulnetix scan --list-default-rules
# Skip all SAST-kind rules (general static analysis)
vulnetix scan --no-sast
# Skip secret detection
vulnetix scan --no-secrets
# Skip all SAST entirely (all four sub-categories)
vulnetix scan --no-sast --no-secrets --no-containers --no-iac
# Skip built-in rules but load a custom rule repo from GitHub
vulnetix scan --disable-default-rules --rule myorg/custom-rules
# Load additional rules on top of the built-in set
vulnetix scan --rule myorg/extra-rules
# Use a self-hosted registry for custom rules
vulnetix scan --rule myorg/rules --rule-registry https://git.example.com
# Skip exploit intelligence and remediation details
vulnetix scan --no-exploits --no-remediation
Skip license analysis
vulnetix scan --no-licenses
Dry run (detect files, no API calls)
Reconstruct results from previous scan
# From memory — no API calls
vulnetix scan --from-memory
# From memory with fresh exploit intel
vulnetix scan --from-memory --fresh-exploits
# From memory with fresh remediation plans
vulnetix scan --from-memory --fresh-advisories
Check scan status (legacy remote scan)
# One-shot check
vulnetix scan status abc123def
# Poll until complete
vulnetix scan status abc123def --poll --poll-interval 10
Org Quality Gate Policy
When you run a scan while authenticated and your organization has configured a Quality Gate, its settings are pulled in before the gate is evaluated and override the matching scan flag defaults — org policy always wins, even over a flag you pass explicitly. The override applies to --severity, --block-eol, --block-malware, --block-unpinned, --exploits, --version-lag, --cooldown, --sca-autofix-strategy, and --sca-autofix-max-major-bump. Settings the org left unset fall back to your flag or the builtin default.
Run with --verbose to see which settings were applied or superseded. Inspect the active policy with:
vulnetix config get quality-gate
Non-authenticated scans (no credentials, or the community fallback) have no organization to read from and use only the CLI flags you pass.
Exit Codes
| Code | Meaning |
|---|
0 | Scan completed successfully (no threshold breach) |
1 | A gate was breached (--severity, --block-eol, --block-malware, --block-unpinned, --exploits, --version-lag, --cooldown), or a fatal error occurred |