• Hi Solid Security team,

    I maintain a client site that’s hitting a fatal PHP error

    Environment

    • WordPress 7.0
    • PHP 8.x
    • Solid Security (better-wp-security)

    What happens
    When the scheduled “digest” notification fires, the plugin crashes while building the lockouts summary section of the email. The fatal call is preg_replace() being passed a string pattern but an array replacement — PHP 8 requires the pattern to also be an array in that case. The user_count tag appears to be passed into replace_tag() as an array rather than a scalar.

    Error
    Uncaught TypeError: preg_replace(): Argument #1 ($pattern) must be of type array when argument #2 ($replacement) is an array, string given in …/wp-content/plugins/better-wp-security/core/lib.php:983

    Stack trace (condensed)
    preg_replace() — core/lib.php:983 (fatal)
    ITSEC_Lib::replace_tag(‘/{{ $user_coun…/’, ‘user_count’, Array) — core/lib.php:983
    ITSEC_Lib::replace_tags(…) — core/lib.php:996
    ITSEC_Mail->replace_all(…) — core/lib/class-itsec-mail.php:946
    ITSEC_Mail->add_lockouts_summary(Array, Array) — core/lib/class-itsec-mail.php:330
    ITSEC_Notify->send_daily_digest(…) — core/notify.php:156
    ITSEC_Notification_Center->send_scheduled_notification(‘digest’)
    (triggered via the init hook / WP-Cron)

    Thanks!

Viewing 3 replies - 1 through 3 (of 3 total)
  • Plugin Support Pawel [SolidWP Support]

    (@solidwppawel)

    Hi @espressivo,

    Thanks for the detailed trace, that made this quick to pin down.

    You’re right that user_count is reaching replace_tag() as an array, but the array is created upstream of the mailer, in ITSEC_Lockout::get_lockouts() (core/lockout.php). When the digest runs, send_daily_digest() asks for the lockout counts like this:

    $user_count = $itsec_lockout->get_lockouts( 'user', array( 'after' => $last_sent, 'current' => false, 'return' => 'count' ) );

    Inside get_lockouts(), the count path is guarded this way:

    if ( $is_count && $results ) {
    return $results[0]['COUNT'];
    }
    // ...falls through...
    return $results;

    A SELECT COUNT(1) query always returns exactly one row (with COUNT = 0) when it runs successfully, so under normal conditions you get a scalar 0 back. The only way $results comes back empty here is when that query fails to execute at all, which on this plugin means the lockouts table ({prefix}itsec_lockouts) is missing or damaged on the site. When that happens the count branch is skipped and the method returns an empty array() instead of 0.

    That empty array then slips past the if ( $host_count > 0 || $user_count > 0 ) check in send_daily_digest() (in PHP an array compares as greater than 0), so add_lockouts_summary() runs with arrays, and they land in preg_replace() as the replacement value, giving you the PHP 8 TypeError at lib.php:983.

    So the fatal is really a symptom: the digest is blowing up because the lockouts table isn’t returning data. To get the site healthy:

    1. Check the table. Adjust the prefix if the site isn’t on wp_:
      SHOW TABLES LIKE 'wp_itsec_lockouts';
      and, if it exists:
      CHECK TABLE wp_itsec_lockouts;
    2. If it’s missing or reports as corrupt, regenerate it. Deactivating and reactivating Kadence Security re-runs the schema setup and recreates any missing tables without touching your settings. If CHECK TABLE flagged corruption, run REPAIR TABLE wp_itsec_lockouts; first.
    3. Let the digest run again (or trigger the cron event manually) and confirm the fatal is gone.

    I’d take a quick database backup before the repair/regenerate step, just as standard practice.

    If the table checks out clean and you still hit this, paste the output of the two SQL checks above and I’ll dig in further.

    Best regards,

    Pawel P.

    Liquid Web Software Support

    Thread Starter espressivo

    (@espressivo)

    For now deleting and reinstalling the plugin seems to work. I’ll keep you updated

    Hi @espressivo,

    If you require no further assistance please mark this topic as ‘Resolved’.

Viewing 3 replies - 1 through 3 (of 3 total)

You must be logged in to reply to this topic.