Summary
The /webhook endpoint currently accepts any incoming POST request without verifying its origin. GitHub signs every webhook payload using a shared secret and includes the signature in the X-Hub-Signature-256 header. We should validate this header to reject forged or unauthorized requests.
Problem
Any party that knows the webhook URL can send arbitrary payloads to trigger deployments. This is a security risk — a bad actor could craft a push event payload and cause the server to run git pull and docker compose up on any configured repo.
Proposed Solution
- Add a
WEBHOOK_SECRET environment variable (set in .env).
- In the
/webhook handler, compute HMAC-SHA256 of the raw request body using the secret.
- Compare against the
X-Hub-Signature-256 header value using a constant-time comparison (hmac.compare_digest).
- Return
403 Forbidden if the signature is missing or does not match.
import hmac, hashlib
def verify_signature(payload: bytes, signature_header: str, secret: str) -> bool:
expected = "sha256=" + hmac.new(secret.encode(), payload, hashlib.sha256).hexdigest()
return hmac.compare_digest(expected, signature_header)
Acceptance Criteria
References
Summary
The
/webhookendpoint currently accepts any incoming POST request without verifying its origin. GitHub signs every webhook payload using a shared secret and includes the signature in theX-Hub-Signature-256header. We should validate this header to reject forged or unauthorized requests.Problem
Any party that knows the webhook URL can send arbitrary payloads to trigger deployments. This is a security risk — a bad actor could craft a push event payload and cause the server to run
git pullanddocker compose upon any configured repo.Proposed Solution
WEBHOOK_SECRETenvironment variable (set in.env)./webhookhandler, computeHMAC-SHA256of the raw request body using the secret.X-Hub-Signature-256header value using a constant-time comparison (hmac.compare_digest).403 Forbiddenif the signature is missing or does not match.Acceptance Criteria
WEBHOOK_SECRETis read from the environment on startupX-Hub-Signature-256header return403.envReferences