Security policy
This project handles payment-message construction and signing; we take vulnerability reports seriously and appreciate coordinated disclosure.
Reporting a vulnerability
Section titled “Reporting a vulnerability”Do not open a public issue for security problems.
Preferred channel: GitHub private vulnerability reporting — use the “Report a vulnerability” button under the repository’s Security tab.
If you cannot use GitHub, email joaobuenosi@gmail.com with subject
[SECURITY] fednow-oss.
What to include: affected crate and version/commit, reproduction steps or PoC, and impact assessment if you have one.
What to expect
Section titled “What to expect”- Acknowledgement within 72 hours.
- A triage verdict (accepted / not a vulnerability / needs info) within 7 days.
- Fix timeline agreed case by case; critical issues in released code get priority.
- Credit in the release notes and a CVE requested via GitHub Security Advisories when applicable, unless you prefer to stay anonymous.
Scope notes
Section titled “Scope notes”- This project never ships with credentials, certificates or live endpoints; reports about the absence of those are out of scope.
- The simulator (
fednow-sim) is a development tool and is not hardened for exposure to untrusted networks; running it on the public internet is out of scope.
Supply chain
Section titled “Supply chain”Every release is built by a public GitHub Actions workflow
(.github/workflows/release.yml) and ships with:
| Asset | What it is |
|---|---|
fednow-oss-<tag>-x86_64-linux.tar.gz |
the binaries, LICENSE, README.md, CHANGELOG.md |
fednow-oss-<tag>.cdx.json |
CycloneDX SBOM of the workspace, generated by cargo-cyclonedx from Cargo.lock |
fednow-oss-<tag>.spdx.json |
SPDX SBOM of the same release |
SHA256SUMS |
SHA-256 of the tarball and both SBOMs |
*.cosign.bundle |
one Sigstore signature bundle per asset above |
Signing is keyless. There is no private key and no signing secret in this repository: the workflow exchanges its short-lived GitHub Actions OIDC token for an ephemeral certificate from Sigstore’s CA (Fulcio), signs with it, and records the signature in the public Rekor transparency log. The certificate binds the signature to this workflow, in this repository, at that tag — which is what you check when you verify.
Verifying a release
Section titled “Verifying a release”Signing starts with v0.3.1. Earlier releases ship no
.cosign.bundle; there is nothing to verify on them, and this section does not claim otherwise. v0.3.0 is a special case: its release run failed in the SBOM step, before cosign ran, so that release carries no assets at all — not the tarball, not the SBOMs, not the checksums. Do not treat v0.3.0 as a release; use v0.3.1.
You need cosign v3 or newer — the version the release workflow signs with, and the one that reads the bundle format it writes. Nothing else: no key to fetch, no keyring to trust.
Download the asset you want and its .cosign.bundle, then run the following with TAG
set to the release tag you downloaded:
$ TAG=v0.3.1 # the release you downloaded$ cosign verify-blob \ --bundle "fednow-oss-$TAG-x86_64-linux.tar.gz.cosign.bundle" \ --certificate-identity "https://github.com/joaoabuenosi/fednow-oss/.github/workflows/release.yml@refs/tags/$TAG" \ --certificate-oidc-issuer "https://token.actions.githubusercontent.com" \ "fednow-oss-$TAG-x86_64-linux.tar.gz"Verified OKVerified OK means: this exact byte sequence was signed by a run of this release
workflow at that tag, and the signature is in the transparency log. Any other output
is a failure — do not use the artifact.
The same command verifies the SBOMs and SHA256SUMS; swap both filenames:
$ cosign verify-blob \ --bundle "SHA256SUMS.cosign.bundle" \ --certificate-identity "https://github.com/joaoabuenosi/fednow-oss/.github/workflows/release.yml@refs/tags/$TAG" \ --certificate-oidc-issuer "https://token.actions.githubusercontent.com" \ SHA256SUMSTwo things worth being explicit about:
- Do not verify with
--certificate-identity-regexpand a permissive pattern. The point of the check is the exact workflow-and-tag identity above. - Checksums alone prove nothing about origin:
SHA256SUMSis published through the same channel as the artifacts. Verify its signature, then check the sums against it.
Practices
Section titled “Practices”- Third-party GitHub Actions are pinned to a commit SHA, not a tag — in every
workflow, with a trailing
# <version>comment recording which release the SHA stands for. A pin is reviewed by reading the pinned commit’saction.ymland confirming it accepts the inputs the workflow passes, not by re-resolving the version comment: some upstream tags (dtolnay/rust-toolchain’sv1,rustsec/audit-check’sv2) are moved as new versions ship, so the comment can drift from the tag while the pin itself stays exactly as intended. - Workflows declare
permissions: {}at the top level; each job requests only the scopes it needs, and each scope carries a comment saying which call needs it. - Both of the above are enforced on every CI run, not just asserted here:
.github/scripts/check-workflow-hardening.shfails the build if any workflow gains auses:that is not a 40-character commit SHA, or loses its top-levelpermissions:key. - Action pins are kept current by Dependabot, which bumps the SHA and rewrites the
version comment with it (
.github/dependabot.yml). cargo auditruns on every lockfile change and daily (.github/workflows/audit.yml).- OpenSSF Scorecard runs weekly and on pushes to
main, publishes its results to the public OpenSSF API, and uploads findings to this repository’s code scanning tab (.github/workflows/scorecard.yml). - Container images are not yet published; when they are (see issue #64) they will be signed by digest with the same keyless flow.
Pacsmith is an independent open-source project. Not affiliated with, endorsed by or sponsored by the Federal Reserve. FedNow is a service mark of the Federal Reserve Banks.