WASViking Docs
⌘K
Sentinel agent

wasviking-sentinel in CI/CD

Drop the same Go binary in your pipeline for SBOM, secrets, and policy-driven cloud scans. Three independent gates, one preflight, deterministic exit codes.

The same wasviking-sentinel binary that opens the mTLS tunnel also runs as a one-shot tool in CI/CD pipelines. In a CI/CD context the agent does not need to be registered (no mTLS bootstrap, no certificates). It authenticates with an organization API key.

Three independent gates ship today, each a top-level subcommand:

Subcommand Gate OWASP
wasviking-sentinel sbom Vulnerable components (SCA). A06
wasviking-sentinel secrets Hard-coded credentials. A07 / CWE-798
wasviking-sentinel scan Cloud DAST, template-driven. varies

Each subcommand is documented in detail on its own page:

Quick start (GitHub Actions)

# .github/workflows/security.yml
- name: WASViking · SCA
  run: ./wasviking-sentinel sbom --path . --fail-on high --submit
  env:
    WASV_API_KEY: ${{ secrets.WASVIKING_CI_KEY }}

- name: WASViking · Secrets
  run: ./wasviking-sentinel secrets --path . --verify --submit
  env:
    WASV_API_KEY: ${{ secrets.WASVIKING_CI_KEY }}

- name: WASViking · Cloud DAST
  run: ./wasviking-sentinel scan --template prod-web-strict --target https://staging.example.com
  env:
    WASV_API_KEY: ${{ secrets.WASVIKING_CI_KEY }}

Equivalent for GitLab, CircleCI, Jenkins, and Buildkite. Any Linux runner that can execute the binary works.

Authentication

export WASV_API_KEY=wv_live_xxxxxxxxxxxxxxxxxxxxxxxx
./wasviking-sentinel version

API keys are created in the portal under Settings → API Keys. The key needs the right scopes for what you actually do:

Subcommand Required scopes
sbom (license check only) any active org key
sbom --submit sca:submit
secrets (license check only) any active org key
secrets --submit secrets:submit
scan scans:run, templates:read

Use a dedicated CI key with only the scopes you need.

License check (preflight)

Every sbom, secrets, and CI-side scan invocation calls POST /api/v1/sentinel/preflight before doing any work. The preflight is mandatory: an empty or rejected API key blocks the run.

  • --api-key (or env WASV_API_KEY) is required, even when you are not submitting results.
  • Successful approvals cache at ~/.wasviking/preflight_cache.json (mode 0600) for 30 minutes.
  • 24-hour grace window if the API is unreachable but a recent approval exists on disk.
  • Active rejection (401 / 403) does not get the grace window: revoked keys block on the next cache expiration.
  • Cache invalidates on key rotation (cache key is a truncated SHA-256 of the API key).

For the full preflight model, see the License check section on the sbom page.

SCA gate (sbom)

./wasviking-sentinel sbom \
  --path . \
  --app-name checkout-api \
  --app-version "$CI_COMMIT_TAG" \
  --fail-on high \
  --submit

Behavior:

  1. Walk manifests under --path (recursive).
  2. Build a CycloneDX 1.5 SBOM.
  3. Enrich with OSV.dev advisories and CISA KEV.
  4. Apply --fail-on policy.
  5. If --submit, POST to the WASViking API.

Exit codes:

Exit code Meaning
0 OK. No findings at or above --fail-on.
1 Generic failure (parse, IO, network).
60 OSV or KEV enrichment failed but SBOM produced.
61 Submission failed; SBOM is on disk.
70 Findings at or above the --fail-on threshold.

Full flag reference: wasviking-sentinel sbom.

Secrets gate (secrets)

./wasviking-sentinel secrets \
  --path . \
  --git \
  --verify \
  --fail-on high \
  --submit

Behavior:

  1. Walk the working tree under --path.
  2. With --git, also walk the local git history.
  3. Match against 32 detectors.
  4. With --verify, probe provider identity endpoints (read-only) for the 10 detectors that support live verification.
  5. Apply --fail-on policy.
  6. If --submit, POST to the WASViking API (hash + masked preview; raw secrets never leave the host).

Exit codes:

Exit code Meaning
0 OK. No findings at or above --fail-on.
1 Generic failure.
70 Findings at or above the --fail-on threshold.

Full flag reference: wasviking-sentinel secrets.

Cloud DAST gate (scan)

./wasviking-sentinel scan \
  --template prod-web-strict \
  --target https://staging.example.com

The scan subcommand triggers a cloud scan using an org-scoped scan template. The template is resolved server-side, so secrets configured in the template never reach the CI runner. The binary tracks the scan to completion and exits with a policy-aware code.

Common exit codes:

Exit code Meaning
0 Scan completed, findings under the template's threshold.
70 Template not found.
71 Forbidden (key lacks the scope for this template).
75 Scan completed, findings exceeded the template's threshold.
76 Scan failed (engine error or timeout).
77 Org's concurrent-scan cap reached after the 60-second queue window.
78 Monthly metering exhausted.

scan is the cloud counterpart of the local sbom and secrets gates. It does not require the mTLS agent to be registered.

Concurrency and metering

For the scan subcommand, the platform enforces:

  • A concurrent-scan cap per organization. When at the cap, the gate queues briefly (up to 60 seconds) and then either runs or returns exit 77.
  • A monthly metering window. When the meter is exhausted, the gate returns exit 78.

Both events are surfaced in the portal's CI Usage tab.

What you should pin in CI

  • Binary version. Distribute a specific signed release and verify with cosign before running.
  • Template slug for scan. Templates are versioned server-side; the slug always resolves to the active version of the template.
  • API key scopes. Use the minimum scope per pipeline stage.
  • --fail-on thresholds per pipeline lane (strict on main, permissive on feature branches).

What this binary is NOT in CI mode

  • It does not open the mTLS tunnel. run is the tunneling mode; sbom, secrets, and scan are one-shot CI subcommands.
  • It does not call the portal's session login. The API key is the credential.
  • It does not store findings locally beyond the SBOM / report artifacts in --out. Persistence is portal-side after --submit.