v5.1.1
This commit is contained in:
parent
31f7e97d39
commit
db98c4438c
12 changed files with 123 additions and 133 deletions
|
|
@ -1,5 +1,25 @@
|
|||
== Changelog ==
|
||||
|
||||
= [5.1.1] - 2026-07-09 =
|
||||
|
||||
**Fixed**
|
||||
|
||||
* Site Health: the memcached, Redis, and SQLite vulnerability tests always returned "Invalid software type" because those components were missing from the software list. They now run correctly.
|
||||
* "Send test email" failed when no email recipients were configured: the forced-test path added the admin email but the send gate used a flag computed before the override. The test email now sends.
|
||||
* "Run notification now" reported failure when only webhook channels (Slack/Teams/Discord/Telegram) were enabled and email was disabled. The notification result now reflects whether any channel delivered successfully.
|
||||
* Weekly notification cron events were never auto-scheduled, because the `weekly` cron schedule was registered only at `init` while the on-load scheduling runs earlier. The weekly/daily schedule registration moved to the always-loaded scheduler so weekly notifications schedule correctly.
|
||||
* Deactivation deleted the per-component analysis settings (`wpvulnerability-analyze`), so deactivating and reactivating reset which components were hidden. Analysis settings are now preserved on deactivation (only uninstall removes them).
|
||||
* The debug "Cron Status" panel always showed the notification event as "not scheduled" because it checked the wrong hook name (`wpvulnerability_send_notification` instead of `wpvulnerability_notification`).
|
||||
* The debug "last run" timestamp was always empty because it read a `wpvulnerability-logs` option that is never written; it now reads the most recent API log entry.
|
||||
* Redis detection called `close()` twice on the success path (once in the `try` block, once in `finally`); the redundant close was removed.
|
||||
* The single-site vulnerable-themes count was hardcoded to `0` instead of reading the stored option.
|
||||
|
||||
**Changed**
|
||||
|
||||
* Single-site email recipient sanitization now uses `is_email()` for strict validation, matching the multisite behaviour.
|
||||
* Removed a redundant nonce field from the single-site "Reset Plugin" form (the form only submits the full-reset action).
|
||||
* Removed dead code: the unused `wpvulnerability_sanitize_messages` callback and its setting registration, and an unused `$tools_action` variable in the multisite admin.
|
||||
|
||||
= [5.1.0] - 2026-07-08 =
|
||||
|
||||
**Security**
|
||||
|
|
|
|||
24
readme.txt
24
readme.txt
|
|
@ -3,9 +3,9 @@ Contributors: javiercasares, davidperez, lbonomo, alexclassroom
|
|||
Tags: security, vulnerability, site-health
|
||||
Requires at least: 5.6
|
||||
Tested up to: 7.1
|
||||
Stable tag: 5.1.0
|
||||
Stable tag: 5.1.1
|
||||
Requires PHP: 7.0
|
||||
Version: 5.1.0
|
||||
Version: 5.1.1
|
||||
License: GPL-3.0-or-later
|
||||
License URI: https://spdx.org/licenses/GPL-3.0-or-later.html
|
||||
|
||||
|
|
@ -201,6 +201,26 @@ First of all, peace of mind. Investigate what the vulnerability is and, above al
|
|||
|
||||
== Changelog ==
|
||||
|
||||
= [5.1.1] - 2026-07-09 =
|
||||
|
||||
**Fixed**
|
||||
|
||||
* Site Health: the memcached, Redis, and SQLite vulnerability tests always returned "Invalid software type" because those components were missing from the software list. They now run correctly.
|
||||
* "Send test email" failed when no email recipients were configured: the forced-test path added the admin email but the send gate used a flag computed before the override. The test email now sends.
|
||||
* "Run notification now" reported failure when only webhook channels (Slack/Teams/Discord/Telegram) were enabled and email was disabled. The notification result now reflects whether any channel delivered successfully.
|
||||
* Weekly notification cron events were never auto-scheduled, because the `weekly` cron schedule was registered only at `init` while the on-load scheduling runs earlier. The weekly/daily schedule registration moved to the always-loaded scheduler so weekly notifications schedule correctly.
|
||||
* Deactivation deleted the per-component analysis settings (`wpvulnerability-analyze`), so deactivating and reactivating reset which components were hidden. Analysis settings are now preserved on deactivation (only uninstall removes them).
|
||||
* The debug "Cron Status" panel always showed the notification event as "not scheduled" because it checked the wrong hook name (`wpvulnerability_send_notification` instead of `wpvulnerability_notification`).
|
||||
* The debug "last run" timestamp was always empty because it read a `wpvulnerability-logs` option that is never written; it now reads the most recent API log entry.
|
||||
* Redis detection called `close()` twice on the success path (once in the `try` block, once in `finally`); the redundant close was removed.
|
||||
* The single-site vulnerable-themes count was hardcoded to `0` instead of reading the stored option.
|
||||
|
||||
**Changed**
|
||||
|
||||
* Single-site email recipient sanitization now uses `is_email()` for strict validation, matching the multisite behaviour.
|
||||
* Removed a redundant nonce field from the single-site "Reset Plugin" form (the form only submits the full-reset action).
|
||||
* Removed dead code: the unused `wpvulnerability_sanitize_messages` callback and its setting registration, and an unused `$tools_action` variable in the multisite admin.
|
||||
|
||||
= [5.1.0] - 2026-07-08 =
|
||||
|
||||
**Security**
|
||||
|
|
|
|||
|
|
@ -1437,7 +1437,6 @@ function wpvulnerability_render_admin_tab_tools() {
|
|||
<strong style="color: #b32d2e;"><?php esc_html_e( 'This action cannot be undone.', 'wpvulnerability' ); ?></strong>
|
||||
</p>
|
||||
<form method="post" action="<?php echo esc_url( $tools_action ); ?>" onsubmit="return confirm('<?php echo esc_js( __( 'Are you sure you want to reset all WPVulnerability data? This action cannot be undone.', 'wpvulnerability' ) ); ?>');">
|
||||
<?php wp_nonce_field( 'wpvulnerability_reset_action', 'wpvulnerability_reset_nonce' ); ?>
|
||||
<?php wp_nonce_field( 'wpvulnerability_full_reset_action', 'wpvulnerability_full_reset_nonce' ); ?>
|
||||
<input type="submit" name="wpvulnerability_full_reset" value="<?php esc_attr_e( 'Reset Plugin', 'wpvulnerability' ); ?>" class="button button-delete">
|
||||
</form>
|
||||
|
|
@ -2211,7 +2210,7 @@ function wpvulnerability_admin_sanitize( $input ) {
|
|||
foreach ( $input_email_text as $input_email ) {
|
||||
$input_email = sanitize_email( trim( (string) $input_email ) );
|
||||
|
||||
if ( $input_email ) {
|
||||
if ( is_email( $input_email ) ) {
|
||||
$input_emails[] = $input_email;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1447,14 +1447,6 @@ function wpvulnerability_render_network_admin_tab_logs() {
|
|||
function wpvulnerability_render_network_admin_tab_tools() {
|
||||
global $wpvulnerability_settings;
|
||||
|
||||
$tools_action = add_query_arg(
|
||||
array(
|
||||
'page' => 'wpvulnerability-options',
|
||||
'tab' => 'tools',
|
||||
),
|
||||
network_admin_url( 'settings.php' )
|
||||
);
|
||||
|
||||
$wpvulnerability_cron_config = is_multisite() ? get_site_option( 'wpvulnerability-config', array() ) : get_option( 'wpvulnerability-config', array() );
|
||||
if ( ! is_array( $wpvulnerability_cron_config ) ) {
|
||||
$wpvulnerability_cron_config = array();
|
||||
|
|
@ -2959,24 +2951,6 @@ function wpvulnerability_sanitize_config( $input ) {
|
|||
return $sanitized;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sanitizes the messages generated by the plugin (simple messages).
|
||||
*
|
||||
* @since 2.0.0
|
||||
*
|
||||
* @param array<string, mixed> $input Input values.
|
||||
* @return array<string, string> Sanitized values.
|
||||
*/
|
||||
function wpvulnerability_sanitize_messages( $input ) {
|
||||
$sanitized = array();
|
||||
|
||||
foreach ( $input as $key => $message ) {
|
||||
$sanitized[ sanitize_key( (string) $key ) ] = sanitize_text_field( is_scalar( $message ) ? (string) $message : '' );
|
||||
}
|
||||
|
||||
return $sanitized;
|
||||
}
|
||||
|
||||
/**
|
||||
* Strictly sanitizes the analysis options (booleans).
|
||||
*
|
||||
|
|
@ -3037,18 +3011,6 @@ function wpvulnerability_admin_init() {
|
|||
)
|
||||
);
|
||||
|
||||
// Register messages.
|
||||
register_setting(
|
||||
'admin_wpvulnerability_settings',
|
||||
'wpvulnerability-messages',
|
||||
array(
|
||||
'sanitize_callback' => 'wpvulnerability_sanitize_messages',
|
||||
'default' => array(),
|
||||
'show_in_rest' => false,
|
||||
'type' => 'array',
|
||||
)
|
||||
);
|
||||
|
||||
// Add a section to the settings page.
|
||||
add_settings_section(
|
||||
'admin_wpvulnerability_settings',
|
||||
|
|
|
|||
|
|
@ -494,7 +494,7 @@ function wpvulnerability_debug_get_cron_status() {
|
|||
'scheduled' => false,
|
||||
),
|
||||
'send_notification' => array(
|
||||
'hook' => 'wpvulnerability_send_notification',
|
||||
'hook' => 'wpvulnerability_notification',
|
||||
'next_run' => null,
|
||||
'last_run' => null,
|
||||
'scheduled' => false,
|
||||
|
|
@ -509,28 +509,28 @@ function wpvulnerability_debug_get_cron_status() {
|
|||
}
|
||||
|
||||
// Check notification cron.
|
||||
$next_notification = wp_next_scheduled( 'wpvulnerability_send_notification' );
|
||||
$next_notification = wp_next_scheduled( 'wpvulnerability_notification' );
|
||||
if ( $next_notification ) {
|
||||
$cron_status['send_notification']['next_run'] = $next_notification;
|
||||
$cron_status['send_notification']['scheduled'] = true;
|
||||
}
|
||||
|
||||
// Try to get last run times from logs.
|
||||
$logs_raw = is_multisite() ? get_site_option( 'wpvulnerability-logs', array() ) : get_option( 'wpvulnerability-logs', array() );
|
||||
$logs = is_array( $logs_raw ) ? $logs_raw : array();
|
||||
if ( ! empty( $logs ) ) {
|
||||
// Get the most recent log entry for each type.
|
||||
foreach ( array_reverse( $logs ) as $log ) {
|
||||
if ( ! is_array( $log ) ) {
|
||||
continue; }
|
||||
if ( isset( $log['time'] ) && isset( $log['url'] ) ) {
|
||||
$timestamp = $log['time'];
|
||||
|
||||
// Check if this is an update-related log.
|
||||
if ( ! $cron_status['update_database']['last_run'] ) {
|
||||
$cron_status['update_database']['last_run'] = $timestamp;
|
||||
}
|
||||
}
|
||||
// Last run = most recent API response log (stored as the wpvulnerability_log CPT).
|
||||
$last_log = get_posts(
|
||||
array(
|
||||
'post_type' => 'wpvulnerability_log',
|
||||
'post_status' => 'any',
|
||||
'posts_per_page' => 1,
|
||||
'orderby' => 'date',
|
||||
'order' => 'DESC',
|
||||
'fields' => 'ids',
|
||||
'no_found_rows' => true,
|
||||
)
|
||||
);
|
||||
if ( ! empty( $last_log ) ) {
|
||||
$timestamp = get_post_timestamp( $last_log[0] );
|
||||
if ( false !== $timestamp ) {
|
||||
$cron_status['update_database']['last_run'] = $timestamp;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1070,10 +1070,6 @@ function wpvulnerability_detect_redis() {
|
|||
$result['method'] = 'redis_extension';
|
||||
$result['reliability'] = 90;
|
||||
|
||||
if ( $temporary_connection ) {
|
||||
$redis_client->close();
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -9,60 +9,6 @@
|
|||
|
||||
defined( 'ABSPATH' ) || die( 'No script kiddies please!' );
|
||||
|
||||
/**
|
||||
* Adds a custom schedule for a weekly cron job.
|
||||
*
|
||||
* This function adds a new schedule interval of one week (604800 seconds)
|
||||
* to the system's available cron schedules. It allows tasks to be scheduled
|
||||
* to run every week using the 'weekly' interval.
|
||||
*
|
||||
* @since 2.0.0
|
||||
*
|
||||
* @param array<string, array<string, int|string>> $schedules The existing system schedules.
|
||||
*
|
||||
* @return array<string, array<string, int|string>> The updated list of schedules with the added weekly interval.
|
||||
*/
|
||||
function wpvulnerability_add_every_week( $schedules ) {
|
||||
// Add a weekly schedule interval of 604800 seconds (1 week).
|
||||
// Use did_action('init') guard: cron_schedules fires before init (WP 6.7+ textdomain notice).
|
||||
$schedules['weekly'] = array(
|
||||
'interval' => 604800,
|
||||
'display' => did_action( 'init' ) ? __( 'Every week', 'wpvulnerability' ) : 'Every week',
|
||||
);
|
||||
|
||||
// Return the modified list of schedules.
|
||||
return $schedules;
|
||||
}
|
||||
// Hook the function to the 'cron_schedules' filter to add the custom schedule.
|
||||
add_filter( 'cron_schedules', 'wpvulnerability_add_every_week' );
|
||||
|
||||
/**
|
||||
* Adds a custom schedule for daily events.
|
||||
*
|
||||
* This function adds a new schedule interval of one day (86400 seconds)
|
||||
* to the system's available cron schedules. It allows tasks to be scheduled
|
||||
* to run every day using the 'daily' interval.
|
||||
*
|
||||
* @since 2.0.0
|
||||
*
|
||||
* @param array<string, array<string, int|string>> $schedules List of available schedules.
|
||||
*
|
||||
* @return array<string, array<string, int|string>> Modified list of available schedules with the added daily interval.
|
||||
*/
|
||||
function wpvulnerability_add_every_day( $schedules ) {
|
||||
// Define a new schedule with a 24 hour interval.
|
||||
// Use did_action('init') guard: cron_schedules fires before init (WP 6.7+ textdomain notice).
|
||||
$schedules['daily'] = array(
|
||||
'interval' => 86400,
|
||||
'display' => did_action( 'init' ) ? __( 'Every day', 'wpvulnerability' ) : 'Every day',
|
||||
);
|
||||
|
||||
// Return the modified list of schedules.
|
||||
return $schedules;
|
||||
}
|
||||
// Hook the function to the 'cron_schedules' filter to add the custom schedule.
|
||||
add_filter( 'cron_schedules', 'wpvulnerability_add_every_day' );
|
||||
|
||||
/**
|
||||
* Disables email notifications when requested via URL.
|
||||
*
|
||||
|
|
@ -715,7 +661,7 @@ function wpvulnerability_execute_notification( $forced = false ) {
|
|||
|
||||
$wpmail = false;
|
||||
|
||||
if ( $email_enabled ) {
|
||||
if ( $email_enabled || $forced ) {
|
||||
$mail_to = is_array( $wpvulnerability_settings['emails'] ) ? array_map(
|
||||
static function ( $e ) {
|
||||
return is_scalar( $e ) ? (string) $e : '';
|
||||
|
|
@ -728,23 +674,27 @@ function wpvulnerability_execute_notification( $forced = false ) {
|
|||
$text_message_body = wpvulnerability_html_to_plain_text( $email_content );
|
||||
$text_message = trim( (string) ( $email_subject . "\n\n" . $text_message_body ) );
|
||||
|
||||
if ( $slack_enabled ) {
|
||||
wpvulnerability_send_slack_notification( ( is_scalar( $wpvulnerability_settings['slack_webhook'] ) ? (string) $wpvulnerability_settings['slack_webhook'] : '' ), $text_message );
|
||||
// Track whether any webhook channel delivered successfully, so a webhook-only
|
||||
// notification (email disabled) is not reported as a failure.
|
||||
$webhook_sent = false;
|
||||
|
||||
if ( $slack_enabled && wpvulnerability_send_slack_notification( ( is_scalar( $wpvulnerability_settings['slack_webhook'] ) ? (string) $wpvulnerability_settings['slack_webhook'] : '' ), $text_message ) ) {
|
||||
$webhook_sent = true;
|
||||
}
|
||||
|
||||
if ( $teams_enabled ) {
|
||||
wpvulnerability_send_teams_notification( ( is_scalar( $wpvulnerability_settings['teams_webhook'] ) ? (string) $wpvulnerability_settings['teams_webhook'] : '' ), $text_message );
|
||||
if ( $teams_enabled && wpvulnerability_send_teams_notification( ( is_scalar( $wpvulnerability_settings['teams_webhook'] ) ? (string) $wpvulnerability_settings['teams_webhook'] : '' ), $text_message ) ) {
|
||||
$webhook_sent = true;
|
||||
}
|
||||
|
||||
if ( $discord_enabled ) {
|
||||
wpvulnerability_send_discord_notification( ( is_scalar( $wpvulnerability_settings['discord_webhook'] ) ? (string) $wpvulnerability_settings['discord_webhook'] : '' ), $text_message );
|
||||
if ( $discord_enabled && wpvulnerability_send_discord_notification( ( is_scalar( $wpvulnerability_settings['discord_webhook'] ) ? (string) $wpvulnerability_settings['discord_webhook'] : '' ), $text_message ) ) {
|
||||
$webhook_sent = true;
|
||||
}
|
||||
|
||||
if ( $telegram_enabled ) {
|
||||
wpvulnerability_send_telegram_notification( ( is_scalar( $wpvulnerability_settings['telegram_bot_token'] ) ? (string) $wpvulnerability_settings['telegram_bot_token'] : '' ), ( is_scalar( $wpvulnerability_settings['telegram_chat_id'] ) ? (string) $wpvulnerability_settings['telegram_chat_id'] : '' ), $text_message );
|
||||
if ( $telegram_enabled && wpvulnerability_send_telegram_notification( ( is_scalar( $wpvulnerability_settings['telegram_bot_token'] ) ? (string) $wpvulnerability_settings['telegram_bot_token'] : '' ), ( is_scalar( $wpvulnerability_settings['telegram_chat_id'] ) ? (string) $wpvulnerability_settings['telegram_chat_id'] : '' ), $text_message ) ) {
|
||||
$webhook_sent = true;
|
||||
}
|
||||
|
||||
return $wpmail;
|
||||
return $wpmail || $webhook_sent;
|
||||
}
|
||||
|
||||
// phpcs:disable WordPress.NamingConventions.ValidVariableName.UsedPropertyNotSnakeCase -- DOM properties follow upstream naming.
|
||||
|
|
|
|||
|
|
@ -365,7 +365,6 @@ function wpvulnerability_deactivation() {
|
|||
$options = array(
|
||||
'wpvulnerability_settings',
|
||||
'wpvulnerability-data',
|
||||
'wpvulnerability-analyze',
|
||||
'wpvulnerability-themes',
|
||||
'wpvulnerability-themes-cache',
|
||||
'wpvulnerability-themes-vulnerable',
|
||||
|
|
|
|||
|
|
@ -37,6 +37,47 @@ function wpvulnerability_add_every_six_hours( $schedules ) {
|
|||
return $schedules;
|
||||
}
|
||||
|
||||
// Add weekly and daily schedules used by the notification cron.
|
||||
// These must be registered in this file (always loaded pre-init) so that the
|
||||
// on-load notification scheduling at the bottom of this file can resolve the
|
||||
// 'weekly' schedule before notifications.php is loaded at init.
|
||||
add_filter( 'cron_schedules', 'wpvulnerability_add_every_week' );
|
||||
add_filter( 'cron_schedules', 'wpvulnerability_add_every_day' );
|
||||
|
||||
/**
|
||||
* Registers a custom weekly cron schedule.
|
||||
*
|
||||
* @since 2.0.0
|
||||
*
|
||||
* @param array<string, array<string, int|string>> $schedules Existing schedules.
|
||||
* @return array<string, array<string, int|string>> Schedules with the weekly interval added.
|
||||
*/
|
||||
function wpvulnerability_add_every_week( $schedules ) {
|
||||
$schedules['weekly'] = array(
|
||||
'interval' => 604800,
|
||||
'display' => did_action( 'init' ) ? __( 'Every week', 'wpvulnerability' ) : 'Every week',
|
||||
);
|
||||
|
||||
return $schedules;
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers a custom daily cron schedule.
|
||||
*
|
||||
* @since 2.0.0
|
||||
*
|
||||
* @param array<string, array<string, int|string>> $schedules Existing schedules.
|
||||
* @return array<string, array<string, int|string>> Schedules with the daily interval added.
|
||||
*/
|
||||
function wpvulnerability_add_every_day( $schedules ) {
|
||||
$schedules['daily'] = array(
|
||||
'interval' => 86400,
|
||||
'display' => did_action( 'init' ) ? __( 'Every day', 'wpvulnerability' ) : 'Every day',
|
||||
);
|
||||
|
||||
return $schedules;
|
||||
}
|
||||
|
||||
// Remove legacy scheduled events on subsites in multisite installs.
|
||||
if ( is_multisite() && ! is_main_site() ) {
|
||||
wpvulnerability_clear_plugin_cron_hooks();
|
||||
|
|
|
|||
|
|
@ -182,6 +182,9 @@ function wpvulnerability_test_software( $software ) {
|
|||
'mysql' => __( 'MySQL', 'wpvulnerability' ),
|
||||
'imagemagick' => __( 'ImageMagick', 'wpvulnerability' ),
|
||||
'curl' => __( 'curl', 'wpvulnerability' ),
|
||||
'memcached' => __( 'memcached', 'wpvulnerability' ),
|
||||
'redis' => __( 'Redis', 'wpvulnerability' ),
|
||||
'sqlite' => __( 'SQLite', 'wpvulnerability' ),
|
||||
);
|
||||
|
||||
if ( ! array_key_exists( $software, $software_list ) ) {
|
||||
|
|
|
|||
|
|
@ -687,7 +687,7 @@ function wpvulnerability_themes_view( $views ) {
|
|||
return $views;
|
||||
}
|
||||
|
||||
$raw_count = is_multisite() ? get_site_option( 'wpvulnerability-themes-vulnerable', '0' ) : '0';
|
||||
$raw_count = is_multisite() ? get_site_option( 'wpvulnerability-themes-vulnerable', '0' ) : get_option( 'wpvulnerability-themes-vulnerable', '0' );
|
||||
$wpvulnerability_themes_total = ( is_scalar( json_decode( is_string( $raw_count ) ? $raw_count : '0', true ) ) ? (int) json_decode( is_string( $raw_count ) ? $raw_count : '0', true ) : 0 );
|
||||
|
||||
if ( is_multisite() && is_network_admin() ) {
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@
|
|||
* Description: Receive information about possible vulnerabilities in your WordPress from WordPress Vulnerability Database API.
|
||||
* Requires at least: 5.6
|
||||
* Requires PHP: 7.0
|
||||
* Version: 5.1.0
|
||||
* Version: 5.1.1
|
||||
* Author: ROBOTSTXT
|
||||
* Author URI: https://www.robotstxt.es/
|
||||
* License: GPL-3.0-or-later
|
||||
|
|
@ -16,7 +16,7 @@
|
|||
*
|
||||
* @package WPVulnerability
|
||||
*
|
||||
* @version 5.1.0
|
||||
* @version 5.1.1
|
||||
*/
|
||||
|
||||
defined( 'ABSPATH' ) || die( 'No script kiddies please!' );
|
||||
|
|
@ -24,7 +24,7 @@ defined( 'ABSPATH' ) || die( 'No script kiddies please!' );
|
|||
/**
|
||||
* Set some constants that I can change in future versions.
|
||||
*/
|
||||
define( 'WPVULNERABILITY_PLUGIN_VERSION', '5.1.0' );
|
||||
define( 'WPVULNERABILITY_PLUGIN_VERSION', '5.1.1' );
|
||||
define( 'WPVULNERABILITY_API_HOST', 'https://www.wpvulnerability.net/' );
|
||||
|
||||
/**
|
||||
|
|
|
|||
Loading…
Reference in a new issue