Repository navigation
fix(webhook): authenticate replay ledger IDs before deduplication - #93
Conversation
Codex Review SummaryThis comment shows the latest Codex review activity on this pull request.
ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings. |
|
CI evidence verified from the completed run and downloaded JUnit artifact: run 36346072944 succeeded on the workflow's Python 3.15 / PostgreSQL 16 / Valkey 9.0.6 configuration. The final diff was reviewed and merged as 35689df. This completes the replay-identity defect only; #81 and #85 remain open for their remaining acceptance work. No production deployment. |
Scope
Refs #81 and #85. This is a small security regression fix, not closure of either umbrella issue.
The previous receiver verifier authenticated
timestamp + raw bodybut used unsignedMsg-Delivery-Idas its replay-ledger key. An attacker holding one valid delivery could change that header and bypassseen. Event headers likewise were not bound to the signed envelope.Changes
src/msg/workers/webhook.py: validate case-insensitive/non-ambiguous headers, HMAC, strict JSON and equality of envelope/header delivery ID, event ID and timestamp before reading/updating dedupe state. Malformed values produce stable failures without exposing payloads.tests/test_webhook_identity.py: 13 regressions, including changed delivery/event headers, missing/non-string/non-ASCII headers, duplicate JSON keys, invalid signed envelopes, case-insensitive HTTP headers and ambiguous duplicates.tests/test_webhook_delivery.py: existing receiver examples now use the actual authenticated envelope produced by EffectWorker; all prior assertions retained.Evidence
The new regression suite failed 13/13 on the original implementation. After the fix,
python -m pytest -q tests/test_webhook_identity.py tests/test_webhook_delivery.py tests/test_webhook_domain_events.pypassed 29 tests using Python 3.13.5 and a real isolated PostgreSQL 16.15 instance. This local result is not Python 3.15 CI or production evidence; CI on this PR must independently pass.Compatibility / boundaries
No database/schema migration, sender wire-format change, authorization change or deployment. The helper now intentionally rejects nonconforming unsigned/identity-incomplete receiver envelopes; the official sender already includes all required fields. Production consumers must persist the authenticated delivery ID atomically with their side effect; the optional in-memory
seenset is not durable dedupe.Remaining #81 acceptance includes full collaboration Resource/Revision primitives, comprehensive notification preferences and real external deployment matrices. #85 retains its other cross-module refactor items. No production deployment is authorized.