response ) && 'upgrade' === $update->response ) { $needs_update = true; break; } } } global $wp_version; if ( $needs_update ) { return $this->fail( Aardwolf_Check_Result::SEVERITY_HIGH, sprintf( /* translators: %s: current WordPress version. */ __( 'This site runs WordPress %s and a newer release is available. Attackers actively scan for sites running versions with published vulnerabilities.', 'aardwolf-security-scanner' ), esc_html( $wp_version ) ), __( 'Update WordPress from Dashboard → Updates as soon as possible, ideally after taking a backup. Enable automatic background updates for minor/security releases by adding define( \'WP_AUTO_UPDATE_CORE\', \'minor\' ); to wp-config.php.', 'aardwolf-security-scanner' ), 'https://wordpress.org/documentation/article/updating-wordpress/' ); } return $this->pass( sprintf( /* translators: %s: current WordPress version. */ __( 'WordPress core (%s) is current.', 'aardwolf-security-scanner' ), esc_html( $wp_version ) ) ); } } /** * Plugins with available updates. */ class Aardwolf_Check_Plugin_Updates extends Aardwolf_Check { public function id() { return 'plugin_updates'; } public function label() { return __( 'Plugins are up to date', 'aardwolf-security-scanner' ); } public function category() { return __( 'Software Updates', 'aardwolf-security-scanner' ); } public function run() { if ( ! function_exists( 'get_plugin_updates' ) ) { require_once ABSPATH . 'wp-admin/includes/update.php'; } wp_update_plugins(); $updates = function_exists( 'get_plugin_updates' ) ? get_plugin_updates() : array(); $count = is_array( $updates ) ? count( $updates ) : 0; if ( $count > 0 ) { $names = array(); foreach ( $updates as $plugin ) { if ( isset( $plugin->Name ) ) { // phpcs:ignore WordPress.NamingConventions.ValidVariableName $names[] = $plugin->Name; // phpcs:ignore WordPress.NamingConventions.ValidVariableName } } return $this->fail( Aardwolf_Check_Result::SEVERITY_HIGH, sprintf( /* translators: 1: number of plugins, 2: comma separated plugin names. */ _n( '%1$d plugin needs updating: %2$s. Vulnerable plugins are the most common entry point for automated attacks.', '%1$d plugins need updating: %2$s. Vulnerable plugins are the most common entry point for automated attacks.', $count, 'aardwolf-security-scanner' ), $count, esc_html( implode( ', ', array_slice( $names, 0, 15 ) ) ) ), __( 'Update the listed plugins from Dashboard → Updates. Remove any plugin you no longer use — deactivated plugins still ship exploitable code. Consider enabling per-plugin auto-updates on the Plugins screen.', 'aardwolf-security-scanner' ), 'https://wordpress.org/documentation/article/manage-plugins/' ); } return $this->pass( __( 'All installed plugins are up to date.', 'aardwolf-security-scanner' ) ); } } /** * Themes with available updates. */ class Aardwolf_Check_Theme_Updates extends Aardwolf_Check { public function id() { return 'theme_updates'; } public function label() { return __( 'Themes are up to date', 'aardwolf-security-scanner' ); } public function category() { return __( 'Software Updates', 'aardwolf-security-scanner' ); } public function run() { if ( ! function_exists( 'get_theme_updates' ) ) { require_once ABSPATH . 'wp-admin/includes/update.php'; } wp_update_themes(); $updates = function_exists( 'get_theme_updates' ) ? get_theme_updates() : array(); $count = is_array( $updates ) ? count( $updates ) : 0; if ( $count > 0 ) { return $this->fail( Aardwolf_Check_Result::SEVERITY_MEDIUM, sprintf( /* translators: %d: number of themes. */ _n( '%d theme has an available update.', '%d themes have available updates.', $count, 'aardwolf-security-scanner' ), $count ), __( 'Update the affected themes from Dashboard → Updates and delete any unused themes (including the default bundled themes you do not need). An inactive theme with a vulnerability can still be exploited.', 'aardwolf-security-scanner' ), 'https://wordpress.org/documentation/article/work-with-themes/' ); } return $this->pass( __( 'All installed themes are up to date.', 'aardwolf-security-scanner' ) ); } } /** * Inactive plugins/themes still present on disk. */ class Aardwolf_Check_Unused_Extensions extends Aardwolf_Check { public function id() { return 'unused_extensions'; } public function label() { return __( 'No dormant (inactive) plugins or themes', 'aardwolf-security-scanner' ); } public function category() { return __( 'Software Updates', 'aardwolf-security-scanner' ); } public function run() { if ( ! function_exists( 'get_plugins' ) ) { require_once ABSPATH . 'wp-admin/includes/plugin.php'; } $all_plugins = array_keys( get_plugins() ); $active_plugins = (array) get_option( 'active_plugins', array() ); // Account for network-activated plugins on multisite. if ( is_multisite() ) { $network_active = array_keys( (array) get_site_option( 'active_sitewide_plugins', array() ) ); $active_plugins = array_merge( $active_plugins, $network_active ); } $inactive_plugins = array_diff( $all_plugins, $active_plugins ); $all_themes = wp_get_themes(); $active_theme = wp_get_theme(); $active_stylesheet = $active_theme->get_stylesheet(); $active_template = $active_theme->get_template(); // parent theme when a child is active. $inactive_themes = array(); foreach ( $all_themes as $stylesheet => $theme ) { if ( $stylesheet !== $active_stylesheet && $stylesheet !== $active_template ) { $inactive_themes[] = $stylesheet; } } $inactive_plugin_count = count( $inactive_plugins ); $inactive_theme_count = count( $inactive_themes ); if ( $inactive_plugin_count > 0 || $inactive_theme_count > 0 ) { return $this->warn( Aardwolf_Check_Result::SEVERITY_LOW, sprintf( /* translators: 1: inactive plugin count, 2: inactive theme count. */ __( 'Found %1$d inactive plugin(s) and %2$d inactive theme(s). Their code remains on disk and can be exploited even while deactivated.', 'aardwolf-security-scanner' ), $inactive_plugin_count, $inactive_theme_count ), __( 'Delete any plugins and themes you are not actively using. Keep at most one recent default theme as a fallback. Fewer components means a smaller attack surface.', 'aardwolf-security-scanner' ) ); } return $this->pass( __( 'No unnecessary inactive plugins or themes were found.', 'aardwolf-security-scanner' ) ); } }