Merge pull request #38 from ArnasDon/fix/automations-meta-send-contact-ownership

fix(automations): scope meta-send contact lookup by user_id
This commit is contained in:
Arnas Donauskas 2026-04-17 21:53:05 +03:00 committed by GitHub
commit 3758711f5a
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194

View File

@ -52,13 +52,22 @@ type SendInput =
async function sendViaMeta(input: SendInput): Promise<{ whatsapp_message_id: string }> { async function sendViaMeta(input: SendInput): Promise<{ whatsapp_message_id: string }> {
const db = supabaseAdmin() const db = supabaseAdmin()
// Scope the contact lookup by user_id. The engine uses the
// service-role client (bypassing RLS), and the public
// /api/automations/engine endpoint accepts contact_id from the
// request body — without this filter, an authenticated user could
// fire their own automations against another tenant's contact UUID
// and send via their own WhatsApp config to that contact's phone.
// Practical risk is low (UUIDs are unguessable) but the check is
// cheap defense-in-depth.
const { data: contact, error: contactErr } = await db const { data: contact, error: contactErr } = await db
.from('contacts') .from('contacts')
.select('id, phone') .select('id, phone')
.eq('id', input.contactId) .eq('id', input.contactId)
.eq('user_id', input.userId)
.maybeSingle() .maybeSingle()
if (contactErr || !contact?.phone) { if (contactErr || !contact?.phone) {
throw new Error('contact phone missing') throw new Error('contact not found for this user')
} }
const sanitized = sanitizePhoneForMeta(contact.phone) const sanitized = sanitizePhoneForMeta(contact.phone)