fix(security): validate ingestId param on ingest routes - #299
Conversation
Add TypeBox params schema (ingestId as a non-empty numeric string) to the GET, PATCH and DELETE /ingest/:ingestId routes so ingestId is validated by Fastify before parseInt, rejecting malformed input with 400. Closes #257 Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
birme
left a comment
There was a problem hiding this comment.
code-reviewer (daily-backlog-pr Phase 3):
Code Review
Verdict: Needs Changes
Summary: The TypeBox params schema is correct, minimal, and idiomatic (single quotes, no trailing commas, matches existing schema style), and it does close the unvalidated-parseInt gap described in #257. However, the change ships with no regression test for the exact failure path it claims to fix, which the project's review criteria treat as a Blocking omission for a security bug fix. There is also important context the PR does not acknowledge: every ingest route is currently gated behind a preHandler that returns 501, so the real-world exposure is effectively zero today.
Blocking
src/api_ingests.ts:138,181,256— No regression test accompanies this security fix. Project rule (code-reviewer TESTING): "Every bug fix must include a test that would have caught the original bug... verify a test exercises the exact failure path." There is noapi_ingests.test.ts, and neitherapi_validation.test.tsnoringest_manager.test.tswas updated. Add aserver.inject()test asserting thatGET/PATCH/DELETE /ingest/:ingestIdwith a non-numericingestId(e.g.abc, empty,1.5,-1) returns 400, and that a valid numeric id passes schema validation. This is cheap because Fastify schema validation runs in the validation phase, which fires before the 501preHandlerhook — so a validation test is observable and meaningful even while the route body is disabled.
Warnings
src/api_ingests.ts:28-30— Context the PR body omits: all ingest routes are behindfastify.addHook('preHandler', ...)returning501 Not Implemented. Fastify's lifecycle runs schema validation beforepreHandler, so behavior is: badingestId-> 400 (new), validingestId-> 501 (unchanged); the handler body never executes in either case. The fix is therefore correct hardening for when the API is re-enabled, but its present security value is nil. The PR description ("rejected with 400 before any handler logic runs") is accurate but should note the routes are otherwise disabled, so reviewers/ops don't over-attribute impact.
Suggestions
src/api_ingests.ts:138,181,256— The three identicalType.Object({ ingestId: ... })literals could be hoisted into a single sharedIngestIdParamsconst (module scope) to keep the pattern DRY and guarantee the three routes never drift. Optional.src/api_ingests.ts:139—pattern: '^[0-9]+$'already implies non-empty, sominLength: 1is redundant (harmless, belt-and-suspenders). Fine to leave.- Consider a
maximum/length bound: an arbitrarily long digit string still passes^[0-9]+$and then hitsparseInt(...,10), which can silently overflow to a lossy/Infinity-adjacent number. Not a real risk while the route is 501-gated, but worth a bound when re-enabled.
Domain Note
This change touches the WHIP/WHEP-adjacent ingest session surface. If/when these routes are re-enabled, consider consulting the intercom-expert agent for ingest/WHIP lifecycle validation.
Next steps: pass Blocking items to bug-fixer (add the
server.inject()validation regression test) -> once resolved, use pr-author to update the PR.
Covers the exact failure path from the code review: GET/PATCH/DELETE /api/v1/ingest/:ingestId reject non-numeric, empty, float, negative and special-character ingestId with 400 (Fastify schema validation runs before the 501 preHandler), while a valid numeric id passes validation (501, not 400). Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
|
Addressed the Blocking review item: added Acknowledging the review's context note: these ingest routes are currently |
Code ReviewVerdict: LGTM Summary: Adds TypeBox Reviewed against the Open Intercom |
Summary
paramsschema (ingestIdas a non-empty numeric string,^[0-9]+$) to the GET, PATCH and DELETE/api/v1/ingests/:ingestIdroutes insrc/api_ingests.ts.ingestIdwas declared only as a TS generic with no Fastify schema, so it reachedparseIntunvalidated. Malformed input is now rejected with 400 before any handler logic runs.Test plan
npm run typecheckcleannpm test— 243/243 pass (worker teardown warning is pre-existing/expected)npm run lint— 0 errors (pre-existing warnings only)Closes #257