fix: incidentio dedup-key as a min 3 hour window - #3823
Conversation
|
|
||
| %{ | ||
| "deduplication_key" => "#{hash}-#{now.minute}", | ||
| "deduplication_key" => "#{alert_query_id}-#{alert_name}-#{window}", |
There was a problem hiding this comment.
🟡 Severity: MEDIUM
Raw log and rule-triggered events do not set alert_query_id or title, making this key identical for every batch within a 3-hour window. An attacker who can submit one event can cause Incident.io to deduplicate later security-relevant events instead of paging, hiding incidents for up to three hours.
Helpful? Add 👍 / 👎
💡 Fix Suggestion
Suggestion: When alert_query_id is not present in the config (i.e., for raw log events not triggered by an alert query), the deduplication key collapses to "unknown-unknown-#{window}" for every batch, which allows any ingested event to suppress all subsequent raw-log incident pages for up to 3 hours. The fix is to generate a unique deduplication key (e.g., a UUID) when no alert_query_id is available, so raw log event batches are never deduplicated against each other, while proper alert-query-driven events continue to use the stable "#{alert_query_id}-#{alert_name}-#{window}" key for intentional 3-hour deduplication.
⚠️ Experimental Feature: This code suggestion is automatically generated. Please review carefully.
| "deduplication_key" => "#{alert_query_id}-#{alert_name}-#{window}", | |
| "deduplication_key" => if(Map.has_key?(config, :alert_query_id), do: "#{alert_query_id}-#{alert_name}-#{window}", else: Ecto.UUID.generate()), |
| hash = :erlang.phash2(batch) | ||
| alert_name = Map.get(config, :title, "unknown") | ||
| alert_query_id = Map.get(config, :alert_query_id, "unknown") | ||
| window = div(DateTime.to_unix(DateTime.utc_now()), 3 * 60 * 60) |
There was a problem hiding this comment.
🤖
Dividing Unix time into fixed buckets does not guarantee three hours between new keys. Firings immediately before and after a UTC bucket boundary can generate different keys seconds apart. If the requirement is a minimum rolling three-hour interval, persist per-alert expiry state and rotate only after three elapsed hours. Otherwise, document this explicitly as an epoch-aligned three-hour bucket.
|
|
||
| %{ | ||
| "deduplication_key" => "#{hash}-#{now.minute}", | ||
| "deduplication_key" => "#{alert_query_id}-#{alert_name}-#{window}", |
There was a problem hiding this comment.
🤖
The key now contains the unique alert-query ID, so including the mutable
alert_namemakes the deduplication identity unstable. Renaming a firing alert changes its key and creates another Incident.io alert within the same window. Use only the immutable query ID and the chosen window identity; retain the name as display data.
Remove minutely deduplication key in incidentio adaptor
Fixes the issue where an alert constantly pages due to the changing minute