G3.5: accept platform.test_ping unverified — unverifiable by construction
All checks were successful
check / gate (push) Successful in 19s
canary / probe (push) Successful in 26s

Read the sender rather than guessing: Eternitas generates the webhook secret at
registration time and pings the URL to prove reachability BEFORE returning that
secret. The ping IS signed — with a secret the receiver cannot possibly hold
yet. Unverifiable by construction, not by oversight.

Accepting it is safe because the event is definitionally a no-op: nothing read,
nothing written, acted:false. Every event that changes anything still requires a
valid HMAC. The alternative, skip_validation:true, would permanently disable
reachability checking for this platform 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:36:03 -04:00
parent 5dd914b8a6
commit a094960da3
2 changed files with 20 additions and 12 deletions

View File

@@ -54,22 +54,30 @@ 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.
# `platform.test_ping` is the ONE event accepted without verification, and
# the reason is structural rather than convenient.
#
# 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
# Eternitas generates the webhook secret at registration time and pings the
# URL to prove it is reachable BEFORE returning that secret. The ping is
# signed — with a secret the receiver cannot possibly hold yet. So the
# signature is unverifiable by construction, not by oversight.
#
# Accepting it is safe because the event is definitionally a no-op: nothing
# is read, nothing is written, `acted` is false. Every event that changes
# anything — `passport.revoked` above all — still requires a valid HMAC
# below. The alternative was `skip_validation: true` at registration, which
# would permanently disable reachability checking for this platform to
# solve a one-time ordering problem.
if not x_eternitas_event and not x_eternitas_signature:
if x_eternitas_event == "platform.test_ping" or (
not x_eternitas_event and not x_eternitas_signature
):
return {
"ready": True,
"acted": False,
"detail": "reachability probe acknowledged; signed events are verified",
"detail": (
"reachability ping acknowledged; it is unverifiable by "
"construction and changes nothing. Signed events are verified."
),
}
secret = settings.eternitas_webhook_secret