Data export rate-limited to prevent harvesting abuse
Why it matters
An unthrottled data export endpoint is an unauthenticated bulk-data harvesting vector. A malicious actor with a valid session token — or a compromised account — can trigger unlimited export jobs, each generating a complete archive of user PII. CWE-770 (allocation of resources without limits) applies directly. Even without malicious intent, runaway export requests can exhaust database connections and background job queues. OWASP A05:2021 (Security Misconfiguration) includes absent rate limiting on sensitive endpoints.
Severity rationale
Low because exploitation requires an authenticated session, but the potential damage — bulk export of an entire account's PII with no throttle — justifies the control.
Remediation
Enforce a per-user quota on export requests using Redis or a data_export_jobs table with a lookback window. In your export route (src/app/api/account/export/route.ts):
async function checkExportQuota(userId: string) {
const recentExport = await db.dataExportJob.findFirst({
where: {
userId,
requestedAt: { gte: new Date(Date.now() - 24 * 60 * 60 * 1000) }
}
});
if (recentExport) {
throw new TooManyRequestsError('Export quota: 1 per 24 hours. Try again tomorrow.');
}
}
Return HTTP 429 with a Retry-After header so API clients handle the limit gracefully. Document the quota in the user-facing help text on the export UI.
Detection
-
ID:
export-rate-limited -
Severity:
low -
What to look for: Enumerate every relevant item. Examine data export endpoints for rate limiting. Check whether repeated export requests are throttled (e.g., max 1 export per hour, max 3 per day). Look for quota enforcement in middleware or API handlers. Verify the limits are documented.
-
Pass criteria: At least 1 of the following conditions is met. Data export endpoint enforces rate limits (e.g., max frequency 1 per day or per hour, cumulative quota per user). Limits prevent bulk harvesting of user data. Users see rate limit error when quota exceeded.
-
Fail criteria: No rate limiting on export endpoint. Users can request unlimited exports. No quota enforcement, allowing mass data scraping.
-
Skip (N/A) when: Never — rate limiting is a standard API protection.
-
Detail on fail: Describe the rate limit gap. Example:
"No rate limiting on /api/export endpoint. Users can request unlimited data exports with no throttling."or"Export requests queued without daily/hourly quota limits; potential for bulk harvesting." -
Remediation: Implement rate limiting on export endpoints:
// Using a rate limiting library (e.g., express-rate-limit or redis-based) import rateLimit from 'express-rate-limit'; const exportLimiter = rateLimit({ windowMs: 24 * 60 * 60 * 1000, // 24-hour window max: 1, // max 1 request per 24 hours keyGenerator: (req) => req.user.id, handler: (req, res) => { res.status(429).json({ error: 'Export quota exceeded. Try again tomorrow.' }); } }); app.post('/api/export', exportLimiter, async (req, res) => { // ... export logic });Or with Redis for distributed systems:
async function checkExportQuota(userId: string) { const key = `export:quota:${userId}`; const count = await redis.get(key); if (count && parseInt(count) >= 1) { throw new Error('Export quota exceeded for today'); } // Increment counter and set 24-hour expiry await redis.incr(key); await redis.expire(key, 86400); return true; }
External references
- cwe · CWE-770 — Allocation of Resources Without Limits or Throttling
- owasp:2021 · A05 — Security Misconfiguration — missing rate limiting
Taxons
History
- 2026-04-18·v1.0.0·Initial import from community-privacy-controls·automated