create_ticket_api.php: dedup/escalation race can duplicate notifications or drop a real escalation #35

Open
opened 2026-08-31 21:29:43 -04:00 by jared · 0 comments
Owner

Severity: Medium

create_ticket_api.php (~lines 253-347 and ~457-470): the dedup lookup (SELECT ... WHERE hash = ?) and the subsequent priority-escalation UPDATE run with no transaction or row lock.

Two related failure modes:

  1. Two concurrent hwmonDaemon requests carrying the same dedup hash (e.g. overlapping monitoring runs) can both read the same pre-update snapshot and each independently conclude "priority escalated," each posting its own hwmonDaemon raised priority... comment and firing its own Matrix notification for what is really one escalation event.
  2. On the rarer SELECT→INSERT race (two near-simultaneous creates for the same dedup hash), the loser gets {success:false, error:'Duplicate ticket'} and the request is dropped entirely — it never falls back to applying the priority-escalation/description-refresh logic the normal (non-race) duplicate path performs, so a genuinely-worsening alert that loses the race is silently discarded instead of escalating the existing ticket.

Fix: Wrap the dedup-check + escalate/reopen/insert sequence in a transaction with a row lock (SELECT ... FOR UPDATE) on the matched ticket (or a unique constraint + INSERT ... ON DUPLICATE KEY pattern) so concurrent requests for the same hash serialize correctly instead of racing.

**Severity:** Medium `create_ticket_api.php` (~lines 253-347 and ~457-470): the dedup lookup (`SELECT ... WHERE hash = ?`) and the subsequent priority-escalation `UPDATE` run with no transaction or row lock. **Two related failure modes:** 1. Two concurrent hwmonDaemon requests carrying the same dedup hash (e.g. overlapping monitoring runs) can both read the same pre-update snapshot and each independently conclude "priority escalated," each posting its own `hwmonDaemon raised priority...` comment and firing its own Matrix notification for what is really one escalation event. 2. On the rarer SELECT→INSERT race (two near-simultaneous *creates* for the same dedup hash), the loser gets `{success:false, error:'Duplicate ticket'}` and the request is dropped entirely — it never falls back to applying the priority-escalation/description-refresh logic the normal (non-race) duplicate path performs, so a genuinely-worsening alert that loses the race is silently discarded instead of escalating the existing ticket. **Fix:** Wrap the dedup-check + escalate/reopen/insert sequence in a transaction with a row lock (`SELECT ... FOR UPDATE`) on the matched ticket (or a unique constraint + `INSERT ... ON DUPLICATE KEY` pattern) so concurrent requests for the same hash serialize correctly instead of racing.
jared added the concurrencynotificationspriority/medium labels 2026-09-08 10:15:44 -04:00
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: LotusGuild/tinker_tickets#35