Skip to content

GET /channels and GET /api/admin/people coerce malformed limit instead of refusing it #496

Description

@Ayush7614

What

GET /channels (server/src/channels/routes.ts:1066-1073) and GET /api/admin/people (server/src/app.ts:587-599) parse paging with:

const limit = Number.parseInt(url.searchParams.get("limit") ?? "", 10);
...(Number.isFinite(limit) ? { limit } : {}),

parseInt coerces, so ?limit=12abc → 12, ?limit=3.9 → 3, ?limit=-5 → -5 (then clamped to 1 in the store), ?limit=0 → 1, ?limit=999999 → MAX. All 200 with a silently coerced page. There is no 400 path at all.

The audit list route (server/src/audit.ts:647-655 auditQueryFromUrl) already does the strict thing: trim + /^\d+\$/ + clamp 1..100 (falling back to 50 only when absent).

Repro

  1. GET /channels?limit=12abc → 200 with limit 12 instead of 400.
  2. GET /channels?limit=3.9 → 200 with limit 3.
  3. GET /api/admin/people?limit=-5 → 200 with limit 1.
  4. Huge ?limit=999999 forces a MAX+1 DB read every time instead of being clamped at the edge.

Expected: malformed limit → 400 naming the parameter; valid integers clamped 1..MAX at the edge like the store already does; absent stays default. Same behavior on both endpoints.

Where it runs

Stateless query parsing in the server process. Same 400/clamp on every replica; the store clamp stays as the second line of defence.

Fix sketch

Shared strict limit parser mirroring auditQueryFromUrl (trim, /^\d+\$/, 400 on mismatch, clamp 1..MAX), used by both routes. Add route tests for 12abc/3.9/-5/0/absent/huge.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions