Back to Advisories

CVE-2026-27458 - Stored XSS in Atom Feed via CDATA Escape in List Description

Author and Researcher

Ravindu Wickramasinghe

Ravindu Wickramasinghe

@rvz

LinkAce Stored XSS via CDATA escape - JavaScript alert executing in browser

1. Description

LinkAce v2.4.2 is vulnerable to stored cross-site scripting through the Atom feed endpoint for lists (/lists/feed). An authenticated user can inject a CDATA-breaking payload into a list description that escapes the XML CDATA section, injects a native SVG element into the Atom XML document, and executes arbitrary JavaScript directly in the browser when the feed URL is visited. No RSS reader or additional rendering context is required - the browser's native XML parser processes the injected SVG and fires the onload event handler.

This vulnerability exists because the lists feed template outputs list descriptions using Blade's raw syntax ({!! !!}) without sanitization inside a CDATA block. The v2.4.0 release patched the equivalent links feed template with strip_tags(), but the lists feed was overlooked. The critical detail is that because the output sits inside <![CDATA[...]]>, an attacker can inject the sequence ]]> to close the CDATA section prematurely, then inject arbitrary XML/SVG elements that the browser parses and executes natively as part of the Atom document.

Affected versions: LinkAce <= v2.4.2
Patched version: 2.5.2

2. Source Code Analysis

In resources/views/app/feed/links.blade.php, line 17 (patched in v2.4.0):

terminal
summary type="text"    [CDATA[{ strip_tags($link->description) }]]summary

In resources/views/app/feed/lists.blade.php, line 16 (unpatched):

terminal
summary type="html"    [CDATA[{ $list->description }]]summary

When the payload is stored as a list description, the rendered Atom XML becomes:

terminal
<summary type="html">    <![CDATA[]]><svg xmlns="http://www.w3.org/2000/svg" onload="alert(document.domain)"/><![CDATA[]]></summary>

The browser's XML parser sees: an empty CDATA section (<![CDATA[]]>), followed by a valid SVG element with an onload handler, followed by another empty CDATA section. The SVG element is parsed as a first-class XML node and its onload fires immediately.

CDATA escape payload visible in Atom XML source

3. Steps to Reproduce

  1. Log in to LinkAce as any authenticated user.
  2. Create a new list or edit an existing one.
  3. Set the list visibility to "Internal" or "Public".
  4. In the description field, enter the following CDATA escape payload:
    terminal
    ]]><svg xmlns="http://www.w3.org/2000/svg" onload="alert(document.domain)"/><![CDATA[
  5. Save the list.
  6. Open a browser and navigate to /lists/feed.
  7. The browser renders the Atom XML natively. The injected SVG element breaks out of the CDATA section and the onload handler fires, displaying a JavaScript alert with the current domain.
  8. For comparison, create a link with the same payload in its description and access /links/feed - the links feed strips all HTML tags via strip_tags() and does not execute.

4. CVSS

CVSS 4.0 Score: 8.7 (High)

CVSS:4.0/AV:N/AC:L/AT:N/PR:L/UI:N/VC:H/VI:H/VA:L/SC:N/SI:N/SA:N

5. Recommendations

The list description output in the feed template must be sanitized to prevent CDATA escape. At minimum, apply strip_tags() to match the existing links feed fix, changing line 16 of resources/views/app/feed/lists.blade.php from {!! $list->description !!} to {!! strip_tags($list->description) !!}, and change the summary type attribute from html to text.

However, strip_tags() alone does not neutralize CDATA escape sequences. A more robust fix should also escape or remove the literal string ]]> from any user content rendered inside CDATA blocks, or use htmlspecialchars() to entity-encode the output entirely. A review of all Blade templates using raw output syntax {!! !!} with user-controlled data inside CDATA sections should be conducted to identify additional instances.

6. References