This article will introduce concepts about how computers schedule tasks with cron and how WordPress’s cron implementation “WP-Cron” works more like a queue instead of a scheduler. I will share some of the implications queueing instead of scheduling may have, as well as how to remediate the risk for site owners and what WordPress core is doing about this.
It was written in response to CVE-2023-22622 published by MITRE.
What is CVE-2023-22622?
This is a Common Vulnerability Enumeration reference number describing a security concern about how tasks get scheduled on WordPress applications. The CVE claims WordPress relies on an unpredictable variable, site visitors, in order to check if there are any tasks to be run. This may lead to important scheduled tasks (such as software updates) running inconsistently or not at all.
This is only an issue for sites that get low-to-no traffic, but there is an easy way to address it for site owners and for WordPress core which I will get into at the end.
What is a Cron?
The term cron means “scheduler” in the software world. You use cron to schedule tasks or “cronjobs” to be performed at specific intervals on the server. The operating system runs a background process or service called “cron” which you can think of as always checking the time and executing any jobs that are scheduled to run at that time. Like efficient public transit, you can expect cron jobs to run on time, every time, short of major catastrophes.
What is WP-Cron?
WP-Cron is an implementation of a task scheduler for WordPress. Unlike cron, WordPress is a web application, so it can not run background processes itself. The way the WordPress developers worked around this limitation, was to schedule tasks for a future time, and any time the application is running (e.g. when someone visits the website) you have the application check if there are any tasks that have not yet been run but should have been run (e.g. they have a scheduled time in the past) then run them.
To understand WP-Cron better, it helps to think of WP-Cron as a queue and not a scheduler. A task may not run on time, but it will run the next time WP-Cron checks for it.
Using the train analogy again. Scheduling tasks through WP-Cron is like a light rail or subway, if you miss the train (or if a train is skipped) you just queue up and wait. When the next train arrives it will pick up all of the passengers and proceed. Everybody gets to where they are going, eventually.
This is a clever way to get around the inability to run a persistent background process on the web server. As long as the WordPress website gets at a few visitors per hour, WP-Cron tasks will be performed reasonably “on time”.
Thanks to bots, every public-facing website gets a regular flow of traffic. Although bot traffic is normally unwanted, it is very handy to make sure WP-Cron is regularly running.
What type of sites could be affected?
If a WordPress site gets low to no traffic, then the WP-Cron queue will never be checked and scheduled tasks would not be performed. This isn’t an issue for a public-facing website, but it could be a concern for a few edge cases, like sites running on private networks, sites running on docker images, sites strictly firewalled, development/staging environments, and sites only accessible on a VPN. Just to name a few, but there may be more.
WordPress applications in these low-to-no traffic environments will not run some important WP-Cron tasks.
What are some of the important WP-Cron tasks?
WordPress core uses WP-Cron to schedule some highly important tasks. Such as checking for updates in plugins, themes, and WordPress core. WP-Cron also schedules the tasks to perform the updates themselves. Without WP-Cron functioning correctly, sites may miss important security updates.
Plugins may introduce many more important tasks which you may want to ensure are performed on a proper schedule too.
How to make WP-Cron run on a schedule?
The WordPress documentation team already has your back. They provide easy-to-follow steps for how to use the Mac, Linux, and Windows task schedules to ensure WP-Cron is running on a schedule.
The way WP-Cron functions as an intermittently processed queue is for all purposes completely safe and functional for any public-facing website.
But this may not be right for every installation.
If you prefer a more predictable schedule or manage sites that have low-to-no traffic, then you should consider using the operating system’s task scheduler instead of the default method. There are performance considerations and benefits to switching to a predictable scheduler from the default behavior as well (but this change is done on the web server, not within the web application.)
How WordPress mitigates CVE-2023-22622
If I had to explain CVE-2023-22622 in the simplest terms possible, I would say it is a “silent failure” concern. In information security jargon, CVE-2023-22622 describes a CWE-392 or “Missing Error Report” concern. This can be mitigated by making it clear to the user that a failure or error has happened.
Interactions with technology improve when users receive important warnings when something is malfunctioning. Like a notification when a train or flight is delayed, or a check engine light.
WordPress currently informs users when WP-Cron tasks are failing to run in two ways:
- Site Health checks will report when scheduled events are not performed.
- Notifying users with automatic updates enabled when those tasks are not performed. Including when the last time they were run, and pointing out there may be a problem with WP-Cron
Finally, there is a discussion surrounding improving the communication surrounding WP-Cron errors happening in WordPress trac ticket #57159. This may be a good place to have further discussion on the matter. This ticket has been updated with details regarding CVE-2023-22622 concerns based on discussions and knowledge I gained while preparing this post.
I must share my appreciation for the many people who have written about WP-Cron concerns in the past (See references below) as well as share my appreciation with the anonymous MITRE and NIST team members and non-anonymousWordPress.org community members (johnbillion, clorith, and sebastienserre) thank you for discussing this matter with me, clarifying points, sharing your knowledge, and for collaborating to work toward a resolution.
theCpanelGuy: The Nightmare that is wp-cron.php
Published 2018-06, theCpanelGuy highlights concerns they encountered with WP-Cron tasks leading to resource usage spikes and unnecessary traffic. theCpanelGuy encourages people to use a task scheduler and recommends there should be: “a notice placed within the WordPress admin interface”.
Tenable: Finding: WordPress Cron Enabled
On 2022-12-21, Tenable released an advisory about wp-cron.php. Citing the article from theCpanelGuy only, Tenable describes the issue as a Denial of Service concern.
On 2023-01-05, MITRE created a CVE describing the issue affecting low-to-no traffic WordPress websites have scheduling concerns with WP-Cron, they make it clear without consistent traffic important WP_Cron tasks may not be performed in a timely manner on WordPress websites.
WP-Crontrol: Reasons WP-Cron events can miss their schedule
The developers of WP-Crontrol know WP-Cron deeply. They have prepared the above documentation for users to better understand why and what to do if WP-Cron is not running on schedule.
What is WP-Cron?
States: “WP-Cron does not run constantly as the system cron does; it is only triggered on page load. Scheduling errors could occur if you schedule a task for 2:00PM and no page loads occur until 5:00PM.”
Understanding WP-Cron scheduling
States “Unlike a traditional system cron that schedules tasks for specific times, WP-Cron uses intervals to simulate a system cron.”
Hooking WP-Cron into the system task schedule
Shows how to set up WP-Cron using the operating system’s task scheduler. Including steps on how to do so in Windows using PowerShell.