MEDIUM: Admin routes use req.params.id without integer validation #79
Labels
No Label
architecture
backend
bug
feature
frontend
priority:critical
priority:high
priority:low
priority:medium
priority:nice-to-have
ux
No Milestone
No project
No Assignees
1 Participants
Notifications
Due Date
No due date set.
Dependencies
No dependencies set.
Reference: null/BillTracker#79
Loading…
Reference in New Issue
No description provided.
Delete Branch "%!s(<nil>)"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Bug Description
Several admin routes use Number(req.params.id) without parseInt + Number.isInteger() validation:
SQLite is permissive with type coercion - Number(abc) becomes NaN which SQLite treats as NULL, causing these routes to silently fail to find the target user (returning 404) rather than returning a proper 400 validation error.
Compare with routes/bills.js which properly validates: parseInt(req.params.id, 10) + Number.isInteger() checks.
Impact
Confusing error responses (404 instead of 400) for invalid IDs. Could mask bugs in admin UI code.
Recommended Fix
Add parseInt + Number.isInteger validation for all admin :id parameters, consistent with the pattern used in bills routes.
Added at the top of admin.js:
function parseUserId(params) {
const n = parseInt(params.id, 10);
return Number.isInteger(n) && n > 0 ? n : null;
}
Applied to all 5 user routes:
Route Before After
PUT /users/:id/password raw req.params.id in queries parseUserId + early 400
PUT /users/:id/role Number(req.params.id) parseUserId + early 400
PUT /users/:id/active Number(req.params.id) parseUserId + early 400
PUT /users/:id/username Number(req.params.id) parseUserId + early 400
DELETE /users/:id raw req.params.id in query parseUserId + early 400
Backup routes (GET/POST/DELETE /backups/:id) left unchanged — those params are filenames, not integers.