fix: add app_id scope check to V1 API handlers (#244)#257
fix: add app_id scope check to V1 API handlers (#244)#257
Conversation
V1 item handlers (handleGetItem, handleAddMessage, handleAssignItem,
handleResolveItem, handleVerifyItem, handleReopenItem, handleCloseItem,
handleRespondToItem) did not verify that the requested item belongs to
the authenticated user's app_id. This allowed any authenticated user to
read, modify, or close items belonging to other apps.
Add the same app_id scoping check used by V2 endpoints:
if (req.v2Auth?.app_id && item.app_id !== req.v2Auth.app_id)
→ 403 Forbidden
For handlers that previously skipped the item fetch (assign, resolve,
verify, reopen, close), an explicit getItem() call is added before the
scope check.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
jessie-coco
left a comment
There was a problem hiding this comment.
Codex Review R1: CLEAN — 0 P1 + 0 P2 + 1 P3
Scope check pattern matches V2 endpoints exactly (req.v2Auth?.app_id && item.app_id !== req.v2Auth.app_id). All 8 V1 item handlers are covered. Consistent and correct.
Checked dimensions:
- Correctness ✅ — Logic mirrors V2 pattern. Guard placement is correct (after 404 check, before mutation).
- Security ✅ — Fixes broken access control for V1 endpoints. 403 on app_id mismatch.
- Edge cases ✅ — JWT with null app_id (no default app) skips check gracefully via optional chaining. Same behavior as V2.
- Integration ✅ — No callers broken. V1 routes already have
v2Authmiddleware, soreq.v2Authis always set when handlers execute.
P3 (non-blocking): In handleAssignItem, handleResolveItem, handleVerifyItem, handleReopenItem, handleCloseItem — the new getItem() + 404 check makes the subsequent if (!result.changes) return 404 unreachable (item was just confirmed to exist). Dead code, harmless. Could be cleaned up later if desired.
Not in scope (noted for awareness): handleGetItems, handleCreateItem, and handleGetItemsFull still use resolveAppId(req) from URL params rather than auth-resolved app_id. V2 equivalents use req.v2Auth.app_id. This is a separate issue from #244.
R1 CLEAN. Approved.
Summary
app_idbefore allowing accessreq.v2Auth?.app_id && item.app_id !== req.v2Auth.app_idcheck already present in V2 endpoints, returning 403 on mismatchgetItem()call was added before the scope checkAffected handlers
handleGetItem,handleAddMessage,handleAssignItem,handleResolveItem,handleVerifyItem,handleReopenItem,handleCloseItem,handleRespondToItemTest plan
v2Auth) are unaffected (guard uses optional chaining)🤖 Generated with Claude Code