Skip to content

GitHub Actions

import { Aside, Steps } from ‘@astrojs/starlight/components’;

The official opaquev/ov-scan-action drops ov scan into your GitHub Actions pipeline. It downloads a signed ov binary, verifies the signature against a vendored minisign trust root, and runs the scanner against your checkout — all without touching the network for scan content.


Drop this into .github/workflows/secret-scan.yml:

name: secret-scan
on: [pull_request]
jobs:
scan:
runs-on: ubuntu-latest
permissions:
contents: read
steps:
- uses: actions/checkout@v4
- uses: opaquev/ov-scan-action@<40-char-sha> # see "Pin to SHA" below
with:
path: .
fail-on: high

For the <40-char-sha> pin value, copy the latest commit SHA from the opaquev/ov-scan-action releases page.


When the action runs in your CI, it:

  1. Downloads ov from releases.opaquevault.com for the runner’s platform.
  2. Verifies the binary against a minisign signature using a vendored verifier — no go install, no third-party action proxies.
  3. Runs ov scan against your repository checkout.
  4. Emits findings counts via the action’s outputs, fails the job per your fail-on threshold.

The action is load-bearing trusted code, so it shipped after 6 rounds of pre-implementation security review catching 35+ findings, plus another ~15 implementation-time defects fixed during PR review.


Production users must pin to a commit SHA: uses: opaquev/ov-scan-action@<40-char-sha>.

The @v1 tag is informational only. Pinning to a tag means a maintainer (or a compromise of the action repo) can ship a malicious update that you consume on the next CI run. SHA pinning + Dependabot’s actions ecosystem gives you reviewable, auditable bumps.

# ✅ DO — SHA pin
uses: opaquev/ov-scan-action@<40-char-sha>
# ❌ DON'T — tag pin in production
uses: opaquev/ov-scan-action@v1

InputDefaultDescription
path.Path to scan (relative to repo root). Allowlist regex; no .. segments, no absolute paths.
baseline-file.ovscan-baseline.txtPath to baseline file with HMAC-fingerprinted accepted findings.
fail-onhighSeverity threshold: verified|critical|high|medium|low|info.
min-ov-version''Minimum ov binary version (e.g., v0.10.0). Customer floor; cannot loosen the action’s embedded OV_VERSION floor.
max-ov-version''Maximum ov binary version.
allow-pull-request-targetfalseDANGEROUS — see pwn-request hardening below.
allow-binary-versionfalseOverride binary version (refused on fork PRs).
allow-ci-baselinefalseAllow baseline modifications in CI (refused on fork PRs).
time-budget300Wallclock seconds for ov scan invocation.
memory-budget1048576Memory budget in KB (Linux only; macOS no-op per ulimit -v semantics).
OutputDescription
findings-countTotal findings (includes baselined; subtract baselined-count for unbaselined-only).
baselined-countFindings suppressed by baseline.
verified-countFindings whose liveness was verified.

RunnerStatusNotes
ubuntu-latest (linux_amd64)✅ supported
Linux ARM64 (linux_arm64)✅ supportedself-hosted ARM runners
macos-latest / macos-14+ (darwin_arm64)✅ supported
macos-13 (darwin_amd64, Intel)not supportedjedisct1’s signed minisign 0.12 macOS release is arm64-only Mach-O; we don’t ship a self-built darwin_amd64 binary because it would weaken the supply-chain trust chain. macOS 13 is deprecated by GitHub anyway; migrate to macos-14+ (arm64).
windows-latest❌ not yettracked under OV-245.

By default the action refuses to run under pull_request_target. This is the most dangerous workflow trigger in GitHub Actions: it runs in the base repo’s context with base-repo secrets, but a malicious PR author can influence what the workflow does.

The combination most users get wrong:

# ❌ DON'T — CVE-class misconfiguration
on: pull_request_target
jobs:
scan:
steps:
- uses: actions/checkout@v4
with:
ref: ${{ github.event.pull_request.head.sha }} # ← attacker-controlled checkout
- uses: opaquev/ov-scan-action@<sha>
with:
allow-pull-request-target: true # ← unlocks the gate

If you set allow-pull-request-target: true AND check out the PR head ref, you’ve created a fork-PR-controlled execution path with access to your base-repo GITHUB_TOKEN. A malicious PR’s hooks/scripts/dependencies can exfiltrate the token. See the GitHub Security Lab “pwn requests” writeup.

The action emits a ::warning:: whenever allow-pull-request-target=true is honored. If you see that warning in production CI, double-check your actions/checkout step.


The action follows GitHub’s standard versioning conventions. To upgrade:

  1. Recommended (SHA-pin): bump the pinned commit SHA in your workflow file. Dependabot’s actions ecosystem will open these PRs automatically when configured.
  2. Tag-pin (not recommended for production): if you’ve used @v1, you’ll get the latest v1.x.y automatically — at the cost of trusting that no compromise lands on main between releases.

Each release ships:

  • An immutable v1.x.y tag
  • A floating v1 tag updated to point at the latest v1.x.y
  • A GitHub Release with full changelog

Customers running self-hosted GitHub Enterprise: the action is a composite action (no Docker image). Mirror the repo into your enterprise’s actions/ cache or use the published tags directly.


Action vs. CLI install — when to use which

Section titled “Action vs. CLI install — when to use which”
SurfaceUse
GitHub Actions CIUse opaquev/ov-scan-action. It bundles signature verification + platform selection + fail-closed parsing.
Local developmentInstall ov directly: curl https://get.opaquevault.com | sh. See installation.
Other CI systems (GitLab, CircleCI, etc.)Install ov directly in your pipeline: curl https://get.opaquevault.com | sh, then run ov scan. The shell-script wrapper does the same signature verification work the action does for GH Actions.

The action is specifically for GitHub Actions because it leverages the composite-action surface (inputs, outputs, env-binding) for workflow-injection prevention. Other CI systems should call ov scan directly via the install script.


The action’s full threat model is documented at opaquev/ov-scan-action/docs/threat-model.md. Key defenses:

  • Vendored minisign verifier — no runtime go install, no third-party CDN trust beyond the binary CDN itself.
  • Same-UID swap defense(inode, mtime, size) stat-snapshot + recheck before every consumer use of every trust-root file.
  • exec env -i env-stripov scan is launched with a clean environment; GITHUB_TOKEN, *_KEY, *_SECRET, LD_PRELOAD, etc. are stripped.
  • Stale-checksums replay defeated — unconditional version-floor check against the action’s embedded OV_VERSION runs before customer-supplied bounds.
  • Fork-PR strict mode — refuses allow-binary-version, allow-ci-baseline, max-ov-version overrides on fork-PR runs (non-overridable).

For vulnerability reports, see opaquev/ov-scan-action/SECURITY.md.