githubwebhook attestor
Verifies a GitHub webhook payload's HMAC-SHA256 signature against a configured shared secret and records the parsed payload plus event name so a verifier can prove which webhook delivery triggered the pipeline.
| Name | githubwebhook |
|---|---|
| Predicate type | https://aflock.ai/attestations/githubwebhook/v0.1 |
| Lifecycle | postproduct |
| Default binary? | No |
| Recommended trace | off — no syscall tracing needed |
| Auto-attaches when | Not auto-detected — attach explicitly with -a. |
The facts in this box are generated from the cilock binary's own catalog (cilock tools list). Do not hand-edit — run npm run gen:catalog.
What it captures
The attestor struct has two JSON-tagged fields written into the predicate:
payload(map[string]interface{}) — the full webhook body parsed as JSON.event(string) — the GitHub event name (push,pull_request,pull_request_review, or any other delivered event).
For known events, the attestor also derives subjects and back-references from the parsed payload:
- Always:
event:<name>, plusreponame:/repourl:(fromrepository.name/repository.html_url) andsender:(fromsender.login) when present. push: onecommit:<sha>subject per entry incommits[], plus author username/email hashes.pull_request/pull_request_review:pullrequest:<html_url>,pullrequestheadref:,pullrequestheadsha:<sha>, and (when set)mergecommitsha:<sha>. Head SHA and merge SHA are also emitted as back-refs so the webhook attestation can be chained to downstream git/build attestations.
Neither the raw body bytes nor the received HMAC signature are written into the predicate — they are consumed only to validate the delivery.
When to use
For self-hosted CI (Jenkins, Tekton, custom runners) that receives GitHub webhook deliveries directly and needs to prove "this build was triggered by a webhook GitHub actually signed." Not needed inside GitHub Actions itself — use the github and github-action attestors there.
Flags
None. The attestor has no CLI surface in cilock today; it is configured in-process via Go options (WithBody, WithSecret, WithRecievedSignature, WithEvent) by an embedding application that has already received the webhook.
Output shape
{
"payload": {
"repository": { "name": "rookery", "html_url": "https://github.com/aflock-ai/rookery" },
"sender": { "login": "octocat" },
"pull_request": {
"html_url": "https://github.com/aflock-ai/rookery/pull/42",
"merge_commit_sha": "deadbeef...",
"head": { "sha": "cafef00d...", "ref": "feature/x" }
}
},
"event": "pull_request"
}
Gotchas
- HMAC verification is mandatory and fail-closed.
Attest()returns an error if any ofbody,secret, orreceivedSigis empty, and computesHMAC-SHA256(body, secret)and compares it (constant-time) against the hex value after stripping thesha256=prefix from theX-Hub-Signature-256header. A mismatch aborts attestation; no partial record is emitted. - Secret comes from the embedder, not a flag. Because there is no CLI wiring, the shared secret must be supplied by whatever component invokes the attestor in-process. Do not pass it on the command line.
- Payload bytes must be the exact bytes GitHub signed. Any re-serialization (pretty-printing, key reordering) before passing to
WithBodywill fail HMAC verification. - Unknown event types still attest. If
eventis notpush,pull_request, orpull_request_review, the payload and event are still recorded, but no event-specific subjects or back-refs are derived (a debug log is emitted). - cilock-native. This attestor exists only in rookery/cilock; there is no upstream witness equivalent.
CLI example
See the constraint summary + reproduction recipe at https://github.com/aflock-ai/attestor-compliance-examples/tree/main/21-githubwebhook. This attestor is currently blocked or doc-only — the linked example explains why and shows the recipe to validate once the constraint is removed.