---
id: b05b67af-8f59-4937-9107-8bee57577889
title: Pages inbox quota stops checking at 1000 objects; rate map has no hard cap
state: closed
labels:
- kind:security
assignees: []
milestone: null
created: 2026-10-27T19:38:20.426674442Z
updated: 2026-10-27T19:53:10.601819764Z
---
## Problem

The Pages inbox quota is only checked against the first 1000 R2 objects. `overQuota` calls `bucket.list({ limit: Math.min(limit, 1000) })` once; if `INBOX_QUOTA` is above 1000, submissions keep being stored after the limit because the returned list can never reach the configured quota.

Verified with the real `onRequestPost` and a fake bucket containing 1001 objects, `INBOX_QUOTA=1500`:

```
status 200 stored 1002
```

Expected 503. `functions/inbox/[kind].js:276-279`.

The isolate-local rate-limit map also has no hard cap: it only prunes expired entries when `size > 10000`, so an attacker rotating source IPs can keep growing it. Cloudflare's WAF rule is the documented durable control, but the in-function map should still fail closed at a fixed key limit like `serve`'s `RATE_MAX_KEYS` (f0rge #65).

## Fix

- Paginate `bucket.list` with `cursor` until `limit` objects are counted or the list ends.
- Add a hard `MAX_KEYS` check for new rate-limit keys after the expiry sweep.
- Add Node tests for quota 1500 and the rate-map cap.
