Monitoring: Threshold-Debounce auf sliding-window (statt floor-to-hour)
Bug: zweimal CRITICAL-Alert für dieselbe Brute-Force-Erkennung kam an. Ursache: detectThresholds() hat als Cutoff für den "existing"-Check floor(now, hour) genutzt. Bei Stundenwechsel resettete der Bucket und der nächste Cron-Lauf fand nichts mehr "in der aktuellen Stunde" → erzeugte zweites SUSPICIOUS-Event → zweite Mail. Fix: gleitendes 60min-Fenster (now - 60min). Pro IP gibt es jetzt zuverlässig max. 1 CRITICAL-Alert pro Stunde, unabhängig von der absoluten Uhrzeit. Live-verifiziert in DB: zwei Alerts kamen um 07:41 und 08:00 – genau das Pattern, das der Stunden-Reset erzeugt. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
96feb6a663
commit
389b878dbd
|
|
@ -155,14 +155,16 @@ export async function detectThresholds(): Promise<void> {
|
||||||
});
|
});
|
||||||
for (const g of grouped) {
|
for (const g of grouped) {
|
||||||
if ((g._count as number) < b.threshold) continue;
|
if ((g._count as number) < b.threshold) continue;
|
||||||
// Prüfen ob wir für diese (IP+Type+Stunde) schon einen CRITICAL emittiert haben
|
// Debounce: pro IP max. 1 SUSPICIOUS-Alert pro 60min (sliding window).
|
||||||
const hourBucket = new Date(now.getTime() - (now.getTime() % (60 * 60 * 1000)));
|
// Vorher: floor(now, hour) → resettete bei Stundenwechsel und produzierte
|
||||||
|
// doppelte Alerts (Bug aus Runde 10).
|
||||||
|
const oneHourAgo = new Date(now.getTime() - 60 * 60 * 1000);
|
||||||
const existing = await prisma.securityEvent.findFirst({
|
const existing = await prisma.securityEvent.findFirst({
|
||||||
where: {
|
where: {
|
||||||
type: 'SUSPICIOUS',
|
type: 'SUSPICIOUS',
|
||||||
severity: 'CRITICAL',
|
severity: 'CRITICAL',
|
||||||
ipAddress: g.ipAddress,
|
ipAddress: g.ipAddress,
|
||||||
createdAt: { gte: hourBucket },
|
createdAt: { gte: oneHourAgo },
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
if (existing) continue;
|
if (existing) continue;
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue