How we sign modules
The short version: we use Sigstore's cosign in keyless mode, signing with GitHub Actions' OIDC identity, writing the result to the public Rekor transparency log. This page unpacks each part.
Keyless signing
Traditional code signing requires a long-lived private key, stored somewhere. That key is a compromise magnet: if it leaks, the attacker can impersonate you until you rotate. Worse, distributing your public key to verifiers is its own trust problem.
Keyless signing skips the long-lived key entirely. Instead:
- At build time, our GitHub Actions workflow authenticates to Fulcio using its OIDC identity token (the same token GitHub mints for every workflow run).
- Fulcio verifies the token and issues a short-lived certificate (~10 minutes) bound to that identity.
- cosign uses the short-lived cert to sign the image digest.
- The signature and cert are published to the Rekor transparency log.
- The cert expires. The signature remains verifiable forever because Rekor's inclusion proof timestamps it to the moment it was valid.
To verify, consumers check:
- The signature is valid under the cert
- The cert was issued by Fulcio
- The cert's identity matches what they expect (
https://github.com/Yolo1105/...) - The Rekor entry exists and its inclusion proof checks out
No key material for us to lose. No keys for you to distribute.
The specific identity we sign with
Every Flareo image signature claims this identity:
| Field | Value |
|---|---|
| OIDC issuer | https://token.actions.githubusercontent.com |
| Identity (SAN) | https://github.com/Yolo1105/flareo/.github/workflows/canary-rebuild.yml@refs/heads/main |
When you verify, use a regex on the identity:
cosign verify \
--certificate-identity-regexp 'https://github.com/Yolo1105/.+' \
--certificate-oidc-issuer 'https://token.actions.githubusercontent.com' \
public.ecr.aws/flareo/<module>@sha256:<digest>
Rekor log index
Every signature we publish gets an entry in the Rekor transparency log with a monotonic index. You can look up any Flareo signature at search.sigstore.dev using either the image digest or the Rekor log index. The module's detail page links directly.
The log is append-only and tamper-evident. If Rekor itself were compromised, the inclusion proof chain would break, and any verifier with an old trust root would notice. This is the core property that makes keyless signing work.
Trust score breakdown
Every module has a 0-100 trust score computed as the equal-weight mean of four signals (each 0–100). Equal weights are a judgment call — see /docs/trust-score:
| Signal | Weight | What we measure |
|---|---|---|
| Vulnerability status | 25% | CVE count by severity, scaled — criticals hurt more |
| Provenance | 25% | Rekor entry present and upstream digest recorded |
| Signature freshness | 25% | Cosign keyless identity + Rekor index |
| SBOM completeness | 25% | CycloneDX package coverage |
A fresh republish with zero CVEs and signed provenance (upstream digest recorded) scores in the low-to-mid 90s. A module with one high CVE drops; a module with any critical CVE flips status to failing regardless of the raw score.
Provenance signal
We record signed provenance, upstream digest recorded — a Rekor transparency-log entry for the signed image plus the upstream digest we re-published from. We do not claim an SLSA build level: the pipeline re-publishes upstream images rather than producing hermetic build provenance of its own.
VEX — telling your scanner what's actually exploitable
Trivy is intentionally noisy. A typical mature image has 5-30 findings that don't represent real risk because the vulnerable code path isn't reachable in the way the image is configured. Flareo's reviewer team annotates these per the OpenVEX 0.2.0 spec.
Each module's VEX document is at /api/v1/modules/<slug>/vex. Trivy, Grype, and Snyk all consume it: point your scanner at the URL and CVEs marked not_affected or fixed get suppressed; what's left is the residual real risk.
This isn't an exoneration mechanism. The reviewer team writes a public impact statement for every not_affected annotation explaining why. If you disagree with a justification, the module's contact email is in flareo.json.
For the full picture — scanner config snippets, the four OpenVEX statuses, how VEX feeds the admission policy verdict — see /docs/vex.
Admission policy verdict
Beyond the per-module receipts, the catalog runs an active admission policy against every module — CVE thresholds (post-VEX), signature/SBOM/Rekor presence, SLSA level, composite trust score. The verdict (pass, warn, or fail) plus the per-rule breakdown is at /api/v1/modules/<slug>/policy. If you operate Kubernetes admission for downstream teams, this gives you a higher-level signal than the raw signature: "Flareo's policy passed" means a known set of rules cleared, not just "a signature exists."
The policy is OPA-shaped JSON evaluated by a pure-TypeScript evaluator. If you self-host an internal Flareo and want to swap in a Rego runtime, the input/output contract doesn't change.
What the signature does NOT prove
- Not that the upstream source code is trustworthy. We sign what we built, not what upstream shipped.
- Not that the binary is free of zero-day vulnerabilities. Trivy catches known CVEs; unknown ones are, by definition, unknown.
- Not that the image is appropriate for your use case. Vaultwarden is secure but if you run it on a public IP without a password, Flareo's signature is not relevant to that failure mode.
Next steps
- Verify from the CLI — the commands to run
- Threat model — what this all adds up to