All vulnerabilities
CVE-2026-57232GHSA-87mg-5grr-rhwh

contao/contao: Contao: Server-Side Request Forgery (SSRF) via Unvalidated RSS Feed URL in Feed Reader Module

contao contao/contaocomposerLibraries & packages
CVSS
3.1Low
ExploitationNo known exploitationNot in CISA KEV, which does not prove it is unexploitedCISA KEV
Exploit odds (EPSS)0.29%Chance of exploitation activity in the next 30 days, higher than 20% of CVEs. Scored 23 Oct 2026FIRST EPSS
Fixed in5.3.48Also 5.7.9GitHub
Published31 Jul 2026Updated 24 Sep 2026CVE List

What fixes it

  • 5.3.48contao/contao, composerGitHubcomposer require "contao/contao:^5.3.48"
  • 5.7.9contao/contao, composerGitHubcomposer require "contao/contao:^5.7.9"
  • 5.3.48contao/core-bundle, composerGitHubcomposer require "contao/core-bundle:^5.3.48"
  • 5.7.9contao/core-bundle, composerGitHubcomposer require "contao/core-bundle:^5.7.9"
  • 5.3.48contao/contao, PackagistOSVcomposer require "contao/contao:^5.3.48"
  • 5.7.9contao/contao, PackagistOSVcomposer require "contao/contao:^5.7.9"
Show all 8 fixed versions
  • 5.3.48contao/core-bundle, PackagistOSVcomposer require "contao/core-bundle:^5.3.48"
  • 5.7.9contao/core-bundle, PackagistOSVcomposer require "contao/core-bundle:^5.7.9"

A fixed version on one release line is not the upgrade target for every line. Check your exact version and any vendor backports.

Description

Summary

The Feed Reader front-end module passes RSS feed URLs from its configuration directly to $this->feedIo->read($url) without any scheme validation or private-IP blocklist. A backend user with module-edit permissions can configure an arbitrary URL pointing to internal network services, cloud-provider metadata endpoints, or loopback addresses, causing the server to fetch those resources unconditionally. Confirmed live: the server successfully reaches the internal MySQL database container and its own loopback Apache instance.

---

Details

In core-bundle/src/Controller/FrontendModule/FeedReaderController.php, the getResponse() function iterates over the configured feed URLs and passes each one directly to the HTTP client with no validation:

// Line 50-55
foreach (StringUtil::trimsplit('[\n\t ]', trim($model->rss_feed)) as $url) {
    try {
        $feed = $this->cache->get(
            'feed_reader_'.$model->id.'_'.md5($url),
            function (ItemInterface $item) use ($url, $model) {
                $readerResult = $this->feedIo->read($url, new Feed()); // <-- no validation

The DCA field definition for rss_feed in tl_module.php carries no URL scheme or host validation:

'eval' => array('mandatory'=>true, 'decodeEntities'=>true, 'style'=>'height:60px')

The HTTP client is wired as @psr18.http_client (Symfony HttpClient) with no SSRF protection configured (NoPrivateNetworkHttpClient is not used).

---

Impact

This is a CWE-918 (SSRF) vulnerability. A backend user with module-edit access can:

  1. Enumerate internal network services -- probe any IP/port on the internal network by observing response times and error messages
  2. Reach internal APIs -- access unauthenticated services inside the Docker/Kubernetes network (databases, caches, admin panels)
  3. Steal cloud metadata credentials -- on AWS, fetch http://169.254.169.254/latest/meta-data/iam/security-credentials/ to obtain IAM role credentials (IMDSv1 has no authentication)
  4. Pivot to internal infrastructure -- use the server as a proxy to interact with services not exposed to the public internet

Confirmed in live testing: the server successfully connected to the internal MySQL container (172.19.0.3:3306) and retrieved a full HTTP response from its own loopback interface (127.0.0.1:80).

---

Remediation

  1. **Use NoPrivateNetworkHttpClient** -- wrap the injected HTTP client with Symfony's built-in SSRF protection before passing it to feedIo:
   use Symfony\Component\HttpClient\NoPrivateNetworkHttpClient;

   $safeClient = new NoPrivateNetworkHttpClient($this->httpClient);

This blocks all RFC-1918, loopback, and link-local addresses at the HTTP client level.

  1. Validate URL scheme and host -- before calling feedIo->read(), parse the URL and reject anything that is not http:// or https:// with a public routable IP or hostname.
  1. Configure the DCA field -- add 'rgxp' => 'url' and a custom validation callback to tl_module.rss_feed to reject non-public URLs at save time.

Text from GitHub Advisory Database

Affected versions 136

  • contao/contao, composer>= 5.3.35, < 5.3.48GitHub
  • contao/contao, composer>= 5.4.0, < 5.7.9GitHub
  • contao/core-bundle, composer>= 5.3.35, < 5.3.48GitHub
  • contao/core-bundle, composer>= 5.4.0, < 5.7.9GitHub
  • contaoaffected: >= 5.7.0-RC1, < 5.7.9CVE List
  • contaoaffected: >= 5.3.35, < 5.3.48CVE List
  • contao/contao, Packagistfrom 5.3.35, fixed in 5.3.48OSV
  • contao/contao, Packagist5.3.35OSV
  • contao/contao, Packagist5.3.36OSV
  • contao/contao, Packagist5.3.37OSV
  • contao/contao, Packagist5.3.38OSV
  • contao/contao, Packagist5.3.39OSV
  • contao/contao, Packagist5.3.40OSV
  • contao/contao, Packagist5.3.41OSV
  • contao/contao, Packagist5.3.42OSV
  • contao/contao, Packagist5.3.43OSV
  • contao/contao, Packagist5.3.44OSV
  • contao/contao, Packagist5.3.45OSV
  • contao/contao, Packagist5.3.46OSV
  • contao/contao, Packagist5.3.47OSV
  • contao/contao, Packagistfrom 5.4.0, fixed in 5.7.9OSV
  • contao/contao, Packagist5.4.0OSV
  • contao/contao, Packagist5.4.1OSV
  • contao/contao, Packagist5.4.10OSV
  • contao/contao, Packagist5.4.11OSV
  • contao/contao, Packagist5.4.12OSV
  • contao/contao, Packagist5.4.13OSV
  • contao/contao, Packagist5.4.14OSV
  • contao/contao, Packagist5.4.2OSV
  • contao/contao, Packagist5.4.3OSV
  • contao/contao, Packagist5.4.4OSV
  • contao/contao, Packagist5.4.5OSV
  • contao/contao, Packagist5.4.6OSV
  • contao/contao, Packagist5.4.7OSV
  • contao/contao, Packagist5.4.8OSV
  • contao/contao, Packagist5.4.9OSV
  • contao/contao, Packagist5.5.0OSV
  • contao/contao, Packagist5.5.0-RC1OSV
  • contao/contao, Packagist5.5.0-RC2OSV
  • contao/contao, Packagist5.5.0-RC3OSV
  • contao/contao, Packagist5.5.0-RC4OSV
  • contao/contao, Packagist5.5.1OSV
  • contao/contao, Packagist5.5.10OSV
  • contao/contao, Packagist5.5.11OSV
  • contao/contao, Packagist5.5.12OSV
  • contao/contao, Packagist5.5.13OSV
  • contao/contao, Packagist5.5.14OSV
  • contao/contao, Packagist5.5.15OSV
  • contao/contao, Packagist5.5.16OSV
  • contao/contao, Packagist5.5.2OSV
  • contao/contao, Packagist5.5.3OSV
  • contao/contao, Packagist5.5.4OSV
  • contao/contao, Packagist5.5.5OSV
  • contao/contao, Packagist5.5.6OSV
  • contao/contao, Packagist5.5.7OSV
  • contao/contao, Packagist5.5.8OSV
  • contao/contao, Packagist5.5.9OSV
  • contao/contao, Packagist5.6.0OSV
  • contao/contao, Packagist5.6.0-RC1OSV
  • contao/contao, Packagist5.6.0-RC2OSV
  • contao/contao, Packagist5.6.0-RC3OSV
  • contao/contao, Packagist5.6.1OSV
  • contao/contao, Packagist5.6.10OSV
  • contao/contao, Packagist5.6.11OSV
  • contao/contao, Packagist5.6.2OSV
  • contao/contao, Packagist5.6.3OSV
  • contao/contao, Packagist5.6.4OSV
  • contao/contao, Packagist5.6.5OSV
  • contao/contao, Packagist5.6.6OSV
  • contao/contao, Packagist5.6.7OSV
  • contao/contao, Packagist5.6.8OSV
  • contao/core-bundle, Packagistfrom 5.3.35, fixed in 5.3.48OSV
  • contao/core-bundle, Packagist5.3.35OSV
  • contao/core-bundle, Packagist5.3.36OSV
  • contao/core-bundle, Packagist5.3.37OSV
  • contao/core-bundle, Packagist5.3.38OSV
  • contao/core-bundle, Packagist5.3.39OSV
  • contao/core-bundle, Packagist5.3.40OSV
  • contao/core-bundle, Packagist5.3.41OSV
  • contao/core-bundle, Packagist5.3.42OSV
  • contao/core-bundle, Packagist5.3.43OSV
  • contao/core-bundle, Packagist5.3.44OSV
  • contao/core-bundle, Packagist5.3.45OSV
  • contao/core-bundle, Packagist5.3.46OSV
  • contao/core-bundle, Packagist5.3.47OSV
  • contao/core-bundle, Packagistfrom 5.4.0, fixed in 5.7.9OSV
  • contao/core-bundle, Packagist5.4.0OSV
  • contao/core-bundle, Packagist5.4.1OSV
  • contao/core-bundle, Packagist5.4.10OSV
  • contao/core-bundle, Packagist5.4.11OSV
  • contao/core-bundle, Packagist5.4.12OSV
  • contao/core-bundle, Packagist5.4.13OSV
  • contao/core-bundle, Packagist5.4.14OSV
  • contao/core-bundle, Packagist5.4.2OSV
  • contao/core-bundle, Packagist5.4.3OSV
  • contao/core-bundle, Packagist5.4.4OSV
  • contao/core-bundle, Packagist5.4.5OSV
  • contao/core-bundle, Packagist5.4.6OSV
  • contao/core-bundle, Packagist5.4.7OSV
  • contao/core-bundle, Packagist5.4.8OSV
  • contao/core-bundle, Packagist5.4.9OSV
  • contao/core-bundle, Packagist5.5.0OSV
  • contao/core-bundle, Packagist5.5.0-RC1OSV
  • contao/core-bundle, Packagist5.5.0-RC2OSV
  • contao/core-bundle, Packagist5.5.0-RC3OSV
  • contao/core-bundle, Packagist5.5.0-RC4OSV
  • contao/core-bundle, Packagist5.5.1OSV
  • contao/core-bundle, Packagist5.5.10OSV
  • contao/core-bundle, Packagist5.5.11OSV
  • contao/core-bundle, Packagist5.5.12OSV
  • contao/core-bundle, Packagist5.5.13OSV
  • contao/core-bundle, Packagist5.5.14OSV
  • contao/core-bundle, Packagist5.5.15OSV
  • contao/core-bundle, Packagist5.5.16OSV
  • contao/core-bundle, Packagist5.5.2OSV
  • contao/core-bundle, Packagist5.5.3OSV
  • contao/core-bundle, Packagist5.5.4OSV
  • contao/core-bundle, Packagist5.5.5OSV
  • contao/core-bundle, Packagist5.5.6OSV
  • contao/core-bundle, Packagist5.5.7OSV
  • contao/core-bundle, Packagist5.5.8OSV
  • contao/core-bundle, Packagist5.5.9OSV
  • contao/core-bundle, Packagist5.6.0OSV
  • contao/core-bundle, Packagist5.6.0-RC1OSV
  • contao/core-bundle, Packagist5.6.0-RC2OSV
  • contao/core-bundle, Packagist5.6.0-RC3OSV
  • contao/core-bundle, Packagist5.6.1OSV
  • contao/core-bundle, Packagist5.6.10OSV
  • contao/core-bundle, Packagist5.6.11OSV
  • contao/core-bundle, Packagist5.6.2OSV
  • contao/core-bundle, Packagist5.6.3OSV
  • contao/core-bundle, Packagist5.6.4OSV
  • contao/core-bundle, Packagist5.6.5OSV
  • contao/core-bundle, Packagist5.6.6OSV
  • contao/core-bundle, Packagist5.6.7OSV
  • contao/core-bundle, Packagist5.6.8OSV

References 10