fix(audit): security HIGHs — rate-limit hard-delete codes, collapse error msgs, doc bad-secret per-IP
H1: hard-delete-request and bulk-hard-delete-request endpoints had no rate limit; an admin's compromised account could email-bomb the operator's inbox or use the endpoints as a client-id oracle. Added a new `hardDeleteCode` limiter (5 per hour per user). H3: hard-delete error messages distinguished "no code requested" from "wrong code", letting an attacker brute-force the 4-digit space with ~5k attempts (vs the full 10k). Both single + bulk paths now return the same 'Invalid or expired confirmation code' message. H5: invalid Documenso webhook secret submissions are now rate-limited per-IP (10 per 15min) and only audit-logged inside the cap, so a slow enumeration can't fill the audit log silently. Real Documenso traffic won't fail the secret check, so any traffic beyond the cap is brute-force. 1175/1175 vitest passing. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -77,6 +77,15 @@ export const rateLimiters = {
|
||||
upload: { windowMs: 60 * 1000, max: 10, keyPrefix: 'upload' },
|
||||
/** Bulk operations: 5 per minute. */
|
||||
bulk: { windowMs: 60 * 1000, max: 5, keyPrefix: 'bulk' },
|
||||
/** Hard-delete code requests: 5 per hour per user. Each request emails
|
||||
* a fresh code; without the cap a compromised admin account could
|
||||
* email-bomb the operator's inbox or use the endpoint as a client-id
|
||||
* oracle. */
|
||||
hardDeleteCode: { windowMs: 60 * 60 * 1000, max: 5, keyPrefix: 'hard-delete-code' },
|
||||
/** Inbound webhook with bad secret: 10 attempts per 15 minutes per IP.
|
||||
* Real webhooks won't fail the secret check, so any traffic here is
|
||||
* enumeration / brute-force. Block beyond the cap with a 429. */
|
||||
webhookBadSecret: { windowMs: 15 * 60 * 1000, max: 10, keyPrefix: 'wh-bad-secret' },
|
||||
/** Receipt scanner: 10 OCR runs per minute per user. */
|
||||
ocr: { windowMs: 60 * 1000, max: 10, keyPrefix: 'ocr' },
|
||||
/** Server-side AI calls (summary, embeddings, etc): 60 per minute per user. */
|
||||
|
||||
Reference in New Issue
Block a user