Problem
The async folder virus scan endpoint (POST /api/files/scan, added in #96) is not rate-limited. The existing cloudpage.rate-limit.* tiers only cover upload, download, and listing, so scanning is currently unbounded per user.
A single scan is expensive: it walks the entire target subtree and opens a clamd INSTREAM connection for every regular file. A user (or a stolen session) can start many scans in a row; jobs pile up on the background executor and stay in memory until eviction, and clamd itself can be overwhelmed. This is a realistic DoS / resource-exhaustion vector against both the app instance and the shared clamd daemon.
Example: a user repeatedly calls POST /api/files/scan on a large folder. Each call queues another full-tree scan behind the bounded executor, and clamd is hit with a connection per file for each of them.
Proposed solution
Add a dedicated scan category to the existing per-client rate limiter so it stays consistent with upload/download/listing, and default it to at most one folder scan per user every 5 minutes:
cloudpage.rate-limit.per-client.scan.capacity=1
cloudpage.rate-limit.per-client.scan.refill-period=5m
The limit should apply to scan starts (POST /api/files/scan), keyed by username (or client IP for unauthenticated calls, matching the other tiers). Polling (GET /api/files/scan/{jobId}) should not be limited by this budget. As with the other categories, a non-positive capacity disables the limit.
Acceptance criteria
Follow-up to #96.
Problem
The async folder virus scan endpoint (
POST /api/files/scan, added in #96) is not rate-limited. The existingcloudpage.rate-limit.*tiers only cover upload, download, and listing, so scanning is currently unbounded per user.A single scan is expensive: it walks the entire target subtree and opens a clamd
INSTREAMconnection for every regular file. A user (or a stolen session) can start many scans in a row; jobs pile up on the background executor and stay in memory until eviction, and clamd itself can be overwhelmed. This is a realistic DoS / resource-exhaustion vector against both the app instance and the shared clamd daemon.Example: a user repeatedly calls
POST /api/files/scanon a large folder. Each call queues another full-tree scan behind the bounded executor, and clamd is hit with a connection per file for each of them.Proposed solution
Add a dedicated
scancategory to the existing per-client rate limiter so it stays consistent withupload/download/listing, and default it to at most one folder scan per user every 5 minutes:The limit should apply to scan starts (
POST /api/files/scan), keyed by username (or client IP for unauthenticated calls, matching the other tiers). Polling (GET /api/files/scan/{jobId}) should not be limited by this budget. As with the other categories, a non-positive capacity disables the limit.Acceptance criteria
POST /api/files/scanis rate-limited via a newcloudpage.rate-limit.per-client.scan.*category.429), not a 500.application.propertiesdocuments the new keys alongside the existing rate-limit settings.Follow-up to #96.