fix: Robustheits-Luecken aus zweitem, unabhaengigem Sicherheitsaudit behoben

Ein zweiter, unabhaengiger Audit-Durchlauf (frischer Blick, keine
Vorkenntnis meiner eigenen Fixes) bestaetigte alle bisherigen Fixes als
korrekt verdrahtet und fand 3 LOW-severity Robustheitsluecken - keine
davon war ausnutzbar, aber alle sind jetzt behoben:

- HarvestsService.create/ExtractionsService.create pruefen jetzt, dass
  referenzierte colonyIds/harvestIds tatsaechlich existieren, bevor die
  Transaktion laeuft - vorher fuehrte eine unbekannte Id zu einem
  ungefangenen 500 mit rohem Prisma-Fehler statt einer sauberen 400.
- Etiketten-Bildelemente durchlaufen jetzt denselben Magic-Byte-Check
  wie Avatar-/Dokument-Uploads, statt pdfkits Bildparser ungepruefte
  Bytes zu uebergeben.
- Webhook-Secret-Redaktion im Audit-Log nutzt jetzt explizites delete
  statt sich auf Prismas JSON-Serialisierung zu verlassen, die
  undefined-Werte verwirft (fragil, falls sich die Serialisierung mal
  aendert).

Co-Authored-By: Claude Sonnet 5 <[email protected]>
This commit is contained in:
Nick SzaunigandClaude Sonnet 5 committed 2026-09-02 15:13:02 +02:00
1 parent f57cffe6a8
commit 4bd7e9791a
7 files changed
+173 -7

No files matched your search

@@ -52,7 +52,7 @@ export class WebhooksService {
entityId: subscription.id,
action: 'CREATE',
userId: actingUserId,
afterData: { ...subscription, secret: undefined },
afterData: this.omitSecret(subscription),
});
return subscription;
}
@@ -70,10 +70,22 @@ export class WebhooksService {
entityId: id,
action: 'DELETE',
userId: actingUserId,
beforeData: { ...subscription, secret: undefined },
beforeData: this.omitSecret(subscription),
});
}
// Explicit deletion rather than `{ ...subscription, secret: undefined }`:
// that pattern only works because Prisma's JSON serialization happens to
// drop undefined-valued keys today - an explicit delete doesn't depend on
// that being true forever.
private omitSecret(
subscription: WebhookSubscription,
): Record<string, unknown> {
const redacted: Partial<WebhookSubscription> = { ...subscription };
delete redacted.secret;
return redacted;
}
async dispatch(event: WebhookEvent, payload: unknown): Promise<void> {
const subscriptions = await this.prisma.webhookSubscription.findMany({
where: { active: true, events: { has: event } },