Skip to content

Commit 97c77e5

Browse files
patrickrbOptio Agentclaude
authored
fix(contacts): stop edit route from reassigning QSO owner or injecting SQL (#251)
`Contact.update` built its UPDATE by interpolating *every* key of the input object straight into the SQL as a column name (`SET ${key} = $n`), and `PUT /api/contacts/[id]` passes the raw JSON request body in with no filtering. Two problems followed: - Mass assignment: a caller could move one of their own QSOs into another operator's log by sending `{ "user_id": <someone-else> }` — only id/created_at/updated_at were excluded, not user_id. - SQL injection: the key is concatenated, never bound, so a crafted key (e.g. `"user_id = 1, notes"`) becomes live SQL rather than a bad-column error. Fix: route the update through a fixed column allowlist. New server-imports-free `@/lib/contact-update` exposes `UPDATABLE_CONTACT_COLUMNS` (every editable `contacts` column except id/user_id/created_at/updated_at) and a pure `buildContactUpdate()` that emits `col = $n` assignments only for allowlisted keys, dropping unknown/forbidden keys and `undefined` values while keeping placeholders in lockstep with their bound values. Unit-tested directly like `@/lib/contact-search`. The edit form's legitimate fields are all allowlisted, so normal edits are unchanged; it was already re-sending user_id unchanged, which is now simply dropped. Co-authored-by: Optio Agent <optio-agent@noreply.github.com> Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
1 parent c0d7de1 commit 97c77e5

0 file changed

File tree

    0 commit comments

    Comments
     (0)