Problem
The API currently crashes and restarts when receiving malformed query parameters like ?limit=abc. This causes parseInt("abc") → NaN which propagates to MongoDB as { $limit: NaN }, triggering a MongoServerError that becomes an unhandled rejection and terminates the Node process.
Current Impact
- Production returns nginx 502 errors for these requests
- All in-flight requests on the instance are dropped during crash
- Service recovers via supervisor restart, but symptom is observable as intermittent 502s
- At 25-30k visitors/day with no auth/rate limiting, this is trivially exploitable
Affected Paths
?limit=abc (and other non-numeric limit values)
?limit=10&limit=20 (repeated query keys - Express returns array, not handled)
?hours=999 (currently unbounded, can cause timeouts)
?start=garbage (silent failure, produces empty results)
Proposed Solution
Two changes:
1. Add unhandled rejection handler
In src/index.ts:
process.on("unhandledRejection", (reason) => {
Logger.error(`Unhandled rejection: ${reason instanceof Error ? reason.stack : reason}`)
// do not exit — log and continue
})
This is a Node hygiene measure independent of the specific bugs. Node's default behaviour of terminating on unhandled rejection was designed to surface bugs. In a production service, surfacing the bug should be a log line, not a process death. This single handler stops the crash even before the underlying bug is fixed.
2. Add input coercion with bounds
In src/meetings.controller.ts, add a helper function:
const parseIntOrDefault = (raw: unknown, fallback: number, min: number, max: number): number => {
const s = Array.isArray(raw) ? raw[0] : raw
const n = typeof s === "string" ? Number.parseInt(s, 10) : NaN
if (!Number.isInteger(n) || n < min || n > max) return fallback
return n
}
Apply to query params:
limit: use parseIntOrDefault(req.query.limit, 1000, 1, 1000)
hours: use parseIntOrDefault(req.query.hours, 24, 1, 168) (168 = 1 week max)
Acceptance Criteria
Notes
At 25-30k visitors/day with no auth/rate limiting, anyone can send ?limit=abc repeatedly and hold the service in a perpetual restart loop. Bots, buggy frontends, or debugging sessions will trigger this. The system needs to not die when it happens.
~30 lines of code total, plus tests.
Problem
The API currently crashes and restarts when receiving malformed query parameters like
?limit=abc. This causesparseInt("abc") → NaNwhich propagates to MongoDB as{ $limit: NaN }, triggering aMongoServerErrorthat becomes an unhandled rejection and terminates the Node process.Current Impact
Affected Paths
?limit=abc(and other non-numeric limit values)?limit=10&limit=20(repeated query keys - Express returns array, not handled)?hours=999(currently unbounded, can cause timeouts)?start=garbage(silent failure, produces empty results)Proposed Solution
Two changes:
1. Add unhandled rejection handler
In
src/index.ts:This is a Node hygiene measure independent of the specific bugs. Node's default behaviour of terminating on unhandled rejection was designed to surface bugs. In a production service, surfacing the bug should be a log line, not a process death. This single handler stops the crash even before the underlying bug is fixed.
2. Add input coercion with bounds
In
src/meetings.controller.ts, add a helper function:Apply to query params:
limit: useparseIntOrDefault(req.query.limit, 1000, 1, 1000)hours: useparseIntOrDefault(req.query.hours, 24, 1, 168)(168 = 1 week max)Acceptance Criteria
?limit=abc?limit=10&limit=20?hours=999?start=garbageNotes
At 25-30k visitors/day with no auth/rate limiting, anyone can send
?limit=abcrepeatedly and hold the service in a perpetual restart loop. Bots, buggy frontends, or debugging sessions will trigger this. The system needs to not die when it happens.~30 lines of code total, plus tests.