Skip to content

OWASP SPVS Coverage

The OWASP Software Provenance Verification Standard (SPVS) 1.6 is a supply-chain control catalog for how software is identified, built, signed, published, and monitored. You may also see it abbreviated as OSVS; the official name is SPVS. It is not the same standard as OWASP SCVS.

Fencer covers the GitHub-reachable subset of SPVS 1.6 across three surfaces:

  • GitHub SaaS checks — organization, repository, workflow, dependency, and release posture evaluated through the GitHub App. Findings are Vulnerabilities on the GitHub SaaS Account asset.
  • OpenGrep GitHub Actions rules — static analysis of workflow YAML during code scans. Findings are Vulnerabilities on the repository.
  • SIEM detections — GitHub audit and webhook events matched by built-in detection rules.

SPVS 1.6 defines 50 requirements. 37 of those can be assessed from GitHub APIs, repository contents, and GitHub audit events without an endpoint agent or live admission control. Fencer’s target for that GitHub-reachable set is 36 of 37 Covered. One requirement is excluded by design. Five others can only ever be Partial because GitHub or Fencer cannot observe the remaining half of the control. Remaining gaps are listed under Planned coverage.

  • A connected GitHub App Code installation, with repositories imported as assets.
  • SaaS Scanning for organization and repository posture checks.
  • Code Scanning for OpenGrep GitHub Actions rules.
  • Security Monitoring with the GitHub Monitor app for provenance detections (package publish and workflow configuration change).
StatusMeaning
CoveredFencer raises a Vulnerability or Detection when the GitHub-visible control fails
Partial by designFencer covers the observable half; the rest is not visible via GitHub APIs or Fencer’s role
Not covered by designDeliberately out of scope (would expand GitHub App install-time trust)
PlannedReachable on GitHub, not yet shipped

Default repository permission (High, SaaS) — Organization default_repository_permission must be none. Member read, write, or admin access to every repository by default fails SPVS V1.1.3.

Unsigned commits on the default branch (High, SaaS) — Recent default-branch commits must have verified signatures. If you configure an approved signer list, verified commits from anyone else also fail (SPVS V1.4.1). An empty allowlist treats any verified signer as acceptable.

Also covered on this section’s GitHub surface: organization 2FA enforcement, privileged role minimization, GitHub App token minting, fine-grained PATs for automation, dedicated bot accounts, environment reviewers, deployment branch restriction, and custom protection rules.

Partial by design — phishing-resistant MFA (V1.1.1). GitHub’s API reports whether 2FA is on, not whether the factor is phishing-resistant. Fencer can require 2FA; it cannot distinguish TOTP from a hardware key.

Lockfile drift (Medium, SaaS) — The lockfile must satisfy the manifest’s declared ranges (SPVS V2.2.3). Fencer compares these pairs when both files are present:

LanguageManifestLockfile
JavaScript / TypeScriptpackage.jsonpackage-lock.json, pnpm-lock.yaml, yarn.lock, or bun.lock
Pythonpyproject.tomluv.lock
RubyGemfileGemfile.lock
Gogo.modgo.sum
RustCargo.tomlCargo.lock
Javapom.xml, build.gradle, or build.gradle.ktsgradle.lockfile
C#.csproj, Directory.Packages.props, or packages.configpackages.lock.json
PHPcomposer.jsoncomposer.lock
Dartpubspec.yamlpubspec.lock
SwiftPackage.swiftPackage.resolved
Elixirmix.exsmix.lock

Platform packages, git/path sources, and unpinned branch/revision constraints are skipped. Composer php / ext-* / lib-* packages, Dart SDK/git/path deps, Swift branch/revision/path deps, and Mix git/path/GitHub deps are not compared.

Direct public registry installs (OpenGrep) — CI run: steps that install from a known public host (npmjs.org, pypi.org, rubygems.org, crates.io, proxy.golang.org, nuget.org, packagist.org, Maven Central, pub.dev, hex.pm, and similar) or omit a private --registry / --index-url / GOPROXY override fail SPVS V2.2.6.

Install scripts enabled (OpenGrep) — npm/yarn/pnpm/bun without --ignore-scripts, Composer without --no-scripts, and pip with --no-build-isolation fail SPVS V2.2.1. This sits alongside the existing Dependabot insecure-external-code-execution rule; it does not replace it.

Also covered: binary blob dependencies, and OpenGrep rules for Dependabot insecure external code execution, dependency cooldowns, Cargo feature minimization, and installer checksum verification.

Partial by design — local env-file secrets (V2.1.1). Workstation filesystem secrets are outside GitHub’s API and Fencer’s GitHub App scope.

Floating package installs (OpenGrep) — Workflow run: steps that install floating versions fail SPVS V3.1.1. Lockfile-exact commands pass, including npm ci, yarn/pnpm/bun --frozen-lockfile, pip install --require-hashes, uv sync --frozen, bundle install --frozen, cargo build --locked, composer install, dotnet restore --locked-mode, dart pub get, and mix deps.get.

Self-hosted runners (Critical on public, Informational on private, SaaS) — Jobs with runs-on: self-hosted (or a runner group) fail SPVS V3.1.6’s GitHub-visible half. Public repositories are Critical because pull requests can execute untrusted code on organization-managed machines.

Static registry credentials with OIDC (OpenGrep) — Workflows that grant id-token: write and still interpolate a static registry token (NPM_TOKEN, PYPI_TOKEN, CARGO_REGISTRY_TOKEN, NUGET_API_KEY, PACKAGIST_TOKEN, MAVEN_CENTRAL_TOKEN, and similar) fail SPVS V3.2.3. Existing missing-OIDC rules are unchanged.

Reusable workflow secret overshare (High, SaaS) — Named secrets passed into a reusable workflow must be declared under the callee’s on.workflow_call.secrets. Extra names fail SPVS V3.2.1. secrets: inherit is handled by a separate OpenGrep rule, not this check.

Whole credential context exposure (OpenGrep) — Passing the whole secrets context into a reusable workflow or action also fails SPVS V3.2.1.

Sigstore untrusted builder (High, SaaS) — When attestations exist, the SLSA builder identity must match an accepted prefix (GitHub-hosted runner, GitHub artifact-attestations workflows, or SLSA GitHub generator by default). Unparseable builder IDs fail closed (SPVS V3.4.6).

Also covered on this section: default Actions permissions, Actions execution policy, dangerous triggers, job permission minimization, impostor commits, mutable binary downloads, stale Action pins, archived Actions, caching in public release jobs, secrets scoped to environments, long-lived registry credentials, Sigstore attestation presence, unpinned Actions and container images, missing OIDC trusted publishing, GITHUB_ENV / GITHUB_PATH injection, spoofable actor conditions, unsound if: expressions, typosquatted action names, actions/checkout persist-credentials, and missing release code signing.

Partial by design — runner re-imaging (V3.1.6). Whether a persistent self-hosted runner is re-imaged and scanned is infrastructure state with no GitHub API. Fencer flags use of self-hosted runners; it cannot verify the host image.

Partial by design — consumers validate (V3.4.2). Downstream verification in another organization or repository is generally not visible to this GitHub App installation.

Not covered by design — org-wide secret visibility (V3.2.2). Confirming that secrets are not scoped to the whole organization or all repositories requires the organization_secrets / secrets GitHub App permission. Fencer does not request that permission and does not expand install-time trust to get it.

Covered on GitHub: organization and repository tag rulesets, tag immutability, immutable releases, tag creation gated on deployment, and admin bypass of organization rulesets.

GitHub Package Publish (Medium, SIEM) — Detects GitHub release publishes, package registry publishes, and pushes of git tags so unexpected publishes can be investigated before they are trusted (SPVS V5.2.4).

GitHub Workflow Configuration Change (Medium, SIEM) — Detects changes to .github/workflows files and enable/disable of workflows, including the acting identity (SPVS V5.2.6).

Also covered: GitHub push protection disabled, repository ruleset change, tag modification, webhook created, and webhook configuration change. See Detection Rules.

Partial by design — validated before deploy (V5.1.1). Fencer can alert after a deployment. It has no admission-control mechanism to block a deploy that lacks a validated SBOM.

These GitHub-reachable requirements are not Covered yet:

  • Screening new packages for install scripts, maintainer count, age, and linked source before first use
  • Integrity-checking security-scanner invocations in CI
  • Diffing published release artifacts against pipeline build output
  • Verifying the previous stage’s artifact signature between pipeline jobs
  • Documented break-glass (with alert and review) for signature or attestation bypass
  • Publish blast-radius: one identity releasing a second package inside a cooldown without extra approval
  • Fuzzy typosquat screening of popular Actions and package names
  • Detecting release jobs that rebuild instead of consuming a held artifact
  • Checksum verification after cache restore in release-adjacent jobs
  • Resolving transitive GitHub Action dependencies and flagging unpinned refs
  • Alerting when a production deployment has no matching SBOM
  • Tightening app-token and PAT checks toward one-credential-one-resource isolation
  • Requiring reviewers, branch restriction, and custom protection together on release environments