We wrote a post a while back on how to set up server side CRON jobs for WordPress. We set these up for our hosting customers who request them – and also on high traffic sites to help with server loads. It’s a good idea to set CRON up this way but it’s not always mission critical or even a security threat. If it were truly a threat the WordPress dev team would have mitigated it many years ago.
TLDR; : skip to the script
We still get requests once in a while from hosting customers who are concerned that wp-cron.php
is publicly available even after disabling wp-cron (define('DISABLE_WP_CRON', true);
).
We’re happy to help but as an FYI, having wp-cron.php publicly accessible is actually a very low security risk:
- The file can only execute pre-registered WordPress cron tasks/hooks
- It cannot accept external parameters – there’s no attack surface for injection
- It has built-in locking mechanisms to prevent multiple simultaneous executions
- At worst, someone could trigger your scheduled tasks more frequently than intended, which is mainly just a performance consideration
The main concerns would be:
- Unnecessary server load if someone repeatedly hits it
- Potential timing issues if tasks run out of expected sequence
- Minor resource waste
This is why WordPress itself doesn’t block access by default – it’s designed to be safely triggered via HTTP request.
Yeah cool but…
If you are concerned for compliance / audit reasons, let’s look at blocking public access, and allowing only the server to access. Add this to .htaccess
:
# Block direct access to wp-cron.php
<Files "wp-cron.php">
Order Deny,Allow
Deny from all
# Only allow server-side requests
Allow from 127.0.0.1
Allow from ::1
</Files>
This will deny access from public sources while allowing the server to still run it’s timed cron.
127.0.0.1
allows IPv4 and ::1
is the IPv6 localhost equivalent.
What are the downsides?
If properly configured, there’s no downside to denying access to wp-cron.php
. The only access needed is from localhost (127.0.0.1/::1) for your server cron, which we’re explicitly allowing.
The only potential “gotcha” would be if:
- Your server cron is running from a different IP (like in some clustered/load-balanced setups)
- You’re using a service that needs to trigger cron externally (rare but exists)
- Your .htaccess rules are somehow blocking the localhost access despite the Allow directives