CVE-2026-32112: ha-mcp has XSS via Unescaped HTML in OAuth Consent Form
Summary The ha-mcp OAuth consent form renders user-controlled parameters via Python f-strings with no HTML escaping. An attacker who can reach the OAuth endpoint and convince the server operator to follow a crafted authorization URL could execute JavaScript in the operator's browser.
Published Mar 12, 2026
Affected packages
ha-mcp
- Ecosystem
- PyPI
- Affected
- < 7.0.0
- Fixed in
- 7.0.0
- Check
pip show ha-mcp
Advisory details
From the GitHub Advisory Database (CC BY 4.0).
Summary
The ha-mcp OAuth consent form renders user-controlled parameters via Python f-strings with no HTML escaping. An attacker who can reach the OAuth endpoint and convince the server operator to follow a crafted authorization URL could execute JavaScript in the operator's browser. This affects only users running the beta OAuth mode (ha-mcp-oauth), which is not part of the standard setup and requires explicit configuration.
Details
Unescaped f-string rendering
consent_form.py builds HTML using Python f-strings. No call to html.escape() exists anywhere in the file. The following values are rendered unescaped:
client_name/client_id— in HTML element context (lines 299, 303)client_id,redirect_uri,state— in HTML attribute context (lines 310–312), where a"character breaks out ofvalue=""error_message,error,error_description— in error display paths (lines 36–40, 496–497)
An attacker can register a client with a malicious client_name via the /register (DCR) endpoint, which accepts client_name without sanitization. If the server operator then visits a crafted authorization URL for that client, the payload executes in their browser.
Open Dynamic Client Registration
DCR is enabled by default with no initial access token required. This is intentional: Claude.ai and ChatGPT must self-register on first use, which is the standard MCP OAuth flow (RFC 7591). Requiring a pre-shared token would break those integrations. Registration alone grants no access — authorization requires an explicit action by the server operator.
Impact
Affected configuration: OAuth mode only (ha-mcp-oauth, requires MCP_BASE_URL). This mode is in beta and is not included in the main setup documentation. The vast majority of ha-mcp users run stdio mode, which is not affected.
Attack requirements:
- The attacker can reach the ha-mcp OAuth endpoint (it binds to
0.0.0.0in HTTP mode) - The attacker registers a malicious client via
/register - The attacker convinces the server operator — the person who set up ha-mcp — to follow a crafted authorization URL for an unrecognized application
Step 3 is a meaningful social engineering bar: the consent form displays the (unfamiliar) application name, and the operator has no legitimate reason to authorize an OAuth client they didn't initiate through Claude.ai or ChatGPT. Normal usage involves being redirected to the consent form from one of those platforms, not from an external link.
If exploited, a JavaScript payload could exfiltrate data entered into the consent form, including the Home Assistant Long-Lived Access Token.
Fix
Upgrade to 7.0.0
Credited to yotampe-pluto, julienld.
References
How this page is made: the data panel comes from the GitHub Advisory Database, CISA’s KEV catalog, the NVD and FIRST EPSS, and updates twice a day. No analysis has been written for this entry yet. Methodology
More Other MCP servers and tools vulnerabilities
All Other MCP servers and tools entriesCVE-2026-77361
obsidian-tc : Symlink read-ACL scope bypass via lexical path checks
medium4.7Oct 23, 2026CVE-2026-114126
Storybook dev server vulnerable to code injection from the local network
high8.7Oct 22, 2026CVE-2026-113731
djust: Arbitrary absolute-path file read in the find_handlers_for_template MCP tool
low3.3Oct 21, 2026CVE-2026-114125
Storybook: Missing origin validation in Storybook preview allows code injection from malicious websites
critical9.4Oct 21, 2026CVE-2026-111770
MCP TypeScript server SDK: Shared transport or server instances delivered one HTTP client's messages to another
high7.7Oct 20, 2026GHSA-953h-535j-jg2v
agent-router: MCP session resume does not verify the embedded anti-hijacking subject; default Helm seed makes session IDs forgeable
medium6.8Oct 19, 2026
