Skip to content

Stored XSS in Kaizen mandate preview (dangerouslySetInnerHTML without escaping) #8

Description

@wstlima

frontend/src/pages/Kaizen.tsx's renderMarkdown() (used for the agent "mandate" preview via dangerouslySetInnerHTML, line 357) applies regex-based markdown substitutions directly to raw user-editable text, without escaping HTML first. The mandate field is user-editable free text (the agent's behavioral directive, edited on the same page) and is rendered as HTML whenever "Preview" is toggled.

Impact

Stored XSS. Any mandate value containing raw HTML/script (e.g. <img src=x onerror=alert(1)>), whether entered directly in the UI or written via the API by an integration/compromised agent, executes in the browser of anyone who opens the Preview tab for that mandate.

Fix

Escape HTML special characters (&, <, >, ", ') before applying the markdown-to-HTML regex substitutions, so any embedded tags render as literal text instead of being interpreted as markup. This preserves all existing markdown formatting (headers, bold, italic, lists, hr, line breaks) since escaping runs before those regexes and none of them rely on raw angle brackets from the input.

Purely a client-side rendering fix — no backend change needed.

Tested fix, ready as a PR if useful: wstlima@a4768e4

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions