WordPress Security

Automating WordPress Security Tasks with Cron Jobs

Set up automated security scanning, log cleanup, and maintenance tasks using WordPress cron and server cron jobs.

S
Sarah Chen
8 min read
2,363 views
Guide to automating WordPress security with cron jobs

Introduction

Security requires constant vigilance, but manual checks are impractical. Automating security tasks through WordPress cron and server cron ensures continuous protection without daily manual intervention.

WordPress Cron vs Server Cron

Understanding the difference:

  • WordPress Cron - Triggered by site visits, may be delayed on low-traffic sites
  • Server Cron - Runs at exact times regardless of traffic
  • Recommendation - Use server cron for critical security tasks

Setting Up Security Cron Jobs

Create reliable automated security tasks:

Disable WordPress Cron for Server Cron

// Add to wp-config.php
define('DISABLE_WP_CRON', true);

// Set up server cron (crontab -e)
// Run WP-Cron every 5 minutes
*/5 * * * * wget -q -O - https://yoursite.com/wp-cron.php?doing_wp_cron >/dev/null 2>&1

// Or use WP-CLI
*/5 * * * * cd /path/to/wordpress && wp cron event run --due-now

Automated Security Scanning

// Schedule daily malware scan
function schedule_security_scan() {
    if (!wp_next_scheduled('wpfs_daily_security_scan')) {
        wp_schedule_event(strtotime('03:00:00'), 'daily', 'wpfs_daily_security_scan');
    }
}
add_action('init', 'schedule_security_scan');

// Perform the scan
add_action('wpfs_daily_security_scan', function() {
    $scanner = new WPFS_Malware_Scanner();

    // Scan core files
    $core_issues = $scanner->scan_core_files();

    // Scan plugins
    $plugin_issues = $scanner->scan_plugins();

    // Scan uploads for PHP
    $upload_issues = $scanner->scan_uploads_for_php();

    $all_issues = array_merge($core_issues, $plugin_issues, $upload_issues);

    if (!empty($all_issues)) {
        // Send alert
        $message = "Security scan found issues:

";
        foreach ($all_issues as $issue) {
            $message .= "- {$issue['file']}: {$issue['type']}
";
        }

        wp_mail(
            get_option('admin_email'),
            '[ALERT] Security Issues Detected',
            $message
        );
    }

    // Log scan result
    update_option('wpfs_last_scan', array(
        'time' => current_time('mysql'),
        'issues' => count($all_issues),
    ));
});

Log Rotation and Cleanup

// Schedule log cleanup
function schedule_log_cleanup() {
    if (!wp_next_scheduled('wpfs_log_cleanup')) {
        wp_schedule_event(time(), 'daily', 'wpfs_log_cleanup');
    }
}
add_action('init', 'schedule_log_cleanup');

add_action('wpfs_log_cleanup', function() {
    global $wpdb;

    // Clean security logs older than 90 days
    $wpdb->query("
        DELETE FROM {$wpdb->prefix}security_logs
        WHERE created_at < DATE_SUB(NOW(), INTERVAL 90 DAY)
    ");

    // Clean login attempt logs older than 30 days
    $wpdb->query("
        DELETE FROM {$wpdb->prefix}login_attempts
        WHERE attempt_time < DATE_SUB(NOW(), INTERVAL 30 DAY)
    ");

    // Archive important logs before deletion
    $critical_logs = $wpdb->get_results("
        SELECT * FROM {$wpdb->prefix}security_logs
        WHERE event_type IN ('breach_detected', 'malware_found')
        AND created_at BETWEEN DATE_SUB(NOW(), INTERVAL 90 DAY) AND DATE_SUB(NOW(), INTERVAL 89 DAY)
    ");

    if (!empty($critical_logs)) {
        // Archive to file
        $archive_file = WP_CONTENT_DIR . '/security-archives/' . date('Y-m') . '.json';
        file_put_contents($archive_file, json_encode($critical_logs), FILE_APPEND);
    }

    // Log cleanup completion
    error_log('Security log cleanup completed');
});

Automated Backup Verification

// Weekly backup integrity check
function schedule_backup_check() {
    if (!wp_next_scheduled('wpfs_backup_verification')) {
        wp_schedule_event(time(), 'weekly', 'wpfs_backup_verification');
    }
}
add_action('init', 'schedule_backup_check');

add_action('wpfs_backup_verification', function() {
    $backup_dir = WP_CONTENT_DIR . '/backups/';

    // Check for recent backup
    $recent_backup = false;
    $files = glob($backup_dir . '*.zip');

    foreach ($files as $file) {
        $age_days = (time() - filemtime($file)) / DAY_IN_SECONDS;
        if ($age_days < 7) {
            $recent_backup = true;

            // Verify integrity
            $zip = new ZipArchive();
            if ($zip->open($file) !== true) {
                wp_mail(
                    get_option('admin_email'),
                    '[WARNING] Backup File Corrupted',
                    "Backup file appears corrupted: {$file}"
                );
            }
            $zip->close();
            break;
        }
    }

    if (!$recent_backup) {
        wp_mail(
            get_option('admin_email'),
            '[WARNING] No Recent Backup Found',
            'No backup file found in the last 7 days. Please verify your backup system.'
        );
    }
});

SSL Certificate Monitoring

// Check SSL certificate expiration
function schedule_ssl_check() {
    if (!wp_next_scheduled('wpfs_ssl_check')) {
        wp_schedule_event(time(), 'daily', 'wpfs_ssl_check');
    }
}
add_action('init', 'schedule_ssl_check');

add_action('wpfs_ssl_check', function() {
    $domain = parse_url(home_url(), PHP_URL_HOST);
    $context = stream_context_create(array(
        'ssl' => array('capture_peer_cert' => true),
    ));

    $stream = @stream_socket_client(
        "ssl://{$domain}:443",
        $errno, $errstr, 30,
        STREAM_CLIENT_CONNECT, $context
    );

    if (!$stream) {
        wp_mail(get_option('admin_email'), '[CRITICAL] SSL Connection Failed', $errstr);
        return;
    }

    $params = stream_context_get_params($stream);
    $cert = openssl_x509_parse($params['options']['ssl']['peer_certificate']);
    fclose($stream);

    $expires = $cert['validTo_time_t'];
    $days_until_expiry = ($expires - time()) / DAY_IN_SECONDS;

    if ($days_until_expiry < 14) {
        wp_mail(
            get_option('admin_email'),
            '[WARNING] SSL Certificate Expiring Soon',
            "SSL certificate expires in {$days_until_expiry} days. Please renew immediately."
        );
    }
});

Blocked IP Cleanup

// Clean expired IP blocks
add_action('wpfs_hourly_cleanup', function() {
    $blocked_ips = get_option('wpfs_blocked_ips', array());
    $updated = false;

    foreach ($blocked_ips as $ip => $data) {
        if (isset($data['expires']) && $data['expires'] < time()) {
            unset($blocked_ips[$ip]);
            $updated = true;
        }
    }

    if ($updated) {
        update_option('wpfs_blocked_ips', $blocked_ips);
    }
});

// Schedule hourly cleanup
if (!wp_next_scheduled('wpfs_hourly_cleanup')) {
    wp_schedule_event(time(), 'hourly', 'wpfs_hourly_cleanup');
}

Conclusion

Automated security tasks ensure continuous protection. Schedule malware scanning, log cleanup, backup verification, and SSL monitoring through cron jobs for reliable unattended security maintenance.

Share:
S
Written by Sarah Chen

WP Folder Shield Team

Related Articles

SEO Spam Injection: How to Detect Hidden Links and Malicious Redirects
SEO Spam Injection: How to Detect Hidden Links and Malicious Redirects

Learn how hackers inject hidden links and malicious redirects into WordPress sites to steal your...

January 18, 2026
Understanding WordPress Malware Signatures and Detection Patterns
Understanding WordPress Malware Signatures and Detection Patterns

Learn how malware scanners detect threats using signatures and patterns. Understand the technology...

January 15, 2026
Country Blocking for WooCommerce: Protect Your Online Store
Country Blocking for WooCommerce: Protect Your Online Store

Learn how to implement country blocking for WooCommerce stores. Prevent fraud, reduce chargebacks...

January 10, 2026

Ready to Secure Your WordPress Site?

Get complete protection with WP Folder Shield.

Get Started