Sep 22, 2026·5 min read·19 visits
Unescaped entity friendly names in Home Assistant Statistics Graph tooltips allow DOM-based XSS, leading to potential administrative session hijacking.
CVE-2026-91130 is a critical DOM-based Cross-Site Scripting (XSS) vulnerability in the Home Assistant open-source home automation platform. Prior to version 2026.7.0, the Statistics Graph card rendered series tooltips using raw HTML string interpolation without escaping user-controlled entity friendly names. By abusing this vulnerability, an authenticated user with low-privilege access can inject arbitrary HTML and JavaScript into entity name fields, which executes in the context of an administrative user's browser session upon hovering over a data point on an affected chart.
The Home Assistant web-based user interface relies on several custom UI cards to display real-time sensor metrics and state changes. Within this interface, the Statistics Graph card allows users to visualize historical data such as temperature, power consumption, and device metrics using the third-party Apache ECharts visualization library.\n\nBecause the Home Assistant backend utilizes a dynamic state machine, the names and friendly labels of individual entities are passed directly from backend components to the frontend visualization cards. This establishes a communication channel between backend databases, user inputs, external integration components, and the administrative dashboard.\n\nPrior to the release of version 2026.7.0, the Statistics Graph card rendered tooltips using raw string values without sanitizing individual metadata fields. This structural oversight created a DOM-based Cross-Site Scripting vulnerability, where unauthenticated or low-privileged actors can execute malicious client-side code inside the security context of other users.
The technical root cause of CVE-2026-91130 lies in the custom tooltip formatter callback assigned to the Apache ECharts instance within src/components/chart/statistics-chart.ts. The formatter function was programmed to return a raw string containing HTML markup that represented the data point series name and value.\n\nWhen ECharts processes a custom formatter that returns a raw string, it writes the string directly to the DOM using a sink that evaluates HTML markup. Since the formatter used a template literal to interpolate the param.seriesName parameter, any HTML sequence embedded in the entity friendly name is directly executed by the browser rendering engine.\n\nThis behavior bypasses standard frontend input filters because the entity name is retrieved directly from the state history store. The state history data is populated by backend processes, which trust state modifications submitted via local integrations, external API requests, or user customization utilities.
The vulnerable implementation in the frontend codebase relied on string interpolation to build the HTML string structure that was returned to the charting component.\n\ntypescript\n// Vulnerable string-based tooltip formatter\nconst rawTime = formatDateTimeWithSeconds(startTime, this.hass.locale, this.hass.config);\nconst time = index === 0 ? rawTime : \"\";\nreturn `${time}${param.marker} ${param.seriesName}: ${value}`;\n\n\nThe patched version replaces the raw string interpolation logic entirely by transitioning the tooltip formatting pipeline to use Lit templates, ensuring that variables are automatically escaped.\n\ntypescript\n// Secure Lit-based tooltip formatting implementation\nreturn html`${rows.map(\n (row, i) =>\n html`${row.time\n ? html`${row.time}<br />`\n : nothing}<ha-chart-tooltip-marker\n .color=${row.color}\n ></ha-chart-tooltip-marker>\n ${row.seriesName}:\n ${row.value}${i < rows.length - 1 ? html`<br />` : nothing}`\n)}`;\n\n\nBy passing a custom Web Component <ha-chart-tooltip-marker> and evaluating structural variables through Lit templates, the application enforces compile-time sanitization. The row.seriesName variable is handled strictly as text, rendering any embedded HTML entities harmlessly without script evaluation.
To exploit this vulnerability, an attacker requires low-privileged administrative access or control over a connected device integration to update an entity's metadata attributes. This is commonly achieved by submitting a state change to the Home Assistant REST API or modifying the core registry files.\n\nbash\ncurl -X POST \\\n -H \"Authorization: Bearer <Attacker_Token>\" \\\n -H \"Content-Type: application/json\" \\\n -d '{\"state\": \"22.5\", \"attributes\": {\"friendly_name\": \"<img src=x onerror=alert(document.domain)>\", \"state_class\": \"measurement\"}}' \\\n http://homeassistant.local:8123/api/states/sensor.vulnerable_sensor\n\n\nmermaid\ngraph LR\n A[\"Attacker Payload\"] --> B[\"API / State Registry\"]\n B --> C[\"ECharts Tooltip Component\"]\n C --> D[\"Victim Browser DOM\"]\n\n\nOnce the payload is successfully injected into the entity registry database, the attacker waits for an administrative viewer to inspect the Lovelace dashboard containing a Statistics Graph card tracking the affected entity. The moment the administrator hovers over a data point, ECharts executes the callback formatter, inserts the payload into the browser DOM, and executes the script context.
A successful exploitation of CVE-2026-91130 leads to a complete compromise of the victim's frontend browser session. Because Home Assistant utilizes active session cookies and local storage tokens to maintain administrative access, the executed payload has complete read and write authority under the administrator's profile.\n\nAn attacker can construct client-side scripts to steal the long-lived access tokens stored in browser LocalStorage. These stolen tokens allow the attacker to issue API commands remotely, control physical smart home locks, disable cameras, modify alarm configurations, or trigger internal automation events.\n\nIn environments where shell commands or command-line integrations are enabled, administrative access can be leveraged to execute shell tools. This elevates the local client-side vulnerability to remote command execution on the host operating system running the Home Assistant Core container.
Remediation requires upgrading the Home Assistant Core installation to version 2026.7.0 or higher. This upgrade replaces the vulnerable frontend component code with the secure Lit-based rendering template library.\n\nIf an immediate upgrade is not feasible, administrators should restrict dashboard configuration permissions to trusted roles and limit the use of custom integrations. Additionally, the existing configuration files and integration state database should be audited regularly to ensure no raw HTML payloads are embedded within entity friendly names.\n\nTo identify potential active payload indicators within the local state database, administrators can run the following SQL command against the SQLite state file.\n\nsql\nSELECT entity_id, attributes FROM states \nWHERE attributes LIKE '%<script%' \n OR attributes LIKE '%onerror%' \n OR attributes LIKE '%onload%';\n
| Product | Affected Versions | Fixed Version |
|---|---|---|
Home Assistant Core Home Assistant | < 2026.7.0 | 2026.7.0 |
| Attribute | Detail |
|---|---|
| CWE ID | CWE-80 |
| Attack Vector | Network (AV:N) |
| CVSS v4.0 Score | 9.3 (Critical) |
| Required Privilege | Low (PR:L) |
| User Interaction | Active (UI:A) |
| Exploit Status | Proof-of-Concept |
| KEV Status | Not Listed |
GeoNode versions prior to 5.0.3 contain an unrestricted file upload vulnerability (CWE-434) within the document and dataset ingestion architecture. Authenticated low-privileged users can bypass upload validation via direct REST API interactions, file extension masquerading, metadata mutation via PATCH requests, or malicious archive submissions. This allows attackers to store and serve dangerous file types, alter on-disk file references, or trigger path traversal and resource exhaustion during archive extraction.
CVE-2026-55649 is a stored Cross-Site Scripting (XSS) vulnerability in GeoNode versions prior to 5.0.3. The flaw exists because document abstract metadata fields are ingested via the metadata management pipeline and stored in the backend database without HTML sanitization or input neutralization. An authenticated attacker with privileges to create or edit document metadata can inject arbitrary HTML and JavaScript payloads into these fields. When another user, such as an administrator, views the affected document page or catalog listing, the unencoded payload is rendered into the Document Object Model (DOM) and executes within the victim's browser session.
CVE-2026-55622 (GHSA-qx75-2p3r-pwm5) is an improper access control vulnerability (CWE-284) in Canonical LXD and LXC Incus (tracked as GHSA-c9f5-j9c3-mhrg). In multi-tenant deployments utilizing project-based isolation, the REST API handler for instance creation via POST /1.0/instances verifies that the authenticated user has authorization in the destination project specified by the query parameter, but fails to verify whether the user holds read or view permissions for the source instance when executing a copy operation across projects. Consequently, an authenticated client restricted to a single project can clone instances or snapshots from unauthorized projects into their own project, resulting in complete disclosure of the target instance filesystem and embedded credentials.
An authorization bypass vulnerability in Canonical LXD (tracked as GHSA-7mr3-28h5-m5vx and CVE-2026-55621, and as GHSA-64f3-v33m-w89f in Linux Containers Incus) allows an authenticated user with restricted project access to copy custom storage volumes and volume snapshots from unauthorized projects. The flaw resides in the storagePoolVolumesPost REST API handler, which verifies permissions on the destination project but fails to check whether the caller holds view entitlements on the source project or volume specified in the request body.
A missing authorization and configuration validation vulnerability in Canonical LXD and LXC Incus allows authenticated users within restricted projects to bypass project security boundaries. By smuggling prohibited low-level configuration directives (such as raw.lxc or raw.qemu) inside instance snapshots or backup archives, an attacker can restore these configurations within a restricted project and execute arbitrary commands with root privileges on the underlying host operating system.
A symbolic link traversal vulnerability (CWE-59) in Canonical LXD and Linux Containers Incus allows an authenticated user with image import permissions to read and write arbitrary files on the host filesystem. During image archive unpacking, the daemon fails to reject top-level symbolic links for the instance `templates` directory. Subsequent requests to the instance template API endpoints follow this symbolic link outside the instance storage directory with root privileges, enabling complete host compromise.