-
Notifications
You must be signed in to change notification settings - Fork 37
Description
Problem
The lookupRemoteFollower GraphQL query (previously lookupWebFinger) requires no authentication but triggers up to 3 outbound HTTP requests per call:
- WebFinger lookup (
acct:user@domain) - ActivityPub object fetch (actor profile)
- NodeInfo lookup (server software detection)
A malicious user could abuse this for amplification attacks (1 inbound request → 3 outbound) or SSRF scanning of internal networks by supplying crafted domain names.
This query cannot simply require authentication because it is used by the RemoteFollowButton component, which is specifically designed for unauthenticated users (visitors from other Fediverse instances who don't have a Hackers' Pub account).
Proposed Solution
Add IP-based rate limiting using the existing Keyv (ctx.kv) infrastructure:
- Limit to ~10–20 requests per IP per minute
- Store counters in Keyv with TTL-based expiry
- IP address is already available via
ctx.connectionInfo?.remoteAddr - Return
null(or a GraphQL error) when the limit is exceeded
Reusable rate limiting utility
Rather than a one-off fix, implement this as a reusable utility (e.g., rateLimit(ctx, key, { limit, windowMs })) that can be selectively applied to any resolver. This would benefit other unauthenticated or expensive queries in the future, such as:
actorByHandle— performs a remotelookupObjectfallback for unknown handlessearch— could trigger external federation lookups- Any future queries that make outbound HTTP requests or perform expensive operations
Having a shared rate limiting primitive means new queries can opt in with a single function call, without duplicating logic.
Context
Originally raised as a review comment by @dahlia on #214:
#214 (comment)
Notes
- No rate limiting infrastructure currently exists in the codebase — this would be the first implementation
- The existing query complexity plugin (Pothos) controls query cost but not time-based request frequency