Skip to content

Security M2: No rate limiting on expensive Edge Function operations #222

Description

@sonyccd

Part of #213.

Risk

Several Edge Function endpoints perform expensive or external-traffic-generating operations with no per-caller throttling beyond Supabase's gateway:

Function Operation Cost
manage-question-links (refresh) Re-fetches every link across every question, sequentially High; #215
manage-question-links (unfurl) Per-call outbound fetch Medium; #215 SSRF concern
question-opengraph Image rendering (CPU + memory) Medium
sync-discourse-topics Long-running paginated Discourse sync High

Reference good pattern: calculate-readiness/index.ts:128-145 has a 30s cache-freshness gate that prevents repeated computation per user.

Fix

Per function, the simplest mechanism:

  1. sync-discourse-topics, manage-question-links/refresh — already admin-gated (or will be after Security C2: manage-question-links Edge Function — unauthenticated service_role + SSRF via unfurl #215); add a last_run_at timestamp column or a single-row table to enforce "not run more than once per N minutes globally."
  2. question-opengraph — already cached at CDN level by Vercel/Supabase; ensure Cache-Control: public, max-age=3600 is set on success responses.
  3. unfurl — bound by the auth fix in Security C2: manage-question-links Edge Function — unauthenticated service_role + SSRF via unfurl #215; additionally cap loop iterations per request to N URLs.

For per-IP throttling, the cleanest option is an upstash/ratelimit-style table or a small in-memory cache (acceptable for single-region Supabase functions).

Verification

  • Hit the throttled endpoints in a loop; confirm 429 after the configured budget is exhausted.

Metadata

Metadata

Assignees

No one assigned

    Labels

    securitySecurity-related issueseverity:mediumHardening or defense-in-depth — backlog

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions