Problem
In apps/api/src/middleware/auth.ts, the rate-limiter falls back to an in-process counter when Redis is unavailable:
const key = `ratelimit:${orgId}`;
// fallback: in-memory Map<key, count>
Cloudflare Workers can spawn multiple isolates per PoP. Each isolate gets its own in-process fallback counter. During a Redis outage, an org on a 100 req/min plan could effectively get 100 × N req/min (where N is the number of live isolates). This could be exploited by intentionally saturating Redis (or during a natural outage) to bypass rate limits for bulk subscription-session verification.
Fix
On Redis failure, fail-open with a hard cap per isolate that is much lower than the plan limit, or fail-closed with a 503:
// Option A — fail-closed on Redis outage:
if (redisError) {
throw new ServiceUnavailableError('Rate limiter unavailable — try again shortly');
}
// Option B — conservative in-isolate cap (e.g. 10% of plan limit):
const FALLBACK_CAP = Math.floor(planLimit / 10);
Severity
MEDIUM — exploitable only during Redis outage; rate-limit bypass allows bulk session verification spam.
Problem
In
apps/api/src/middleware/auth.ts, the rate-limiter falls back to an in-process counter when Redis is unavailable:Cloudflare Workers can spawn multiple isolates per PoP. Each isolate gets its own in-process fallback counter. During a Redis outage, an org on a 100 req/min plan could effectively get 100 × N req/min (where N is the number of live isolates). This could be exploited by intentionally saturating Redis (or during a natural outage) to bypass rate limits for bulk subscription-session verification.
Fix
On Redis failure, fail-open with a hard cap per isolate that is much lower than the plan limit, or fail-closed with a 503:
Severity
MEDIUM — exploitable only during Redis outage; rate-limit bypass allows bulk session verification spam.