Security

Serialization Safety

WPZylos Queue uses PHP's serialize() / unserialize() to store and restore job objects. This is a well-known attack vector if untrusted data reaches the unserialize() call.

Mitigations

  1. Database-only payloads — Job payloads are stored in and read from the database, not from user input.
  2. Type checking — The worker verifies that the unserialized object is an instance of Job before calling handle().
  3. Error suppression@unserialize() is used to prevent warnings from corrupt payloads.

Recommendations

  • Restrict database access — Ensure only the WordPress database user can read/write queue tables.
  • Use allowlists — In PHP 8.0+, consider extending the worker to use unserialize($payload, ['allowed_classes' => [Job::class, ...]]).
  • Monitor failures — Regularly check the queue_failures table for unusual payloads.

SQL Injection Prevention

All database queries use the Connection wrapper, which relies on WordPress $wpdb->prepare() for parameterized queries. Table names are generated by ContextInterface::tableName() and are not user-controlled.

Job Data Validation

Always validate and sanitize data within your handle() method:

public function handle(): void
{
    $user = get_userdata($this->userId);
    
    if (!$user) {
        throw new \RuntimeException("User {$this->userId} not found");
    }

    $email = sanitize_email($user->user_email);
    
    if (!is_email($email)) {
        throw new \RuntimeException("Invalid email for user {$this->userId}");
    }

    wp_mail($email, 'Subject', 'Body');
}

Atomic Locking

The worker uses UPDATE ... WHERE reserved_at IS NULL to prevent two concurrent workers from processing the same job. This is atomic at the database level and prevents duplicate execution.

Timeout Protection

Jobs set set_time_limit() before execution to prevent runaway processes. However, this only works in environments where set_time_limit() is available (not in safe mode or some hosting configurations).

Failure Information Disclosure

The queue_failures table stores full exception traces, which may contain sensitive information (file paths, variable contents). Ensure:

  • The failures table is not exposed via any API endpoint
  • Failed job data is periodically cleaned up
  • Exception messages don't leak sensitive configuration values

Recommendations Summary

PracticePriority
Validate data in handle()Critical
Restrict DB table accessHigh
Monitor failures tableHigh
Clean up old failuresMedium
Use unserialize allowlistsMedium
Set appropriate timeoutsMedium
Avoid storing secrets in job propertiesHigh