CVE-2026-62247 Overview
Supabase Realtime contains an authorization flaw that allows private-channel clients to receive presence data they should be denied. The service delivers Broadcast, Presence, and Postgres Changes over WebSockets. Prior to version 2.111.2, Realtime authorization did not correctly honor the per-extension presence.read row-level security (RLS) policy. When a client held presence.write but was explicitly denied presence.read, the server still forwarded presence_diff messages containing other members' metadata. Leaked fields can include application-defined location, online-status, roster, viewing, or typing information. The issue is classified under [CWE-863: Incorrect Authorization] and affects only deployments with differential presence visibility.
Critical Impact
Clients with write-only presence permissions can read other members' presence metadata on private channels, breaking RLS-based access control assumptions.
Affected Products
- Supabase Realtime versions prior to 2.111.2
- Deployments using private channels with differential presence.read / presence.write policies
- Applications relying on per-extension RLS to isolate presence metadata between users
Discovery Timeline
- 2026-09-21 - CVE-2026-62247 published to NVD
- 2026-09-22 - Last updated in NVD database
Technical Details for CVE-2026-62247
Vulnerability Analysis
The defect resides in Supabase Realtime's authorization probe logic for presence extensions. Realtime evaluates channel permissions by inserting authorization probe rows and letting Postgres RLS decide the outcome. The pre-patch code inferred read permission from the presence of an inserted row identifier, without independently checking the SELECT policy. This conflated write with read, so a member allowed to insert presence but denied SELECT still passed the read gate. Once the gate opened, the Realtime channel forwarded presence_diff payloads describing joins, leaves, and metadata updates from all other channel members. The postgres_changes extension row data is unaffected, and uniform-visibility deployments carry no differential to exploit.
Root Cause
The probe used RETURNING * on the authorization insert, which forces Postgres to evaluate the SELECT policy for the returned row. Realtime then updated read policies for every extension based on membership in the returned identifier set, effectively treating successful insert as proof of read. Extensions that were never probed were also assigned a boolean read verdict, erasing the distinction between denied and unevaluated.
Attack Vector
An authenticated client connects to a private Realtime channel over WebSocket with credentials that satisfy presence.write but not presence.read. After joining, the client passively receives presence_diff frames broadcast by the server for other members. No additional exploitation primitive is required beyond a valid session and channel subscription.
// Patch: lib/realtime/tenants/authorization.ex
with {:ok, res} <- Repo.all(conn, query, Message) do
returned_ids = MapSet.new(res, & &1.id)
+ # Only the requested extensions were inserted, so we only set read for those. Extensions that
+ # were not checked are left unevaluated (nil) so callers can tell "denied" (false) apart from
+ # "not checked yet" (nil).
{:ok,
- Enum.reduce(@all_extensions, policies, fn extension, acc ->
- can? =
- Map.has_key?(messages_by_extension, extension) and
- MapSet.member?(returned_ids, messages_by_extension[extension])
-
- Policies.update_policies(acc, extension, :read, can?)
+ Enum.reduce(messages_by_extension, policies, fn {extension, id}, acc ->
+ Policies.update_policies(acc, extension, :read, MapSet.member?(returned_ids, id))
end)}
end
end
Source: Supabase Realtime Commit c039bca
A companion change in lib/realtime/tenants/repo.ex introduces a returning: false option so authorization probe inserts no longer trigger Postgres SELECT policy evaluation, keeping write checks isolated from read checks.
Detection Methods for CVE-2026-62247
Indicators of Compromise
- WebSocket clients receiving presence_diff events on private channels where their JWT claims should deny presence.read.
- Realtime tenant logs showing authorization probes that succeed on write but were expected to fail on read for the same extension.
- Application audit logs recording presence metadata reads from user identities lacking SELECT privileges on presence tables.
Detection Strategies
- Inventory all Supabase Realtime deployments and compare running versions against 2.111.2 using the container image tag or release manifest.
- Review RLS policies for any tenant that grants presence.write without a matching presence.read for the same role, flagging channels affected by the differential.
- Instrument the Realtime tenant to log presence payload delivery per subscriber and correlate against the subscriber's effective RLS verdicts.
Monitoring Recommendations
- Alert on WebSocket sessions that receive presence broadcasts after authorization decisions denied the read scope for the same channel.
- Track version drift for the supabase/realtime container in registries and Kubernetes clusters to catch pre-patch instances brought online.
- Forward Realtime and Postgres audit logs to a central data lake and build queries around presence extension authorization outcomes.
How to Mitigate CVE-2026-62247
Immediate Actions Required
- Upgrade Supabase Realtime to version 2.111.2 or later across all self-hosted and managed tenants.
- Audit RLS policies on private channels for any differential between presence.write and presence.read and treat affected channels as exposed until patched.
- Rotate or invalidate long-lived Realtime JWTs issued to clients that only require write access to presence, in case they were used to read metadata.
Patch Information
The fix ships in Supabase Realtime v2.111.2 via Pull Request #1969 and commit c039bca. Details are documented in the Supabase Security Advisory GHSA-rcr8-2525-4r7p. The patch stops using RETURNING * on authorization probe inserts and only sets read verdicts for extensions actually probed, preserving the distinction between denied and unevaluated.
Workarounds
- Adopt uniform presence visibility until upgraded — either grant presence.read alongside presence.write or deny both — removing the differential the flaw depends on.
- Disable the Presence extension on channels where write-only members exist, restricting them to Broadcast until the patch is deployed.
- Move sensitive presence metadata out of the Presence payload and into a table protected by strict SELECT RLS enforced independently of Realtime.
# Verify the running Supabase Realtime version
docker inspect supabase/realtime --format '{{.Config.Image}}'
# Pull and deploy the patched release
docker pull supabase/realtime:v2.111.2
docker compose up -d realtime
# Confirm the upgrade
curl -s http://localhost:4000/api/health | jq '.version'
Disclaimer: This content was generated using AI. While we strive for accuracy, please verify critical information with official sources.

