Contao discloses information in the news module
Description
Contao is an Open Source CMS. In versions starting from 5.0.0 and prior to 5.3.38 and 5.6.1, if a news feed contains protected news archives, their news items are not filtered and become publicly available in the RSS feed. This issue has been patched in versions 5.3.38 and 5.6.1. A workaround involves not adding protected news archives to the news feed page.
AI Insight
LLM-synthesized narrative grounded in this CVE's description and references.
Contao CMS fails to filter protected news archives from RSS feeds, exposing restricted news items publicly.
Vulnerability
The vulnerability lies in the news feed generation logic of Contao CMS. When an RSS feed includes protected news archives, the system does not filter out news items belonging to those archives, making them publicly accessible in the feed. This results in information disclosure of content that should be restricted.
Exploitation
An attacker can exploit this by simply accessing the RSS feed URL, which is typically publicly available. No authentication or user interaction is required. The attack only requires network access to the feed endpoint.
Impact
Successful exploitation leads to the exposure of confidential information from protected news archives. This could include sensitive announcements, articles, or other content that the site administrator intended to restrict to authorized users. The scope of disclosure depends on the content placed in protected archives.
Mitigation
The issue has been patched in Contao versions 5.3.38 and 5.6.1. As a workaround, administrators can avoid adding protected news archives to news feed pages. Users are strongly advised to update to the latest patched versions [1][4].
AI Insight generated on May 19, 2026. Synthesized from this CVE's description and the cited reference URLs; citations are validated against the source bundle.
Affected packages
Versions sourced from the GitHub Security Advisory.
| Package | Affected versions | Patched versions |
|---|---|---|
contao/core-bundlePackagist | >= 5.0.0-RC1, < 5.3.38 | 5.3.38 |
contao/core-bundlePackagist | >= 5.4.0-RC1, < 5.6.1 | 5.6.1 |
contao/contaoPackagist | >= 5.0.0-RC1, < 5.3.38 | 5.3.38 |
contao/contaoPackagist | >= 5.4.0-RC1, < 5.6.1 | 5.6.1 |
Affected products
2- Range: <5.3.38, <5.6.1
- contao/contaov5Range: >= 5.0.0-RC1, < 5.3.38
Patches
1e75f46b11974Merge commit from fork
3 files changed · +51 −5
news-bundle/config/services.yaml+1 −0 modified@@ -67,6 +67,7 @@ services: - '%kernel.project_dir%' - '@contao.cache.entity_tags' - '%kernel.charset%' + - '@security.helper' contao_news.listener.preview_url_convert: class: Contao\NewsBundle\EventListener\PreviewUrlConvertListener
news-bundle/src/EventListener/NewsFeedListener.php+26 −1 modified@@ -19,9 +19,11 @@ use Contao\CoreBundle\Image\ImageFactoryInterface; use Contao\CoreBundle\InsertTag\InsertTagParser; use Contao\CoreBundle\Routing\ContentUrlGenerator; +use Contao\CoreBundle\Security\ContaoCorePermissions; use Contao\Environment; use Contao\File; use Contao\FilesModel; +use Contao\NewsArchiveModel; use Contao\NewsBundle\Event\FetchArticlesForFeedEvent; use Contao\NewsBundle\Event\TransformArticleForFeedEvent; use Contao\NewsModel; @@ -35,6 +37,7 @@ use Symfony\Component\EventDispatcher\Attribute\AsEventListener; use Symfony\Component\Filesystem\Path; use Symfony\Component\Routing\Generator\UrlGeneratorInterface; +use Symfony\Component\Security\Core\Authorization\AuthorizationCheckerInterface; /** * @internal @@ -49,14 +52,15 @@ public function __construct( private readonly string $projectDir, private readonly EntityCacheTags $cacheTags, private readonly string $charset, + private readonly AuthorizationCheckerInterface $authorizationChecker, ) { } #[AsEventListener(FetchArticlesForFeedEvent::class)] public function onFetchArticlesForFeed(FetchArticlesForFeedEvent $event): void { $pageModel = $event->getPageModel(); - $archives = StringUtil::deserialize($pageModel->newsArchives, true); + $archives = $this->sortOutProtected(StringUtil::deserialize($pageModel->newsArchives, true)); $featured = match ($pageModel->feedFeatured) { 'featured' => true, @@ -197,4 +201,25 @@ private function getEnclosures(NewsModel $article, TransformArticleForFeedEvent return $enclosures; } + + /** + * @param list<int> $archiveIds + * + * @return list<int> + */ + private function sortOutProtected(array $archiveIds): array + { + $newsArchiveModel = $this->framework->getAdapter(NewsArchiveModel::class); + $allowedIds = []; + + foreach ($newsArchiveModel->findMultipleByIds($archiveIds) ?? [] as $archive) { + if ($archive->protected && !$this->authorizationChecker->isGranted(ContaoCorePermissions::MEMBER_IN_GROUPS, $archive->groups)) { + continue; + } + + $allowedIds[] = (int) $archive->id; + } + + return $allowedIds; + } }
news-bundle/tests/EventListener/NewsFeedListenerTest.php+24 −4 modified@@ -23,6 +23,7 @@ use Contao\FilesModel; use Contao\Image\ImageInterface; use Contao\Model\Collection; +use Contao\NewsArchiveModel; use Contao\NewsBundle\Event\FetchArticlesForFeedEvent; use Contao\NewsBundle\Event\TransformArticleForFeedEvent; use Contao\NewsBundle\EventListener\NewsFeedListener; @@ -38,6 +39,7 @@ use Symfony\Component\Filesystem\Path; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\Routing\Generator\UrlGeneratorInterface; +use Symfony\Component\Security\Core\Authorization\AuthorizationCheckerInterface; class NewsFeedListenerTest extends ContaoTestCase { @@ -57,6 +59,8 @@ public function testFetchesArticlesFromArchives(string $feedFeatured, bool|null $imageFactory = $this->createMock(ImageFactoryInterface::class); $cacheTags = $this->createMock(EntityCacheTags::class); $newsModel = $this->createMock(NewsModel::class); + $normalArchive = $this->mockClassWithProperties(NewsArchiveModel::class, ['id' => 1, 'protected' => 0]); + $protectedArchive = $this->mockClassWithProperties(NewsArchiveModel::class, ['id' => 2, 'protected' => 1]); $collection = $this->createMock(Collection::class); $collection @@ -73,20 +77,35 @@ public function testFetchesArticlesFromArchives(string $feedFeatured, bool|null ->willReturn($collection) ; - $framework = $this->mockContaoFramework([NewsModel::class => $newsAdapter]); + $newsArchiveAdapter = $this->mockAdapter(['findMultipleByIds']); + $newsArchiveAdapter + ->expects($this->once()) + ->method('findMultipleByIds') + ->with([1, 2]) + ->willReturn(new Collection([$normalArchive, $protectedArchive], 'tl_news_archive')) + ; + + $framework = $this->mockContaoFramework([NewsModel::class => $newsAdapter, NewsArchiveModel::class => $newsArchiveAdapter]); $feed = $this->createMock(Feed::class); $request = $this->createMock(Request::class); $urlGenerator = $this->createMock(ContentUrlGenerator::class); + $authorizationChecker = $this->createMock(AuthorizationCheckerInterface::class); + $authorizationChecker + ->expects($this->once()) + ->method('isGranted') + ->willReturn(false) + ; + $pageModel = $this->mockClassWithProperties(PageModel::class, [ - 'newsArchives' => serialize([1]), + 'newsArchives' => serialize([1, 2]), 'feedFeatured' => $feedFeatured, 'maxFeedItems' => 0, ]); $event = new FetchArticlesForFeedEvent($feed, $request, $pageModel); - $listener = new NewsFeedListener($framework, $imageFactory, $urlGenerator, $insertTags, $this->getTempDir(), $cacheTags, 'UTF-8'); + $listener = new NewsFeedListener($framework, $imageFactory, $urlGenerator, $insertTags, $this->getTempDir(), $cacheTags, 'UTF-8', $authorizationChecker); $listener->onFetchArticlesForFeed($event); $this->assertSame([$newsModel], $event->getArticles()); @@ -211,6 +230,7 @@ public function testTransformsArticlesToFeedItems(string $feedSource, array $hea $feed = $this->createMock(Feed::class); $cacheTags = $this->createMock(EntityCacheTags::class); + $authorizationChecker = $this->createMock(AuthorizationCheckerInterface::class); $urlGenerator = $this->createMock(ContentUrlGenerator::class); $urlGenerator @@ -229,7 +249,7 @@ public function testTransformsArticlesToFeedItems(string $feedSource, array $hea $baseUrl = 'example.org'; $event = new TransformArticleForFeedEvent($article, $feed, $pageModel, $request, $baseUrl); - $listener = new NewsFeedListener($framework, $imageFactory, $urlGenerator, $insertTags, $this->getTempDir(), $cacheTags, 'UTF-8'); + $listener = new NewsFeedListener($framework, $imageFactory, $urlGenerator, $insertTags, $this->getTempDir(), $cacheTags, 'UTF-8', $authorizationChecker); $listener->onTransformArticleForFeed($event); $item = $event->getItem();
Vulnerability mechanics
Generated on May 9, 2026. Inputs: CWE entries + fix-commit diffs from this CVE's patches. Citations validated against bundle.
References
5- github.com/advisories/GHSA-w53m-gxvg-vx7pghsaADVISORY
- nvd.nist.gov/vuln/detail/CVE-2025-57757ghsaADVISORY
- contao.org/en/security-advisories/information-disclosure-in-the-news-moduleghsax_refsource_MISCWEB
- github.com/contao/contao/commit/e75f46b11974fbf7a4652e65c19ad6ca84c59271ghsax_refsource_MISCWEB
- github.com/contao/contao/security/advisories/GHSA-w53m-gxvg-vx7pghsax_refsource_CONFIRMWEB
News mentions
0No linked articles in our index yet.