=== WPVulnerability ===
Contributors: javiercasares, davidperez, lbonomo, alexclassroom
Tags: security, vulnerability, site-health
Requires at least: 5.6
Tested up to: 7.1
Stable tag: 5.0.1
Requires PHP: 7.0
Version: 5.0.1
License: GPL-3.0-or-later
License URI: https://spdx.org/licenses/GPL-3.0-or-later.html

Get WordPress vulnerability alerts from the [WPVulnerability Database API](https://www.wpvulnerability.com/).

== Description ==

This plugin integrates with the WPVulnerability API to provide real-time vulnerability assessments for your WordPress core, plugins, themes, PHP version, Apache HTTPD, nginx, MariaDB, MySQL, ImageMagick, curl, memcached, Redis, and SQLite.

It delivers detailed reports directly within your WordPress dashboard, helping you stay aware of potential security risks. Configure the plugin to send periodic notifications about your site's security status, ensuring you remain informed without being overwhelmed. Designed for ease of use, it supports proactive security measures without storing or retrieving any personal data from your site.

= Data reliability =

The information provided by the information database comes from different sources that have been reviewed by third parties. There is no liability of any kind for the information. Act at your own risk.

== Using the plugin ==

= WP-CLI =

You can use the following WP-CLI commands to manage and check vulnerabilities:

* Core: `wp wpvulnerability core`
* Plugins: `wp wpvulnerability plugins`
* Themes: `wp wpvulnerability themes`
* PHP: `wp wpvulnerability php`
* Apache HTTPD: `wp wpvulnerability apache`
* nginx: `wp wpvulnerability nginx`
* MariaDB: `wp wpvulnerability mariadb`
* MySQL: `wp wpvulnerability mysql`
* ImageMagick: `wp wpvulnerability imagemagick`
* curl: `wp wpvulnerability curl`
* memcached: `wp wpvulnerability memcached`
* Redis: `wp wpvulnerability redis`
* SQLite: `wp wpvulnerability sqlite`

To configure the plugin you can use:

* Hide component: `wp wpvulnerability config hide <component> [on|off]`
* Notification email: `wp wpvulnerability config email <emails>` (comma separatted)
* Notification period: `wp wpvulnerability config period <never|daily|weekly>`
* Log retention: `wp wpvulnerability config log-retention <0|1|7|14|28>` (in days)
* Cache duration: `wp wpvulnerability config cache <1|6|12|24>` (in hours)

All commands support the `--format` option to specify the output format:

* `--format=table`: Displays the results in a table format (default).
* `--format=json`: Displays the results in JSON format.

Need help?

* `wp wpvulnerability --help`: Displays help information for WPVulnerability commands.
* `wp wpvulnerability [command] --help`: Displays help information for a WPVulnerability command.

= REST API =

The WPVulnerability plugin provides several **REST API endpoints** to fetch vulnerability information for different components of your WordPress site.

* Core: `/wpvulnerability/v1/core`
* Plugins: `/wpvulnerability/v1/plugins`
* Themes: `/wpvulnerability/v1/themes`
* PHP: `/wpvulnerability/v1/php`
* Apache HTTPD: `/wpvulnerability/v1/apache`
* nginx: `/wpvulnerability/v1/nginx`
* MariaDB: `/wpvulnerability/v1/mariadb`
* MySQL: `/wpvulnerability/v1/mysql`
* ImageMagick: `/wpvulnerability/v1/imagemagick`
* curl: `/wpvulnerability/v1/curl`
* memcached: `/wpvulnerability/v1/memcached`
* Redis: `/wpvulnerability/v1/redis`
* SQLite: `/wpvulnerability/v1/sqlite`

The WPVulnerability REST API uses **Application Passwords** for authentication. You need to include a valid Application Password in the Authorization header of your requests.

Example Request with Authentication

`curl -X GET https://example.com/wp-json/wpvulnerability/v1/plugins -u username:application_password`

Replace username with your WordPress `username` and `application_password` with your [Application Password](https://make.wordpress.org/core/2020/11/05/application-passwords-integration-guide/).

== Extra Configurations ==

= "From:" mail (since: 3.2.2) =

If, for some reason, you need the emails sent by the plugin to have a From different from the site administrator, you can change it from the `wp-config.php` by adding a constant:

`define( 'WPVULNERABILITY_MAIL', 'sender@example.com' );`

If the constant is active, it will be visible in the configuration screen.

= Force hiding checks (since: 4.1.0) =

If you want to always hide a specific component, you can define a constant in `wp-config.php`. When set to `true`, the option will be checked automatically in the settings screen and the related analysis will be skipped.

Example:

`define( 'WPVULNERABILITY_HIDE_APACHE', true );`

Available constants: `WPVULNERABILITY_HIDE_CORE`, `WPVULNERABILITY_HIDE_PLUGINS`, `WPVULNERABILITY_HIDE_THEMES`, `WPVULNERABILITY_HIDE_PHP`, `WPVULNERABILITY_HIDE_APACHE`, `WPVULNERABILITY_HIDE_NGINX`, `WPVULNERABILITY_HIDE_MARIADB`, `WPVULNERABILITY_HIDE_MYSQL`, `WPVULNERABILITY_HIDE_IMAGEMAGICK`, `WPVULNERABILITY_HIDE_CURL`, `WPVULNERABILITY_HIDE_MEMCACHED`, `WPVULNERABILITY_HIDE_REDIS`, `WPVULNERABILITY_HIDE_SQLITE`.

= Cache duration (since: 4.1.0) =

By default, data from the API is cached for 12 hours. To change this, define `WPVULNERABILITY_CACHE_HOURS` in `wp-config.php` with one of `1`, `6`, `12` or `24`. This value overrides the setting screen and WP-CLI command.

`define( 'WPVULNERABILITY_CACHE_HOURS', 24 );`

= Log rotation (since: 4.2.0) =

WPVulnerability stores the most recent API responses so you can review recent calls from the new log tab. Define `WPVULNERABILITY_LOG_RETENTION_DAYS` in `wp-config.php` to control how many days of entries are preserved. Supported values are `0`, `1`, `7`, `14` or `28`; using `0` disables logging entirely.

`define( 'WPVULNERABILITY_LOG_RETENTION_DAYS', 14 );`

When the constant is present its value is enforced in the settings UI and through WP-CLI, ensuring consistent log rotation across environments.

= Security configuration (since: 4.3.0) =

WPVulnerability uses a hybrid detection approach for server software (ImageMagick, Redis, Memcached, SQLite): PHP extensions first (most secure), then shell commands as fallback (most accurate). You can control this behavior using security configuration constants in `wp-config.php`.

**Global disable of shell commands:**

`define( 'WPVULNERABILITY_DISABLE_SHELL_EXEC', true );`

Completely disables shell command usage. Falls back to PHP extensions only. Use for maximum security when accuracy loss is acceptable.

**Security mode (standard/strict/disabled):**

`define( 'WPVULNERABILITY_SECURITY_MODE', 'strict' );`

* `standard` - Hybrid detection: PHP extensions first, shell commands fallback (default, best accuracy)
* `strict` - PHP extensions only, no shell commands (high security, lower accuracy)
* `disabled` - No software detection at all (maximum security)

**Component whitelist:**

`define( 'WPVULNERABILITY_SHELL_EXEC_WHITELIST', 'imagemagick,redis' );`

Allows shell commands only for specified components. Available components: `imagemagick`, `redis`, `memcached`, `sqlite`. Use for granular control.

**Examples:**

Maximum security (no shell commands):

`define( 'WPVULNERABILITY_SECURITY_MODE', 'strict' );`

Only allow ImageMagick shell detection:

`define( 'WPVULNERABILITY_SHELL_EXEC_WHITELIST', 'imagemagick' );`

Complete disable:

`define( 'WPVULNERABILITY_DISABLE_SHELL_EXEC', true );`

All shell commands are hardcoded and validated - no user input is involved. Commands are logged for security auditing.

== Installation ==

= Automatic download =

Visit the plugin section in your WordPress, search for [wpvulnerability]; download and install the plugin.

= Manual download =

Extract the contents of the ZIP and upload the contents to the `/wp-content/plugins/wpvulnerability/` directory. Once uploaded, it will appear in your plugin list.

== Frequently Asked Questions ==

= Where does the vulnerability information come from? =

The origin is in the WPVulnerability.com API. The vulnerabilities that appear in this API come from different sources, such as CVEs.

= Is data from my site sent anywhere? =

No. Never. Your privacy is very important to us. We do not commercialize with your data.

= What vulnerabilities will I find? =

Vulnerabilities in WordPress Core, Plugins, Themes, PHP, Apache HTTPD, nginx, MariaDB, MySQL, ImageMagick, curl, memcached, Redis, and SQLite are documented.

= What do I do if my site has a vulnerability? =

First of all, peace of mind. Investigate what the vulnerability is and, above all, check that you have the latest version of the compromised element. We actively recommend that you keep all your WordPress and its plugins up to date. Contact your hosting provider to patch non-WordPress vulnerabilities (like web server, databases, and other software).

== Screenshots ==

1. WP-Admin Dashboard widget.
2. Vulnerability list at Plugins list.
3. Vulnerability list at Site Health.

== Compatibility ==

* WordPress: 5.6 - 7.1
* PHP: 7.0 - 8.5
* WP-CLI: 2.3.0 - 2.12.0

== Changelog ==

= [5.0.1] - 2026-06-02 =

**Fixed**

* `wp_cache_flush()` removed from the plugin/theme update hook and the plugin reset routine. The function was wiping the entire Object Cache (Redis, Memcached, APCu) on every update, causing CPU spikes on high-traffic sites. The targeted transient cleanup that already runs before it is sufficient.

= [5.0.0] - 2026-05-26 =

**Added**

* Vulnerability detail panels fully redesigned: Bootstrap-inspired score/severity badge, source attribution pills (hostname extracted from URL), and a structured "References:" row on the same line as the pills.
* CVSS priority order: CVSS 4 > CVSS 3 > CVSS 2 > legacy CVSS. The highest available score and severity are always shown.
* `ssvc.exploitation` field displayed: `poc` → "⚡ Public exploit" badge; `active` → included in the "Actively exploited" KEV label.
* `ssvc.automatable: yes` → "⚙ Automatable" badge alongside KEV/PoC.
* `ssvc.kev_date` → date appended to the "Actively exploited" label (e.g. "⚠ Actively exploited · 2024-03-15").
* `epss` field → "EPSS X.X%" badge on the same line as the CVSS score badge.
* CVE description (`source[].description`) now displayed for all vulnerability types: plugins, themes, core, and server software. Language prefix (e.g. `[en-US]`) stripped automatically.
* CWE name and description displayed in server software vulnerability details (was missing).
* Core vulnerabilities on `update-core.php` now rendered with the same badges, description, and pills as plugin/theme rows (replaces the old plain table).
* Theme details modal (single-site): vulnerability section injected after the Tags field using the `wp_prepare_themes_for_js` filter and a JS template patch. Shows the same version range + badge + description + references layout as the plugin rows.
* Version range display: leading `-` or `*` stripped when there is no lower bound (e.g. `- < 1.3.28` → `< 1.3.28`).
* Helper functions added to `wpvulnerability-process.php`: `wpvulnerability_source_css_slug()`, `wpvulnerability_render_source_pills()`, `wpvulnerability_render_score_badge()`, `wpvulnerability_clean_version_range()`, `wpvulnerability_get_source_description()`.
* Helper functions added to `wpvulnerability-themes.php`: `wpvulnerability_theme_modal_html()`, `wpvulnerability_filter_prepare_themes_for_js()`, `wpvulnerability_theme_modal_template_patch()`.
* KEV badge displayed in vulnerability details when the CVE is listed in the CISA Known Exploited Vulnerabilities (KEV) catalog (`impact.ssvc.kev` for plugins/themes/core; `impact.kev` for server software).
* Vulnerability severity now uses the full-word value from `cvss3.severity` (`"critical"`, `"high"`, `"medium"`, `"low"`) when available, falling back to the legacy single-character `cvss.severity` code.
* Publication date shown next to each source link in vulnerability details (`source[].date` field from the API).
* Server software lifecycle status (Supported / End of Life + EOL date) in vulnerability details and dashboard grid (`data.status`, `data.date_end` fields from the API).
* EOL badge in the dashboard software grid (PHP, Apache, nginx, MariaDB, MySQL, ImageMagick, curl, memcached, Redis, SQLite) when the detected version has reached end-of-life.
* REST API: all vulnerability endpoints now expose `uuid`, `kev` (boolean), `ssvc` block, and `severity` from `cvss3`. Source entries include a `date` field.
* About tab: new **Intelligence Sources** table showing per-source vulnerability counts (CVE, EUVD, JVN, Patchstack, WPScan, Wordfence) broken down by Core / Plugins / Themes.

**Security**

* `wpvulnerability-adminms.php`: config form handler now requires `manage_network_options` capability (via `current_user_can()`) in addition to the nonce check. Previously a user with a valid nonce could update plugin options without the required capability.
* WP-CLI: all vulnerability commands (`core`, `plugins`, `themes`, and all software components) and all config commands (`hide`, `email`, `cache`, `log-retention`, `period`) now require `manage_options` / `manage_network_options`. Commands abort with a clear error and `--user=<admin_login>` hint if the check fails.
* REST API permission check now passes strict mode (`true`) to `base64_decode()` when parsing the HTTP Basic Authorization header. A malformed or padding-stripped token is immediately rejected instead of decoding unpredictable bytes.
* Debug web server detection (LiteSpeed, OpenLiteSpeed, Caddy) now routes through the `wpvulnerability_safe_shell_exec()` wrapper, ensuring `WPVULNERABILITY_DISABLE_SHELL_EXEC`, security mode, command whitelist, and audit logging are respected even when `WP_DEBUG` is enabled.
* Page render callbacks (`wpvulnerability_create_admin_page`, `wpvulnerability_admin_dashboard_content`) now include explicit `current_user_can()` / `wp_die()` guards as defense-in-depth, per the WordPress Plugin Handbook.

**Fixed**

* Forced test email on a fresh install (no email address configured yet) no longer produces an `E_WARNING` on PHP 7.x or a `TypeError` on PHP 8.x.
* `determine_locale()` call is now guarded by `function_exists()` instead of `version_compare()`, which is more forward-compatible and correctly recognised by static analysis.
* `preg_replace()` return values in the HTML-to-plain-text converter are now handled safely when `null` is returned on error.
* `DOMDocument::$documentElement` null check added in the HTML-to-plain-text converter.
* JSON-encoded vulnerability count options are validated as strings before `json_decode()` throughout the codebase.
* `cron_schedules` callbacks now use `did_action('init')` guard before `__()`, eliminating the textdomain-too-early notice introduced in WordPress 6.7.
* WP-CLI vulnerability commands now display a clear success message when no vulnerabilities are found, instead of an empty table.
* WP-CLI `config period monthly` now returns a proper error. Valid periods: `daily`, `weekly`, `never`.
* `uninstall.php` created. Plugin data is preserved by default; a new "Delete all plugin data on uninstall" checkbox in the Tools tab allows opting in to full removal.
* Large vulnerability data options are now stored with `autoload=false`, preventing unnecessary loading of JSON blobs on every WordPress request.

**Changed**

* Minimum required PHP version raised from 5.6 to 7.0. The null coalescing operator (`??`) used throughout for improved type safety requires PHP 7.0. PHP 5.6 reached end-of-life in December 2018.
* Minimum required WordPress version raised from 4.7 to 5.6, enabling full use of Application Passwords, `wp_timezone()`, `wp_date()`, and `determine_locale()` without version guards.
* `wpvulnerability_get_cron_snapshot()` now uses only public WordPress Cron API functions (`wp_next_scheduled()`, `wp_get_schedule()`); `_get_cron_array()` (private WP API) removed.

**Developer**

* PHPStan level 9: 0 errors across all 18 PHP files; 1,092 pre-existing type errors resolved; baseline is now empty.
* Added dev tooling: `composer.json`, `phpstan.neon` (level 9), `phpcs.xml`, `phpunit.xml.dist`, `bin/deploy.sh`, `docs/`.
* Added 18 PHPUnit plugin header tests.

**Compatibility**

* WordPress: 5.6 - 7.1
* PHP: 7.0 - 8.5
* WP-CLI: 2.3.0 - 2.12.0

**Tests**

* PHP Coding Standards: 3.13.5
* WordPress Coding Standards: 3.3.0
* PHPStan: 2.1.55 (level 9, 0 errors)
* PHPUnit: 9.6.34 (18 tests)
* Plugin Check (PCP): 1.8.0

= [4.3.2] - 2026-05-20 =

**Performance**

* Notification scheduling no longer rewrites the `cron` row in `wp_options` on every WordPress request. The boot-time call now verifies the current schedule with `wp_get_schedule()` and only clears or reschedules the `wpvulnerability_notification` event when the desired period actually differs from the currently scheduled one. This eliminates 1-2 unnecessary `UPDATE wp_options` queries per page load, removing lock contention under concurrent load and the corresponding entries from the MariaDB/MySQL slow query log.

**Changed**

* `wpvulnerability_schedule_notification_event()` gained an optional `$force` parameter (default `true`, backwards compatible). The boot-time invocation passes `false` to opt into the idempotent path; all other callers (admin save handlers, WP-CLI config command, update flow, repair helpers) keep the default and continue forcing a reschedule so that changes to hour/minute/day still update the next-run timestamp.

**Compatibility**

* WordPress: 4.7 - 6.9
* PHP: 5.6 - 8.5
* WP-CLI: 2.3.0 - 2.11.0

**Tests**

* PHP Coding Standards: 3.13.5
* WordPress Coding Standards: 3.3.0
* Plugin Check (PCP): 1.8.0

= [4.3.1] - 2026-01-20 =

**Fixed**

* Dashboard widget now correctly counts only vulnerabilities from enabled components, excluding disabled ones from settings.
* Status badge calculation (Critical/Warning) now properly considers only enabled components when determining severity level.
* Fixed PHPCS warnings for global variables without plugin prefix in wpvulnerability-admin.php and wpvulnerability-adminms.php.

**Compatibility**

* WordPress: 4.7 - 6.9
* PHP: 5.6 - 8.5
* WP-CLI: 2.3.0 - 2.11.0

**Tests**

* PHP Coding Standards: 3.13.5
* WordPress Coding Standards: 3.3.0
* Plugin Check (PCP): 1.8.0

= [4.3.0] - 2026-01-19 =

**Highlights**

This major release brings a complete redesign of the admin interface, comprehensive debugging tools, enhanced security, and new notification channels.

* **Complete Admin Interface Redesign**: Modern card-based layout with visual component cards, improved spacing, color-coded status badges, and responsive grid layouts across all Settings tabs (Security, About, Logs, Tools, Analysis, and Notifications).
* **New Debug Mode**: Comprehensive debugging tools visible when WP_DEBUG is enabled, including System Information, Component Detection with cache status, interactive API Testing with AJAX buttons, Configuration Summary, Cron Status with manual execution, Database Options Viewer, and Quick Actions (clear caches, reset signatures, export debug data as JSON). Includes enhanced web server detection for 9 different servers.
* **Dashboard Widget Redesign**: Modern interface with prominent status badges (All Clear/Issues Found/Critical Issues Found), last check timestamp with human-readable format, empty state display with centered checkmark, separated component sections (WordPress Components vs Server Software), color-coded badges, and 2-column grid layout for server software.
* **New Notification Channels**: Discord webhook support and Telegram bot integration for vulnerability notifications, with proper character limit handling and webhook URL validation.
* **Enhanced Security**: CSRF protection via nonces for plugin/theme vulnerability filters, hybrid software detection system (PHP extensions first, shell commands as fallback), complete audit logging for shell executions, webhook URL validation with HTTPS enforcement and domain whitelisting, and new wp-config.php security constants.
* **Multisite Improvements**: Fixed all form submission issues in Network Admin, proper nonce handling, correct URL generation with network_admin_url(), preserved settings when saving individual forms, and fixed Security tab with all required helper functions.
* **Tools & Maintenance**: Cron event repair functionality for single sites and multisite networks, "Delete all logs" button, full plugin reset action, and improved cache management.

**Added**

* Tools tab now lists expected WPVulnerability cron events, shows the scheduled instances, and lets administrators repair them on single sites.
* Network Tools highlights unexpected WPVulnerability cron events on subsites and provides a one-click repair to clear and reschedule across the network.
* Logs tab now includes a "Delete all logs" button to purge stored API log entries manually.
* Hybrid software detection system: PHP extensions first (most secure), shell commands fallback (most accurate).
* Four-level security control system for shell_exec usage with granular configuration.
* Shell command validation with whitelist and dangerous pattern detection.
* Complete audit logging for all shell executions (component, command, output, user, IP, timestamp).
* New wp-config.php constants: `WPVULNERABILITY_DISABLE_SHELL_EXEC`, `WPVULNERABILITY_SECURITY_MODE`, `WPVULNERABILITY_SHELL_EXEC_WHITELIST`.
* Detection reliability scoring (0-100) for each software detection method.
* Discord webhook support for vulnerability notifications with 2000-character limit handling.
* Telegram bot support for vulnerability notifications with bot token and chat ID configuration.
* Documentation links for Discord webhook setup (https://support.discord.com/hc/articles/228383668).
* Documentation links for Telegram bot setup (https://core.telegram.org/bots).
* Debug tab (visible only when WP_DEBUG is enabled) providing comprehensive debugging tools for administrators.
* wpvulnerability-debug.php file with 11 helper functions for debug functionality (~18KB).
* Debug Section 1: System Information displaying WordPress version, PHP version/extensions/memory, database type (MariaDB vs MySQL with proper detection), web server (nginx/Apache/LiteSpeed/OpenLiteSpeed/Caddy/IIS/Angie/OpenResty/Tengine), debug modes status, and debug log file information.
* Debug log file information showing file path, size, and direct browser link when web-accessible.
* Debug Section 2: Component Detection table listing all 13 components with detection status, version, analyzed state, and cache expiration time.
* Debug Section 3: API Testing with interactive AJAX-powered buttons to test API connectivity for each component individually, showing HTTP status, response time, and data preview.
* Debug Section 4: Configuration Summary displaying current plugin settings at a glance.
* Debug Section 5: Cron Status showing scheduled tasks with manual execution buttons (permission-gated with nonce verification).
* Debug Section 6: Database Options Viewer with dropdown to inspect all stored plugin options.
* Debug Section 7: Quick Actions with buttons to clear all caches, reset plugin/theme signatures, and export debug information as JSON.
* Enhanced web server detection supporting 9 different servers: nginx, Angie (nginx fork), Apache, LiteSpeed, OpenLiteSpeed, Caddy, IIS, OpenResty (nginx-based), and Tengine (nginx fork).
* Three-level detection logic for web servers: (1) plugin's standard function, (2) SERVER_SOFTWARE parsing, (3) shell commands as fallback.
* Database detection properly distinguishes MariaDB from MySQL via version_comment SQL query.
* AJAX handler `wpvulnerability_ajax_test_api()` for API testing with nonce verification and capability checks.
* Debug helper functions: `wpvulnerability_debug_get_log_file_info()`, `wpvulnerability_debug_detect_webserver()`, `wpvulnerability_debug_get_system_info()`, `wpvulnerability_debug_get_component_status()`, `wpvulnerability_debug_test_api_component()`, `wpvulnerability_debug_get_cron_status()`, `wpvulnerability_debug_export_info()`, `wpvulnerability_debug_clear_all_caches()`, `wpvulnerability_debug_reset_signatures()`, `wpvulnerability_debug_get_option_names()`.
* Debug tab POST handlers in both wpvulnerability-admin.php and wpvulnerability-adminms.php with nonce verification for all actions.
* Debug tab render functions in wpvulnerability-admin.php: `wpvulnerability_render_admin_tab_debug()`, `wpvulnerability_render_debug_section_system_info()`, `wpvulnerability_render_debug_section_components()`, `wpvulnerability_render_debug_section_config()`, `wpvulnerability_render_debug_section_cron()`, `wpvulnerability_render_debug_section_api_testing()`, `wpvulnerability_render_debug_section_database_options()`, `wpvulnerability_render_debug_section_quick_actions()`.

**Security**

* Added CSRF protection via nonces for plugin vulnerability filter links to prevent forced navigation attacks.
* Added CSRF protection via nonces for theme vulnerability filter links to prevent forced navigation attacks.
* Plugin and theme filter URLs now include security nonces that are verified before applying filters.
* Enhanced security against timing attacks on vulnerability enumeration by requiring valid nonces.
* Enhanced ImageMagick, Redis, Memcached, and SQLite detection with hybrid approach and security controls.
* All shell commands hardcoded and validated - no user input involved.
* Shell execution wrapper with complete security checks and logging.
* Webhook URLs now validated on save: enforces HTTPS and verifies hostname matches allowed domains (Slack: hooks.slack.com, Teams: office.com/office365.com/api.hooks.microsoft.com, Discord: discord.com/discordapp.com).
* Telegram bot token validation with regex pattern check (format: 123456:ABC-DEF1234ghIkl-zyx57W2v1u123ew11).
* Invalid webhook URLs and bot tokens are rejected with user-friendly error messages instead of silently failing on notification send.
* Security audit score improved from 85/100 to 98/100 (comprehensive security audit completed 2026-01-19).

**Changed**

* Database error hook now fires the prefixed `wpvulnerability_wpdb_last_error` action while keeping the legacy hook deprecated.
* Database update cron now follows the configured cache duration (hourly, 6h, 12h, or 24h).
* Translations load on init to avoid early textdomain warnings.
* Vulnerability data now refreshes only via scheduled cron or the manual reload action; admin requests, REST, CLI, notifications, and view rendering no longer trigger API calls to reduce load.
* Cron scheduling no longer re-queues the update event on every page load; it keeps the configured interval (hourly/6h/12h/24h) unless the schedule changes.
* REST API now requires administrator capabilities for session or application password access.
* Admin reset and test email actions enforce admin capabilities.
* API client timeouts corrected to 2.5 seconds to avoid long hangs.
* Slack/Teams webhooks restricted to allowed HTTPS hosts to limit SSRF exposure.
* Tools tab adds a full reset action that clears all plugin data, restores defaults, and reloads from the API.
* Complete redesign of the admin settings interface with modern card-based layout for all tabs: Security, About, Logs, Tools, Analysis, and Notifications.
* Settings tabs now feature visual component cards with icons, improved spacing, color-coded status badges, and responsive grid layouts for enhanced usability.
* Complete redesign of the Dashboard widget with modern, clean interface replacing the basic list layout.
* Dashboard widget now features prominent status badge with three states: "All Clear" (green, 0 vulnerabilities), "X Issues Found" (yellow, minor issues), "X Critical Issues Found" (red, Core/PHP vulnerable or 5+ total vulnerabilities).
* Dashboard widget displays last check timestamp with human-readable format ("X minutes ago", "X hours ago") and "Refresh Now" link.
* Dashboard widget shows attractive empty state with centered green checkmark when no vulnerabilities are detected.
* Dashboard widget separates components into two clear sections: "WordPress Components" (Core, Plugins, Themes) and "Server Software" (PHP, web server, database, etc.).
* Dashboard widget uses color-coded badges: green for secure (✓ 0), yellow/red for vulnerabilities (✕ N) with consistent design.
* Dashboard widget displays server software in 2-column grid layout for better space utilization.
* Dashboard widget shows vulnerable plugin/theme lists indented below their respective components.
* Dashboard widget uses inline CSS with modern styling: flexbox layouts, proper spacing, WordPress admin color palette, improved typography (13px components, 12px meta).
* Dashboard widget footer includes links to Site Health and Settings with visual separation.
* All CSS class names, HTML IDs, and JavaScript references changed from short prefix `.wpv-` to full prefix `.wpvulnerability-` to prevent naming conflicts with other plugins and themes (affects 73+ unique classes across admin panels).
* All inline CSS from admin panels moved to external assets/admin.css file for better performance and cacheability (~1084 lines extracted from 14 style blocks across single-site and multisite admin panels).
* License updated from GPL2+ to GPL3+.

**Fixed**

* Saving partial forms (e.g., log retention) no longer resets other notification settings to their defaults; existing values are preserved unless explicitly changed.
* Network (adminms) settings now preserve existing values when saving individual forms and keep notification scheduling consistent.
* Cache column in Component Detection (Debug tab) now correctly displays cache expiration time by properly decoding JSON-encoded timestamps from database.
* Database detection now properly distinguishes between MariaDB and MySQL instead of always showing "MySQL".
* Multisite network admin forms (Notifications, Analysis, Configuration) now submit correctly by using proper network admin URLs and nonces instead of incompatible Settings API methods.
* All form submission buttons in multisite admin now include proper `name` attribute (`wpvulnerability_submit`) for backend processing.
* Delete logs form in multisite now uses `network_admin_url()` instead of single-site `admin_url()` for correct URL generation.
* All multisite form nonce verifications now match their corresponding form nonce fields (reset, email, repair cron, delete logs) instead of using generic nonce.
* Security tab in multisite network admin now works correctly by including all required helper functions (wpvulnerability_display_security_status, wpvulnerability_display_detection_methods, wpvulnerability_display_security_logs) instead of calling undefined single-site functions.
* Tools tab buttons in multisite network admin no longer show "nonce expired" errors by submitting forms to the same page (action="") instead of explicit URL paths that fail referer validation.
* Delete All Logs button in Logs tab no longer shows "The link you followed has expired" error by using empty form action (action="") in both single-site and multisite admin panels.
* Logs tab pagination now displays horizontally instead of vertically by properly targeting list elements (ul with inline-flex) and individual page links (a and span within li) to work correctly with WordPress paginate_links() 'type' => 'list' output.

**Compatibility**

* WordPress: 4.7 - 6.9
* PHP: 5.6 - 8.5
* WP-CLI: 2.3.0 - 2.11.0

**Tests**

* PHP Coding Standards: 3.13.5
* WordPress Coding Standards: 3.3.0
* Plugin Check (PCP): 1.8.0

= [4.2.2.1] - 2026-01-16 =

**Security**

* Fixed authorization vulnerability in REST API endpoints that allowed low-privileged users to access sensitive vulnerability data. API now properly verifies user capabilities (`manage_options` for single sites, `manage_network_options` for multisite) in addition to authentication.
* Added direct access protection to wpvulnerability-api.php to prevent direct file execution outside WordPress context.

**Compatibility**

* WordPress: 4.7 - 6.9
* PHP: 5.6 - 8.4
* WP-CLI: 2.3.0 - 2.11.0

**Tests**

* PHP Coding Standards: 3.13.5
* WordPress Coding Standards: 3.3.0
* Plugin Check (PCP): 1.8.0

= [4.2.1] - 2025-12-17 =

**Fixed**

* Clear legacy WPVulnerability cron events from multisite subsites so updates and log cleanup only run on the main site.

**Compatibility**

* WordPress: 4.7 - 6.9
* PHP: 5.6 - 8.4
* WP-CLI: 2.3.0 - 2.11.0

**Tests**

* PHP Coding Standards: 3.13.5
* WordPress Coding Standards: 3.3.0
* Plugin Check (PCP): 1.7.0

= Previous versions =

If you want to see the full changelog, visit the [changelog.txt](https://plugins.trac.wordpress.org/browser/wpvulnerability/trunk/changelog.txt) file.

== Security ==

This plugin adheres to the following security measures and review protocols for each version:

* [WordPress Plugin Handbook](https://developer.wordpress.org/plugins/)
* [WordPress Plugin Security](https://developer.wordpress.org/plugins/wordpress-org/plugin-security/)
* [WordPress APIs Security](https://developer.wordpress.org/apis/security/)
* [WordPress Coding Standards](https://github.com/WordPress/WordPress-Coding-Standards)
* [Plugin Check (PCP)](https://wordpress.org/plugins/plugin-check/)

== Privacy ==

* This plugin or the WordPress Vulnerability Database API does not collect any information about your site, your identity, the plugins, themes or content the site has.

== Vulnerabilities ==

* A security vulnerability was found and fixed in version 4.2.2.1. All previous versions (3.3.0 - 4.2.1) are affected. Please update to version 4.2.2.1 or later.

Found a security vulnerability? Please report it to us privately at the [WPVulnerability GitHub repository](https://github.com/javiercasares/wpvulnerability/security/advisories/new).

== Contributors ==

You can contribute to this plugin at the [WPVulnerability GitHub repository](https://github.com/javiercasares/wpvulnerability).
