GHSA-5974-gfqc-wrcm CVE-2026-107851
Contao: Improper access control in the table access voter
- Severity
- 4.3 / 10
- Medium · CVSS 3.1
- Exploit chance (EPSS)
- 0.19%
- Chance of exploitation in the next 30 days. Higher than 9.03% of scored vulnerabilities.
- Known exploited
- No
- Not in CISA's catalog
- Fix
5.7.12- Upgrade contao/core-bundle to this version or later
Description
Due to a caching defect in the security voter that governs table-level access to Contao's Data Container (DCA) backend, a low-privileged, non-admin backend user can obtain unauthorized read, create, update, and delete access to database tables outside their assigned module permissions. This includes tables containing sensitive personal data, such as frontend member records and newsletter subscriber e-mail addresses.
Vulnerability Details
In plain terms: Contao's backend is organized into modules (e.g. "News", "Members"). Every backend user is assigned to a group, and that group decides which modules, and therefore which database tables, they are allowed to work with. Before Contao lets a user touch a table, it is supposed to check: "does this user's group actually include this table?"
To avoid doing that check over and over, Contao remembers the answer for the rest of the request. The problem is that it remembers the answer under the wrong label. Instead of remembering "is this user allowed to access table X", it only remembers "is this user allowed to access something", without recording which table the answer was actually about.
So if a request first checks a table the user IS allowed to see, and then checks a second, completely different table the user is NOT allowed to see, Contao reuses the first answer for the second table too. The user ends up with access to a table their group was never given permission for.
Technical detail
Contao's backend enforces per-table access control through a chain of Symfony security voters. The relevant one is
TableAccessVoter::hasAccessToModule(), in core-bundle/src/Security/Voter/DataContainer/TableAccessVoter.php:
private array $canAccessTable = [];
private array $canReadAccessTable = [];
private function hasAccessToModule(TokenInterface $token, ...): bool
{
$tokenHash = hash('xxh128', serialize($token));
if (isset($this->canAccessTable[$tokenHash]) || (...)) {
return $this->canAccessTable[$tokenHash] ?? $this->canReadAccessTable[$tokenHash];
}
$table = $subject->getDataSource();
foreach ($GLOBALS['BE_MOD'] as $modules) {
...
return $this->canAccessTable[$tokenHash] = true; // or false
}
}
The cache key, $tokenHash, is built only from the current user's security token. It does not include the table being checked. Because TableAccessVoter is a normal, shared Symfony service, this cache stays alive for the whole duration of one HTTP request. So the first table checked for a user in a request decides the cached answer for every other table checked afterwards in that same request, whether or not that answer is actually correct for the second table.
This is made worse by DefaultDataContainerVoter, a low-priority, permissive fallback voter that grants access to any table-related permission unless another voter explicitly denies it. When TableAccessVoter gives a wrong "no opinion" answer because of the stale cache, this fallback voter turns that into a full grant.
Most database tables in Contao have no second, table-specific check to catch this. Only tl_content, tl_favorites, tl_form, tl_form_field, tl_module, tl_image_size(_item), tl_job, tl_layout, tl_page, tl_preview_link, tl_undo, and tl_user have one. Tables such as tl_member (website member data), tl_newsletter_recipients (subscriber e-mail addresses), tl_news, tl_calendar_events, tl_faq, and tl_comments rely only on the defective check described above.
Credits
This security vulnerability was found by Sven Jäger of SySS GmbH.
Affected versions
Packagist
| Package | Vulnerable | Fixed in |
|---|---|---|
| contao/core-bundle | >= 5.7.0, < 5.7.12 |
5.7.12 |
How to fix
Move to the fixed version or later with your package manager, update the lockfile, and run your tests. If the package only arrives through another dependency, upgrade that dependency first. If none of its releases pulls a fixed version yet, force the version with your package manager's override.
contao/core-bundle Packagist → 5.7.12
- composer
composer require contao/core-bundle:^5.7.12
Severity breakdown
CVSS 3.1 4.3
CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:L/I:N/A:N
- Attack vector
- Network
- Attack complexity
- Low
- Privileges required
- Low
- User interaction
- None
- Scope
- Unchanged
- Confidentiality
- Low
- Integrity
- None
- Availability
- None
Weakness
CWE-524: Use of Cache Containing Sensitive Information
The code uses a cache that contains sensitive information, but the cache can be read by an actor outside of the intended control sphere.
How to prevent it
- Architecture and Design: Protect information stored in cache.
- Architecture and Design: Do not store unnecessarily sensitive information in the cache.
- Architecture and Design: Consider using encryption in the cache.
CWE-863: Incorrect Authorization
The product performs an authorization check when an actor attempts to access a resource or perform an action, but it does not correctly perform the check.
How to prevent it
- Architecture and Design: Divide the product into anonymous, normal, privileged, and administrative areas. Reduce the attack surface by carefully mapping roles with data and functionality. Use role-based access control (RBAC) [REF-229] to enforce the roles at the appropriate boundaries. Note that this approach may not protect against horizontal authorization, i.e., it will not protect a user from attacking others with the same role.
- Architecture and Design: Ensure that access control checks are performed related to the business logic. These checks may be different than the access control checks that are applied to more generic resources such as files, connections, processes, memory, and database records. For example, a database may restrict access for medical records to a specific database user, but each record might only be intended to be accessible to the patient and the patient's doctor [REF-7].
- Architecture and Design: Use a vetted library or framework that does not allow this weakness to occur or provides constructs that make this weakness easier to avoid. For example, consider using authorization frameworks such as the JAAS Authorization Framework [REF-233] and the OWASP ESAPI Access Control feature [REF-45].
- Architecture and Design: For web applications, make sure that the access control mechanism is enforced correctly at the server side on every page. Users should not be able to access any unauthorized functionality or information by simply requesting direct access to that page. One way to do this is to ensure that all pages containing sensitive information are not cached, and that all such pages restrict access to requests that are accompanied by an active and authenticated session token associated with a user who has the required permissions to access that page.
- System Configuration, Installation: Use the access control capabilities of your operating system and server environment and define your access control lists accordingly. Use a "default deny" policy when defining these ACLs.
References
Packages
Other links
Timeline
- Published
- Last updated by the source
- Latest EPSS score
Related advisories
| Advisory | Severity | Why it's related |
|---|---|---|
| GHSA-9ff2-p842-45wq Contao: Cross-site request forgery in custom backend actions | Low | Also affects contao/core-bundle |
| GHSA-q6wp-fr43-gm9v Contao: Improper access control in the preview links module | Medium | Also affects contao/core-bundle |
| GHSA-mrvp-7wmx-5m4h Contao: Path traversal in the images controller | Medium | Also affects contao/core-bundle |
| GHSA-mfxh-vp55-7gc6 Contao: The registration module re-sends activation mails | Medium | Also affects contao/core-bundle |
| GHSA-x2rp-9qf7-2fmq Contao: Protected page content is disclosed to anonymous visitors after contao.search.index_protected is disabled | Medium | Also affects contao/core-bundle |
| GHSA-grm4-wm43-9jh5 Contao: Possible path traversal in job download URIs | Low | Also affects contao/core-bundle |
| GHSA-87mg-5grr-rhwh Contao: Server-Side Request Forgery (SSRF) via Unvalidated RSS Feed URL in Feed Reader Module | Low | Also affects contao/core-bundle |
| GHSA-3mr9-p497-58f6 Contao crawler leaks auth credentials to external hosts | Low | Also affects contao/core-bundle |
MergeHarbor checks every repository's dependencies against this database, ranks what matters by exploitability and reachability, routes it to the owning team and opens the fix pull request.
Check your repos with MergeHarbor