CI/CD Integration Guide
Tool:
vise-scanCLI (single-file, self-contained — no runtime to install) Platforms: Linux x64 · macOS ARM64 · Windows x64/ARM64 Distribution:https://download.visesec.com/cli/<version>/(same endpoint the IDE extensions use) Updated: 2026-06-22
The CLI is a single self-contained binary. Every recipe below pins a version and
verifies the download against a published SHA256SUMS before running it — never
pipe an unverified binary into your pipeline.
Important — CI/CD scanning is an Enterprise (Team-CI) capability
The CLI detects a CI environment and exits
4unless it sees a valid Enterprise entitlement. Authenticate it with a machine-unbound CI token, not a license key:
- In your account portal → Settings → CI tokens → Generate CI token. The token is machine-unbound (works on ephemeral runners), does not consume a developer seat, and is revocable any time.
- Store it as a secret named
VISE_CI_TOKEN; every recipe reads it from the environment (it never appears on the command line).- A regular
--license-keyis machine-bound and will not work in CI.- Local, non-CI scanning stays free at any tier — this gate only applies to pipelines.
Quick Start
# Local (free, any tier) — exits 2 if Critical/High found
vise-scan ./src --format text --quiet
# In CI (Enterprise) — VISE_CI_TOKEN is read from the environment
export VISE_CI_TOKEN="<your-ci-token>"
vise-scan ./src --edition enterprise --format sarif --output results.sarif --quiet
Exit Codes
The exit code is the gate. It reflects the highest severity found (plus error states):
| Code | Meaning | Pipeline Action |
|---|---|---|
0 |
No vulnerabilities | Pass |
1 |
Medium/Low/Info only | Pass (or warn) |
2 |
Critical or High found | Fail the build |
3 |
Invalid arguments | Fail (config error) |
4 |
Entitlement error — missing/invalid VISE_CI_TOKEN, or non-Enterprise in CI |
Fail (setup error) |
5 |
Scan error | Fail (runtime error) |
6 |
Cancelled | Fail |
7 |
Timeout | Fail (raise --timeout) |
A clean gate is simply: fail when exit code ≥ 2.
GitHub Actions
Recommended: the vise-action
The published Action handles download, checksum verification, OS/arch detection, the scan, the gate, and the SARIF upload — in one step:
name: Security Scan
on: [push, pull_request]
permissions:
contents: read
security-events: write # required for the SARIF upload
jobs:
security-scan:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: visesec/vise-action@v1
with:
path: .
ci-token: ${{ secrets.VISE_CI_TOKEN }}
min-severity: medium
upload-sarif: true
That's the whole integration. The job fails automatically when Critical/High are found.
Action inputs
| Input | Default | Description |
|---|---|---|
path |
. |
Directory to scan |
version |
1.0.0 |
CLI version to download (pin it) |
ci-token |
— | Enterprise CI token (machine-unbound). Pass ${{ secrets.VISE_CI_TOKEN }} |
edition |
enterprise |
Scan edition (CI requires enterprise) |
min-severity |
info |
info / low / medium / high / critical |
format |
sarif |
sarif / json / text |
output |
vise-results.sarif |
Report path |
exclude |
— | Comma-separated globs to skip |
fail-on-findings |
true |
Set false for report-only (don't fail on exit 2) |
upload-sarif |
false |
Auto-upload SARIF to GitHub code scanning |
download-base-url |
https://download.visesec.com/cli |
Override for an air-gapped mirror |
Outputs: exit-code (raw scanner code) and sarif-file (report path).
PR gate — report findings, fail only on High+
name: PR Security Gate
on:
pull_request:
branches: [main]
permissions:
contents: read
security-events: write
jobs:
security-gate:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- id: scan
uses: visesec/vise-action@v1
with:
path: .
ci-token: ${{ secrets.VISE_CI_TOKEN }}
min-severity: high
exclude: "**/test/**,**/node_modules/**,**/bin/**"
upload-sarif: true
# The action already fails the job on Critical/High. For a custom message
# instead, set fail-on-findings: false and branch on steps.scan.outputs.exit-code.
Without the Action (manual install)
If you prefer not to use the Action, the same canonical install snippet works in any
GitHub job — see Manual install below, then run the scan with
VISE_CI_TOKEN in the environment.
Manual install (any CI)
Use this canonical snippet on any Linux runner. It pins the version and verifies the checksum — copy it verbatim:
# Pin the version — never float to "latest" in CI.
VISE_VERSION="1.0.0"
BASE="https://download.visesec.com/cli/${VISE_VERSION}"
# Download the single-file binary + its checksum manifest, then verify before use.
curl -fsSL --retry 3 -o vise-scan-linux-x64 "${BASE}/vise-scan-linux-x64"
curl -fsSL --retry 3 -o SHA256SUMS "${BASE}/SHA256SUMS"
grep ' vise-scan-linux-x64$' SHA256SUMS | sha256sum -c - # aborts on mismatch
chmod +x vise-scan-linux-x64 && mv vise-scan-linux-x64 vise-scan
For macOS runners use vise-scan-osx-arm64 and shasum -a 256 -c -. For Windows use
vise-scan-win-x64.exe and CertUtil -hashfile.
Then scan with the Enterprise CI token in the environment:
export VISE_CI_TOKEN="$VISE_CI_TOKEN" # from your CI secret store
./vise-scan . --edition enterprise --format sarif --output results.sarif --min-severity medium --quiet
GitLab CI
security-scan:
stage: test
image: ubuntu:22.04
variables:
VISE_VERSION: "1.0.0"
# Set VISE_CI_TOKEN as a masked CI/CD variable (Settings -> CI/CD -> Variables).
before_script:
- apt-get update && apt-get install -y curl
- BASE="https://download.visesec.com/cli/${VISE_VERSION}"
- curl -fsSL --retry 3 -o vise-scan-linux-x64 "${BASE}/vise-scan-linux-x64"
- curl -fsSL --retry 3 -o SHA256SUMS "${BASE}/SHA256SUMS"
- grep ' vise-scan-linux-x64$' SHA256SUMS | sha256sum -c -
- chmod +x vise-scan-linux-x64 && mv vise-scan-linux-x64 vise-scan
script:
- ./vise-scan . --edition enterprise --format sarif --output gl-sast-report.sarif --quiet
artifacts:
reports:
sast: gl-sast-report.sarif
paths:
- gl-sast-report.sarif
when: always
allow_failure: false
Azure DevOps
trigger:
branches:
include:
- main
- develop
pool:
vmImage: 'ubuntu-latest'
variables:
VISE_VERSION: '1.0.0'
# Add VISE_CI_TOKEN as a secret pipeline variable (do not echo it).
steps:
- task: Bash@3
displayName: 'Install vise-scan'
inputs:
targetType: inline
script: |
BASE="https://download.visesec.com/cli/$(VISE_VERSION)"
curl -fsSL --retry 3 -o vise-scan-linux-x64 "${BASE}/vise-scan-linux-x64"
curl -fsSL --retry 3 -o SHA256SUMS "${BASE}/SHA256SUMS"
grep ' vise-scan-linux-x64$' SHA256SUMS | sha256sum -c -
chmod +x vise-scan-linux-x64 && mv vise-scan-linux-x64 vise-scan
- task: Bash@3
displayName: 'Run Security Scan'
env:
VISE_CI_TOKEN: $(VISE_CI_TOKEN)
inputs:
targetType: inline
script: |
./vise-scan . \
--edition enterprise \
--format sarif \
--output $(Build.ArtifactStagingDirectory)/results.sarif \
--quiet
- task: PublishBuildArtifacts@1
displayName: 'Publish SARIF Report'
condition: always()
inputs:
PathtoPublish: $(Build.ArtifactStagingDirectory)/results.sarif
ArtifactName: security-report
Jenkins
pipeline {
agent any
environment {
VISE_VERSION = '1.0.0'
VISE_CI_TOKEN = credentials('vise-ci-token') // Enterprise CI token
}
stages {
stage('Install Scanner') {
steps {
sh '''
BASE="https://download.visesec.com/cli/${VISE_VERSION}"
curl -fsSL --retry 3 -o vise-scan-linux-x64 "${BASE}/vise-scan-linux-x64"
curl -fsSL --retry 3 -o SHA256SUMS "${BASE}/SHA256SUMS"
grep ' vise-scan-linux-x64$' SHA256SUMS | sha256sum -c -
chmod +x vise-scan-linux-x64 && mv vise-scan-linux-x64 vise-scan
'''
}
}
stage('Security Scan') {
steps {
sh '''
./vise-scan . \
--edition enterprise \
--format sarif \
--format json \
--output results.sarif \
--min-severity medium \
--quiet
'''
}
post {
always {
archiveArtifacts artifacts: 'results.*', fingerprint: true
recordIssues tool: sarif(pattern: 'results.sarif')
}
}
}
}
post {
failure {
echo 'Security scan found Critical/High vulnerabilities!'
}
}
}
Bitbucket Pipelines
pipelines:
default:
- step:
name: Security Scan
image: ubuntu:22.04
# Set VISE_CI_TOKEN as a secured repository variable.
script:
- apt-get update && apt-get install -y curl
- export VISE_VERSION="1.0.0"
- BASE="https://download.visesec.com/cli/${VISE_VERSION}"
- curl -fsSL --retry 3 -o vise-scan-linux-x64 "${BASE}/vise-scan-linux-x64"
- curl -fsSL --retry 3 -o SHA256SUMS "${BASE}/SHA256SUMS"
- grep ' vise-scan-linux-x64$' SHA256SUMS | sha256sum -c -
- chmod +x vise-scan-linux-x64 && mv vise-scan-linux-x64 vise-scan
- ./vise-scan . --edition enterprise --format sarif --output results.sarif --quiet
artifacts:
- results.sarif
Docker
Build a self-contained scanner image with the binary baked in and verified:
FROM ubuntu:22.04
ARG VISE_VERSION=1.0.0
RUN apt-get update && apt-get install -y curl ca-certificates && rm -rf /var/lib/apt/lists/* && \
BASE="https://download.visesec.com/cli/${VISE_VERSION}" && \
curl -fsSL --retry 3 -o vise-scan-linux-x64 "${BASE}/vise-scan-linux-x64" && \
curl -fsSL --retry 3 -o SHA256SUMS "${BASE}/SHA256SUMS" && \
grep ' vise-scan-linux-x64$' SHA256SUMS | sha256sum -c - && \
chmod +x vise-scan-linux-x64 && mv vise-scan-linux-x64 /usr/local/bin/vise-scan && rm SHA256SUMS
ENTRYPOINT ["vise-scan"]
# Build
docker build -t vise-scan .
# Scan a local project (pass the Enterprise CI token through)
docker run --rm -e VISE_CI_TOKEN -v "$(pwd)":/project vise-scan \
/project --edition enterprise --format sarif --output /project/results.sarif --quiet
CLI Reference
Options
| Option | Description | Default |
|---|---|---|
<path> |
Directory to scan (required) | - |
--edition |
basic, pro, enterprise (CI requires enterprise) |
basic |
--format |
sarif, json, text (repeatable; SARIF is Enterprise) |
sarif |
--output, -o |
Output file path | vise-report.{format} |
--languages |
Comma-separated language filter | all detected |
--exclude |
Glob exclusion patterns | none |
--min-severity |
info, low, medium, high, critical |
info |
--baseline |
Baseline report for delta comparison | none |
--max-vulns |
Maximum vulnerabilities to report | 10000 |
--license-key |
License key for local Pro/Enterprise (machine-bound; not for CI) | none |
--nvd-api-key |
NVD API key (or use NVD_API_KEY env) |
none |
--no-secrets |
Disable secret detection | enabled |
--no-deps |
Disable dependency scanning | enabled |
--no-config |
Disable configuration scanning | enabled |
--no-iac |
Disable IaC scanning | enabled |
--no-live-cve |
Disable live CVE lookup | enabled |
--quiet, -q |
Suppress progress output | verbose |
Environment Variables
| Variable | Purpose |
|---|---|
VISE_CI_TOKEN |
Enterprise CI token (machine-unbound) — the supported way to authenticate in CI |
VISE_LICENSE_KEY |
Local license key (machine-bound; alternative to --license-key for non-CI use) |
NVD_API_KEY |
NVD API key for higher CVE lookup rate limits |
Best Practices
- Store the CI token as a secret named
VISE_CI_TOKEN— never hardcode it in pipeline files - Pin the version — set
VISE_VERSION/ the Action'sversion; never float to "latest" in CI - Verify the checksum — every recipe here does; don't strip it out
- Use
--quietin CI — cleaner logs, only summary output - Use
--min-severity medium— ignore Info/Low to reduce noise - Upload SARIF — enables GitHub Code Scanning, IDE annotations, PR comments
- Use
--exclude— skipnode_modules,bin,obj,vendor, test fixtures - Cache the binary — key the cache on
VISE_VERSIONto avoid re-downloading - Gate on exit code ≥ 2 — Critical/High fail the build; errors (≥3) fail loudly
SARIF Integration
The --format sarif output is OASIS SARIF 2.1.0 compliant, includes
partialFingerprints for stable cross-run dedup, and integrates with:
- GitHub Code Scanning —
github/codeql-action/upload-sarif@v3 - GitLab SAST — via
artifacts.reports.sast - Azure DevOps — SARIF Viewer extension
- VS Code — SARIF Viewer extension
- Visual Studio — built-in SARIF support
- JetBrains IDEs — SARIF support via plugin
Vise CLI v1.0.0 · Generated 2026-06-22