Logged-out Users Run Your WordPress Cron Jobs
💡 Code that works in a plugin might not behave the same in a scheduled wp-cron job.
Things That Don’t Always Work in WordPress Cron Jobs
get_posts()
calls that return posts with unpublished statuses
Workaround: use$wpdb
queries to retrieve posts or force admintax_input
parameter duringwp_insert_post()
orwp_update_post()
calls
Workaround: usewp_set_object_terms()
or force_adminwp_get_update_data()
- Other functions or codes that call
current_user_can()
orcurrent_user_can_for_blog()
Why do wp-cron jobs behave differently?
WordPress cron jobs are triggered by any visitor to your site on or after the scheduled time. A logged-out visitor could be running your WordPress cron job.
Any code that uses current_user_can()
to restrict permissions can behave differently during wp-cron, including get_posts()
and wp_update_post()
calls.
SOLUTIONS
1. Test Your Code as a Logged-Out Visitor
Testing wp-cron job code with a tool that runs tasks on demand (like the fantastic Advanced Cron Manager) will fool you into believing the code will always run as an Administrator user. It’s not true. Use a short interval during development so it’s easier to trigger jobs as a logged-out visitor.
2. Briefly Force Administrator
Use wp_set_current_user()
to explicitly use an Administrator account at the beginning of your job’s code, and restore the original user ID even if zero to avoid leaking Administrator privileges.
$user_id = get_current_user_id(); //could be 0
wp_set_current_user( 1 ); //1 is the user ID of an Administrator
//do the stuff that needs to run as an admin
$drafts = get_posts( array(
'post_status' => 'draft', //drafts aren't accessible to logged-out users
) );
//don't leak Administrator privileges, restore the previous user even
wp_set_current_user( $user_id );
2. Use Real Cron
Almost every hosting company on the planet has written an article about triggering wp-cron with a real cron job. Here’s one at Kinsta.