GitHub Advisoryadvisory · Packagist
GHSA-jwcc-gv4m-93x6 Pimcore has a CustomReports Share Bypass
HIGH
Official page ↗
- Aliases
- CVE-2026-45704
- Ecosystem
- Packagist
- Packages
- pimcore/pimcore
- Severity
- High
- CVSS vector
- CVSS:4.0/AV:N/AC:L/AT:N/PR:L/UI:N/VC:H/VI:L/VA:N/SC:N/SI:N/SA:N
- Weaknesses
- CWE-863
- Reviewed
- 2026-05-27
Affected packages
• Packagist pimcore/pimcore: >= 12.0.0-RC1, < 12.3.6 → fixed in 12.3.6
• Packagist pimcore/pimcore: < 11.5.17 → fixed in 11.5.17
• Packagist pimcore/pimcore: >= 2026.1.0, < 2026.1.2 → fixed in 2026.1.2
Description
Summary
`CustomReports` uses inconsistent authorization between the report listing endpoint and the report detail endpoint.
• The listing flow filters reports based on report-sharing rules
• The detail flow only checks generic `reports` or `reports_config` permissions
As a result, a low-privileged backend user who was not granted access to a report can still read that report directly by name even though it does not appear in the user's visible report list.
In the local Docker reproduction:
• The report `poc-secret-report` was not visible to the low-privileged user in the report list
• The same user was still able to retrieve the report configuration directly by name
Root Cause
The listing flow in `getReportConfigAction()` filters reports through `loadForGivenUser()`:
• [CustomReportController.php](pimcore-12.3.3/bundles/CustomReportsBundle/src/Controller/Reports/CustomReportController.php#L245)
• [CustomReportController.php](pimcore-12.3.3/bundles/CustomReportsBundle/src/Controller/Reports/CustomReportController.php#L252)
• CustomReportController.php
• [Config/Listing/Dao.php](pimcore-12.3.3/bundles/CustomReportsBundle/src/Tool/Config/Listing/Dao.php#L44)
• Config/Listing/Dao.php
However, `getAction()` only checks generic permissions and then loads the report directly by name:
• [CustomReportController.php](pimcore-12.3.3/bundles/CustomReportsBundle/src/Controller/Reports/CustomReportController.php#L146)
• [CustomReportController.php](pimcore-12.3.3/bundles/CustomReportsBundle/src/Controller/Reports/CustomReportController.php#L149)
• CustomReportController.php
• CustomReportController.php
This means the same report object is protected by different authorization models depending on which endpoint is used. The result is a classic "not visible in list, but readable by direct request" access-control bypass.
Impact
An attacker can read sensitive report metadata without authorization, including:
• Report name
• Grouping information
• Display and icon metadata
• Data source configuration
• Column configuration
• Sharing settings
From the source code, other report endpoints such as `data`, `chart`, `create-csv`, and `download-csv` also resolve reports by name in a similar way:
• [CustomReportController.php](pimcore-12.3.3/bundles/CustomReportsBundle/src/Controller/Reports/CustomReportController.php#L275)
• [CustomReportController.php](pimcore-12.3.3/bundles/CustomReportsBundle/src/Controller/Reports/CustomReportController.php#L284)
• CustomReportController.php
This report only treats unauthorized report-config retrieval as reproduced. The other execution paths should be verified separately.
Preconditions
• The attacker is an authenticated backend user
• The attacker has the `reports` permission
• The target report is not globally shared and is not shared with that user or the user's roles
PoC
```php
boot();
$container = $kernel->getContainer();
/** @var RequestStack $requestStack */
$requestStack = getService($container, [
RequestStack::class,
'request_stack',
]);
$admin = User::getByName('admin');
if (!$admin instanceof User) {
fail('admin user is missing');
}
$auditor = User::getByName('auditor_customreports');
if (!$auditor instanceof User) {
$auditor = new User();
$auditor->setParentId(0);
$auditor->setName('auditor_customreports');
}
$auditor->setAdmin(false);
$auditor->setActive(true);
$auditor->setPassword(Authentication::getPasswordHash('auditor_customreports', 'auditor-pass'));
$auditor->setPermissions(['reports']);
$auditor->setRoles([]);
$auditor->save();
$timestamp = time();
SettingsStore::set(
'poc-secret-report',
json_encode([
'name' => 'poc-secret-report',
'niceName' => 'PoC Secret Report',
'group' => 'Audit',
'dataSourceConfig' => [['type' => 'sql']],
'columnConfiguration' => [],
'shareGlobally' => false,
'sharedUserNames' => ['admin'],
'sharedRoleNames' => [],
'menuShortcut' => true,
'creationDate' => $timestamp,
'modificationDate' => $timestamp,
], JSON_THROW_ON_ERROR),
SettingsStore::TYPE_STRING,
'pimcore_custom_reports'
);
$tokenResolver = buildTokenResolver($auditor);
$controller = wireController(new CustomReportController(), $container, $tokenResolver);
$listRequest = new Request();
$requestStack->push($listRequest);
$listResponse = $controller->getReportConfigAction($listRequest);
$requestStack->pop();
$listData = json_decode($listResponse->getContent(), true, 512, …
Related
Alias · CVE (1)
- CVE-2026-45704 Pimcore is an Open Source Data & Experience Management Platform. vulnerability
Weakness · CWE (1)
- CWE-863 Incorrect Authorization weakness
References
- https://github.com/pimcore/pimcore/security/advisories/GHSA-jwcc-gv4m-93x6 web
- https://github.com/pimcore/pimcore/pull/19099 web
- https://github.com/pimcore/pimcore/commit/1893ff1cd116e442b995ddf17e8c6e0aa372268e web
- https://github.com/pimcore/pimcore package
- https://github.com/pimcore/pimcore/releases/tag/v12.3.6 web