Summary
The Plugin editor can execute attacker-controlled HTML/JS when loading an external OpenAPI schema URL.
loadFromUrl() fetches a remote schema and stores the raw schema string in plugin.content. The plugin title is then extracted from definition.info.title. In the edit modal, the same schema content is rendered with dangerouslySetInnerHTML, so HTML placed in fields such as info.title is parsed by the browser instead of being displayed as plain code.
Affected Code
app/components/plugin.tsx
loadFromUrl() fetches remote schema content and updates plugin.content: lines 88-117
- plugin title itself is displayed safely via React text rendering: lines 195-202
- vulnerable sink:
dangerouslySetInnerHTML={{ __html: editingPlugin.content }}: lines 345-351
app/store/plugin.ts
- parses plugin content via
yaml.load(plugin.content): lines 55, 71-72
- stores built-in plugin schema content and sets
plugin.title from definition.info.title: lines 239-264
Reproduction
- Host the following OpenAPI schema as JSON:
{
"openapi": "3.0.0",
"info": {
"title": "<img src=x onerror=alert('nextchat-plugin-title-xss')>",
"version": "1.0.0"
},
"servers": [
{ "url": "https://example.com" }
],
"paths": {
"/ping": {
"get": {
"operationId": "ping",
"responses": {
"200": { "description": "ok" }
}
}
}
}
}
- Open the NextChat Plugin page.
- Create or edit a plugin.
- Paste the hosted schema URL into the Content URL field.
- Click Load.
- The schema content is rendered through
dangerouslySetInnerHTML, and the payload inside info.title executes.
Expected Behavior
The OpenAPI schema should be displayed as plain text/code only. HTML inside schema fields such as info.title, info.version, summary, or description should never be parsed as DOM.
Actual Behavior
The schema content is inserted as HTML via dangerouslySetInnerHTML, allowing attacker-controlled schema content to execute script in the NextChat origin.
Security Impact
This is a DOM-based / stored client-side XSS issue.
An attacker who convinces a user to load a malicious plugin schema URL may execute JavaScript in the NextChat origin. Depending on deployment and stored settings, this may allow access to browser-side persisted data such as local settings, plugin auth tokens, custom endpoints, access codes, and API keys stored in local storage or IndexedDB.
- CWE: CWE-79
- Tentative severity: High
- User interaction is required because the victim must load a malicious plugin schema.
Suggested Fix
Avoid dangerouslySetInnerHTML for schema display.
For example:
<code contentEditable={true} onBlur={onChangePlugin}>
{editingPlugin.content}
</code>
A safer long-term approach would be to use a controlled textarea or code editor component and treat schema content strictly as text.
Additional hardening:
- Validate
definition.info.title and definition.info.version as plain strings.
- Apply length limits to plugin metadata fields.
- Ensure all schema-derived UI fields are rendered only as React text nodes.
- Consider allowlisting or integrity checks for built-in plugin schema sources.
CVE Request
I would like to request CVE assignment for this vulnerability if the maintainers confirm it as a valid security issue
Summary
The Plugin editor can execute attacker-controlled HTML/JS when loading an external OpenAPI schema URL.
loadFromUrl()fetches a remote schema and stores the raw schema string inplugin.content. The plugin title is then extracted fromdefinition.info.title. In the edit modal, the same schema content is rendered withdangerouslySetInnerHTML, so HTML placed in fields such asinfo.titleis parsed by the browser instead of being displayed as plain code.Affected Code
app/components/plugin.tsxloadFromUrl()fetches remote schema content and updatesplugin.content: lines 88-117dangerouslySetInnerHTML={{ __html: editingPlugin.content }}: lines 345-351app/store/plugin.tsyaml.load(plugin.content): lines 55, 71-72plugin.titlefromdefinition.info.title: lines 239-264Reproduction
{ "openapi": "3.0.0", "info": { "title": "<img src=x onerror=alert('nextchat-plugin-title-xss')>", "version": "1.0.0" }, "servers": [ { "url": "https://example.com" } ], "paths": { "/ping": { "get": { "operationId": "ping", "responses": { "200": { "description": "ok" } } } } } }dangerouslySetInnerHTML, and the payload insideinfo.titleexecutes.Expected Behavior
The OpenAPI schema should be displayed as plain text/code only. HTML inside schema fields such as
info.title,info.version,summary, ordescriptionshould never be parsed as DOM.Actual Behavior
The schema content is inserted as HTML via
dangerouslySetInnerHTML, allowing attacker-controlled schema content to execute script in the NextChat origin.Security Impact
This is a DOM-based / stored client-side XSS issue.
An attacker who convinces a user to load a malicious plugin schema URL may execute JavaScript in the NextChat origin. Depending on deployment and stored settings, this may allow access to browser-side persisted data such as local settings, plugin auth tokens, custom endpoints, access codes, and API keys stored in local storage or IndexedDB.
Suggested Fix
Avoid
dangerouslySetInnerHTMLfor schema display.For example:
A safer long-term approach would be to use a controlled
textareaor code editor component and treat schema content strictly as text.Additional hardening:
definition.info.titleanddefinition.info.versionas plain strings.CVE Request
I would like to request CVE assignment for this vulnerability if the maintainers confirm it as a valid security issue