high · 8.7CVE-2026-55839Aug 18, 2026

CVE-2026-55839: Kestra Stored XSS via Custom Markdown [[link]] Attribute Injection

Pranav Khune
Penetration Testing Team Lead, SecureLayer7

A flaw in Kestra's custom Markdown renderer lets anyone who can write a Flow description inject JavaScript event handlers that execute in other users' browsers.

Packageio.kestra:kestra
Ecosystemmaven
Affected< 1.3.24
Fixed in1.3.24
CVE-2026-55839: Kestra Stored XSS via Custom Markdown [[link]] Attribute Injection

The problem

Kestra's Markdown renderer supports a custom [[link ...]] syntax that is converted into a <router-md> HTML element. The plugin in ui/src/utils/markdown_plugins/link.ts maps every parsed token attribute directly into the generated HTML string with no allowlist and no sanitization.

Any user who can create or edit a Flow can store a malicious payload in the Flow description field. When a second user opens the Flow list and views the description panel, the stored JavaScript runs in their browser under that user's session.

Proof of concept

A working proof-of-concept for CVE-2026-55839 in io.kestra:kestra, with the exact payload below.

text
[[link x="y" style="position:fixed;inset:0;z-index:9999;background:rgba(255,0,0,0.05)" onmouseover="alert(document.domain)"]]

The vulnerable code path is straightforward. The renderer does token.attrs.map(([name, value]) => name+"="+value).join("") and drops the result raw into <router-md ${attrs}>. Nothing filters attribute names beginning with on, nothing rejects style, and nothing HTML-escapes values before the string reaches v-html.

The patch at commit 6c8e6d0 (v1.3.24) introduces an attribute allowlist so only the specific properties the router-md component actually needs are ever emitted. Arbitrary attributes, including all on* event handlers and style, are silently dropped before the HTML string is built.

This is CWE-79: unsanitized attacker input reflected into a rendered HTML context.

The fix

Upgrade to Kestra v1.3.24 or later. The fix is in commit 6c8e6d099ed172cbb6b003b7fb30b7bb1f8f710e: the [[link]] Markdown plugin now allowlists only the attributes the router component requires, rejects all on* event-handler attributes, rejects style, and HTML-escapes all attribute values before building the output string.

No workaround exists in older versions short of restricting Flow create/edit permissions to fully trusted users.

Reporter not attributed.

References: [1][2][3][4]

Related research