Root cause
Authentication & access control introduced
A Claude-assisted change adds a manual automation endpoint and engine that act on whatever contact ID the caller sends.
How AI contributed: Direct introductionPublished Jun 8, 2026 in
arnasdon/wacrmAll 2 findings in this repository
Provisional finding. Full causal and release verification remains incomplete.
wacrm's manual automation endpoint took a contact ID from the request body and ran the account's automations against it through a service-role database client, without checking that the contact belonged to the caller's account. A signed-in user whose automations had the matching steps could change another tenant's contact fields, add or remove its tags, or attach deals to it. A Claude-assisted change introduced the endpoint and engine this way. A later change checks ownership for new runs, but a run already paused at a wait step resumes with the stored contact ID unchecked, and its custom-field, tag-removal, tag-condition and deal steps still act on that contact; no complete repair exists in the repository through October 2026.
Root cause
A Claude-assisted change adds a manual automation endpoint and engine that act on whatever contact ID the caller sends.
Fix status
No minimum fix commit has been established for this finding.
Fix status unresolved
Case facts
@@ -0,0 +1,31 @@+import { NextResponse } from 'next/server'+import { createClient } from '@/lib/supabase/server'+import { runAutomationsForTrigger } from '@/lib/automations/engine'+import type { AutomationTriggerType } from '@/types'++/**+ * Manual trigger for testing or for external integrations that want+ * to fire automations. Auth is required — the caller's user_id is+ * used so RLS-safe data remains per-user.+ */+export async function POST(request: Request) {+ const supabase = await createClient()+ const {+ data: { user },+ } = await supabase.auth.getUser()+ if (!user) return NextResponse.json({ error: 'Unauthorized' }, { status: 401 })++ const body = await request.json().catch(() => null)+ if (!body?.trigger_type) {+ return NextResponse.json({ error: 'trigger_type required' }, { status: 400 })+ }++ await runAutomationsForTrigger({+ userId: user.id,+ triggerType: body.trigger_type as AutomationTriggerType,+ contactId: body.contact_id ?? null,+ context: body.context ?? {},+ })++ return NextResponse.json({ ok: true })+}