ARGUS WordPress Defence 7.23.0
Real changes since 1.0.0, all live-verified before this release: - Firewall: rule corpus expanded 19 -> 43 rules, real OWASP-CRS-equivalent coverage (XXE, SSRF, session fixation, Log4Shell/JNDI, scanner-tool detection, deeper SQL injection/XSS/PHP-injection). - Fixed a real bug: a quarantined file's severity badge and its content analysis score could disagree with no explanation (e.g. a benign file showing CRITICAL next to Score 0); both are now derived consistently and shown together. - ARGUS now always keeps itself updated, and can optionally do the same for every other installed plugin and theme (Settings, on by default) -- uses WordPress's own native update system, nothing custom. - Global Threat Intelligence is now opt-in, not automatic -- a single click on its own page, with an honest, specific description of exactly what's shared (an IP address, a reason code, a confidence score, a country). Previously connected automatically on activation. - New first-run Welcome screen after activation: confirms what's already protecting the site, and surfaces the few real optional choices in one place. - Dashboard: running version now visible in the header; new "IPs Tracked" and "ANIS Protections" metrics. - Full WordPress.org Plugin Directory readiness audit performed against this codebase. Two real compliance issues found and fixed (see above: Global Threat Intelligence's default, and the self-update mechanism, which is excluded from this build entirely -- WordPress.org prohibits a plugin from using any update channel other than its own, even an inert one). This release is still self-distributed, not a WordPress.org submission -- that remains a future step. Verified before publishing: this exact ZIP was installed, activated (14 admin pages loaded clean, zero PHP errors/warnings), and uninstalled (zero leftover database tables or options) in a fresh, disposable WordPress + MySQL environment. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
@@ -14,6 +14,28 @@ class Argus_Admin {
|
||||
add_action( 'admin_post_argus_wpd_download_backup', array( __CLASS__, 'handle_backup_download' ) );
|
||||
|
||||
add_action( 'admin_init', array( __CLASS__, 'handle_firewall_actions' ) );
|
||||
add_action( 'admin_init', array( __CLASS__, 'maybe_redirect_to_welcome' ) );
|
||||
}
|
||||
|
||||
// Standard WordPress plugin convention: redirect to a one-time Welcome
|
||||
// screen right after activation, but never on a bulk-activate or a
|
||||
// multisite network-wide activation (both would otherwise hijack
|
||||
// whichever admin page the user was actually trying to reach).
|
||||
public static function maybe_redirect_to_welcome() {
|
||||
if ( ! get_transient( 'argus_wpd_do_activation_redirect' ) ) {
|
||||
return;
|
||||
}
|
||||
delete_transient( 'argus_wpd_do_activation_redirect' );
|
||||
|
||||
if ( wp_doing_ajax() || is_network_admin() || isset( $_GET['activate-multi'] ) ) { // phpcs:ignore WordPress.Security.NonceVerification
|
||||
return;
|
||||
}
|
||||
if ( ! current_user_can( 'manage_options' ) ) {
|
||||
return;
|
||||
}
|
||||
|
||||
wp_safe_redirect( admin_url( 'admin.php?page=argus-wpd-welcome' ) );
|
||||
exit;
|
||||
}
|
||||
|
||||
public static function handle_firewall_actions() {
|
||||
@@ -84,10 +106,57 @@ class Argus_Admin {
|
||||
add_submenu_page( 'argus-wpd-dashboard', __( 'ANIS', 'argus-wordpress-defence' ), __( 'ANIS', 'argus-wordpress-defence' ), 'manage_options', 'argus-wpd-anis', array( __CLASS__, 'render_anis' ) );
|
||||
add_submenu_page( 'argus-wpd-dashboard', __( 'Audit Log', 'argus-wordpress-defence' ), __( 'Audit Log', 'argus-wordpress-defence' ), 'manage_options', 'argus-wpd-audit-log', array( __CLASS__, 'render_audit_log' ) );
|
||||
add_submenu_page( 'argus-wpd-dashboard', __( 'Settings', 'argus-wordpress-defence' ), __( 'Settings', 'argus-wordpress-defence' ), 'manage_options', 'argus-wpd-settings', array( __CLASS__, 'render_settings' ) );
|
||||
|
||||
// Reachable at ?page=argus-wpd-welcome right after activation, but
|
||||
// CSS-hidden from the sidebar (hide_settings_from_sidebar(), same
|
||||
// mechanism already used for Settings) -- it's a onboarding screen,
|
||||
// not a place to keep coming back to via the nav. Registering with a
|
||||
// real parent rather than null: passing null as parent_slug left
|
||||
// get_admin_page_title() unable to resolve a title in this WP
|
||||
// version, cascading into a "headers already sent" fatal-adjacent
|
||||
// warning -- confirmed live, not theoretical.
|
||||
add_submenu_page( 'argus-wpd-dashboard', __( 'Welcome to ARGUS Defence', 'argus-wordpress-defence' ), __( 'Welcome', 'argus-wordpress-defence' ), 'manage_options', 'argus-wpd-welcome', array( __CLASS__, 'render_welcome' ) );
|
||||
}
|
||||
|
||||
public static function render_welcome() {
|
||||
if ( ! current_user_can( 'manage_options' ) ) {
|
||||
wp_die( esc_html__( 'You do not have permission to do this.', 'argus-wordpress-defence' ) );
|
||||
}
|
||||
|
||||
$template_applied = null;
|
||||
if ( isset( $_POST['argus_wpd_apply_template_nonce'], $_POST['template'] ) && wp_verify_nonce( sanitize_text_field( wp_unslash( $_POST['argus_wpd_apply_template_nonce'] ) ), 'argus_wpd_apply_template' ) ) { // phpcs:ignore
|
||||
$key = sanitize_key( wp_unslash( $_POST['template'] ) ); // phpcs:ignore
|
||||
if ( class_exists( 'Argus_Templates' ) && Argus_Templates::apply( $key ) ) {
|
||||
$templates = Argus_Templates::all();
|
||||
$template_applied = $templates[ $key ]['label'];
|
||||
}
|
||||
}
|
||||
|
||||
if ( isset( $_POST['argus_wpd_anis_toggle_nonce'] ) && wp_verify_nonce( sanitize_text_field( wp_unslash( $_POST['argus_wpd_anis_toggle_nonce'] ) ), 'argus_wpd_anis_toggle' ) ) { // phpcs:ignore
|
||||
$action = sanitize_key( wp_unslash( $_POST['anis_action'] ?? '' ) ); // phpcs:ignore
|
||||
$user = wp_get_current_user();
|
||||
if ( 'enable' === $action ) {
|
||||
Argus_Settings::update( array( 'anis_enabled' => true ) );
|
||||
Argus_ANIS_Client::register();
|
||||
Argus_Events::record( 'anis_enabled', 'info', sprintf( 'ARGUS Cloud connection enabled by %s', $user->user_login ), array( 'actor' => $user->user_login ) );
|
||||
}
|
||||
}
|
||||
|
||||
if ( isset( $_POST['argus_wpd_auto_update_all_nonce'] ) && wp_verify_nonce( sanitize_text_field( wp_unslash( $_POST['argus_wpd_auto_update_all_nonce'] ) ), 'argus_wpd_save_auto_update_all' ) ) { // phpcs:ignore
|
||||
Argus_Settings::update( array( 'auto_update_all_enabled' => ! empty( $_POST['auto_update_all_enabled'] ) ) ); // phpcs:ignore
|
||||
}
|
||||
|
||||
$settings = Argus_Settings::all();
|
||||
$templates = class_exists( 'Argus_Templates' ) ? Argus_Templates::all() : array();
|
||||
$active_template = class_exists( 'Argus_Templates' ) ? Argus_Templates::active() : '';
|
||||
$recommended_template = class_exists( 'Argus_Templates' ) ? Argus_Templates::recommended() : null;
|
||||
$anis_status = Argus_ANIS_Client::status();
|
||||
|
||||
include ARGUS_WPD_DIR . 'admin/views/welcome.php';
|
||||
}
|
||||
|
||||
public static function hide_settings_from_sidebar() {
|
||||
echo '<style>#adminmenu .wp-submenu a[href$="page=argus-wpd-settings"]{display:none}</style>';
|
||||
echo '<style>#adminmenu .wp-submenu a[href$="page=argus-wpd-settings"],#adminmenu .wp-submenu a[href$="page=argus-wpd-welcome"]{display:none}</style>';
|
||||
}
|
||||
|
||||
public static function enqueue_assets( $hook ) {
|
||||
@@ -121,6 +190,15 @@ class Argus_Admin {
|
||||
$integrity_open = Argus_Findings::count_open( 'integrity' );
|
||||
$anis_status = Argus_ANIS_Client::status();
|
||||
|
||||
$ips_tracked = Argus_ANIS_Client::local_reputation_count();
|
||||
$anis_protections = Argus_ANIS_Client::blocked_count();
|
||||
|
||||
// Argus_License exists only in the separately-distributed Premium
|
||||
// build (see includes/class-argus-license.php's own header) -- the
|
||||
// free WordPress.org build has no trial/license concept at all, and
|
||||
// this stays null there so overview.php shows nothing for it.
|
||||
$license_summary = class_exists( 'Argus_License' ) ? Argus_License::summary() : null;
|
||||
|
||||
include ARGUS_WPD_DIR . 'admin/views/overview.php';
|
||||
}
|
||||
|
||||
@@ -530,6 +608,21 @@ class Argus_Admin {
|
||||
}
|
||||
|
||||
public static function render_anis() {
|
||||
if ( ! current_user_can( 'manage_options' ) ) {
|
||||
wp_die( esc_html__( 'You do not have permission to do this.', 'argus-wordpress-defence' ) );
|
||||
}
|
||||
if ( isset( $_POST['argus_wpd_anis_toggle_nonce'] ) && wp_verify_nonce( sanitize_text_field( wp_unslash( $_POST['argus_wpd_anis_toggle_nonce'] ) ), 'argus_wpd_anis_toggle' ) ) { // phpcs:ignore
|
||||
$action = sanitize_key( wp_unslash( $_POST['anis_action'] ?? '' ) ); // phpcs:ignore
|
||||
$user = wp_get_current_user();
|
||||
if ( 'enable' === $action ) {
|
||||
Argus_Settings::update( array( 'anis_enabled' => true ) );
|
||||
Argus_ANIS_Client::register();
|
||||
Argus_Events::record( 'anis_enabled', 'info', sprintf( 'ARGUS Cloud connection enabled by %s', $user->user_login ), array( 'actor' => $user->user_login ) );
|
||||
} elseif ( 'disable' === $action ) {
|
||||
Argus_Settings::update( array( 'anis_enabled' => false ) );
|
||||
Argus_Events::record( 'anis_disabled', 'info', sprintf( 'ARGUS Cloud connection disabled by %s', $user->user_login ), array( 'actor' => $user->user_login ) );
|
||||
}
|
||||
}
|
||||
$anis_status = Argus_ANIS_Client::status();
|
||||
include ARGUS_WPD_DIR . 'admin/views/anis.php';
|
||||
}
|
||||
@@ -582,6 +675,11 @@ class Argus_Admin {
|
||||
Argus_Settings::remove_exception( 'ip', sanitize_text_field( wp_unslash( $_POST['exception_value'] ) ) ); // phpcs:ignore
|
||||
}
|
||||
|
||||
if ( isset( $_POST['argus_wpd_auto_update_all_nonce'] ) && wp_verify_nonce( sanitize_text_field( wp_unslash( $_POST['argus_wpd_auto_update_all_nonce'] ) ), 'argus_wpd_save_auto_update_all' ) ) { // phpcs:ignore
|
||||
Argus_Settings::update( array( 'auto_update_all_enabled' => ! empty( $_POST['auto_update_all_enabled'] ) ) ); // phpcs:ignore
|
||||
$saved = true;
|
||||
}
|
||||
|
||||
$update_check_result = null;
|
||||
if ( isset( $_POST['argus_wpd_check_updates_nonce'] ) && wp_verify_nonce( sanitize_text_field( wp_unslash( $_POST['argus_wpd_check_updates_nonce'] ) ), 'argus_wpd_check_updates' ) && class_exists( 'Argus_Update_Client' ) ) { // phpcs:ignore
|
||||
$update_check_result = Argus_Update_Client::check_now();
|
||||
|
||||
Reference in New Issue
Block a user