Skip to content

gha upload, status and setup

Publish every scanner report a GitHub Actions run produced, check what was recorded, and generate the scanner workflow.

Updated 02 Nov 2026Checked against cli@24498404a

The posture subcommands (gha workflows, actions, settings, org, audit) are on GitHub posture commands.

gha upload

vulnetix gha upload [--org-id <uuid>] [flags]

Lists the current run’s artifacts, downloads and extracts each, classifies every file as SARIF, CycloneDX or SPDX, validates it, and publishes it to Vulnetix in the category the report implies, under the tool that produced it (a gosec report is recorded as gosec). It then prints the ingestion snapshot for each file.

Flag Default Effect
--org-id <uuid> the credential’s org Organisation to publish to. With no credential and no flag: --org-id is required (no stored credentials found).
--json off One JSON result per file: name, file, status (uploaded, duplicate, skipped, error), reason, format, category, tool, toolVersion, findings, snapshotUuid, snapshotUrl
--dry-run off Classify and validate, publish nothing
--strict off Count skipped files (unrecognised formats) as failures
--fail-on-empty off Fail when the run produced no publishable artifact. Without it, an empty run succeeds.
--no-github-api off Do not call the GitHub REST API to enrich the CI context

It reads GITHUB_TOKEN (required), GITHUB_REPOSITORY, GITHUB_RUN_ID and GITHUB_API_URL from the environment. Reports written by Vulnetix’s own scanners are skipped: the command that wrote them published them when it ran.

It exits 1 if any file fails to publish. A file that cannot be published says why, for example an empty SARIF left by a shell redirect that captured nothing.

Permissions and placement

  publish:
    runs-on: ubuntu-latest
    needs: [gosec, trivy-fs]       # every job that uploads an artifact
    if: always()                   # one failing scanner must not stop the others publishing
    permissions:
      contents: read
      actions: read                # to list the run's artifacts
    env:
      VULNETIX_ORG_ID: ${{ secrets.VULNETIX_ORG_ID }}
      VULNETIX_API_KEY: ${{ secrets.VULNETIX_API_KEY }}
    steps:
      - name: Install Vulnetix CLI
        run: |
          curl -fsSL https://cli.vulnetix.com/install.sh | sh -s -- --install-dir "$HOME/.local/bin"
          echo "$HOME/.local/bin" >> "$GITHUB_PATH"
      - name: Publish scanner reports
        env:
          GITHUB_TOKEN: ${{ github.token }}
        run: vulnetix gha upload --org-id "$VULNETIX_ORG_ID" --json --no-banner --no-progress

needs and if: always() both matter, and both fail silently when wrong: a job missing from needs may finish after the publish job and is never sent, and without always() one failed scanner stops every other report being published.

Re-runs

Each report is keyed by run, attempt and tool. Re-running the publish job reuses the existing scan instead of recording it twice; a new run attempt is a new scan.

gha status

vulnetix gha status                        # the current run, inside a workflow
vulnetix gha status --run-id 30155614396
vulnetix gha status --run-id 30155614396 --attempt 2 --json
vulnetix gha status --uuid <ingestion-snapshot-uuid>

Reports every tool the run published, its version, the category it was filed under and how many findings it contributed. A tool you set up that is missing from the list did not publish: run this after changing a pipeline rather than trusting a green check.

Flag Default Effect
--run-id <id> GITHUB_RUN_ID Workflow run to report on
--attempt <n> GITHUB_RUN_ATTEMPT One attempt only
--uuid <uuid> One ingestion snapshot instead of a run
--json off JSON output

gha setup

vulnetix gha setup --list
vulnetix gha setup --detect
vulnetix gha setup gosec trivy-fs checkov
vulnetix gha setup --all --dry-run

Writes or updates .github/workflows/vulnetix-scanners.yml: one job per scanner that uploads its report as an artifact, and the publish job above. Running it again for another tool adds that tool and keeps the others. The CLI is installed unpinned in the generated workflow; the scanners are pinned.

Flag Default Effect
[tool...] Scanner IDs from --list
--list List the catalogue
--detect Pick the scanners this repository can feed (a Go module gets gosec and govulncheck, a Dockerfile gets hadolint and the image scanners, language-agnostic ones always). Tools that need a credential or a live target (Snyk, ZAP, Nuclei) are never picked.
--all Every scanner in the catalogue
--on <events> push,workflow_dispatch Triggers: push, pull_request, schedule, workflow_dispatch
--cron <expr> a weekly slot derived from the repository name Schedule, when --on includes schedule
--runs-on <labels> ubuntu-latest Runner labels, e.g. self-hosted,Linux,X64
--dry-run Print the workflow instead of writing it
--force Replace an existing workflow not written by this command

Every scanner, and the exact job it adds, is on Third-party scanners.

Troubleshooting

Symptom Fix
GITHUB_TOKEN environment variable is required Add GITHUB_TOKEN: ${{ github.token }} to the step’s env; it is not in the environment by default
no artifacts found The publish job ran before the scanners finished, or they are missing from needs. Add --fail-on-empty to make this fail the job.
A tool is missing from gha status Its artifact was absent, empty or not SARIF, CycloneDX or SPDX. gha upload --json names the file and the reason.
--org-id is required Set VULNETIX_ORG_ID and VULNETIX_API_KEY on the job
Edit this pageSources: cli/cmd/gha.go, cli/cmd/gha_submit.go, cli/cmd/gha_setup.go, cli/internal/ghasetup/render.go, cli/internal/github
esc
↑ ↓ move↵ openSearches in your browser. A key like autonomy.max or a code like threshold_required jumps straight to it.