Summary
Severity: HIGH
Source: Cursor vulnerability scan (2026-07-13)
Repository: apps/admin
Location: src/pages/overview/Overview.tsx
Verified: code-traced
Scan run: bc-8bc4c86c-6c11-4e73-8ef6-9eb4d2d770c4
Commit: 642e964aecca48aaa75ab160ada9281118a4ccc0
Description
The handleImpersonate function generates magic links via the admin-impersonate edge function for any merchant, but has no isSuperAdmin authorization check. Any admin with overview page access can impersonate any merchant on the platform. The database schema includes allow_staff_impersonation and staff_impersonation_consent_at fields on organizations, and an update_staff_impersonation_consent RPC exists, but these consent mechanisms are completely unused in the impersonation flow. Additionally, the redirect_to parameter sent to the edge function includes a http://localhost:5173/callback option that is visible in production builds with no import.meta.env.DEV guard.
Impact
Any admin with overview page access (the most commonly granted page) can perform full merchant account takeover — accessing merchant PII, initiating payouts, and changing merchant settings. The lack of merchant consent checking means merchants who have not opted in to staff impersonation can still be impersonated.
Attack path
- Attacker has a valid admin JWT with
overview page access (no super-admin needed)
- Attacker clicks "Impersonate" on any merchant in the merchants list (or calls
supabase.functions.invoke("admin-impersonate") directly)
- Edge function returns
action_link magic link — no isSuperAdmin or allow_staff_impersonation consent check is performed client-side
- Attacker opens the magic link and gains a full merchant session on
dashboard.lomi.africa
Evidence
src/pages/overview/Overview.tsx:402-446 — handleImpersonate sends target_merchant_id, target_email, redirect_to with no authorization check
src/pages/overview/Overview.tsx:1815-1830 — Impersonate button rendered for every merchant with no isSuperAdmin guard
src/pages/overview/Overview.tsx:1732-1759 — Localhost impersonation toggle visible in production UI
src/lib/utils/dashboard-url.ts:3-7 — http://localhost:5173/callback hardcoded as valid redirect target
src/lib/types/database.types.ts:5033,5044 — allow_staff_impersonation and staff_impersonation_consent_at fields exist but are never referenced in src/pages/overview/
Remediation
Gate the impersonation feature behind isSuperAdmin in the frontend. Server-side, the admin-impersonate edge function must independently verify the caller is a super-admin, check allow_staff_impersonation on the target organization, and strictly allowlist redirect_to to https://dashboard.lomi.africa/callback only. Remove the localhost callback toggle from production builds by guarding it with import.meta.env.DEV.
PoC
Video not feasible — exploitation requires an authenticated admin session on the live Supabase instance. Vulnerability confirmed through static code analysis showing absence of authorization checks and consent verification in the impersonation flow.
Summary
Severity: HIGH
Source: Cursor vulnerability scan (2026-07-13)
Repository:
apps/adminLocation:
src/pages/overview/Overview.tsxVerified: code-traced
Scan run: bc-8bc4c86c-6c11-4e73-8ef6-9eb4d2d770c4
Commit:
642e964aecca48aaa75ab160ada9281118a4ccc0Description
The
handleImpersonatefunction generates magic links via theadmin-impersonateedge function for any merchant, but has noisSuperAdminauthorization check. Any admin withoverviewpage access can impersonate any merchant on the platform. The database schema includesallow_staff_impersonationandstaff_impersonation_consent_atfields on organizations, and anupdate_staff_impersonation_consentRPC exists, but these consent mechanisms are completely unused in the impersonation flow. Additionally, theredirect_toparameter sent to the edge function includes ahttp://localhost:5173/callbackoption that is visible in production builds with noimport.meta.env.DEVguard.Impact
Any admin with overview page access (the most commonly granted page) can perform full merchant account takeover — accessing merchant PII, initiating payouts, and changing merchant settings. The lack of merchant consent checking means merchants who have not opted in to staff impersonation can still be impersonated.
Attack path
overviewpage access (no super-admin needed)supabase.functions.invoke("admin-impersonate")directly)action_linkmagic link — noisSuperAdminorallow_staff_impersonationconsent check is performed client-sidedashboard.lomi.africaEvidence
src/pages/overview/Overview.tsx:402-446—handleImpersonatesendstarget_merchant_id,target_email,redirect_towith no authorization checksrc/pages/overview/Overview.tsx:1815-1830— Impersonate button rendered for every merchant with noisSuperAdminguardsrc/pages/overview/Overview.tsx:1732-1759— Localhost impersonation toggle visible in production UIsrc/lib/utils/dashboard-url.ts:3-7—http://localhost:5173/callbackhardcoded as valid redirect targetsrc/lib/types/database.types.ts:5033,5044—allow_staff_impersonationandstaff_impersonation_consent_atfields exist but are never referenced insrc/pages/overview/Remediation
Gate the impersonation feature behind
isSuperAdminin the frontend. Server-side, theadmin-impersonateedge function must independently verify the caller is a super-admin, checkallow_staff_impersonationon the target organization, and strictly allowlistredirect_totohttps://dashboard.lomi.africa/callbackonly. Remove the localhost callback toggle from production builds by guarding it withimport.meta.env.DEV.PoC
Video not feasible — exploitation requires an authenticated admin session on the live Supabase instance. Vulnerability confirmed through static code analysis showing absence of authorization checks and consent verification in the impersonation flow.