fix(#950): bound page parameter on /supabase-discover via schema validation and controller clamp#1014
Conversation
…seDiscover Schema layer (primary defence): - Add page field to matchSchemas.getSupabaseDiscover mirroring the existing validation in matchSchemas.getRecommendedPartners - Valid range: integer 1–1000; absent field passes (defaults to page 1) - Any value outside this range or non-numeric returns HTTP 400 before the controller executes Controller layer (defence-in-depth): - Wrap Math.max with Math.min(..., 1000) on the page parse line so even if schema validation is bypassed the range() offset is bounded: max skip = (1000-1) * 100 = 99900 rows, not 999,980,000 Tests added (backend/tests/supabaseDiscover.test.js): - 400 for page=99999, page=0, page=-1, page=1.5, page=abc, limit=101 - Passes (not 400) for page=1000 (boundary) and absent page param - Controller unit test: page=2&limit=10 → skip=10, to=19 - Controller unit test: page=99999 clamped → skip never exceeds 99900
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: defaults Review profile: CHILL Plan: Pro Plus Run ID: ⛔ Files ignored due to path filters (1)
📒 Files selected for processing (2)
🚧 Files skipped from review as they are similar to previous changes (2)
📝 WalkthroughWalkthroughFixes an unbounded ChangesPage Parameter Bounding in getSupabaseDiscover
Estimated code review effort🎯 2 (Simple) | ⏱️ ~12 minutes Possibly related PRs
Suggested labels
🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches🧪 Generate unit tests (beta)
Comment |
There was a problem hiding this comment.
Actionable comments posted: 1
🧹 Nitpick comments (1)
backend/controllers/matchController.js (1)
154-156: ⚡ Quick winHarden
limitparsing at controller level as well.
pagenow has defense-in-depth clamping, butlimitis only capped at the top end. Clampinglimitto1..100here keepsskip/.range()safe even if this handler is invoked outside the validated route path.Suggested patch
- const limit = Math.min(parseInt(req.query.limit, 10) || 100, 100); + const limit = Math.min(Math.max(1, parseInt(req.query.limit, 10) || 100), 100);🤖 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 `@backend/controllers/matchController.js` around lines 154 - 156, The limit variable in the matchController.js file at the limit declaration lacks lower-bound clamping, which could result in zero or negative values if unexpected input is passed directly to the handler outside of validated route paths. Apply the same defense-in-depth clamping strategy used for the page variable by wrapping the parseInt call with Math.max(1, ...) to ensure limit is clamped between 1 and 100, protecting skip and .range() calculations from invalid values.
🤖 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.
Inline comments:
In `@backend/tests/supabaseDiscover.test.js`:
- Around line 152-163: The boundary test for page=1000 uses a weak assertion
that only checks the response status is not 400, which allows other failure
statuses like 500 to pass undetected. Replace the weak
`expect(res.status).not.toBe(400)` assertion in the boundary test with a
positive assertion that explicitly checks for the expected success status code
(200). Apply the same fix to the other boundary test mentioned in the comment at
lines 165-173, ensuring both tests now assert the specific expected successful
response status rather than just excluding a single failure case.
---
Nitpick comments:
In `@backend/controllers/matchController.js`:
- Around line 154-156: The limit variable in the matchController.js file at the
limit declaration lacks lower-bound clamping, which could result in zero or
negative values if unexpected input is passed directly to the handler outside of
validated route paths. Apply the same defense-in-depth clamping strategy used
for the page variable by wrapping the parseInt call with Math.max(1, ...) to
ensure limit is clamped between 1 and 100, protecting skip and .range()
calculations from invalid values.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: defaults
Review profile: CHILL
Plan: Pro Plus
Run ID: 7bf2f243-098d-4820-beb9-4189932e3778
📒 Files selected for processing (3)
backend/controllers/matchController.jsbackend/tests/supabaseDiscover.test.jsbackend/validation/schemas.js
|
@hariom888 is attempting to deploy a commit to the durdana3105's projects Team on Vercel. A member of the Team first needs to authorize it. |
|
@durdana3105 These 6 CI failures are pre-existing on |
Closes #950
Summary
GET /api/match/supabase-discoveraccepted an unboundedpagequery parameter. Because Zod strips unknown keys by default,pagepassed through thevalidate()middleware silently. An authenticated user could passpage=99999&limit=100, issuing a.range(9999800, 9999899)query against theprofilestable — a near-10M row offset on every call.This PR adds two independent layers of defence.
Defence layers
Layer 1 — Schema allowlist (
backend/validation/schemas.js)Added
pagetomatchSchemas.getSupabaseDiscover, mirroring the identical field already present inmatchSchemas.getRecommendedPartners:Any
pagevalue outside 1–1000, or non-numeric, now returns HTTP 400 before the controller is reached.Layer 2 — Controller clamp (
backend/controllers/matchController.js)Maximum possible
.range()offset:(1000 - 1) × 100 = 99,900rows — down from(99999 - 1) × 100 = 9,999,800.Changes
backend/validation/schemas.jspagefield tomatchSchemas.getSupabaseDiscoverbackend/controllers/matchController.jspageto 1000 maximumbackend/tests/supabaseDiscover.test.jsTest coverage
Schema rejection (400):
page=99999·page=0·page=-1·page=1.5·page=abc·limit=101Schema acceptance:
page=1000(boundary) · absentpageparamController unit tests:
page=2&limit=10→skip=10, to=19·page=99999clamped to max skip of99900(never reaches row 9,999,800)Summary by CodeRabbit
Release Notes
Bug Fixes
pageto 1–1000 andlimitto 1–100, preventing invalid pagination requests.Tests