MDL Shield

Automatic enrolment key creator

local_enrolkeycreator

Print Report
Plugin Information

Local plugin that listens for the core enrol_instance_created event and, when enabled by the site administrator, automatically sets a randomly generated enrolment key on newly created self-enrolment instances that have none, while still allowing teachers to remove the key later (unlike core's enrol_self | requirepassword).

Version:2026100501
Release:v5.3-r2
Reviewed for:5.3
Privacy API
Unit Tests
Behat Tests
Reviewed:2026-10-25
6 files·274 lines
Grade Justification

The plugin is very small: one event observer, one admin checkbox, a null privacy provider, a language file and Behat tests. It has no user-facing pages, no request parameters, no forms, no AJAX or web services, no SQL strings and no outbound HTTP.

The observer only runs on a core event, which means a user who could already create an enrolment instance has passed core's capability checks. It reads and updates the enrol record with $DB array conditions. It generates the key with core's \core\authentication\password::generate(20), the same call core's enrol_self makes, and it copies core's enrol_plugin::update_instance() side effects (it updates timemodified and fires enrol_instance_updated). The plugin stores no personal data, so the null privacy provider is correct.

The only finding is a redundant database lookup, rated info. It has no security or functional impact.

AI Summary

local_enrolkeycreator is a single-purpose plugin of about 130 lines of PHP. When an admin turns it on, it gives each new self-enrolment instance a random enrolment key if the instance was created without one. Teachers can still remove the key later, which core's requirepassword setting does not allow.

The security posture is clean. The plugin has no web entry points. It never reads user input, writes no raw SQL, uses no superglobals and makes no network calls. All logic sits in one event observer. It uses the $DB API with array conditions and core's password::generate() to make the key, so the key follows the site password policy in the same way as core's enrol_self default instance. Updating the record directly and then firing enrol_instance_updated is a reasonable copy of enrol_plugin::update_instance(), which I checked against core.

There is nothing that needs action. One info-level note covers a redundant course lookup in the observer. The plugin also ships Behat coverage for every combination of its setting and core's setting.

Findings

best practiceInfo
Redundant course record lookup in event observer

The observer loads the full course record with $DB->get_record() but only uses it to check that the course exists. The $course variable is never used after that check. The enrol row was just created for that course and the event fires with a course context, so the extra query almost never adds anything. It is one extra lookup per new enrolment instance, which matters a little during bulk course creation or restores.

Risk Assessment

Informational. This has no security or correctness impact. The only cost is one extra query on a rare event.

Context

enrol_instance_created() runs every time any enrolment instance is created on the site, including when courses are created, restored or uploaded. It exits early for non-self instances, when requirepassword is on, or when a key is already set. After that it writes the generated key.

Identified Code
$courseid = $enrol->courseid;
$course = $DB->get_record('course', ['id' => $courseid]);

if (!$course) {
    return true;
}
Suggested Fix

Remove the lookup. If the existence check should stay as a safeguard, use a cheaper query:

if (!$DB->record_exists('course', ['id' => $enrol->courseid])) {
    return true;
}
Additional AI Notes

Behaviour note for administrators: the observer listens to every enrol_instance_created event. Besides interactive course creation, that includes course restore, course upload, and a teacher adding a new self-enrolment method while deliberately leaving the key blank. In all of these cases, if the plugin is enabled and the instance has no key, a random key is set and the user is not notified. This is the plugin's intended design, and the key can be removed afterwards, but sites that create open self-enrolment instances on purpose through upload or restore should be aware of it.

Version targeting: version.php requires 2026100500 and declares supported = [503, 503]. This matches the Moodle 5.3 core under review ($version = 2026100500.00, branch 503). The plugin uses \core\authentication\password, which exists in this core tree.

This review was generated by an AI system and may contain inaccuracies. Findings should be verified by a human reviewer before acting on them.