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.listwithcursoruntillimitobjects are counted or the list ends. - Add a hard
MAX_KEYScheck for new rate-limit keys after the expiry sweep. - Add Node tests for quota 1500 and the rate-map cap.