CVE-2026-77239 Overview
CVE-2026-77239 is a broken access control vulnerability in WACRM, a self-hostable CRM template for WhatsApp. The flaw affects version 0.7.0 and earlier. Flow and automation write routes authenticate account viewers but do not enforce the required agent role. The routes then use a service-role Supabase client that bypasses row-level security (RLS). A user holding the read-only viewer role can create, edit, activate, or delete flows and trigger outbound WhatsApp automations. The vulnerability is classified as improper authorization [CWE-285].
Critical Impact
Authenticated viewers can perform destructive flow modifications and dispatch outbound WhatsApp actions using privileges reserved for the agent role.
Affected Products
- WACRM versions 0.7.0 and earlier
- Affected routes: src/app/api/flows/[id]/route.ts, src/app/api/flows/[id]/activate/route.ts, src/app/api/flows/route.ts
- Affected routes: src/app/api/automations/route.ts, src/app/api/automations/engine/route.ts
Discovery Timeline
- 2026-09-18 - CVE-2026-77239 published to NVD
- 2026-09-23 - Last updated in NVD database
- Patch commit 03e851bea56dcf6bb21ff1b80ba531372bf3269f merged via GitHub Pull Request #351
Technical Details for CVE-2026-77239
Vulnerability Analysis
WACRM uses Supabase for data persistence and enforces per-table row-level security policies. Write policies on the flows and automations tables require the caller to hold the agent role. The affected Next.js API route handlers verify that the caller belongs to the account (membership) but never validate the caller's role. After the membership check, the handlers switch to a Supabase admin client (supabaseAdmin) that uses the service key and bypasses RLS entirely. As a result, the agent-gated flows_insert, flows_update, flows_delete, and automations_insert policies are never evaluated. A viewer authenticated to the account can create active automations, delete production flows, and trigger outbound WhatsApp actions from what is intended to be a read-only role.
Root Cause
The root cause is a missing authorization check [CWE-285] combined with a database client that intentionally bypasses RLS. The membership-only guard is insufficient because RLS is the sole layer that enforces role separation for writes. When RLS is bypassed by the service-role client, the API handler becomes the last line of defense — and it does not enforce the agent role.
Attack Vector
An authenticated viewer sends HTTP requests to the vulnerable write endpoints (for example, POST /api/flows, DELETE /api/flows/[id], POST /api/flows/[id]/activate, POST /api/automations, or the automation engine endpoint). The handler accepts the request, confirms the viewer belongs to the account, and then performs the write using supabaseAdmin. Exploitation requires only valid viewer credentials on the target account; no user interaction and no elevated privileges are needed.
// Patch applied in src/app/api/automations/[id]/duplicate/route.ts
import { NextResponse } from 'next/server'
import { createClient } from '@/lib/supabase/server'
+import { requireRole, toErrorResponse } from '@/lib/auth/account'
import { supabaseAdmin } from '@/lib/automations/admin-client'
export async function POST(
_request: Request,
{ params }: { params: Promise<{ id: string }> },
) {
const { id } = await params
+
+ // Duplicating creates a new automation row — a write. Enforce `agent`
+ // (the service-role client below bypasses the agent-gated
+ // automations_insert RLS).
+ try {
+ await requireRole('agent')
+ } catch (err) {
+ return toErrorResponse(err)
+ }
+
const supabase = await createClient()
Source: GitHub Commit 03e851b
Detection Methods for CVE-2026-77239
Indicators of Compromise
- Records in the flows or automations tables created, updated, or deleted by users whose account role is viewer.
- Outbound WhatsApp messages dispatched by the automation engine that correlate to automations owned by viewer accounts.
- Unexpected activations or deactivations of flows outside of change windows attributable to agents or admins.
Detection Strategies
- Audit Supabase logs for service_role writes originating from API routes that lack a requireRole('agent') call in versions 0.7.0 or earlier.
- Correlate WACRM application logs of API calls to /api/flows/* and /api/automations/* against the authenticated user's role.
- Add temporary database triggers that log the acting user's role on inserts, updates, and deletes to flows and automations.
Monitoring Recommendations
- Ingest WACRM application and Supabase audit logs into a centralized logging platform for role-based query analysis.
- Alert on any write to flows or automations where the acting session's role is viewer.
- Track outbound WhatsApp message volume per automation to detect anomalous spikes tied to newly created automations.
How to Mitigate CVE-2026-77239
Immediate Actions Required
- Upgrade WACRM to the version containing commit 03e851bea56dcf6bb21ff1b80ba531372bf3269f.
- Review recent writes to the flows and automations tables and roll back unauthorized changes.
- Rotate the Supabase service-role key if exposure to untrusted viewers is suspected.
- Audit account membership and downgrade or remove any unnecessary viewer accounts.
Patch Information
The fix is applied in commit 03e851bea56dcf6bb21ff1b80ba531372bf3269f, delivered through Pull Request #351. The patch introduces requireRole('agent') guards in every write handler that uses supabaseAdmin, ensuring the agent role is enforced at the API layer before RLS is bypassed. Full details are published in GitHub Security Advisory GHSA-34q7-fv77-625j.
Workarounds
- Restrict access to the WACRM application to trusted users only until the patch is applied.
- Temporarily remove viewer-role accounts, or convert them to a stricter role that has no account membership on sensitive projects.
- Place a reverse proxy in front of the vulnerable API routes that blocks write methods (POST, PUT, PATCH, DELETE) for sessions belonging to viewers.
# Example: verify the deployed WACRM commit includes the fix
git -C /opt/wacrm log --oneline | grep 03e851b
# Example: list viewer-role account members via Supabase CLI
supabase db query "SELECT account_id, user_id, role FROM account_members WHERE role = 'viewer';"
Disclaimer: This content was generated using AI. While we strive for accuracy, please verify critical information with official sources.