wpsecscan v2.9.1
☰
/ verify

Verify a release

Release assets for v2.9.1 ship with checksums, Sigstore signatures, GitHub build-provenance attestations and an SBOM. Check them before you run a binary.

Layer 1 — SHA256 (quick)

Byte-for-byte integrity against the published list. Every release page has a SHA256SUMS.txt.

# Download the files you need from https://github.com/bryanflowers/wpsecscan/releases/tag/v2.9.1
gh release download v2.9.1 --repo bryanflowers/wpsecscan \
  --pattern 'wpsecscan.exe' --pattern 'wpsecscan.exe.sig' --pattern 'wpsecscan.exe.pem' \
  --pattern 'SHA256SUMS.txt'

# Linux / macOS / Git Bash
sha256sum -c --ignore-missing SHA256SUMS.txt

# PowerShell
Get-FileHash wpsecscan.exe -Algorithm SHA256

Layer 2 — Sigstore keyless signature

The executables, the wheel and the sdist each have a .sig and a .pem produced by cosign keyless signing inside the repository's release-attestation workflow. SHA256SUMS.txt and sbom.cyclonedx.json do not have them. Verification checks that the signing certificate was issued to a GitHub Actions run of bryanflowers/wpsecscan.

# Install cosign once: https://docs.sigstore.dev/cosign/system_config/installation/

# Verify
cosign verify-blob wpsecscan.exe \
  --signature wpsecscan.exe.sig \
  --certificate wpsecscan.exe.pem \
  --certificate-identity-regexp \
  'https://github\.com/bryanflowers/wpsecscan/\.github/workflows/release-attestation\.yml@refs/.*' \
  --certificate-oidc-issuer \
  https://token.actions.githubusercontent.com

# On success this should print: "Verified OK"

The identity pattern is pinned to the release-attestation workflow path, so a certificate from any other workflow in the repository will not match. It accepts any git ref (refs/heads/main or refs/tags/*) because that workflow can run on a release or be dispatched manually from main.

Layer 3 — GitHub build-provenance attestation

The same workflow publishes a GitHub artifact attestation for each .exe, wheel and sdist. Verify it with the GitHub CLI; no extra tooling is needed beyond gh.

gh attestation verify wpsecscan.exe --owner bryanflowers

# Show the attested predicate (workflow, repository, commit, run)
gh attestation verify wpsecscan.exe --owner bryanflowers --format json

# Same check for the Python packages: wpsecscan-2.9.1-py3-none-any.whl, wpsecscan-2.9.1.tar.gz

Layer 4 — Build from source yourself

The strongest check is not to run our binary at all. Clone the tagged source, read it, and install it. Windows PyInstaller builds are not byte-reproducible, so a self-built .exe will not match ours hash-for-hash; this layer lets you audit and run the code, not diff the binary.

git clone --branch v2.9.1 https://github.com/bryanflowers/wpsecscan.git
cd wpsecscan
python -m venv .venv && .venv/bin/pip install -e .
.venv/bin/wpsecscan --help

On Windows use .venv\Scripts\pip and .venv\Scripts\wpsecscan. Python 3.10 or newer is required.

SBOM

Each release includes a sbom.cyclonedx.json file listing the dependencies and versions in the build environment. Plug it into any SCA tool.

cat sbom.cyclonedx.json | jq '.components | length'

Use it in CI

The repository ships a composite GitHub Action, .github/actions/wpsecscan/action.yml. It installs wpsecscan from PyPI at run time, so it is not covered by the release-asset checks above; pin the action to a commit SHA.

# replace @main with a commit SHA to pin it
- uses: bryanflowers/wpsecscan/.github/actions/wpsecscan@main
  with:
    target: https://example.com
    max-critical: "0"
    max-high: "5"

What this does NOT prove

Summary