HIGH 7.5

CVE-2026-56812: Phoenix Framework Presence Denial of Service via Prototype Confusion

A vulnerability in Phoenix Framework's JavaScript presence client allows attackers to crash the real-time presence feature for all users viewing a channel. By joining a presence channel with a specially crafted username (such as "__proto__" or "constructor"), an attacker can trigger a JavaScript error that breaks presence synchronization. Unlike many attacks, the attacker doesn't need special permissions—ordinary channel access is sufficient. The disruption persists as long as the attacker remains in the channel, affecting every viewer of that topic until they leave.

Source data · NVD / CISA · public domain

CVSS
3.1 · 7.5 HIGH · CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H
Weaknesses (CWE)
CWE-754
Affected products
1 configuration(s)
Published / Modified
2026-07-07 / 2026-07-09

NVD description (verbatim)

Improper Check for Unusual or Exceptional Conditions vulnerability in phoenixframework phoenix (Presence JavaScript client) allows an attacker with ordinary channel access to cause a persistent client-side denial of service against every viewer of a presence channel topic. This vulnerability is associated with program files assets/js/phoenix/presence.js and program routines Presence.syncState and Presence.syncDiff. The Phoenix JavaScript presence client checks whether a presence already exists with a bare truthiness test (state[key]) instead of an own-property check. Presence keys can be attacker-controlled, because applications track presences under a username or id supplied by the client. A user who joins a channel choosing a key that is an Object.prototype member name (__proto__, constructor, toString, hasOwnProperty, and similar) makes that lookup return JavaScript's built-in Object.prototype instead of undefined. Because the prototype is truthy, the code treats it as an existing presence and reads .metas.map(...) off it, which throws an uncaught TypeError. The exception propagates out of the presence message handler, so the local state is never updated and onSync() never fires. Because the malicious key is tracked on the server, it is re-pushed on every presence update and keeps re-throwing, so presence sync stays broken for every viewer of that channel topic until the attacker leaves. Both syncState and syncDiff use the same unsafe existence-check pattern. The impact is limited to the affected topic and is a read-time confusion of the prototype object, not a mutation of Object.prototype (it is not prototype pollution). This issue affects phoenix: from 1.2.0-rc.0 before 1.5.15, from 1.6.0-rc.0 before 1.6.17, from 1.7.0-rc.0 before 1.7.24, and from 1.8.0-rc.0 before 1.8.9.

8 reference(s) · View on NVD →

SEC.co analysis · AI-assisted, reviewed against source

Technical summary

The vulnerability exists in phoenix/presence.js, specifically in the Presence.syncState and Presence.syncDiff functions. Both routines use a bare truthiness check (state[key]) to determine whether a presence record already exists, instead of employing an own-property check like hasOwnProperty(). When a client supplies an Object.prototype member name as a presence key—such as __proto__, constructor, toString, hasOwnProperty, valueOf, or similar—the lookup returns JavaScript's built-in Object.prototype rather than undefined. Because Object.prototype is truthy, the code treats it as an existing presence object and attempts to call .metas.map(...) on it, which throws an uncaught TypeError. This exception is never caught, preventing the local state from updating and onSync() from firing. Since the malicious key persists on the server and is re-broadcast on every presence update, it re-triggers the same error for every client, keeping presence sync broken. This is not prototype pollution (no mutation of Object.prototype occurs); it is a read-time confusion that exploits the prototype chain.

Business impact

Production applications using Phoenix presence for real-time features—such as collaborative tools, live dashboards, or multi-user sessions—become unusable for all channel viewers once exploited. The attack requires no authentication beyond channel join permissions, making it accessible to any user with legitimate access. For SaaS or multi-tenant platforms, a single malicious user can degrade service for an entire audience. The denial of service is complete and persistent, lasting until the attacker disconnects. This can damage user trust, interrupt critical workflows, and create support burden if the root cause is misdiagnosed as infrastructure failure.

Affected systems

Phoenix Framework versions 1.2.0-rc.0 through 1.5.14, 1.6.0-rc.0 through 1.6.16, 1.7.0-rc.0 through 1.7.23, and 1.8.0-rc.0 through 1.8.8 are vulnerable. Any application running these versions that exposes a Phoenix presence channel is at risk if it allows user-supplied data to influence presence keys. Applications that do not use presence channels are unaffected.

Exploitability

Exploitability is high. An attacker needs only ordinary channel access—no special privileges, no complex exploitation steps, no race conditions. The attack surface is broad: any application permitting user-controlled presence keys is vulnerable. Triggering the vulnerability requires only a single malicious presence join; no additional interaction or user behavior is needed. The attack is deterministic and immediately observable as a service outage. No patched client or special tools are required; a standard Phoenix client configured with a malicious key is sufficient.

Remediation

Upgrade to patched versions: 1.5.15 or later, 1.6.17 or later, 1.7.24 or later, or 1.8.9 or later. Applications should prioritize patching based on their current version branch. As an interim mitigation, restrict or validate presence key inputs on the server side to reject keys matching Object.prototype member names, though this is a defense-in-depth measure and not a substitute for patching.

Patch guidance

The Phoenix maintainers have released patched versions in all affected branches. Update your phoenix dependency to the earliest patched version in your current branch: versions 1.5.15, 1.6.17, 1.7.24, or 1.8.9 and later all contain the fix. Verify the patch by checking that presence.js includes an own-property check (such as Object.prototype.hasOwnProperty.call(state, key)) instead of a bare truthiness test. After patching, clear any cached client-side bundles and redeploy. Test presence functionality across your application, especially with edge-case usernames, before moving to production.

Detection guidance

Monitor for uncaught TypeErrors in browser consoles tied to presence operations, particularly 'Cannot read property metas of undefined' or similar prototype-related errors. Server-side, track presence key names; unusual keys matching Object.prototype methods (e.g., __proto__, constructor, toString) may indicate malicious joins. Log presence join attempts with suspicious keys and correlate them with client-side outages in the same channel. Presence sync breakage manifesting suddenly for all viewers of a topic is a strong indicator of this attack. Review application logs and analytics for unexpected drops in active presence counts.

Why prioritize this

This is a HIGH-severity vulnerability (CVSS 7.5) that is trivial to exploit and affects all Phoenix presence deployments without authentication barriers. The attack surface is broad—any user with channel access can exploit it—and the impact is immediate and disruptive. While not on the KEV list yet, the ease of exploitation and real-world impact to production systems make it a priority for any organization running affected Phoenix versions. The fix is straightforward and low-risk, supporting urgent patching.

Risk score, explained

CVSS 3.1 score of 7.5 reflects HIGH severity: no authentication required (PR:N), low complexity (AC:L), network-based attack (AV:N), no scope change (S:U), no confidentiality or integrity impact (C:N/I:N), but high availability impact (A:H). The vulnerability denies service to all viewers of a channel, satisfying high availability impact. The low barrier to exploitation and broad attack surface reinforce the need for rapid remediation.

Frequently asked questions

Does this vulnerability allow an attacker to modify or steal user data?

No. This is a denial-of-service vulnerability limited to breaking the presence synchronization mechanism. It does not allow unauthorized data access, mutation of Object.prototype, or persistence beyond the attacker's channel membership. Once the attacker leaves, presence sync resumes normally.

Can I work around this without patching?

A partial mitigation is to validate presence keys on the server before tracking them, rejecting keys that match Object.prototype member names. However, this is not a complete fix because the vulnerable client-side code still runs on existing users' browsers. Patching is the recommended solution.

Which versions of Phoenix are affected?

Affected versions are 1.2.0-rc.0 to 1.5.14, 1.6.0-rc.0 to 1.6.16, 1.7.0-rc.0 to 1.7.23, and 1.8.0-rc.0 to 1.8.8. Check your mix.exs or package.json to confirm your version. Patched versions are 1.5.15+, 1.6.17+, 1.7.24+, and 1.8.9+.

How long does the disruption last?

The presence sync remains broken for all channel viewers as long as the attacker stays in the channel. It recovers automatically when the attacker's presence expires or they explicitly leave, which can be within seconds to minutes depending on your timeout configuration.

This analysis is provided for informational purposes. Verify all version numbers and patch availability against official Phoenix Framework advisories before deploying. This vulnerability has not been added to the CISA KEV catalog as of publication. Organizations should conduct their own risk assessment based on their specific use of Phoenix presence features and user trust assumptions. No exploit code or proof-of-concept is provided; this summary is intended for defensive remediation planning only. Source: NVD (public-domain), retrieved 2026-08-16. Analysis generated by SEC.co (claude-haiku-4-5).