GitHub Actions
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. It’s listed on the GitHub Marketplace.
Quickstart
Section titled “Quickstart”Drop this into .github/workflows/secret-scan.yml:
name: secret-scanon: [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: highFor the <40-char-sha> pin value, copy the latest commit SHA from the opaquev/ov-scan-action releases page.
What it does
Section titled “What it does”When the action runs in your CI, it:
- Downloads
ovfromreleases.opaquevault.comfor the runner’s platform. - Verifies the binary against a minisign signature using a vendored verifier — no
go install, no third-party action proxies. - Runs
ov scanagainst your repository checkout. - Emits findings counts via the action’s outputs, fails the job per your
fail-onthreshold.
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.
Pin to SHA, not tag
Section titled “Pin to SHA, not tag”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 pinuses: opaquev/ov-scan-action@<40-char-sha>
# ❌ DON'T — tag pin in productionuses: opaquev/ov-scan-action@v1Inputs
Section titled “Inputs”Defaults below are as of v1.0.3. If you pin to an older release SHA (as the pinning guidance recommends for production), check that release’s own README — notably, memory-budget defaulted to 1 GiB until v1.0.2 raised it to 4 GiB (v1.0.1 still ships the 1 GiB default).
| Input | Default | Description |
|---|---|---|
path |
. |
Path to scan (relative to repo root). Allowlist regex; no .. segments, no absolute paths. |
baseline-file |
'' |
Path to baseline file with HMAC-fingerprinted accepted findings. Empty (default) skips baseline; the action passes --baseline only if explicitly set. |
fail-on |
high |
Severity 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-target |
false |
DANGEROUS — see pwn-request hardening below. |
allow-binary-version |
false |
Override binary version (refused on fork PRs). |
allow-ci-baseline |
false |
Allow baseline modifications in CI (refused on fork PRs). |
time-budget |
300 |
Wallclock seconds for ov scan invocation. |
memory-budget |
4194304 |
Memory budget in KB (Linux only; macOS no-op per ulimit -v semantics). Default 4 GiB — do not set below ~2 GiB: the Go runtime needs that much virtual address space on linux_arm64 and segfaults under a lower cap (OV-256). |
Outputs
Section titled “Outputs”| Output | Description |
|---|---|
findings-count |
Total findings (includes baselined; subtract baselined-count for unbaselined-only). |
baselined-count |
Findings suppressed by baseline. |
verified-count |
Findings whose liveness was verified. |
Supported runners
Section titled “Supported runners”| Runner | Status | Notes |
|---|---|---|
ubuntu-latest (linux_amd64) |
✅ supported | |
| Linux ARM64 (linux_arm64) | ✅ supported | self-hosted ARM runners |
macos-latest / macos-14+ (darwin_arm64) |
✅ supported | |
macos-13 (darwin_amd64, Intel) |
❌ not supported | jedisct1’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 yet | tracked under OV-245. |
pull_request_target hardening
Section titled “pull_request_target hardening”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 misconfigurationon: pull_request_targetjobs: 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 gateIf 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.
Updating
Section titled “Updating”The action follows GitHub’s standard versioning conventions. To upgrade:
- Recommended (SHA-pin): bump the pinned commit SHA in your workflow file. Dependabot’s
actionsecosystem will open these PRs automatically when configured. - Tag-pin (not recommended for production): if you’ve used
@v1, you’ll get the latestv1.x.yautomatically — at the cost of trusting that no compromise lands onmainbetween releases.
Each release ships:
- An immutable
v1.x.ytag - A floating
v1tag updated to point at the latestv1.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”| Surface | Use |
|---|---|
| GitHub Actions CI | Use opaquev/ov-scan-action. It bundles signature verification + platform selection + fail-closed parsing. |
| Local development | Install 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 install script verifies the minisign signature only when minisign is installed on the runner; otherwise it falls back to SHA-256 only and prints a warning. Install minisign in the job and set OV_REQUIRE_SIGNATURE=1 so the install fails closed — see Release signing. |
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.
Security model
Section titled “Security model”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 -ienv-strip —ov scanis 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_VERSIONruns before customer-supplied bounds. - Fork-PR strict mode — refuses
allow-binary-version,allow-ci-baseline,max-ov-versionoverrides on fork-PR runs (non-overridable).
For vulnerability reports, see opaquev/ov-scan-action/SECURITY.md. Published advisories — including GHSA-59j2-rc8j-4q5w (the v1.0.0 baseline auto-load issue described above) — are recorded with verification steps on the security advisories page.
See also
Section titled “See also”ov scan— the underlying scanner CLIov --check-version-bounds— semver gate the action uses- Action repo — source, releases, advisories
- GitHub Marketplace listing — discover and integrate from the Marketplace