Please report suspected vulnerabilities privately by emailing security@pinprick.rs or using GitHub's private vulnerability reporting. Do not open a public issue for an undisclosed vulnerability.
Include the affected component, version, or commit; reproduction steps; potential impact; and any suggested mitigation. We will acknowledge the report, investigate it, and coordinate disclosure with you.
Reports about unsafe runtime fetches performed by third-party GitHub Actions should normally be sent to that action's maintainer; report them here when pinprick fails to detect or accurately describe the behavior.
pinprick ships a catalog of pre-audited action SHAs (audited-actions/)
whose clean verdicts suppress scanning. The catalog reaches users two ways,
with different trust anchors:
- Bundled — compiled into the binary at build time; trusted exactly as
hard as the binary itself (releases carry build provenance attestations).
Because a detection-rule improvement can invalidate a verdict recorded
under older rules, CI re-verifies entries whenever the rules change and a
scheduled workflow re-scans a rotating weekly shard until the full catalog
has been covered (
scripts/verify-audited-actions.sh). - Remote (
https://pinprick.rs/audited-actions/, opt-in viafetch-remote = true) — every served file is signed with minisign during deploy, and the binary verifies the signature against the public key committed atcatalog-minisign.puband embedded at build time. Verification is fail-closed: an unsigned, tampered, legacy-format (non-prehashed), timestamp-less, or stale catalog is ignored with a warning and the action is scanned normally. Freshness is judged by minisign's signedtimestamp:trusted comment — a catalog signed more than 30 days ago is rejected, so a compromised CDN cannot replay a superseded-but-validly-signed catalog indefinitely. Timestamps more than 10 minutes in the future are also rejected: legitimate runner and client clock drift is expected to stay within minutes, and a far-future timestamp would otherwise stay inside the staleness window until it plus 30 days — turning one signing-clock fault (or a compromised signer) into an extended replay horizon. TLS alone is deliberately not trusted.
The catalog signing key (CATALOG_SIGNING_KEY) must be stored as a
passwordless minisign secret key in the GitHub cloudflare environment.
Only deploy-site.yml reads it, on pushes to main that touch site/**,
audited-actions/**, catalog-minisign.pub, or Cargo.toml. The workflow
writes a temporary runner copy and removes it on step exit; maintainers must
not retain additional copies. A compromise of that workflow or environment
is a catalog compromise. Signing the catalog offline
(committing .minisig files next to each JSON and serving them verbatim)
would take the key out of CI at the cost of maintainer friction on every
catalog change; that trade-off remains under consideration.
To rotate the key (or respond to a suspected compromise):
- Generate a new keypair:
minisign -G -p catalog-minisign.pub -s catalog.key -W. - In a maintenance window, replace the
CATALOG_SIGNING_KEYsecret in thecloudflareenvironment with the new secret key. - Commit the matching
catalog-minisign.puband merge. That path triggers a deployment which re-signs every served catalog file and verifies a produced signature against the committed public key before publishing. - Confirm the deployment succeeded, then delete every local secret-key copy.
- Cut a release. The public key is embedded at build time, so binaries built before the rotation reject the newly signed catalog — fail-closed: they warn and fall back to fresh scans until users upgrade.
A wrongly-vouched bundled entry follows the binary, not the site: removing
it from audited-actions/ stops vouching in future builds and (within the
freshness window) in the remote layer, but already-shipped binaries keep
their bundled copy until upgraded.
Only the latest released version of pinprick is supported with security fixes.