# Data export rate-limited to prevent harvesting abuse

- **Pattern:** `ab-000727` (`community-privacy-controls.data-rights.export-rate-limited`)
- **Severity:** low
- **Lifecycle:** active
- **Last modified:** 2026-04-18
- **Canonical URL:** https://auditbuffet.com/patterns/ab-000727
- **License:** CC-BY-4.0 — attribute to AuditBuffet Pattern Catalog (https://auditbuffet.com/patterns/ab-000727)

## 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`):

```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:

  ```ts
  // 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:

  ```ts
  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
- owasp A05

Taxons: cost-efficiency, privacy-consent

HTML version: https://auditbuffet.com/patterns/ab-000727
