CVE-2026-58348
Patch Available.
This Vulnerability has been fixed in the Never-Ending Support (NES) version offered by HeroDevs.
Overview
Moodle is an open source learning management system written in PHP. Schools, universities, and companies use it to run online courses. IOMAD is a multi-tenant distribution of Moodle that lets one installation serve several companies or organizations; it is built on Moodle core and shares the affected code. The report builder (core_reportbuilder) powers custom reports and many system reports, and it loads parts of its interface, such as the filters panel and the audience editor, as HTML fragments fetched in the background.
An Improper Access Control vulnerability (CVE-2026-58348) has been identified in the report builder of Moodle and IOMAD, which allows a logged-in user to request the filters form or audience form of a report they are not allowed to view or edit. Moodle tracks this issue as MSA-26-0029 (MDL-84535).
Per MITRE CWE-862: The product does not perform an authorization check when an actor attempts to access a resource or perform an action.
This issue affects all versions of Moodle before 4.5.12, versions 5.0.0 through 5.0.7, versions 5.1.0 through 5.1.4, and version 5.2.0, including End-of-Life release lines such as Moodle 4.3. IOMAD releases built on these Moodle versions contain the same code and are affected as well.
Details
Module Info
- Product: Moodle, IOMAD
- Affected packages:
moodle/moodle(reportbuilder) - Affected versions: <4.5.12, >=5.0.0 <5.0.8, >=5.1.0 <5.1.5, >=5.2.0 <5.2.1
- GitHub repository: https://github.com/moodle/moodle (Moodle), https://github.com/iomad/iomad (IOMAD)
- Published packages: https://packagist.org/packages/moodle/moodle
- Package manager: Composer
- Fixed in:
- OSS Moodle 4.5.12, 5.0.8, 5.1.5, 5.2.1
- NES for Moodle v4.3.13
- NES for IOMAD v4.3.4
Vulnerability Info
This Low-severity vulnerability is found in the moodle/moodle package in all versions before 4.5.12, 5.0.0 through 5.0.7, 5.1.0 through 5.1.4, and 5.2.0 of Moodle, and in IOMAD releases built on those versions. Moodle rates it Minor.
Moodle's fragment API lets JavaScript ask a component for a piece of rendered HTML by calling a function named <component>_output_fragment_<name>. The report builder defines two of these in reportbuilder/lib.php. Both took the report ID from the request and rendered the form without checking that the user had access to the report:
function core_reportbuilder_output_fragment_filters_form(array $params): string {
$filtersform = new filter(null, null, 'post', '', [], true, [
'reportid' => $params['reportid'],
'parameters' => $params['parameters'],
]);
$filtersform->set_data_for_dynamic_submission();
return $filtersform->render();
}
function core_reportbuilder_output_fragment_audience_form(array $params): string {
global $PAGE;
$audienceform = new audience(null, null, 'post', '', [], true, [
'reportid' => $params['reportid'],
'classname' => $params['classname'],
]);
$audienceform->set_data_for_dynamic_submission();The form classes do check access, but only in check_access_for_dynamic_submission(), which runs when the form is submitted. Rendering the form through the fragment skipped that check. The filters form is built from the report's filter definitions and loaded with the user's current filter values, and the audience form is built from the audience type named in the request. A logged-in user could therefore pass the ID of any report and receive these forms, including filter headings and option lists that can contain values from the site's data, for reports they are not permitted to view or edit. The advisory describes this as potentially allowing users to retrieve report data beyond their permitted access. The issue does not let the user change a report or its audiences, because saving still goes through the form's submission checks.
The fix adds the same checks to the fragment callbacks. The filters form now requires permission to view the report, using the custom report permission check or the system report's own require_can_view():
$report = new report($params['reportid']);
// Verify current user can access the report data.
if ($report->get('type') === report_base::TYPE_CUSTOM_REPORT) {
permission::require_can_view_report($report);
} else {
$reportinstance = manager::get_report_from_persistent($report, (array) json_decode($params['parameters']));
$reportinstance->require_can_view();
}The audience form now requires permission to edit the report and to add the requested audience type:
$report = new report($params['reportid']);
permission::require_can_edit_report($report);
// Verify current user can add the requested audience type.
audience_base::instance(0, (object) $params)->require_user_can_add();Mitigation
Moodle publishes security fixes only for its supported release lines. Earlier release lines, including Moodle 4.3 and the IOMAD releases built on it, are End-of-Life and will not receive any public updates to address this issue.
Users of the affected components should apply one of the following mitigations:
- Upgrade to Moodle 4.5.12, 5.0.8, 5.1.5, 5.2.1, or later, or to an IOMAD release built on one of those versions.
- Leverage a commercial support partner like HeroDevs for post-EOL security support.
Credits
- Paul Holden from Moodle HQ (finder)