Unbounded `limit` on media, comments and social list queries
Nobody has claimed this yet.
- Dominant language
- TypeScript
- Stars
- 0
- Forks
- 0
- Avg merge
- 2h 52m
- Merged PRs (30d)
- 85
Description
Summary
Several list queries accept an unbounded limit. The DTOs validate @Min(1) but no maximum, and the services fall back to a default without clamping — so a caller can ask for any page size and the server will try to serve it.
Four of the affected media queries are @AllowUnauthenticated, so no account is needed.
Where
Unbounded
apps/backend/src/media/dto/media.dto.ts:83-87—MediaFiltersInput.limithas@IsInt() @Min(1)and no@Maxapps/backend/src/media/media.service.ts:133—const limit = filters?.limit || 20, used directly astakeapps/backend/src/social/social.service.ts:533— same patternapps/backend/src/comments/comments.service.ts:252—take: filters.limit, and the DTO (comment.dto.ts:75-77) has@Min(1)with no@Max
MediaFiltersInput reaches four unauthenticated queries: media, userMedia, characterMedia, galleryMedia.
Already correct, and worth copying
apps/backend/src/social/dto/social-query.dto.ts:56—ActivityFeedInput.limithas@Max(100)apps/backend/src/communities/communities.service.ts:224—take: Math.min(filters.limit || 10, 20)
So the codebase already does this both ways; the gap is that it was never applied consistently.
Why it matters
An anonymous request like
query { characterMedia(characterId: "…", filters: { limit: 1000000 }) { media { id } } }
asks Postgres for a million rows and hydrates them with character, species and owner joined, then serialises the lot. A handful of concurrent requests is enough to be a problem, and none of them need to log in.
This is availability rather than disclosure — the visibility filters still apply, so nothing is exposed that the caller could not already page through.
Not urgent, but newly load-bearing
Found during the security review of #292, which adds pagination to the character media gallery. That change only ever asks in steps of 8 or 24, so it does not make this any more reachable — but it does mean the UI now depends on the limit being honoured, which is worth knowing before someone adds a cap.
Suggested fix
A @Max on each input, plus a service-side clamp as the backstop.
One trap worth avoiding. A @Max alone turns an over-large request into a validation error, and this codebase has already been bitten by that: the shop admin page asked for limit: 200 against a @Max(100), the query failed, and the page rendered with its "New listing" button silently missing and nothing to explain why. Either pick a maximum comfortably above any real caller, or clamp server-side and return what fits rather than erroring — but do not add a cap without checking what already asks for more than it.
Contributor guide
No contributing guide indexed for this repository
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start with the DTO and service locations listed in apps/backend/src/media, apps/backend/src/social, and apps/backend/src/comments, then inspect existing callers for limits above the proposed maximum. Compare the ActivityFeedInput and communities service patterns. Done means the affected inputs and service queries consistently bound page sizes without breaking real callers.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- postgresql, typescript
- Domain
- api, backend, databases, security
- Issue type
- Bug
- Difficulty
- 3/5
- Estimated time
- 1-2 days
- Activity status
- Active
- Clarity
- Clearly specified
- Newbie friendliness
- 72/100