Moodle PHP Upgrade: 8.3.36 or 8.4.27 – UK Plugin Compatibility Guide
Moodle 4.5 does not run on PHP 8.4. Discover which patched version to use in your VLE, how to validate the upgrade, and how to roll back if issues arise.
by Cleverson Gouvêa

Upgrading Moodle PHP is no longer a task for 'when you get around to it': since 21 October 2026, any organisation running their VLE on PHP without the PHP2Shell patches is exposed to remote code execution without authentication. In this guide, I'll show you which PHP version each Moodle release supports, how to validate the upgrade without breaking plugins, and how to prepare your rollback strategy before making changes to production.
TL;DR
- PHP2Shell (CVE-2026-109618 and CVE-2026-109619) has a CVSS 4.0 score of 9.2 and requires no authentication. The patch was released on 21/10/2026 in versions 8.5.12, 8.4.27, 8.3.36, and 8.2.35.
- Moodle 4.5 LTS only supports up to PHP 8.3, so the target is 8.3.36. Moodle 5.0 and 5.1 support 8.2 to 8.4: the recommended target is 8.4.27 (or 8.3.36).
- Before upgrading Moodle PHP in production, distinguish between two operations: a patch within the same branch (8.3.x to 8.3.36) rarely breaks plugins; a branch change (8.1 to 8.3) requires full validation.
- Adjustments like
memory_limit=-1reduce risk but do not resolve the vulnerability. Only the patched version provides a fix.- PHP rollback is straightforward if you keep the old pool installed. Plan this in advance, not during an incident.
Why Upgrading Moodle PHP Became Urgent in October 2026
PHP2Shell is the moniker for two core PHP vulnerabilities. CVE-2026-109618 is a memory corruption issue that occurs when a request exceeds its memory limit (out-of-memory): processing is interrupted, leaving internal data partially initialised. CVE-2026-109619 is an obsolete global state problem: request information survives after its memory has been freed (use-after-free), contaminating the subsequent request.
Both vulnerabilities lead to remote code execution with the privileges of the web process, requiring no username or password. In Moodle, this exposes config.php (containing the database password), moodledata, and all student data.
The Timeline for VLE Administrators
- 17/10/2026: Amazon Threat Intelligence recorded an attempted exploit on its honeypot network, four days before public disclosure, according to the Tenable FAQ. The recommendation is to investigate logs from this date, not from the disclosure.
- 20/10/2026: Identifiers leaked on social media, and the PHP security team brought forward the release by one day.
- 21/10/2026: Patched versions were released. Datadog Security Labs began observing widespread, untargeted scanning. watchTowr reported attempts against both CVEs.
- 23/10/2026: Unit 42, from Palo Alto Networks, updated its alert. Cortex Xpanse telemetry indicated over 22.6 million potentially vulnerable exposed instances. On the same day, php.net disclosed CVE-2026-115560, with an improbable vector, and a fix planned for the next regular release.
Who Has Patches and Who Doesn't
| PHP Branch | Status after PHP2Shell |
|---|---|
| 8.2, 8.3, 8.4, 8.5 | Patched in 8.2.35, 8.3.36, 8.4.27, and 8.5.12 |
| 7.4, 8.0, 8.1 | Only minimal source code backports, for those who compile PHP |
| 5.4 a 7.3 | No patches available |
If your Moodle still runs on PHP 8.1, there is no official patched package. The solution is to change branches, and that's where the risk of breaking plugins lies.
Compatibility Matrix: Moodle 4.5, 5.0, and 5.1 x PHP
Before upgrading Moodle PHP, check what your VLE version supports. The official Moodle PHP policy defines a minimum and maximum per branch.
| Moodle | Security Support (Moodle HQ) | Minimum PHP | Maximum PHP | Target Post-PHP2Shell |
|---|---|---|---|---|
| 4.5 LTS | until 04/10/2027 | 8.1 | 8.3 | 8.3.36 |
| 5.0 | ended on 05/10/2026 | 8.2 | 8.4 | 8.4.27 or 8.3.36, and plan to move from 5.0 |
| 5.1 | until 19/04/2027 | 8.2 | 8.4 | 8.4.27 (or 8.3.36) |
| 5.2 | until 04/10/2027 | 8.3 | 8.4 | 8.4.27 |
| 5.3 LTS | until 01/10/2029 | 8.3 | 8.4 (8.5 in development) | 8.4.27 |
Three practical takeaways for upgrading Moodle PHP without exceeding the supported range:
- Moodle 4.5 does not run on PHP 8.4. The policy lists 8.4 only from Moodle 5.0 onwards. Those on 4.5 LTS should target 8.3.36, full stop.
- PHP 8.2 is a short-term solution. According to the official PHP calendar, 8.2 receives security patches only until 31/12/2026. Installing 8.2.35 today resolves PHP2Shell but necessitates another change in two months.
- 8.3 is supported until 31/12/2027 and 8.4 until 31/12/2028. For Moodle 5.x, 8.4 provides more breathing room.
Patch within the Same Branch or Branch Change?
This decision dictates the scope of work. A patch within the same branch (8.3.30 to 8.3.36) brings only fixes: it doesn't change the language, remove functions, or introduce deprecations.
A branch change (8.1 to 8.3, or 8.3 to 8.4) alters the language. Plugins written four years ago, custom themes, and in-house integrations can break. This scenario demands full validation.
For 8.2 or 8.3, apply the patch now and plan the branch change. For 8.1 or below, there is no patch: the change is mandatory and urgent.
What Breaks Plugins When You Change PHP Branches
When upgrading Moodle PHP by changing branches, the core is rarely the issue, as it's tested within the official range. What breaks lies outside of it: third-party plugins, themes, and custom code. I've detailed the assessment of each in essential Moodle plugins and how to check compatibility.
version.php Doesn't Specify PHP
A plugin's version.php file declares $plugin->requires (minimum Moodle version) and, in newer plugins, $plugin->supported (range of Moodle branches). Neither declares a PHP version. A plugin "compatible with Moodle 4.5" may never have been tested on PHP 8.3. Only real-world testing provides the answer.
Key Language Changes That Cause Issues
- PHP 8.2: Creating dynamic properties on objects now generates a deprecation warning. Older code does this all the time. It doesn't break functionality but clutters the log.
- PHP 8.4: Parameters with a default
nullvalue without the nullable type hint (?string) generate a deprecation. Also, IMAP, Pspell, and OCI8 extensions have moved out of the core and now reside in PECL. If any plugin or integration relies on them, this will result in a fatal error. - System extensions: Each branch has its own packages (
php8.3-intl,php8.4-intl). Forgetting a package, such asintl,soap,sodium, orredis, is the most common cause of "it worked yesterday" issues. - New php.ini: The configuration file for the new branch comes with default values. Moodle requires
max_input_varsof at least 5000, while the PHP default is 1000. Without adjustment, large forms (grades, permissions) lose fields without warning.
How to Discover Issues Before Your Students Do
During validation, enable developer-level debugging and review the PHP-FPM log after each test scenario. Look for Deprecated, Fatal error, and Uncaught messages. Each line points to the file and line number of the offending plugin.
Validation Environment: The Step No One Wants to Pay For, But Everyone Needs
Validation involves testing changes on a faithful copy of the production environment before actual deployment. When upgrading Moodle PHP by changing branches, I know of no safe shortcut that bypasses this step.
How to Set Up the Copy
- Same operating system and version as the production server.
- Database dump from production and a copy of
moodledata. If thefilediris too large, copy the structure and a sample; what's essential are the course files used in the test scenario. - Disable email. In the copy's
config.php, use$CFG->noemailever = true;. Without this, the validation cron job will send deadline notifications to thousands of real students. - Turn off outbound integrations that charge or alter data: payment gateways, WhatsApp messaging, ERP synchronisation.
- Install both PHP versions side-by-side (e.g.,
php8.1-fpmandphp8.3-fpm). The virtual host points to the socket of one or the other.
The Minimum Test Scenario
- Local login and SSO (OAuth2, SAML, LDAP), if applicable
- Open a course, watch a video, download a file
- Complete a quiz from start to finish and check the grade
- Submit an assignment with an upload and mark it as a teacher
- Export the gradebook
- Run the cron manually:
php admin/cli/cron.php - Test the Moodle app (web services) and any API integration
- Open the most frequently used reports and paid plugins
Before testing, open Site administration > Server > Environment and confirm that everything appears in green. This panel highlights missing extensions and configurations below the required standard.
Step-by-Step Guide to Upgrading Moodle PHP in Production
Once validation is approved, upgrading Moodle PHP in production becomes a script execution. The sequence I use is:
- Full and tested backup: database,
moodledata, and code. - Notify users in advance and schedule a maintenance window outside peak hours.
- Maintenance mode:
php admin/cli/maintenance.php --enable. - Install the patched PHP with the same extensions validated during testing and copy the
php.iniadjustments (max_input_vars,memory_limit,upload_max_filesize,post_max_size). - Change the PHP-FPM socket in the virtual host and reload the web server.
- Purge caches:
php admin/cli/purge_caches.php. This prevents compiled cache from the previous version. - Check the environment in the Moodle panel and the
phpinfoof the version in use (php -vin the terminal might show a different binary than the FPM one). - Run the short test scenario and only then exit maintenance mode.
- Restart all PHP-FPM workers. PHP2Shell guidelines emphasise this: configuration only applies to new processes.
What if Your Distro Reports a Different Version?
Ubuntu, Debian, and Red Hat often apply patches without changing the upstream version number. Datadog warns about this: the package might be patched even if it shows 8.3.6, for example. In such cases, check the distribution's security bulletin and the package changelog, not the php -v output.
Rollback: How to Revert in Minutes Without Data Loss
The good news: changing PHP does not alter the Moodle database. Unlike upgrading Moodle 4.5 to 5, where the upgrade modifies the database schema and reverting requires restoring a backup, a PHP change is reversible simply by re-pointing the socket.
Prepare Your Rollback Path
Anyone upgrading Moodle PHP needs to have the rollback procedure documented before starting.
- Do not uninstall the old PHP on the day of the change. Keep the pool configured and stopped.
- Document the rollback command: which virtual host file changes and which service to reload.
- Define the trigger: which error justifies reverting (broken login, unsaved quiz) and who decides.
- After reverting, run
php admin/cli/purge_caches.phpagain.
The Rollback Trap in October 2026
Reverting to an unpatched PHP reopens PHP2Shell. A rollback now cannot be to "what worked before". It must be to the patched version of the previous branch. If the previous branch is 8.1 or older, there is no safe rollback: you either patch the plugin, disable it, or isolate the server until resolved. CISA even recommended taking systems running PHP 8.1 or older offline if they could not be updated.
Mitigations While the Update is Pending (and Why They Aren't Enough)
The PHP team itself published configuration adjustments to reduce exposure. These help buy time but do not replace upgrading Moodle PHP to the patched version.
| Adjustment | Against What | Limitation |
|---|---|---|
memory_limit=-1, fixed via php_admin_value in the pool |
CVE-2026-109618 | Removes the controllable memory limit, but an allocation failure can still reach the vulnerable section. Use memory limits in the container or cgroup. |
session.upload_progress.enabled=0 |
Session route for CVE-2026-109619 | Does not cover other variants; Datadog reports it doesn't protect alone. It's also the provisional guidance for CVE-2026-115560. |
fatal_error_backtraces=0 (PHP 8.5 only) |
CVE-2026-109619 | Does not apply to Moodle on 8.3 or 8.4 |
Two specific Moodle considerations. First, permanently setting memory_limit=-1 allows a heavy report or course restoration to consume all server RAM. Second, disabling upload progress does not break Moodle file uploads, but you should still test assignment submissions.
When Not to Update (Yet) and Costly Errors
There are bad times to upgrade Moodle PHP by changing branches. A security patch within the same branch should almost always be applied immediately. However, a branch change deserves a scheduled approach.
Do not change the PHP branch:
- During exam week, grade submission, or enrolment periods.
- Concurrently with a Moodle upgrade. Two changes on the same day make it impossible to determine what broke what.
- Without validation, just because "the vendor said it's compatible."
Common recurring errors I observe:
- Upgrading Moodle PHP only via the command line and forgetting PHP-FPM.
php -vshows the new version, but the site remains vulnerable. - Forgetting the cron job. It runs with the command-line binary; if it points to the old PHP, scheduled tasks run on the wrong version.
- Copying the entire
php.inifrom the old branch to the new one, loading directives that no longer exist. - Ignoring the deprecation log. Today it's a warning; in the next version, it becomes a fatal error.
If the server is a VPS that no one on the team truly manages, it's worth revisiting the discussion on VPS for Moodle or managed hosting. PHP2Shell is the kind of event where this difference becomes apparent.
How Agathas Web Addresses This
I've worked with Moodle and Linux servers since before the Moodle 2 series, and the update routine described above is what we apply to the environments we manage. With Agathas Web's Moodle service, upgrading Moodle PHP is handled as a complete project:
- Inventory: Moodle version, PHP branch and build, distro package, list of plugins and themes, API and WhatsApp integrations.
- Exposure diagnosis: assessing if the environment is protected against PHP2Shell and which mitigations are effective while the change is pending.
- Cloned validation environment with email and integrations disabled, PHP versions side-by-side, and a test scenario agreed with coordination.
- Correction or replacement of plugins that break on the new branch, handled by our PHP development team.
- Scheduled maintenance window at an agreed time, with a documented and tested rollback plan.
- Log review from 17/10/2026, to check for signs of exploitation attempts.
How to engage our services: contact us via the Moodle services page, tell us your Moodle version and where it's hosted, and we'll provide a diagnosis and a timed plan. If you'd rather not handle this work yourself, we can continue managing your operation with our managed hosting services.
Conclusion: Patch Now, Change Branches Methodically
The safe path for upgrading Moodle PHP has two speeds. A patch within the same branch (to 8.3.36 or 8.4.27) should be applied now, as the compatibility risk is minimal and exploitation has already begun. A branch change, mandatory for those on 8.1 or below, requires validation, a test scenario, and a rollback to a patched version.
If you're unsure which PHP your VLE is actually running, the first step to upgrading Moodle PHP is to find out. Request a diagnosis from Agathas Web's Moodle services and resolve the uncertainty before a scanner does it for you.
Related posts

PHP2Shell: UK Risks for Legacy Moodle PHP & Migration Plan
PHP versions 7.4 to 8.1 lack official PHP2Shell patches. Understand backport coverage and the secure migration path to Moodle 4.5 LTS.

Moodle VPS or Managed Hosting: The True Cost for UK Organisations
A VPS might cost less than £30 a month. But updating, backing up, and securing Moodle on it costs significantly more. See the full breakdown.

Moodle 5.3 OAuth2: A UK Guide to Migrating Your VLE Integrations
Static token stuck in your ERP for years? Moodle 5.3 introduces OAuth 2. See what's changing, what's not, and where to begin.