fix(19): WR-07 reject route ids with trailing garbage via strict integer parse

This commit is contained in:
Lucas Berger
2026-06-17 20:32:26 -04:00
parent 4cf2ad4bff
commit 32bdd1e92d
2 changed files with 30 additions and 4 deletions
+17 -4
View File
@@ -78,6 +78,19 @@ const noEchoHook = (result: { success: boolean }, c: Context) => {
}
};
/**
* WR-07: strictly parse a positive-integer route param. parseInt('12abc', 10) returns 12
* and passes an isNaN guard, silently accepting malformed ids. Number('12abc') is NaN, so
* Number.isInteger(Number(raw)) rejects trailing garbage. Returns null for anything that is
* not a whole positive integer (empty, '12abc', '1.5', '-3', '0', etc.) so the caller can 400.
*/
function parsePositiveIntParam(raw: string | undefined): number | null {
if (raw === undefined || raw.trim() === '') return null;
const n = Number(raw);
if (!Number.isInteger(n) || n <= 0) return null;
return n;
}
// ---------------------------------------------------------------------------
// GET /api/admin/members
//
@@ -217,8 +230,8 @@ adminRouter.post(
'/members/:id/password',
zValidator('json', resetPasswordSchema, noEchoHook),
async (c) => {
const targetId = parseInt(c.req.param('id'), 10);
if (isNaN(targetId)) {
const targetId = parsePositiveIntParam(c.req.param('id'));
if (targetId === null) {
return c.json({ error: 'Invalid member id' }, 400);
}
@@ -316,8 +329,8 @@ adminRouter.get('/calendars', async (c) => {
// ---------------------------------------------------------------------------
adminRouter.put('/calendars/:id/shared', async (c) => {
const targetId = parseInt(c.req.param('id'), 10);
if (isNaN(targetId)) {
const targetId = parsePositiveIntParam(c.req.param('id'));
if (targetId === null) {
return c.json({ error: 'Invalid calendar id' }, 400);
}