GHSA-87MG-5GRR-RHWH
Vulnerability from github – Published: 2026-09-24 19:59 – Updated: 2026-09-24 19:59Summary
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:
- Enumerate internal network services -- probe any IP/port on the internal network by observing response times and error messages
- Reach internal APIs -- access unauthenticated services inside the Docker/Kubernetes network (databases, caches, admin panels)
- 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) - 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
- Use
NoPrivateNetworkHttpClient-- wrap the injected HTTP client with Symfony's built-in SSRF protection before passing it to feedIo: ```php 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.
-
Validate URL scheme and host -- before calling
feedIo->read(), parse the URL and reject anything that is nothttp://orhttps://with a public routable IP or hostname. -
Configure the DCA field -- add
'rgxp' => 'url'and a custom validation callback totl_module.rss_feedto reject non-public URLs at save time.
{
"affected": [
{
"package": {
"ecosystem": "Packagist",
"name": "contao/contao"
},
"ranges": [
{
"events": [
{
"introduced": "5.3.35"
},
{
"fixed": "5.3.48"
}
],
"type": "ECOSYSTEM"
}
]
},
{
"package": {
"ecosystem": "Packagist",
"name": "contao/contao"
},
"ranges": [
{
"events": [
{
"introduced": "5.4.0"
},
{
"fixed": "5.7.9"
}
],
"type": "ECOSYSTEM"
}
]
},
{
"package": {
"ecosystem": "Packagist",
"name": "contao/core-bundle"
},
"ranges": [
{
"events": [
{
"introduced": "5.3.35"
},
{
"fixed": "5.3.48"
}
],
"type": "ECOSYSTEM"
}
]
},
{
"package": {
"ecosystem": "Packagist",
"name": "contao/core-bundle"
},
"ranges": [
{
"events": [
{
"introduced": "5.4.0"
},
{
"fixed": "5.7.9"
}
],
"type": "ECOSYSTEM"
}
]
}
],
"aliases": [
"CVE-2026-57232"
],
"database_specific": {
"cwe_ids": [
"CWE-918"
],
"github_reviewed": true,
"github_reviewed_at": "2026-09-24T19:59:16Z",
"nvd_published_at": "2026-07-31T19:17:11Z",
"severity": "LOW"
},
"details": "### Summary\n\nThe Feed Reader front-end module passes RSS feed URLs from its configuration directly to `$this-\u003efeedIo-\u003eread($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.\n\n---\n\n### Details\n\nIn `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:\n\n```php\n// Line 50-55\nforeach (StringUtil::trimsplit(\u0027[\\n\\t ]\u0027, trim($model-\u003erss_feed)) as $url) {\n try {\n $feed = $this-\u003ecache-\u003eget(\n \u0027feed_reader_\u0027.$model-\u003eid.\u0027_\u0027.md5($url),\n function (ItemInterface $item) use ($url, $model) {\n $readerResult = $this-\u003efeedIo-\u003eread($url, new Feed()); // \u003c-- no validation\n```\n\nThe DCA field definition for `rss_feed` in `tl_module.php` carries no URL scheme or host validation:\n```php\n\u0027eval\u0027 =\u003e array(\u0027mandatory\u0027=\u003etrue, \u0027decodeEntities\u0027=\u003etrue, \u0027style\u0027=\u003e\u0027height:60px\u0027)\n```\n\nThe HTTP client is wired as `@psr18.http_client` (Symfony HttpClient) with no SSRF protection configured (`NoPrivateNetworkHttpClient` is not used).\n\n---\n\n### Impact\n\nThis is a CWE-918 (SSRF) vulnerability. A backend user with module-edit access can:\n\n1. **Enumerate internal network services** -- probe any IP/port on the internal network by observing response times and error messages\n2. **Reach internal APIs** -- access unauthenticated services inside the Docker/Kubernetes network (databases, caches, admin panels)\n3. **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)\n4. **Pivot to internal infrastructure** -- use the server as a proxy to interact with services not exposed to the public internet\n\nConfirmed 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`).\n\n---\n\n### Remediation\n\n1. **Use `NoPrivateNetworkHttpClient`** -- wrap the injected HTTP client with Symfony\u0027s built-in SSRF protection before passing it to feedIo:\n ```php\n use Symfony\\Component\\HttpClient\\NoPrivateNetworkHttpClient;\n\n $safeClient = new NoPrivateNetworkHttpClient($this-\u003ehttpClient);\n ```\n This blocks all RFC-1918, loopback, and link-local addresses at the HTTP client level.\n\n2. **Validate URL scheme and host** -- before calling `feedIo-\u003eread()`, parse the URL and reject anything that is not `http://` or `https://` with a public routable IP or hostname.\n\n3. **Configure the DCA field** -- add `\u0027rgxp\u0027 =\u003e \u0027url\u0027` and a custom validation callback to `tl_module.rss_feed` to reject non-public URLs at save time.",
"id": "GHSA-87mg-5grr-rhwh",
"modified": "2026-09-24T19:59:16Z",
"published": "2026-09-24T19:59:16Z",
"references": [
{
"type": "WEB",
"url": "https://github.com/contao/contao/security/advisories/GHSA-87mg-5grr-rhwh"
},
{
"type": "ADVISORY",
"url": "https://nvd.nist.gov/vuln/detail/CVE-2026-57232"
},
{
"type": "WEB",
"url": "https://github.com/contao/contao/commit/27f6201809553bee767dcef15535bb8f0f4eac5f"
},
{
"type": "WEB",
"url": "https://github.com/contao/contao/commit/53b939ff2c4718e3a1d7c54ddd8886e9370618e4"
},
{
"type": "WEB",
"url": "https://contao.org/en/security-advisories/server-side-request-forgery-via-unvalidated-rss-feed-urls"
},
{
"type": "WEB",
"url": "https://github.com/FriendsOfPHP/security-advisories/blob/master/contao/contao/CVE-2026-57232.yaml"
},
{
"type": "WEB",
"url": "https://github.com/FriendsOfPHP/security-advisories/blob/master/contao/core-bundle/CVE-2026-57232.yaml"
},
{
"type": "PACKAGE",
"url": "https://github.com/contao/contao"
},
{
"type": "WEB",
"url": "https://github.com/contao/contao/releases/tag/5.3.48"
},
{
"type": "WEB",
"url": "https://github.com/contao/contao/releases/tag/5.7.9"
}
],
"schema_version": "1.4.0",
"severity": [
{
"score": "CVSS:3.1/AV:N/AC:H/PR:L/UI:N/S:U/C:L/I:N/A:N",
"type": "CVSS_V3"
}
],
"summary": "Contao: Server-Side Request Forgery (SSRF) via Unvalidated RSS Feed URL in Feed Reader Module"
}
Sightings
| Author | Source | Type | Date | Other |
|---|
Nomenclature
- Seen: The vulnerability was mentioned, discussed, or observed by the user.
- Confirmed: The vulnerability has been validated from an analyst's perspective.
- Published Proof of Concept: A public proof of concept is available for this vulnerability.
- Exploited: The vulnerability was observed as exploited by the user who reported the sighting.
- Patched: The vulnerability was observed as successfully patched by the user who reported the sighting.
- Not exploited: The vulnerability was not observed as exploited by the user who reported the sighting.
- Not confirmed: The user expressed doubt about the validity of the vulnerability.
- Not patched: The vulnerability was not observed as successfully patched by the user who reported the sighting.
The approach is described in our paper Mapping CVEs to MITRE ATT&CK Techniques: A Curated Gold-Set Classifier and the Limits of LLM-Assisted Label Expansion.
Browse all ATT&CK techniques and the vulnerabilities related to each.
Related by attack behaviour
Vulnerabilities whose description is nearest to this one in the vector space of the CIRCL/vulnerability-attack-technique-biencoder model. This is a similarity search over the bi-encoder space (plain cosine), not a classification, and it has no measured accuracy.