Skip to content

[Feature]: Rate-limit the folder virus scan endpoint #97

Description

@DenizAltunkapan

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

  • POST /api/files/scan is rate-limited via a new cloudpage.rate-limit.per-client.scan.* category.
  • Default configuration allows at most one scan start per user per 5 minutes.
  • Exceeding the limit returns the same response as other rate-limited endpoints (e.g. 429), not a 500.
  • Polling scan job status is not affected by the scan limit.
  • A non-positive capacity disables the scan limit, consistent with the other tiers.
  • Tests cover the limited case and the disabled case.
  • application.properties documents the new keys alongside the existing rate-limit settings.

Follow-up to #96.

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or requestjavaPull requests that update java codesecurity

    Type

    No type

    Fields

    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions