Skip to content

fix: cap admin per_page at 500#445

Open
VaibhavAcharya wants to merge 1 commit into
masterfrom
vaibhavacharya/ex-1882-identity-adminlistusers-per_page-has-no-upper-bound-gotrue
Open

fix: cap admin per_page at 500#445
VaibhavAcharya wants to merge 1 commit into
masterfrom
vaibhavacharya/ex-1882-identity-adminlistusers-per_page-has-no-upper-bound-gotrue

Conversation

@VaibhavAcharya
Copy link
Copy Markdown
Contributor

- Summary

per_page on /admin/users wasn't bounded, so a caller could ask for 999999999 records and pull the whole user table in one query. This caps it at 500 and returns a 400 if you go over, so misbehaving clients fail loudly instead of silently getting partial pages.

- Test plan

- Description for the changelog

Cap /admin/users per_page query parameter at 500.

- A picture of a cute animal (not mandatory but encouraged)

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented May 26, 2026

Review Change Stack

📝 Walkthrough

Summary by CodeRabbit

  • Bug Fixes

    • Pagination requests exceeding the maximum item limit are now rejected with an error response.
  • Tests

    • Added comprehensive validation tests for pagination request handling.

Walkthrough

This PR adds pagination request validation to the gotrue API. The implementation introduces a maxPerPage constant set to 500 and modifies the pagination parsing function to reject requests where per_page exceeds this limit, returning a bad request error. A comprehensive test suite validates the behavior across multiple scenarios including default values, explicit parameters, boundary conditions, and error cases.

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~10 minutes

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title 'fix: cap admin per_page at 500' clearly and specifically describes the main change: adding a 500-record limit to the per_page parameter.
Description check ✅ Passed The description explains the security issue (unbounded per_page allowing large queries), the fix (capping at 500 with 400 errors), and the benefit (failing loudly instead of silently), all of which directly relate to the changeset.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch vaibhavacharya/ex-1882-identity-adminlistusers-per_page-has-no-upper-bound-gotrue

Warning

There were issues while running some tools. Please review the errors and either fix the tool's configuration or disable the tool if it's a critical failure.

🔧 golangci-lint (2.12.2)

Error: can't load config: unsupported version of the configuration: "" See https://golangci-lint.run/docs/product/migration-guide for migration instructions
The command is terminated due to an error: can't load config: unsupported version of the configuration: "" See https://golangci-lint.run/docs/product/migration-guide for migration instructions


Comment @coderabbitai help to get the list of available commands and usage tips.

@VaibhavAcharya VaibhavAcharya marked this pull request as ready for review May 26, 2026 08:50
@VaibhavAcharya VaibhavAcharya requested a review from a team as a code owner May 26, 2026 08:50
Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
api/pagination.go (1)

61-68: ⚠️ Potential issue | 🔴 Critical | ⚡ Quick win

Reject per_page=0 to avoid divide-by-zero downstream.

Line 62 accepts per_page=0, which can flow into calculateTotalPages(perPage, ...) and panic on division. Please enforce a lower bound together with the new max check.

Suggested fix
 	if queryPerPage != "" {
 		perPage, err = strconv.ParseUint(queryPerPage, 10, 64)
 		if err != nil {
 			return nil, err
 		}
-		if perPage > maxPerPage {
-			return nil, badRequestError("per_page must not exceed %d", maxPerPage)
+		if perPage == 0 || perPage > maxPerPage {
+			return nil, badRequestError("per_page must be between 1 and %d", maxPerPage)
 		}
 	}
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@api/pagination.go` around lines 61 - 68, The handler currently accepts
queryPerPage values including 0 which leads to division-by-zero in
calculateTotalPages; after parsing queryPerPage into perPage (using
strconv.ParseUint) add a lower-bound check: if perPage == 0 return
badRequestError("per_page must be at least 1") (and keep the existing perPage >
maxPerPage check), ensuring calculateTotalPages never receives a zero divisor.
🧹 Nitpick comments (1)
api/pagination_test.go (1)

20-27: ⚡ Quick win

Add a per_page=0 error test case.

Please add a table row for per_page=0 expecting an error, so the lower-bound contract is explicitly covered.

Suggested test row
 		{"per_page at max", fmt.Sprintf("per_page=%d", maxPerPage), 1, maxPerPage, false},
+		{"per_page zero", "per_page=0", 0, 0, true},
 		{"per_page above max", fmt.Sprintf("per_page=%d", maxPerPage+1), 0, 0, true},
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@api/pagination_test.go` around lines 20 - 27, Add a test row to the
pagination test table in api/pagination_test.go to cover the lower-bound
contract: insert an entry like {"per_page zero", "per_page=0", 0, 0, true}
alongside the other cases so the parser/validator for per_page rejects 0;
reference the same test table where entries use defaultPerPage and maxPerPage to
ensure consistency with existing expectations.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Outside diff comments:
In `@api/pagination.go`:
- Around line 61-68: The handler currently accepts queryPerPage values including
0 which leads to division-by-zero in calculateTotalPages; after parsing
queryPerPage into perPage (using strconv.ParseUint) add a lower-bound check: if
perPage == 0 return badRequestError("per_page must be at least 1") (and keep the
existing perPage > maxPerPage check), ensuring calculateTotalPages never
receives a zero divisor.

---

Nitpick comments:
In `@api/pagination_test.go`:
- Around line 20-27: Add a test row to the pagination test table in
api/pagination_test.go to cover the lower-bound contract: insert an entry like
{"per_page zero", "per_page=0", 0, 0, true} alongside the other cases so the
parser/validator for per_page rejects 0; reference the same test table where
entries use defaultPerPage and maxPerPage to ensure consistency with existing
expectations.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 9573baff-ee80-4ee3-b4f6-475cfe8ac0d1

📥 Commits

Reviewing files that changed from the base of the PR and between 30e9d81 and 1cb29c7.

📒 Files selected for processing (2)
  • api/pagination.go
  • api/pagination_test.go

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants