Summary
GET /explore?per_page=0 raises an unhandled ZeroDivisionError and returns HTTP 500. The per_page query parameter is accepted without validation or upper bound, so it can also be used to load the entire catalog in one response.
Evidence
src/routes/main_routes.py:76-77, 119-131:
page = request.args.get("page", 1, type=int)
per_page = request.args.get("per_page", 12, type=int)
...
total_items = len(filtered_projects)
total_pages = math.ceil(total_items / per_page) if total_items > 0 else 1
- With
per_page=0, total_items / per_page is a division by zero → ZeroDivisionError → 500.
- With a negative
per_page (e.g., -1), math.ceil(total_items / -1) is negative, producing total_pages < 0, and the page-bound logic (page > total_pages) misbehaves.
- With a large value (e.g.,
100000), all projects are returned in a single page — unbounded result size with no cap.
Steps to reproduce
GET /explore?per_page=0
- Server returns HTTP 500 (ZeroDivisionError, logged by the global error handler).
GET /explore?per_page=-1 — page count becomes negative and pagination breaks.
Expected vs Actual
- Expected: Invalid
per_page values are rejected (400) or clamped to a sane range (e.g., 1..100).
- Actual:
per_page=0 crashes the endpoint; values are otherwise unbounded.
Suggested Fix
Clamp per_page to a safe range (e.g., min(max(per_page, 1), 100)), and clamp/validate page >= 1. Add tests for per_page=0, negative, and oversized values.
Summary
GET /explore?per_page=0raises an unhandledZeroDivisionErrorand returns HTTP 500. Theper_pagequery parameter is accepted without validation or upper bound, so it can also be used to load the entire catalog in one response.Evidence
src/routes/main_routes.py:76-77, 119-131:per_page=0,total_items / per_pageis a division by zero →ZeroDivisionError→ 500.per_page(e.g.,-1),math.ceil(total_items / -1)is negative, producingtotal_pages < 0, and the page-bound logic (page > total_pages) misbehaves.100000), all projects are returned in a single page — unbounded result size with no cap.Steps to reproduce
GET /explore?per_page=0GET /explore?per_page=-1— page count becomes negative and pagination breaks.Expected vs Actual
per_pagevalues are rejected (400) or clamped to a sane range (e.g., 1..100).per_page=0crashes the endpoint; values are otherwise unbounded.Suggested Fix
Clamp
per_pageto a safe range (e.g.,min(max(per_page, 1), 100)), and clamp/validatepage >= 1. Add tests forper_page=0, negative, and oversized values.