VYPR
Moderate severityOSV Advisory· Published Feb 19, 2024· Updated Aug 1, 2024

Msa-24-0003: h5p attempts report did not respect activity group settings

CVE-2024-25980

Description

CVE-2024-25980: Moodle fails to enforce Separate Groups mode in H5P attempts report, leaking cross-group user data to non-editing teachers.

AI Insight

LLM-synthesized narrative grounded in this CVE's description and references.

CVE-2024-25980: Moodle fails to enforce Separate Groups mode in H5P attempts report, leaking cross-group user data to non-editing teachers.

Vulnerability

Overview

The H5P attempts report in Moodle did not properly respect Separate Groups mode restrictions. When a course (or H5P activity) is configured with Separate Groups mode, users should only be able to view attempts from their own group. However, the report displayed all user attempts, bypassing this group isolation [1]. The bug is rooted in the get_report() function within mod/h5pactivity, which did not filter results by group membership [2].

Exploitation

Conditions

This vulnerability is exploitable under specific prerequisites. The issue primarily affects users with the non-editing teacher role (teacher). By default, the mod/h5pactivity:reviewattempts capability is not granted to non-editing teachers. However, if an administrator or editing teacher explicitly grants that capability (see commit reference for test setup), the non-editing teacher can view the H5P attempts report. In that scenario, the report fails to apply the expected group filter, exposing attempts from students in all groups, not just the teacher's own group [1][2].

Impact

An attacker with non-editing teacher privileges (after the reviewattempts capability is explicitly allowed) can view detailed H5P attempt data for students outside their assigned groups. This constitutes a breach of privacy and group isolation intended by the Separate Groups setting. The impact is limited to information disclosure (student names, scores, and attempt details) and does not include data modification or privilege escalation [1].

Mitigation

Status

A fix has been implemented in Moodle's source repository via commit 662192fcecdefdaae79f55db96bd64dbcdeef85b [2]. Administrators should upgrade to the patched version of Moodle (2.19 or later, depending on the affected branch). The Fedora package announcement (reference [4]) indicates that updates were distributed. No known workaround exists other than restricting the mod/h5pactivity:reviewattempts capability to necessary roles only.

AI Insight generated on May 20, 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.

PackageAffected versionsPatched versions
moodle/moodlePackagist
>= 4.3.0, < 4.3.34.3.3
moodle/moodlePackagist
>= 4.2.0, < 4.2.64.2.6
moodle/moodlePackagist
< 4.1.94.1.9

Affected products

3

Patches

1
662192fcecde

MDL-80501 mod_h5pactivity: activity group mode

https://github.com/moodle/moodleLeon StringerFeb 8, 2024via ghsa
2 files changed · +89 1
  • mod/h5pactivity/classes/local/manager.php+1 1 modified
    @@ -486,7 +486,7 @@ public function get_report(int $userid = null, int $attemptid = null, $currentgr
                 // Ensure user can view the attempt of specific userid, respecting access checks.
                 if ($user && $user->id != $USER->id) {
                     $course = get_course($this->coursemodule->course);
    -                if ($this->coursemodule->effectivegroupmode == SEPARATEGROUPS && !user_can_view_profile($user, $course)) {
    +                if (!groups_user_groups_visible($course, $user->id, $this->coursemodule)) {
                         return null;
                     }
                 }
    
  • mod/h5pactivity/tests/local/manager_test.php+88 0 modified
    @@ -964,6 +964,94 @@ public function get_report_data(): array {
             ];
         }
     
    +    /**
    +     * Test teacher access to student reports (get_report) when course groupmode is SEPARATEGROUPS.
    +     * @covers ::get_report()
    +     * @dataProvider get_report_data_groupmode
    +     *
    +     * @param bool $activitygroupmode Course or activity groupmode
    +     */
    +    public function test_get_report_groupmode(bool $activitygroupmode): void {
    +        global $DB;
    +
    +        $this->resetAfterTest();
    +        $this->setAdminUser();
    +
    +        if ($activitygroupmode) {
    +            $course = $this->getDataGenerator()->create_course(['groupmode' => NOGROUPS, 'groupmodeforce' => 0]);
    +            $activitysettings = ['course' => $course, 'groupmode' => SEPARATEGROUPS];
    +        } else {
    +            $course = $this->getDataGenerator()->create_course(['groupmode' => SEPARATEGROUPS, 'groupmodeforce' => 1]);
    +            $activitysettings = ['course' => $course];
    +        }
    +
    +        $activity = $this->getDataGenerator()->create_module('h5pactivity', $activitysettings);
    +
    +        // Grant mod/h5pactivity:reviewattempts to non-editing teacher.
    +        // At the time of writing this is not set by default (see MDL-80028).
    +        $teacherrole = $DB->get_record('role', ['shortname' => 'teacher']);
    +        role_change_permission($teacherrole->id,
    +            \context_course::instance($course->id), 'mod/h5pactivity:reviewattempts', CAP_ALLOW);
    +
    +        $manager = manager::create_from_instance($activity);
    +
    +        $editingteacher = $this->getDataGenerator()->create_and_enrol($course, 'editingteacher');
    +        $teacher1 = $this->getDataGenerator()->create_and_enrol($course, 'teacher');
    +        $teacher2 = $this->getDataGenerator()->create_and_enrol($course, 'teacher');
    +        $student1 = $this->getDataGenerator()->create_and_enrol($course);
    +        $student2 = $this->getDataGenerator()->create_and_enrol($course);
    +        $student3 = $this->getDataGenerator()->create_and_enrol($course);
    +
    +        $group1 = $this->getDataGenerator()->create_group(['courseid' => $course->id]);
    +        $this->getDataGenerator()->create_group_member(['groupid' => $group1->id, 'userid' => $teacher1->id]);
    +        $this->getDataGenerator()->create_group_member(['groupid' => $group1->id, 'userid' => $student1->id]);
    +
    +        $group2 = $this->getDataGenerator()->create_group(['courseid' => $course->id]);
    +        $this->getDataGenerator()->create_group_member(['groupid' => $group2->id, 'userid' => $student2->id]);
    +
    +        // Check reports.
    +
    +        // Editing teachers can view all users, those in any group or no group.
    +        $this->setUser($editingteacher);
    +        $report = $manager->get_report($student1->id);
    +        $this->assertNotNull($report);
    +        $report = $manager->get_report($student3->id);
    +        $this->assertNotNull($report);
    +
    +        // Non-editing teacher can view student, both members of same group.
    +        $this->setUser($teacher1);
    +        $report = $manager->get_report($student1->id);
    +        $this->assertNotNull($report);
    +
    +        // Non-editing teacher cannot view student in no group.
    +        $report = $manager->get_report($student3->id);
    +        $this->assertNull($report);
    +
    +        // Non-editing teacher cannot view student in different group.
    +        $report = $manager->get_report($student2->id);
    +        $this->assertNull($report);
    +
    +        // Non-editing teacher in no group can view no one.
    +        $this->setUser($teacher2);
    +        $report = $manager->get_report($student1->id);
    +        $this->assertNull($report);
    +        $report = $manager->get_report($student3->id);
    +        $this->assertNull($report);
    +    }
    +
    +    /**
    +     * Data provider for test_get_report_groupmode.
    +     *
    +     * @return array
    +     */
    +    public function get_report_data_groupmode(): array {
    +        return [
    +            // No tracking scenarios.
    +            'course groupmode is SEPARATEGROUPS' => [false],
    +            'course groupmode is NOGROUPS, activity groupmode is SEPARATEGROUPS' => [true],
    +        ];
    +    }
    +
         /**
          * Test get_attempt method.
          *
    

Vulnerability mechanics

Generated on May 9, 2026. Inputs: CWE entries + fix-commit diffs from this CVE's patches. Citations validated against bundle.

References

7

News mentions

0

No linked articles in our index yet.