G3.5: answer the reachability probe honestly instead of skipping validation
All checks were successful
check / gate (push) Successful in 18s

Eternitas verifies a webhook URL answers BEFORE issuing the secret that signs
deliveries, so the very first request can never carry a signature — refusing it
makes registration impossible. Real chicken-and-egg, not a reason to disable
validation.

A probe is a request claiming no event and carrying no signature. Answering it
200 is honest: the endpoint exists and is ready. It changes nothing (acted:
false), and anything claiming to BE an event still goes through full HMAC
verification. Registering with skip_validation:true would have permanently
disabled a safety check to solve a one-time ordering problem.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
Grant Whitmer
2026-08-12 15:33:56 -04:00
parent 339ec70853
commit 5dd914b8a6
2 changed files with 36 additions and 0 deletions

View File

@@ -54,6 +54,24 @@ async def eternitas_webhook(
settings = request.app.state.settings
raw = await request.body()
# Reachability probe. Eternitas verifies a webhook URL answers BEFORE it
# issues the secret that signs deliveries — so the first request can never
# carry a signature, and refusing it makes registration impossible. That is
# a real chicken-and-egg, not a reason to disable validation.
#
# A probe is a request claiming to be no event and carrying no signature.
# Answering it 200 is honest: the endpoint exists and is ready. It changes
# NOTHING — `acted: false` — and anything that claims to be an event still
# goes through full verification below. The alternative, registering with
# `skip_validation: true`, would permanently disable a safety check to
# solve a one-time ordering problem.
if not x_eternitas_event and not x_eternitas_signature:
return {
"ready": True,
"acted": False,
"detail": "reachability probe acknowledged; signed events are verified",
}
secret = settings.eternitas_webhook_secret
if not secret:
# I-8: refuse rather than accept unverified instructions about identity.