' . esc_html( $message ) . '

'; $information .= ''; // Loop through all vulnerabilities for the current version. $core_vuln_array = is_array( $core_vulnerabilities ) ? $core_vulnerabilities : array(); foreach ( $core_vuln_array as $vulnerability ) { if ( ! is_array( $vulnerability ) ) { continue; } $vuln_impact_raw = $vulnerability['impact'] ?? null; $vuln_impact = is_array( $vuln_impact_raw ) ? $vuln_impact_raw : array(); $vuln_cvss_raw = $vuln_impact['cvss'] ?? null; $vuln_cvss = is_array( $vuln_cvss_raw ) ? $vuln_cvss_raw : array(); $vuln_cvss2_raw = $vuln_impact['cvss2'] ?? null; $vuln_cvss2 = is_array( $vuln_cvss2_raw ) ? $vuln_cvss2_raw : array(); $vuln_cvss3_raw = $vuln_impact['cvss3'] ?? null; $vuln_cvss3 = is_array( $vuln_cvss3_raw ) ? $vuln_cvss3_raw : array(); $vuln_cvss4_raw = $vuln_impact['cvss4'] ?? null; $vuln_cvss4 = is_array( $vuln_cvss4_raw ) ? $vuln_cvss4_raw : array(); $vuln_ssvc_raw = $vuln_impact['ssvc'] ?? null; $vuln_ssvc = is_array( $vuln_ssvc_raw ) ? $vuln_ssvc_raw : array(); $vuln_cwe_raw = $vuln_impact['cwe'] ?? null; $vuln_cwe = is_array( $vuln_cwe_raw ) ? $vuln_cwe_raw : array(); $vuln_src_raw = $vulnerability['source'] ?? null; $vuln_sources = is_array( $vuln_src_raw ) ? $vuln_src_raw : array(); $kev = ( isset( $vuln_ssvc['kev'] ) && true === $vuln_ssvc['kev'] ); $exploitation = isset( $vuln_ssvc['exploitation'] ) && is_string( $vuln_ssvc['exploitation'] ) ? $vuln_ssvc['exploitation'] : ''; $automatable = isset( $vuln_ssvc['automatable'] ) && is_string( $vuln_ssvc['automatable'] ) ? $vuln_ssvc['automatable'] : ''; $kev_date_raw = $vuln_ssvc['kev_date'] ?? null; $kev_date = is_string( $kev_date_raw ) && '' !== $kev_date_raw ? $kev_date_raw : null; $epss_raw = $vuln_impact['epss'] ?? null; $epss = is_numeric( $epss_raw ) ? (float) $epss_raw : null; $description = wpvulnerability_get_source_description( $vuln_sources ); $what = array(); foreach ( $vuln_cwe as $vulnerability_cwe ) { if ( ! is_array( $vulnerability_cwe ) ) { continue; } $cwe_name = is_scalar( $vulnerability_cwe['name'] ?? '' ) ? (string) ( $vulnerability_cwe['name'] ?? '' ) : ''; $cwe_desc = is_scalar( $vulnerability_cwe['description'] ?? '' ) ? (string) ( $vulnerability_cwe['description'] ?? '' ) : ''; $what[] = '
' . wp_kses( $cwe_name, 'strip' ) . '
' . esc_html( $cwe_desc ) . '
'; } $source_pills = wpvulnerability_render_source_pills( $vuln_sources ); // Best available CVSS score and severity: cvss4 > cvss3 > cvss2 > legacy cvss. $score = null; $sev_raw = null; foreach ( array( $vuln_cvss4, $vuln_cvss3, $vuln_cvss2, $vuln_cvss ) as $cvss_c ) { if ( empty( $cvss_c ) ) { continue; } $s_raw = $cvss_c['score'] ?? null; $v_raw = $cvss_c['severity'] ?? null; $s = is_numeric( $s_raw ) ? number_format( (float) $s_raw, 1, '.', '' ) : null; $v = is_string( $v_raw ) && '' !== $v_raw ? $v_raw : null; if ( null !== $s || null !== $v ) { $score = $s; $sev_raw = $v; break; } } $vuln_name = is_scalar( $vulnerability['name'] ?? '' ) ? (string) ( $vulnerability['name'] ?? '' ) : ''; $score_badge = wpvulnerability_render_score_badge( $score, $sev_raw, $epss ); $show_active = $kev || 'active' === $exploitation; $show_poc = 'poc' === $exploitation; $show_auto = 'yes' === $automatable; $information .= ''; $information .= ''; $information .= ''; $information .= ''; } $information .= '
WordPress ' . wp_kses( $vuln_name, 'strip' ) . ''; if ( $show_active || $show_poc || $show_auto || '' !== $score_badge ) { $information .= '
'; if ( $show_active ) { $information .= '⚠ ' . esc_html__( 'Actively exploited', 'wpvulnerability' ); if ( $kev && null !== $kev_date ) { $information .= ' · ' . esc_html( $kev_date ); } $information .= ''; } if ( $show_poc ) { $information .= '⚡ ' . esc_html__( 'Public exploit', 'wpvulnerability' ) . ''; } if ( $show_auto ) { $information .= '⚙ ' . esc_html__( 'Automatable', 'wpvulnerability' ) . ''; } if ( '' !== $score_badge ) { $information .= $score_badge; } $information .= '
'; } if ( null !== $description ) { $information .= '
' . esc_html( $description ) . '
'; } if ( count( $what ) ) { $information .= '
' . implode( '', $what ) . '
'; } if ( '' !== $source_pills ) { $information .= '
' . esc_html__( 'References:', 'wpvulnerability' ) . ''; $information .= $source_pills; $information .= '
'; } $information .= '
'; echo $information; // phpcs:ignore } /** * Retrieves vulnerabilities for a given WordPress core version and updates its data. * * @since 2.0.0 * * @return array>|false The updated core data array or false if no vulnerabilities are found. */ function wpvulnerability_get_fresh_core_vulnerabilities() { // Get the core version and sanitize it. $version = wpvulnerability_sanitize_version( get_bloginfo( 'version' ) ); // Retrieve vulnerabilities for the core version. $response = wpvulnerability_get_core( $version, 0 ); $core_data = array(); // If no vulnerabilities are found, return false. if ( empty( $response ) ) { return false; } // If vulnerabilities are found, update the core data. foreach ( $response as $v ) { if ( isset( $v['name'], $v['source'], $v['impact'] ) ) { // Ensure expected keys exist. $core_data[] = array( 'name' => wp_kses( is_scalar( $v['name'] ) ? (string) $v['name'] : '', 'strip' ), 'source' => $v['source'], 'impact' => $v['impact'], 'uuid' => is_scalar( $v['uuid'] ?? '' ) ? (string) ( $v['uuid'] ?? '' ) : '', ); } } return ! empty( $core_data ) ? $core_data : false; // Return false if core_data is empty. } /** * Get Vulnerabilities * * Retrieves and caches the vulnerabilities for the installed WordPress core version. * * @since 2.0.0 * * @return string JSON-encoded array of core data with vulnerabilities and vulnerable status. */ function wpvulnerability_core_get_installed() { $wpvulnerability_core_vulnerable = 0; $current_version = wpvulnerability_sanitize_version( get_bloginfo( 'version' ) ); // Get fresh core vulnerabilities. $core = wpvulnerability_get_fresh_core_vulnerabilities(); // Check if vulnerabilities were found and count them. if ( is_array( $core ) && count( $core ) > 0 ) { $wpvulnerability_core_vulnerable = count( $core ); } // Cache the vulnerability data and the timestamp for cache expiration. if ( is_multisite() ) { update_site_option( 'wpvulnerability-core', wp_json_encode( $core ) ); update_site_option( 'wpvulnerability-core-vulnerable', wp_json_encode( number_format( $wpvulnerability_core_vulnerable, 0, '.', '' ) ) ); update_site_option( 'wpvulnerability-core-cache', wp_json_encode( number_format( time() + ( 3600 * wpvulnerability_cache_hours() ), 0, '.', '' ) ) ); update_site_option( 'wpvulnerability-core-version', wp_json_encode( $current_version ) ); } else { update_option( 'wpvulnerability-core', wp_json_encode( $core ), false ); update_option( 'wpvulnerability-core-vulnerable', wp_json_encode( number_format( $wpvulnerability_core_vulnerable, 0, '.', '' ) ), false ); update_option( 'wpvulnerability-core-cache', wp_json_encode( number_format( time() + ( 3600 * wpvulnerability_cache_hours() ), 0, '.', '' ) ), false ); update_option( 'wpvulnerability-core-version', wp_json_encode( $current_version ), false ); } // Return the JSON-encoded array of core vulnerabilities. $encoded = wp_json_encode( $core ); return false !== $encoded ? $encoded : ''; } /** * Get cached core vulnerabilities without refreshing external data. * * @since 2.0.0 * @since 4.1.2 Refreshes when the stored WordPress core version differs from the running version. * * @return array Array of core with their vulnerabilities. */ function wpvulnerability_core_get_vulnerabilities() { if ( is_multisite() ) { $raw = get_site_option( 'wpvulnerability-core' ); $core_data = json_decode( is_string( $raw ) ? $raw : '', true ); } else { $raw = get_option( 'wpvulnerability-core' ); $core_data = json_decode( is_string( $raw ) ? $raw : '', true ); } return is_array( $core_data ) ? $core_data : array(); } /** * Update the core cache and remove any old cache data. * * @since 2.0.0 * * @return void */ function wpvulnerability_core_get_vulnerabilities_clean() { wpvulnerability_clear_cache( 'core' ); wpvulnerability_core_get_installed(); } /** * Adds vulnerability information after the core version and notices on the update-core.php page. * * @since 2.0.0 * * @return void */ function wpvulnerability_core_page() { // Check if the current page is the update-core.php page. global $pagenow; if ( wpvulnerability_analyze_filter( 'core' ) && 'update-core.php' === $pagenow && wpvulnerability_capabilities() ) { // Get the vulnerabilities for the core. $core = wpvulnerability_core_get_vulnerabilities(); // If there are vulnerabilities, add an action to display them after the core auto updates settings. if ( ! empty( $core ) ) { add_action( 'after_core_auto_updates_settings', 'wpvulnerability_core_info_after' ); } } } // Add notices for vulnerable core on the core page. add_action( 'admin_head', 'wpvulnerability_core_page' );