Plugin Directory

Changeset 3476940


Ignore:
Timestamp:
03/07/2026 08:52:46 AM (3 weeks ago)
Author:
inilerm
Message:

Preparing version 8.8.9

Location:
advanced-ip-blocker/trunk
Files:
21 edited

Legend:

Unmodified
Added
Removed
  • advanced-ip-blocker/trunk/advaipbl-loader.php

    r3464093 r3476940  
    66// Explicit check for direct access to satisfy Plugin Check while allowing auto_prepend_file.
    77if ( ! defined( 'ABSPATH' ) ) {
    8     if ( basename( $_SERVER['SCRIPT_FILENAME'] ) === basename( __FILE__ ) ) {
     8    $script_filename = isset($_SERVER['SCRIPT_FILENAME']) ? sanitize_text_field(wp_unslash($_SERVER['SCRIPT_FILENAME'])) : '';
     9    if ( basename( $script_filename ) === basename( __FILE__ ) ) {
    910        exit( 'Restricted access.' );
    1011    }
  • advanced-ip-blocker/trunk/advanced-ip-blocker.php

    r3472969 r3476940  
    44Plugin URI: https://advaipbl.com/
    55Description: Your complete WordPress security firewall. Blocks IPs, bots & countries. Includes an intelligent WAF, Threat Scoring, and Two-Factor Authentication.
    6 Version: 8.8.8
     6Version: 8.8.9
    77Author: IniLerm
    88Author URI: https://advaipbl.com/
     
    1919}
    2020
    21 define( 'ADVAIPBL_VERSION', '8.8.8' );
     21define( 'ADVAIPBL_VERSION', '8.8.9' );
    2222define( 'ADVAIPBL_PLUGIN_FILE', __FILE__ );
    2323
  • advanced-ip-blocker/trunk/css/advaipbl-styles.css

    r3472969 r3476940  
    11/**
    22 * Advanced IP Blocker - Admin Panel Styles
    3  * Version: 8.8.8
     3 * Version: 8.8.9
    44 */
    55
  • advanced-ip-blocker/trunk/includes/class-advaipbl-2fa-users-list-table.php

    r3419894 r3476940  
    5151        $tfa_status_filter = isset($_REQUEST['tfa_status']) ? sanitize_text_field(wp_unslash($_REQUEST['tfa_status'])) : 'all';
    5252        if ( in_array( $tfa_status_filter, ['active', 'inactive'] ) ) {
     53            // phpcs:ignore WordPress.DB.SlowDBQuery.slow_db_query_meta_key
    5354            $args['meta_key'] = ADVAIPBL_2fa_Manager::META_ENABLED_AT;
    5455            if ( 'active' === $tfa_status_filter ) {
     
    204205       
    205206        // Contar usuarios con 2FA activo
     207        // phpcs:ignore WordPress.DB.SlowDBQuery.slow_db_query_meta_key
    206208        $active_users_count = count( get_users([
    207209            'meta_key' => ADVAIPBL_2fa_Manager::META_ENABLED_AT,
  • advanced-ip-blocker/trunk/includes/class-advaipbl-action-handler.php

    r3442728 r3476940  
    4848                global $wpdb;
    4949                $lockdowns_table = $wpdb->prefix . 'advaipbl_endpoint_lockdowns';
     50                // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching
    5051                $wpdb->delete($lockdowns_table, ['id' => $lockdown_id], ['%d']);
    5152
     
    212213                global $wpdb;
    213214                $table_name = $wpdb->prefix . 'advaipbl_ip_scores';
    214                 // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared
     215                // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared, WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, PluginCheck.Security.DirectDB.UnescapedDBParameter
    215216                $wpdb->query("TRUNCATE TABLE `{$table_name}`");
    216217                /* translators: %s: Username. */
     
    222223                global $wpdb;
    223224                $table_name = $wpdb->prefix . 'advaipbl_malicious_signatures';
    224                 // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared
     225                // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared, WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, PluginCheck.Security.DirectDB.UnescapedDBParameter
    225226                $wpdb->query("TRUNCATE TABLE `{$table_name}`");
    226227                /* translators: %s: Username. */
     
    235236                        $placeholders = implode(', ', array_fill(0, count($log_types_to_clear), '%s'));
    236237                       
    237                         // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared, WordPress.DB.PreparedSQLPlaceholders.UnfinishedPrepare
     238                        // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared, WordPress.DB.PreparedSQLPlaceholders.UnfinishedPrepare, WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, PluginCheck.Security.DirectDB.UnescapedDBParameter
    238239                        $wpdb->query($wpdb->prepare("DELETE FROM {$wpdb->prefix}advaipbl_logs WHERE log_type IN ({$placeholders})", $log_types_to_clear));
    239240                       
     
    250251                case 'clear_all_logs':
    251252                    global $wpdb;
    252                     // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared
     253                    // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared, WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, PluginCheck.Security.DirectDB.UnescapedDBParameter
    253254                    $wpdb->query("TRUNCATE TABLE `{$wpdb->prefix}advaipbl_logs`");
    254                     // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared
     255                    // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared, WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, PluginCheck.Security.DirectDB.UnescapedDBParameter
    255256                    $wpdb->query("TRUNCATE TABLE `{$wpdb->prefix}advaipbl_notifications_queue`");
    256257                    /* translators: %s: Username. */
     
    269270                                global $wpdb;
    270271                                $table_name = $wpdb->prefix . 'advaipbl_blocked_ips';
    271                                 // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared
     272                                // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared, WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, PluginCheck.Security.DirectDB.UnescapedDBParameter
    272273                                $exists = $wpdb->get_var($wpdb->prepare("SELECT id FROM {$table_name} WHERE ip_range = %s", $ip_or_range));
    273274                               
  • advanced-ip-blocker/trunk/includes/class-advaipbl-admin-pages.php

    r3471934 r3476940  
    228228        $where_sql = implode(' AND ', $where_clauses);
    229229       
    230         // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared
     230        // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared, WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, PluginCheck.Security.DirectDB.UnescapedDBParameter
    231231        $total_items = $wpdb->get_var("SELECT COUNT(log_id) FROM $table_name WHERE $where_sql");
    232232        $total_pages = ceil($total_items / $per_page);
    233233        $offset = ($current_page - 1) * $per_page;
    234         // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared
     234        // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared, WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, PluginCheck.Security.DirectDB.UnescapedDBParameter
    235235        $logs = $wpdb->get_results($wpdb->prepare("SELECT * FROM $table_name WHERE $where_sql ORDER BY " . esc_sql($orderby) . " " . esc_sql($order) . " LIMIT %d OFFSET %d", $per_page, $offset), ARRAY_A);
    236236        ?>
     
    469469        // phpcs:enable
    470470
    471         // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared
     471        // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared, WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, PluginCheck.Security.DirectDB.UnescapedDBParameter
    472472        $total_items = $wpdb->get_var("SELECT COUNT(id) FROM {$table_name}");
    473473        $total_pages = ceil($total_items / $per_page);
    474474        $offset = ($current_page - 1) * $per_page;
    475475
    476         // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared
     476        // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared, WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, PluginCheck.Security.DirectDB.UnescapedDBParameter
    477477        $items = $wpdb->get_results($wpdb->prepare(
    478478            "SELECT * FROM {$table_name} ORDER BY " . esc_sql($orderby) . " " . esc_sql($order) . " LIMIT %d OFFSET %d",
     
    627627        <?php
    628628        // Primero, limpiamos los lockdowns expirados.
    629         // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared
     629        // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared, WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, PluginCheck.Security.DirectDB.UnescapedDBParameter
    630630        $wpdb->query($wpdb->prepare("DELETE FROM {$table_name} WHERE expires_at <= %d", time()));
    631631       
    632         // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared
     632        // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared, WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, PluginCheck.Security.DirectDB.UnescapedDBParameter
    633633        $items = $wpdb->get_results("SELECT * FROM {$table_name} ORDER BY created_at DESC", ARRAY_A);
    634634        ?>
     
    14341434    $where_sql = !empty($where_clauses) ? 'WHERE ' . implode(' AND ', $where_clauses) : '';
    14351435
    1436     // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared
     1436    // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared, WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, PluginCheck.Security.DirectDB.UnescapedDBParameter
    14371437    $total_items = $wpdb->get_var("SELECT COUNT(id) FROM {$table_name} {$where_sql}");
    14381438    $total_pages = ceil($total_items / $per_page);
    14391439
    1440     // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared, WordPress.DB.PreparedSQL.InterpolatedNotPrepared
     1440    // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared, WordPress.DB.PreparedSQL.InterpolatedNotPrepared, WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, PluginCheck.Security.DirectDB.UnescapedDBParameter
    14411441    $items_for_page = $wpdb->get_results($wpdb->prepare("SELECT * FROM {$table_name} {$where_sql} ORDER BY " . esc_sql($orderby) . " " . esc_sql($order) . " LIMIT %d OFFSET %d", $per_page, $offset), ARRAY_A);
    14421442
     
    19001900    $where_sql = implode(' AND ', $where_clauses);
    19011901   
    1902     // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared
     1902    // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared, WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, PluginCheck.Security.DirectDB.UnescapedDBParameter
    19031903    $total_items = $wpdb->get_var("SELECT COUNT(log_id) FROM $table_name WHERE $where_sql");
    19041904    $total_pages = ceil($total_items / $per_page);
    19051905    $offset = ($current_page - 1) * $per_page;
    1906     // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared
     1906    // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared, WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, PluginCheck.Security.DirectDB.UnescapedDBParameter
    19071907    $logs = $wpdb->get_results($wpdb->prepare("SELECT * FROM $table_name WHERE $where_sql ORDER BY " . esc_sql($orderby) . " " . esc_sql($order) . " LIMIT %d OFFSET %d", $per_page, $offset), ARRAY_A);
    19081908   
     
    20192019        $where_sql = implode(' AND ', $where_clauses);
    20202020
    2021         // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared
     2021        // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared, WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, PluginCheck.Security.DirectDB.UnescapedDBParameter
    20222022        $total_items = $wpdb->get_var("SELECT COUNT(id) FROM {$table_name} WHERE {$where_sql}");
    20232023        $total_pages = ceil($total_items / $per_page);
    20242024        $offset = ($current_page - 1) * $per_page;
    20252025
    2026         // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared
     2026        // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared, WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, PluginCheck.Security.DirectDB.UnescapedDBParameter
    20272027        $items = $wpdb->get_results($wpdb->prepare(
    20282028            // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared
     
    22012201       
    22022202        $where_sql = implode(' AND ', $where_clauses);
    2203         // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared
     2203        // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared, WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, PluginCheck.Security.DirectDB.UnescapedDBParameter
    22042204        $total_items = $wpdb->get_var("SELECT COUNT(log_id) FROM $table_name WHERE $where_sql");
    22052205        $total_pages = ceil($total_items / $per_page);
    22062206        $offset = ($current_page - 1) * $per_page;
    2207         // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared
     2207        // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared, WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, PluginCheck.Security.DirectDB.UnescapedDBParameter
    22082208        $logs = $wpdb->get_results($wpdb->prepare("SELECT * FROM $table_name WHERE $where_sql ORDER BY " . esc_sql($orderby) . " " . esc_sql($order) . " LIMIT %d OFFSET %d", $per_page, $offset), ARRAY_A);
    22092209    ?>
     
    35803580        $table_name = $wpdb->prefix . 'advaipbl_activity_log';
    35813581       
    3582         // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared
     3582        // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared, WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, PluginCheck.Security.DirectDB.UnescapedDBParameter
    35833583        if ($wpdb->get_var("SHOW TABLES LIKE '$table_name'") != $table_name) {
    35843584             $logs = [];
     
    35903590             
    35913591             // Count total for pagination (Simple implementation)
    3592              // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared
     3592             // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared, WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, PluginCheck.Security.DirectDB.UnescapedDBParameter
    35933593             $total_items = $wpdb->get_var("SELECT COUNT(id) FROM $table_name");
    35943594             $total_pages = ceil($total_items / $per_page);
  • advanced-ip-blocker/trunk/includes/class-advaipbl-ajax-handler.php

    r3472969 r3476940  
    171171        global $wpdb;
    172172        $table_name = $wpdb->prefix . 'advaipbl_endpoint_lockdowns';
    173         // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared
     173        // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared, WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, PluginCheck.Security.DirectDB.UnescapedDBParameter
    174174        $lockdown = $wpdb->get_row($wpdb->prepare("SELECT * FROM {$table_name} WHERE id = %d", $lockdown_id), ARRAY_A);
    175175
     
    953953
    954954            // Check if actively blocked (expires_at is 0 OR expires_at > current_time)
     955            // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared, WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, PluginCheck.Security.DirectDB.UnescapedDBParameter
    955956            $exists = $wpdb->get_var($wpdb->prepare(
    956957                "SELECT COUNT(*) FROM {$table_name} WHERE ip_range = %s AND (expires_at = 0 OR expires_at > %d)",
     
    10211022       
    10221023        // Fetch ALL actively blocked IPs (permanent or not expired)
    1023         // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.PreparedSQL.InterpolatedNotPrepared
     1024        // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.PreparedSQL.InterpolatedNotPrepared, WordPress.DB.DirectDatabaseQuery.NoCaching, PluginCheck.Security.DirectDB.UnescapedDBParameter
    10241025        $results = $wpdb->get_results($wpdb->prepare("SELECT ip_range, reason, expires_at, block_type FROM {$table_name} WHERE expires_at = 0 OR expires_at > %d", $current_time), ARRAY_A);
    10251026
  • advanced-ip-blocker/trunk/includes/class-advaipbl-asn-manager.php

    r3455663 r3476940  
    121121        global $wpdb;
    122122       
    123         // phpcs:disable WordPress.DB.PreparedSQL.InterpolatedNotPrepared
     123        // phpcs:disable WordPress.DB.PreparedSQL.InterpolatedNotPrepared, WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching
    124124        $log_json = $wpdb->get_var($wpdb->prepare(
    125125            "SELECT log_details FROM {$this->table_name} WHERE ip = %s",
    126126            $ip
    127127        ));
    128         // phpcs:enable WordPress.DB.PreparedSQL.InterpolatedNotPrepared
     128        // phpcs:enable WordPress.DB.PreparedSQL.InterpolatedNotPrepared, WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching
    129129
    130130        if ($log_json === null) {
  • advanced-ip-blocker/trunk/includes/class-advaipbl-audit-logger.php

    r3455663 r3476940  
    5858        $ip = $this->main_instance->get_client_ip();
    5959
    60         // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery
     60        // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching
    6161        $wpdb->insert(
    6262            $this->table_name,
     
    123123    public function get_logs($limit = 20, $offset = 0) {
    124124        global $wpdb;
    125         // phpcs:disable WordPress.DB.PreparedSQL.InterpolatedNotPrepared, WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching
     125        // phpcs:disable WordPress.DB.PreparedSQL.InterpolatedNotPrepared, WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, PluginCheck.Security.DirectDB.UnescapedDBParameter
    126126        return $wpdb->get_results($wpdb->prepare(
    127127            "SELECT * FROM {$this->table_name} ORDER BY timestamp DESC LIMIT %d OFFSET %d",
    128128            $limit, $offset
    129129        ), ARRAY_A);
    130         // phpcs:enable WordPress.DB.PreparedSQL.InterpolatedNotPrepared, WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching
     130        // phpcs:enable WordPress.DB.PreparedSQL.InterpolatedNotPrepared, WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, PluginCheck.Security.DirectDB.UnescapedDBParameter
    131131    }
    132132   
     
    148148        $cutoff_date = gmdate('Y-m-d H:i:s', current_time('timestamp') - ($retention_days * DAY_IN_SECONDS));
    149149       
    150         // phpcs:disable WordPress.DB.PreparedSQL.InterpolatedNotPrepared, WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching
     150        // phpcs:disable WordPress.DB.PreparedSQL.InterpolatedNotPrepared, WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, PluginCheck.Security.DirectDB.UnescapedDBParameter
    151151        $wpdb->query($wpdb->prepare("DELETE FROM {$this->table_name} WHERE timestamp < %s", $cutoff_date));
    152         // phpcs:enable WordPress.DB.PreparedSQL.InterpolatedNotPrepared, WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching
     152        // phpcs:enable WordPress.DB.PreparedSQL.InterpolatedNotPrepared, WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, PluginCheck.Security.DirectDB.UnescapedDBParameter
    153153    }
    154154
     
    160160    public function clear_all_logs() {
    161161        global $wpdb;
    162         // phpcs:disable WordPress.DB.PreparedSQL.InterpolatedNotPrepared, WordPress.DB.DirectDatabaseQuery.DirectQuery
     162        // phpcs:disable WordPress.DB.PreparedSQL.InterpolatedNotPrepared, WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, PluginCheck.Security.DirectDB.UnescapedDBParameter
    163163        return $wpdb->query("TRUNCATE TABLE {$this->table_name}");
    164         // phpcs:enable WordPress.DB.PreparedSQL.InterpolatedNotPrepared, WordPress.DB.DirectDatabaseQuery.DirectQuery
     164        // phpcs:enable WordPress.DB.PreparedSQL.InterpolatedNotPrepared, WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, PluginCheck.Security.DirectDB.UnescapedDBParameter
    165165    }
    166166}
  • advanced-ip-blocker/trunk/includes/class-advaipbl-cli.php

    r3455663 r3476940  
    128128        global $wpdb;
    129129        $table_name = $wpdb->prefix . 'advaipbl_logs';
     130        // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery
    130131        @$wpdb->insert( $table_name, [ 'timestamp' => current_time( 'mysql', 1 ), 'ip' => is_array($ip) ? wp_json_encode($ip) : $ip, 'log_type' => 'general', 'level' => $level, 'message' => $message, 'details' => wp_json_encode( [ 'source' => 'WP-CLI' ] ) ] );
    131132    }
     
    171172        global $wpdb;
    172173        $table_name = $wpdb->prefix . 'advaipbl_blocked_ips';
    173         // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared
     174        // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared, WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, PluginCheck.Security.DirectDB.UnescapedDBParameter
    174175        $exists = $wpdb->get_var($wpdb->prepare("SELECT id FROM {$table_name} WHERE ip_range = %s", $ip_or_range));
    175176
     
    678679        global $wpdb; $table_name = $wpdb->prefix . 'advaipbl_logs'; $type = $assoc_args['type'] ?? 'general'; $count = $assoc_args['count'] ?? 20;
    679680        $where_clause = '1=1'; if ( 'all' !== $type ) { $where_clause = $wpdb->prepare( 'log_type = %s', $type ); }
    680         // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared
     681        // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared, WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, PluginCheck.Security.DirectDB.UnescapedDBParameter
    681682        $logs = $wpdb->get_results( $wpdb->prepare( "SELECT timestamp, level, ip, message, details FROM $table_name WHERE $where_clause ORDER BY timestamp DESC LIMIT %d", $count ), ARRAY_A );
    682683        if ( empty( $logs ) ) { WP_CLI::line( 'No log entries found for the specified type.' ); return; }
     
    688689        if ( ! isset( $assoc_args['force'] ) ) { $confirm_message = ( 'all' === $type ) ? 'Are you sure you want to clear ALL logs? This action cannot be undone.' : "Are you sure you want to clear all '{$type}' logs?"; WP_CLI::confirm( $confirm_message ); }
    689690        global $wpdb; $table_name = $wpdb->prefix . 'advaipbl_logs'; $this->log_event_autonomo( "WP-CLI: Clearing logs of type '{$type}'.", 'warning' );
    690         if ( 'all' !== $type ) { $deleted = $wpdb->delete( $table_name, [ 'log_type' => $type ], [ '%s' ] ); WP_CLI::success( "{$deleted} logs of type '{$type}' have been cleared." ); } else {
    691             // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared
     691        if ( 'all' !== $type ) {
     692            // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching
     693            $deleted = $wpdb->delete( $table_name, [ 'log_type' => $type ], [ '%s' ] );
     694            WP_CLI::success( "{$deleted} logs of type '{$type}' have been cleared." );
     695        } else {
     696            // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared, WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, PluginCheck.Security.DirectDB.UnescapedDBParameter
    692697            $wpdb->query( "TRUNCATE TABLE $table_name" ); WP_CLI::success( 'All logs have been cleared.' ); }
    693698    }
  • advanced-ip-blocker/trunk/includes/class-advaipbl-community-manager.php

    r3464093 r3476940  
    3636
    3737        // 1. Vaciar la tabla (Truncate es más rápido que Delete)
    38         // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared, PluginCheck.Security.DirectDB.UnescapedDBParameter
     38        // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared, PluginCheck.Security.DirectDB.UnescapedDBParameter, WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching
    3939        $wpdb->query("TRUNCATE TABLE {$table_name}");
    4040
  • advanced-ip-blocker/trunk/includes/class-advaipbl-dashboard-manager.php

    r3455663 r3476940  
    5858        $results = $wpdb->get_results(
    5959    $wpdb->prepare(
    60         // phpcs:disable WordPress.DB.PreparedSQL.InterpolatedNotPrepared
     60        // phpcs:disable WordPress.DB.PreparedSQL.InterpolatedNotPrepared, WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching
    6161        "SELECT log_type, COUNT(*) as count
    6262         FROM {$table_name}
     
    6464         GROUP BY log_type
    6565         ORDER BY count DESC",
    66          // phpcs:enable WordPress.DB.PreparedSQL.InterpolatedNotPrepared
     66         // phpcs:enable WordPress.DB.PreparedSQL.InterpolatedNotPrepared, WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching
    6767        $date_after
    6868    ),
     
    9292        $results = $wpdb->get_results(
    9393    $wpdb->prepare(
    94         // phpcs:disable WordPress.DB.PreparedSQL.InterpolatedNotPrepared
     94        // phpcs:disable WordPress.DB.PreparedSQL.InterpolatedNotPrepared, WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching
    9595        "SELECT DATE(timestamp) as day, COUNT(*) as count
    9696         FROM {$table_name}
     
    9898         GROUP BY day
    9999         ORDER BY day ASC",
    100          // phpcs:enable WordPress.DB.PreparedSQL.InterpolatedNotPrepared
     100         // phpcs:enable WordPress.DB.PreparedSQL.InterpolatedNotPrepared, WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching
    101101        $date_after
    102102    ),
     
    132132        return $wpdb->get_results(
    133133    $wpdb->prepare(
    134         // phpcs:disable WordPress.DB.PreparedSQL.InterpolatedNotPrepared
     134        // phpcs:disable WordPress.DB.PreparedSQL.InterpolatedNotPrepared, WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching
    135135        "SELECT ip, COUNT(*) as count
    136136         FROM {$table_name}
     
    139139         ORDER BY count DESC
    140140         LIMIT 8",
    141          // phpcs:enable WordPress.DB.PreparedSQL.InterpolatedNotPrepared
     141         // phpcs:enable WordPress.DB.PreparedSQL.InterpolatedNotPrepared, WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching
    142142        $date_after
    143143    ),
     
    157157        return $wpdb->get_results(
    158158    $wpdb->prepare(
    159         // phpcs:disable WordPress.DB.PreparedSQL.InterpolatedNotPrepared
     159        // phpcs:disable WordPress.DB.PreparedSQL.InterpolatedNotPrepared, WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching
    160160        "SELECT JSON_UNQUOTE(JSON_EXTRACT(details, '$.country')) as country,
    161161                JSON_UNQUOTE(JSON_EXTRACT(details, '$.country_code')) as country_code,
     
    169169         ORDER BY count DESC
    170170         LIMIT 8",
    171          // phpcs:enable WordPress.DB.PreparedSQL.InterpolatedNotPrepared
     171         // phpcs:enable WordPress.DB.PreparedSQL.InterpolatedNotPrepared, WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching
    172172        $date_after
    173173    ),
     
    189189        $blocked_count = $wpdb->get_var(
    190190    $wpdb->prepare(
    191         // phpcs:disable WordPress.DB.PreparedSQL.InterpolatedNotPrepared
     191        // phpcs:disable WordPress.DB.PreparedSQL.InterpolatedNotPrepared, WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching
    192192        "SELECT COUNT(DISTINCT ip)
    193193         FROM {$table_name}
     
    195195           AND details LIKE %s
    196196           AND timestamp >= %s",
    197            // phpcs:enable WordPress.DB.PreparedSQL.InterpolatedNotPrepared
     197           // phpcs:enable WordPress.DB.PreparedSQL.InterpolatedNotPrepared, WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching
    198198        '%"source":"Spamhaus"%',
    199199        $date_after
  • advanced-ip-blocker/trunk/includes/class-advaipbl-fingerprint-manager.php

    r3464093 r3476940  
    7171
    7272    // Borramos las firmas que ya han expirado
    73     // phpcs:disable PluginCheck.Security.DirectDB.UnescapedDBParameter, WordPress.DB.PreparedSQL.InterpolatedNotPrepared
     73    // phpcs:disable PluginCheck.Security.DirectDB.UnescapedDBParameter, WordPress.DB.PreparedSQL.InterpolatedNotPrepared, WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching
    7474    $wpdb->query($wpdb->prepare("DELETE FROM {$signatures_table} WHERE expires_at <= %d", time()));
    75     // phpcs:enable PluginCheck.Security.DirectDB.UnescapedDBParameter, WordPress.DB.PreparedSQL.InterpolatedNotPrepared
     75    // phpcs:enable PluginCheck.Security.DirectDB.UnescapedDBParameter, WordPress.DB.PreparedSQL.InterpolatedNotPrepared, WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching
    7676
    7777    $start_time = time() - $analysis_window_seconds;
    7878
    7979    // 1. Encontrar firmas sospechosas (usadas por múltiples IPs)
    80     // phpcs:disable PluginCheck.Security.DirectDB.UnescapedDBParameter, WordPress.DB.PreparedSQL.InterpolatedNotPrepared
     80    // phpcs:disable PluginCheck.Security.DirectDB.UnescapedDBParameter, WordPress.DB.PreparedSQL.InterpolatedNotPrepared, WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching
    8181    $suspicious_signatures = $wpdb->get_results(
    8282        $wpdb->prepare(
     
    9090        )
    9191    );
    92     // phpcs:enable PluginCheck.Security.DirectDB.UnescapedDBParameter, WordPress.DB.PreparedSQL.InterpolatedNotPrepared
     92    // phpcs:enable PluginCheck.Security.DirectDB.UnescapedDBParameter, WordPress.DB.PreparedSQL.InterpolatedNotPrepared, WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching
    9393   
    9494    if (empty($suspicious_signatures)) {
     
    100100    foreach ($suspicious_signatures as $sig) {
    101101        // Comprobamos si esta firma ya está marcada como maliciosa (y no ha expirado)
    102         // phpcs:disable PluginCheck.Security.DirectDB.UnescapedDBParameter, WordPress.DB.PreparedSQL.InterpolatedNotPrepared
     102        // phpcs:disable PluginCheck.Security.DirectDB.UnescapedDBParameter, WordPress.DB.PreparedSQL.InterpolatedNotPrepared, WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching
    103103        $is_already_flagged = $wpdb->get_var($wpdb->prepare("SELECT id FROM {$signatures_table} WHERE signature_hash = %s", $sig->signature_hash));
    104         // phpcs:enable PluginCheck.Security.DirectDB.UnescapedDBParameter, WordPress.DB.PreparedSQL.InterpolatedNotPrepared
     104        // phpcs:enable PluginCheck.Security.DirectDB.UnescapedDBParameter, WordPress.DB.PreparedSQL.InterpolatedNotPrepared, WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching
    105105        if ($is_already_flagged) {
    106106            continue;
     
    108108
    109109        // 2. Obtener un ejemplo de la petición más común para esta firma
    110         // phpcs:disable PluginCheck.Security.DirectDB.UnescapedDBParameter, WordPress.DB.PreparedSQL.InterpolatedNotPrepared
     110        // phpcs:disable PluginCheck.Security.DirectDB.UnescapedDBParameter, WordPress.DB.PreparedSQL.InterpolatedNotPrepared, WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching
    111111        $sample = $wpdb->get_row(
    112112            $wpdb->prepare(
     
    121121            )
    122122        );
    123         // phpcs:enable PluginCheck.Security.DirectDB.UnescapedDBParameter, WordPress.DB.PreparedSQL.InterpolatedNotPrepared
     123        // phpcs:enable PluginCheck.Security.DirectDB.UnescapedDBParameter, WordPress.DB.PreparedSQL.InterpolatedNotPrepared, WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching
    124124
    125125        // Añadimos un log si la consulta de ejemplo falla, para depuración futura.
     
    213213
    214214        // 1. Obtenemos una petición de ejemplo para desglosar la firma (cabeceras, etc.)
    215         // phpcs:disable PluginCheck.Security.DirectDB.UnescapedDBParameter, WordPress.DB.PreparedSQL.InterpolatedNotPrepared
     215        // phpcs:disable PluginCheck.Security.DirectDB.UnescapedDBParameter, WordPress.DB.PreparedSQL.InterpolatedNotPrepared, WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching
    216216        $sample_request = $wpdb->get_row($wpdb->prepare(
    217217            "SELECT user_agent, request_headers FROM {$log_table} WHERE signature_hash = %s LIMIT 1",
    218218            $signature_hash
    219219        ));
    220         // phpcs:enable PluginCheck.Security.DirectDB.UnescapedDBParameter, WordPress.DB.PreparedSQL.InterpolatedNotPrepared
     220        // phpcs:enable PluginCheck.Security.DirectDB.UnescapedDBParameter, WordPress.DB.PreparedSQL.InterpolatedNotPrepared, WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching
    221221
    222222        if (!$sample_request) {
     
    225225       
    226226        // 2. Obtenemos la evidencia: las últimas 15 IPs distintas que usaron esta firma.
    227         // phpcs:disable PluginCheck.Security.DirectDB.UnescapedDBParameter, WordPress.DB.PreparedSQL.InterpolatedNotPrepared
     227        // phpcs:disable PluginCheck.Security.DirectDB.UnescapedDBParameter, WordPress.DB.PreparedSQL.InterpolatedNotPrepared, WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching
    228228        $evidence = $wpdb->get_results($wpdb->prepare(
    229229            "SELECT DISTINCT ip_hash, user_agent, request_uri, timestamp, is_fake_bot as is_impersonator
     
    234234            $signature_hash
    235235        ));
    236         // phpcs:enable PluginCheck.Security.DirectDB.UnescapedDBParameter, WordPress.DB.PreparedSQL.InterpolatedNotPrepared
     236        // phpcs:enable PluginCheck.Security.DirectDB.UnescapedDBParameter, WordPress.DB.PreparedSQL.InterpolatedNotPrepared, WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching
    237237       
    238238        $details = [
  • advanced-ip-blocker/trunk/includes/class-advaipbl-live-feed-manager.php

    r3455663 r3476940  
    5353       
    5454        $table_name = $wpdb->prefix . 'advaipbl_activity_log';
     55        // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching
    5556        if ($wpdb->get_var($wpdb->prepare("SHOW TABLES LIKE %s", $table_name)) != $table_name) {
    5657             return new WP_REST_Response(['attacks' => [], 'last_id' => 0], 200);
     
    7879        }
    7980       
    80         // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared, PluginCheck.Security.DirectDB.UnescapedDBParameter
     81        // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared, PluginCheck.Security.DirectDB.UnescapedDBParameter, WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching
    8182        $results = $wpdb->get_results($query, ARRAY_A);
    8283       
     
    105106                        break;
    106107                    case 'advanced_rule':
     108                        // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared, WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, PluginCheck.Security.DirectDB.UnescapedDBParameter
    107109                        $block_entry = $wpdb->get_row($wpdb->prepare("SELECT reason FROM {$wpdb->prefix}advaipbl_blocked_ips WHERE ip_range = %s", $row['ip']), ARRAY_A);
    108110                        if ($block_entry && !empty($block_entry['reason'])) {
     
    122124                }
    123125               
     126                $obfuscated_ip = $this->obfuscate_ip($row['ip']);
     127               
    124128                $attacks[] = [
    125129                    'id'          => (int) $row['log_id'],
    126130                    'time'        => human_time_diff(strtotime($row['timestamp'])) . ' ago',
    127                     'ip'          => esc_html($row['ip']),
     131                    'ip'          => esc_html($obfuscated_ip),
    128132                    'type'        => esc_html(ucwords(str_replace('_', ' ', $log_type))),
    129133                    'location'    => esc_html($location),
    130134                    'method'      => esc_html($details_data['method'] ?? 'N/A'),
    131                     'details'     => esc_html($details_message),
    132                     'user_agent'  => esc_html($details_data['user_agent'] ?? 'N/A'),
    133                     'uri'         => esc_html($details_data['uri'] ?? ($details_data['url'] ?? '')),
     135                    'details'     => esc_html($details_message)
    134136                ];
    135137            }
     
    143145
    144146    /**
     147     * Obfuscates an IP address for public display (GDPR compliance).
     148     * IPv4: 192.168.1.55 -> 192.168.1.*
     149     * IPv6: 2001:0db8:85a3:0000:0000:8a2e:0370:7334 -> 2001:0db8:85a3:****:****:****:****:****
     150     *
     151     * @param string $ip
     152     * @return string
     153     */
     154    private function obfuscate_ip($ip) {
     155        if (empty($ip)) {
     156            return '';
     157        }
     158
     159        // IPv4 Obfuscation
     160        if (filter_var($ip, FILTER_VALIDATE_IP, FILTER_FLAG_IPV4)) {
     161            $parts = explode('.', $ip);
     162            if (count($parts) === 4) {
     163                // Return 192.168.1.*
     164                return $parts[0] . '.' . $parts[1] . '.' . $parts[2] . '.*';
     165            }
     166        }
     167        // IPv6 Obfuscation
     168        elseif (filter_var($ip, FILTER_VALIDATE_IP, FILTER_FLAG_IPV6)) {
     169            // Expand IPv6 to full length to parse correctly
     170            $expanded = inet_ntop(inet_pton($ip));
     171            if ($expanded !== false) {
     172                $parts = explode(':', $expanded);
     173                if (count($parts) === 8) {
     174                    // Return first 3 blocks, obfuscate the rest
     175                    return $parts[0] . ':' . $parts[1] . ':' . $parts[2] . ':**::**';
     176                }
     177            }
     178        }
     179
     180        // Fallback: simply mask the last half of the string if validation fails
     181        $len = strlen($ip);
     182        return substr($ip, 0, (int)($len / 2)) . '***';
     183    }
     184
     185    /**
    145186     * API Callback for Nonce.
    146187     */
     
    155196     */
    156197    public function render_shortcode($atts) {
    157         // Use the proper paths relative to this file's location in includes/
    158         // Original: plugin_dir_url(dirname(__FILE__)) . 'js/...'
    159         // If this file is in includes/, dirname is includes.
    160         // plugin_dir_url(includes) -> yields URL to includes.
    161         // But 'js/' is usually at the root of the plugin or assets/.
    162         // Original main was in includes/ too? checking...
    163         // Main path: .../includes/class-advaipbl-main.php
    164         // The original code used: plugin_dir_url(dirname(__FILE__)) . 'js/advaipbl-live-feed.js'
    165         // dirname(__FILE__) = .../includes
    166         // plugin_dir_url via dirname would point to the includes folder URL.
    167         // BUT 'js' folder is likely parallel to 'includes', not inside it.
    168         // Original code logic: plugin_dir_url(...) returns URL with trailing slash.
    169         // If dirname is .../includes, url is https://.../includes/
    170         // Then . 'js/...' -> https://.../includes/js/...
    171         // This implies /includes/js/ exists?
    172         // Re-checking list_dir: js is at logical root, includes is at logical root.
    173         // Wait, list_dir of includes showed 'lib' inside.
    174         // list_dir of root (implicit from previous context) showed 'js' folder.
    175         // So 'js' is a sibling of 'includes'.
    176         // So the original code `plugin_dir_url(dirname(__FILE__))` pointing to includes/ seems wrong if it appends 'js/' directly, unless 'js' IS inside includes.
    177         // Let's use `plugin_dir_url( dirname( __DIR__ ) )` to go up one level safely.
    178         // dirname(__DIR__) from includes/class... -> .../plugin-root
    179        
    180         $root_url = plugin_dir_url( dirname( __FILE__ ) ); // Points to .../includes/ OR plugin root?
    181         // plugin_dir_url accepts a FILE path.
    182         // plugin_dir_url( __FILE__ ) ->  .../includes/
    183         // plugin_dir_url( dirname( __FILE__ ) . '/../advanced-ip-blocker.php' ) -> Root.
    184        
    185         // Safer approach used in many plugins:
    186198        $root_url = plugins_url( '/', dirname( __FILE__ ) );
    187199
  • advanced-ip-blocker/trunk/includes/class-advaipbl-main.php

    r3471934 r3476940  
    243243        add_action('wp_ajax_advaipbl_run_fim_scan', [$this->ajax_handler, 'ajax_run_fim_scan']);
    244244       
    245         if (is_admin() || (isset($_GET['action']) && strpos($_GET['action'], 'advaipbl_') === 0)) {
     245        // phpcs:ignore WordPress.Security.NonceVerification.Recommended
     246        $action = isset($_GET['action']) ? sanitize_text_field(wp_unslash($_GET['action'])) : '';
     247        if (is_admin() || (strpos($action, 'advaipbl_') === 0)) {
    246248            add_action('admin_init', [$this, 'initialize_backend_managers'], 0);
    247249
     
    446448    public function log_request_signature() {
    447449        if (empty($this->options['enable_signature_engine'])) { return; }
     450       
     451        $request_uri = isset($_SERVER['REQUEST_URI']) ? sanitize_text_field(wp_unslash($_SERVER['REQUEST_URI'])) : '';
    448452        // No loguear las peticiones del Live Feed interno
    449         if (strpos($_SERVER['REQUEST_URI'], '/advaipbl/v1/live-attacks') !== false) {
     453        if (strpos($request_uri, '/advaipbl/v1/live-attacks') !== false) {
    450454            return;
    451455        }
     
    456460        }
    457461       
    458         $request_uri = $_SERVER['REQUEST_URI'] ?? '';
    459462        if (wp_is_json_request() && strpos($request_uri, '/telemetry/') === false && strpos($request_uri, '/aib-network/') === false && strpos($request_uri, '/aib-scanner/') === false) {
    460463            return;
     
    587590        ];
    588591
     592        // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, PluginCheck.Security.DirectDB.UnescapedDBParameter
    589593        $wpdb->insert($table_name, $data_to_log);
    590594    }           
     
    692696        }
    693697
     698        // phpcs:ignore WordPress.Security.NonceVerification.Missing
    694699        if (isset($_POST['_advaipbl_js_token'])) {
    695700    // Parámetros para el desafío de firmas: cookie 'advaipbl_js_verified', duración 4 horas.
     
    706711       
    707712        // Fix: Check if table exists to avoid fatal error on fresh install
     713        // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared, WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, PluginCheck.Security.DirectDB.UnescapedDBParameter
    708714        if ($wpdb->get_var("SHOW TABLES LIKE '$signatures_table'") != $signatures_table) {
    709715            return;
    710716        }
    711717
     718        // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared, WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, PluginCheck.Security.DirectDB.UnescapedDBParameter
    712719        $is_malicious = $wpdb->get_var($wpdb->prepare(
    713720            "SELECT id FROM {$signatures_table} WHERE signature_hash = %s AND expires_at > %d",
     
    742749            return;
    743750        }
     751        // phpcs:ignore WordPress.Security.NonceVerification.Missing
    744752        if (isset($_POST['_advaipbl_challenge_type']) && $_POST['_advaipbl_challenge_type'] === 'geo_challenge') {
    745753            $duration_hours = (int)($this->options['geo_challenge_cookie_duration'] ?? 24);
     
    978986    }
    979987
     988    // phpcs:ignore WordPress.WP.EnqueuedResourceParameters.MissingVersion
    980989    wp_enqueue_script(
    981990        'google-recaptcha',
     
    11181127    }
    11191128
    1120     if (!isset($_POST['g-recaptcha-response']) || empty($_POST['g-recaptcha-response'])) {
     1129    // phpcs:ignore WordPress.Security.NonceVerification.Missing
     1130    $recaptcha_response = isset($_POST['g-recaptcha-response']) ? sanitize_text_field(wp_unslash($_POST['g-recaptcha-response'])) : '';
     1131    if (empty($recaptcha_response)) {
    11211132        return new WP_Error('recaptcha_empty', __('<strong>ERROR</strong>: Please complete the reCAPTCHA verification.', 'advanced-ip-blocker'));
    11221133    }
    11231134
    1124     $token = sanitize_text_field($_POST['g-recaptcha-response']);
     1135    $token = $recaptcha_response;
    11251136    $visitor_ip = $this->get_client_ip();
    11261137
     
    12621273        global $wpdb;
    12631274        $table_name = $wpdb->prefix . 'advaipbl_blocked_ips';
    1264         // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared
     1275        // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared, WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, PluginCheck.Security.DirectDB.UnescapedDBParameter
    12651276        $count = (int) $wpdb->get_var("SELECT COUNT(id) FROM {$table_name}");
    12661277        wp_cache_set('blocked_ips_count', $count, 'advaipbl', 300); // Cache por 5 minutos
     
    12811292    $count = wp_cache_get('blocked_signatures_count', 'advaipbl');
    12821293    if (false === $count) {
    1283         // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared
     1294        // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared, WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, PluginCheck.Security.DirectDB.UnescapedDBParameter
    12841295        $count = (int) $wpdb->get_var($wpdb->prepare("SELECT COUNT(id) FROM {$table_name} WHERE expires_at > %d", time()));
    12851296        wp_cache_set('blocked_signatures_count', $count, 'advaipbl', 300); // Cache por 5 minutos
     
    12981309    if (false === $count) {
    12991310        // Primero, limpiamos los expirados para un conteo preciso
    1300         // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared
     1311        // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared, WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, PluginCheck.Security.DirectDB.UnescapedDBParameter
    13011312        $wpdb->query($wpdb->prepare("DELETE FROM {$table_name} WHERE expires_at <= %d", time()));
    1302         // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared
     1313        // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared, WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, PluginCheck.Security.DirectDB.UnescapedDBParameter
    13031314        $count = (int) $wpdb->get_var("SELECT COUNT(id) FROM {$table_name}");
    13041315        wp_cache_set('blocked_endpoints_count', $count, 'advaipbl', 300); // Cache por 5 minutos
     
    13841395        global $wpdb;
    13851396        $table_name = $wpdb->prefix . 'advaipbl_cache';
    1386         // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared
     1397        // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared, WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, PluginCheck.Security.DirectDB.UnescapedDBParameter
    13871398        $wpdb->query("TRUNCATE TABLE `{$table_name}`");
    13881399
     
    15231534
    15241535        // --- 1. Determinar la pestaña y sub-pestaña activas ---
     1536        // phpcs:ignore WordPress.Security.NonceVerification.Recommended
    15251537        $current_page_slug = isset($_GET['page']) ? sanitize_key($_GET['page']) : '';
    15261538       
     1539        // phpcs:ignore WordPress.Security.NonceVerification.Recommended
    15271540        if (isset($_GET['tab'])) {
     1541            // phpcs:ignore WordPress.Security.NonceVerification.Recommended
    15281542            $active_main_tab = sanitize_key($_GET['tab']);
    15291543        } else {
     
    15471561        }
    15481562       
     1563        // phpcs:ignore WordPress.Security.NonceVerification.Recommended
    15491564        $active_sub_tab = isset($_GET['sub-tab']) ? sanitize_key($_GET['sub-tab']) : null;
    15501565
     
    16181633            if ( 'main_dashboard' === $active_sub_tab ) {
    16191634                wp_enqueue_script('chartjs', plugin_dir_url( dirname( __FILE__ ) ) . 'assets/js/chart.min.js', [], '3.9.1', true);
     1635                // phpcs:ignore WordPress.WP.EnqueuedResourceParameters.MissingVersion
    16201636                wp_enqueue_style('leaflet-css', plugin_dir_url( dirname( __FILE__ ) ) . 'assets/css/leaflet.css');
    16211637                wp_enqueue_script('leaflet-js', plugin_dir_url( dirname( __FILE__ ) ) . 'assets/js/leaflet.js', [], '1.9.4', true);
     1638                // phpcs:ignore WordPress.WP.EnqueuedResourceParameters.MissingVersion
    16221639                wp_enqueue_style('leaflet-markercluster-css', plugin_dir_url( dirname( __FILE__ ) ) . 'assets/css/MarkerCluster.css');
     1640                // phpcs:ignore WordPress.WP.EnqueuedResourceParameters.MissingVersion
    16231641                wp_enqueue_style('leaflet-markercluster-default-css', plugin_dir_url( dirname( __FILE__ ) ) . 'assets/css/MarkerCluster.Default.css');
    16241642                wp_enqueue_script('leaflet-markercluster-js', plugin_dir_url( dirname( __FILE__ ) ) . 'assets/js/leaflet.markercluster.js', ['leaflet-js'], '1.5.3', true);
     
    16281646            // Cargar assets de la página "About"
    16291647            // STRICT CHECK: Ensure we are explicitly on the about tab to avoid loading Stripe/Sift on other pages (CSP issues)
     1648            // phpcs:ignore WordPress.Security.NonceVerification.Recommended
    16301649            if (isset($_GET['tab']) && $_GET['tab'] === 'about') {
     1650                // phpcs:ignore WordPress.WP.EnqueuedResourceParameters.MissingVersion
    16311651                wp_enqueue_script('stripe-buy-button', 'https://js.stripe.com/v3/buy-button.js', [], null, true);
    16321652            }
     
    20372057    if ( ! empty( $this->options['prevent_author_scanning'] ) && ! is_admin() ) {
    20382058        // Comprobamos directamente el parámetro GET 'author'. Es mucho más fiable.
     2059        // phpcs:ignore WordPress.Security.NonceVerification.Recommended
    20392060        if ( isset( $_GET['author'] ) && is_numeric( $_GET['author'] ) ) {
    20402061            wp_safe_redirect( home_url(), 301 );
     
    24382459        // If a deadlock occurs, it just means another process is handling this IP, which is fine.
    24392460        $wpdb->suppress_errors();
     2461        // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching
    24402462        $lock_acquired = $wpdb->query($wpdb->prepare("INSERT IGNORE INTO {$wpdb->prefix}advaipbl_cache (cache_key, cache_value, expires_at) VALUES (%s, '1', %d)", $lock_key, time() + 15));
    24412463        $wpdb->show_errors();
     
    24482470       
    24492471        $table_name = $wpdb->prefix . 'advaipbl_blocked_ips';
    2450         // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared
     2472        // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared, WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, PluginCheck.Security.DirectDB.UnescapedDBParameter
    24512473        if ($wpdb->get_var($wpdb->prepare("SELECT id FROM {$table_name} WHERE ip_range = %s", $ip))) {
    24522474            $wpdb->delete("{$wpdb->prefix}advaipbl_cache", ['cache_key' => $lock_key]);
     
    24742496$expires_at = ($duration_in_seconds > 0) ? $timestamp + $duration_in_seconds : 0;
    24752497
     2498        // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, PluginCheck.Security.DirectDB.UnescapedDBParameter
    24762499        $wpdb->insert($table_name, [ 'ip_range' => $ip, 'block_type' => $type, 'timestamp' => $timestamp, 'expires_at' => $expires_at, 'reason' => $reason_message ]);
    24772500       
     
    25342557    }
    25352558
     2559    // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared, WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, PluginCheck.Security.DirectDB.UnescapedDBParameter
    25362560    $wpdb->delete("{$wpdb->prefix}advaipbl_cache", ['cache_key' => $lock_key]);
    25372561
     
    25972621        $table_name = $wpdb->prefix . 'advaipbl_logs';
    25982622       
    2599         // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, WordPress.DB.PreparedSQL.InterpolatedNotPrepared
     2623        // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, WordPress.DB.PreparedSQL.InterpolatedNotPrepared, PluginCheck.Security.DirectDB.UnescapedDBParameter
    26002624        $wpdb->query($wpdb->prepare("DELETE FROM $table_name WHERE timestamp < DATE_SUB(NOW(), INTERVAL %d DAY)", $retention_days));
    26012625    }
     
    26162640        $table_blocked = $wpdb->prefix . 'advaipbl_blocked_ips';
    26172641       
     2642        // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared, WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, PluginCheck.Security.DirectDB.UnescapedDBParameter
    26182643        $table_missing = ($wpdb->get_var("SHOW TABLES LIKE '$table_audit'") != $table_audit)
    26192644                      || ($wpdb->get_var("SHOW TABLES LIKE '$table_blocked'") != $table_blocked);
     
    27562781
    27572782                // Insertamos la fila en la nueva tabla.
     2783                // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, PluginCheck.Security.DirectDB.UnescapedDBParameter
    27582784                $wpdb->insert(
    27592785                    $table_name,
     
    32603286    }
    32613287   
     3288    // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, PluginCheck.Security.DirectDB.UnescapedDBParameter
    32623289    @$wpdb->insert(
    32633290        $table_name,
     
    34763503       
    34773504        $wpdb->suppress_errors(); // Avoid deadlock noise
     3505        // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, PluginCheck.Security.DirectDB.UnescapedDBParameter
    34783506        $lock_acquired = $wpdb->query($wpdb->prepare(
    34793507            "INSERT IGNORE INTO {$wpdb->prefix}advaipbl_cache (cache_key, cache_value, expires_at) VALUES (%s, %s, %d)",
     
    34863514        }
    34873515        $table_name_blocked = $wpdb->prefix . 'advaipbl_blocked_ips';
    3488         // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared
     3516        // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared, WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, PluginCheck.Security.DirectDB.UnescapedDBParameter
    34893517        $existing_block = $wpdb->get_var($wpdb->prepare("SELECT id FROM {$table_name_blocked} WHERE ip_range = %s", $ip));
    34903518        if ($existing_block) {
     3519            // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared, WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, PluginCheck.Security.DirectDB.UnescapedDBParameter
    34913520            $wpdb->delete("{$wpdb->prefix}advaipbl_cache", ['cache_key' => $lock_key]);
    34923521            return;
     
    35073536        $option_key = $option_key_map[$type] ?? null;
    35083537        if ( ! $option_key ) {
     3538            // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared, WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, PluginCheck.Security.DirectDB.UnescapedDBParameter
    35093539            $wpdb->delete("{$wpdb->prefix}advaipbl_cache", ['cache_key' => $lock_key]); // Liberar cerrojo antes de salir
    35103540            return;
     
    35793609        } elseif ($notification_enabled && in_array($frequency, ['daily', 'weekly'])) {
    35803610            $table_name_queue = $wpdb->prefix . 'advaipbl_notifications_queue';
     3611            // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, PluginCheck.Security.DirectDB.UnescapedDBParameter
    35813612            @$wpdb->insert($table_name_queue, ['timestamp' => current_time('mysql', 1), 'ip' => $ip, 'block_type' => $type, 'reason' => $reason]);
    35823613        }
     
    35993630        }
    36003631
     3632        // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared, WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, PluginCheck.Security.DirectDB.UnescapedDBParameter
    36013633        $wpdb->delete("{$wpdb->prefix}advaipbl_cache", ['cache_key' => $lock_key]);
    36023634    }
     
    40854117    $this->block_response_initiated = true;
    40864118
    4087     $is_xmlrpc_request = (isset($_SERVER['REQUEST_URI']) && strpos($_SERVER['REQUEST_URI'], 'xmlrpc.php') !== false);
     4119    $request_uri = isset($_SERVER['REQUEST_URI']) ? sanitize_text_field(wp_unslash($_SERVER['REQUEST_URI'])) : '';
     4120    $is_xmlrpc_request = (strpos($request_uri, 'xmlrpc.php') !== false);
    40884121
    40894122    $custom_message = $this->options['custom_block_message'] ?? '';
     
    41524185        $is_single_ip = filter_var($entry_to_unblock, FILTER_VALIDATE_IP);
    41534186
    4154         // Borrar de la nueva tabla
     4187        // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching
    41554188        $wpdb->delete($table_name, ['ip_range' => $entry_to_unblock]);
    41564189       
    41574190        // También borrar de la tabla de reportes pendientes para evitar falsos positivos
    41584191        $table_reports = $wpdb->prefix . 'advaipbl_pending_reports';
     4192        // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching
    41594193        $wpdb->delete($table_reports, ['ip' => $entry_to_unblock]);
    41604194       
     
    42124246
    42134247        // 1. Vaciar la tabla de IPs bloqueadas.
    4214         // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared
     4248        // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared, WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, PluginCheck.Security.DirectDB.UnescapedDBParameter
    42154249        $wpdb->query("TRUNCATE TABLE `{$table_name_blocked}`");
    42164250       
    42174251        // También vaciar la tabla de reportes pendientes
    42184252        $table_reports = $wpdb->prefix . 'advaipbl_pending_reports';
    4219         // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared
     4253        // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared, WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, PluginCheck.Security.DirectDB.UnescapedDBParameter
    42204254        $wpdb->query("TRUNCATE TABLE `{$table_reports}`");
    42214255
     
    42604294        // 1. Obtener todas las IPs que van a expirar
    42614295        // Aumentamos el límite a 100 para procesar en lotes razonables y evitar timeouts masivos
    4262         // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared
     4296        // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared, WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, PluginCheck.Security.DirectDB.UnescapedDBParameter
    42634297        $expiring_ips = $wpdb->get_results($wpdb->prepare(
    42644298            "SELECT ip_range, block_type FROM {$table_name} WHERE expires_at < %d AND expires_at > 0 LIMIT 100",
     
    46834717*/
    46844718public function conditionally_remove_admin_notices() {
     4719    // phpcs:ignore WordPress.Security.NonceVerification.Recommended
    46854720    $current_page_slug = isset($_GET['page']) ? sanitize_key($_GET['page']) : '';
    46864721    $plugin_pages = [
     
    50035038   
    50045039    // Obtenemos los parámetros de la URL actual para mantenerlos al ordenar
     5040    // phpcs:ignore WordPress.Security.NonceVerification.Recommended
    50055041    $current_params = $_GET;
    50065042    $url_params = array_merge($current_params, [
     
    51895225        $definitions = $this->get_all_block_type_definitions();
    51905226       
    5191         // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared
     5227        // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared, WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, PluginCheck.Security.DirectDB.UnescapedDBParameter
    51925228        $results = $wpdb->get_results("SELECT * FROM {$table_name}", ARRAY_A);
    51935229
     
    54865522    public function display_telemetry_notice() {
    54875523        // Condición 1: Solo mostrar en las páginas de nuestro plugin.
    5488         if (!isset($_GET['page']) || strpos($_GET['page'], 'advaipbl_settings_page') === false) {
     5524        // phpcs:ignore WordPress.Security.NonceVerification.Recommended
     5525        $page = isset($_GET['page']) ? sanitize_text_field(wp_unslash($_GET['page'])) : '';
     5526        if (strpos($page, 'advaipbl_settings_page') === false) {
    54895527            return;
    54905528        }
     
    56005638
    56015639        $seven_days_ago = gmdate('Y-m-d H:i:s', strtotime('-7 days'));
     5640        // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching
    56025641        $blocks_by_type_results = $wpdb->get_results( $wpdb->prepare(
    56035642            "SELECT log_type, COUNT(log_id) as count FROM {$wpdb->prefix}advaipbl_logs WHERE level = 'critical' AND timestamp >= %s GROUP BY log_type",
     
    56175656            'blocked_user_agents_count' => count(get_option(self::OPTION_BLOCKED_UAS, [])),
    56185657            'manual_asn_count'        => count(get_option(self::OPTION_BLOCKED_ASNS, [])),
     5658            // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching
    56195659            'total_blocks_7d'         => (int) $wpdb->get_var($wpdb->prepare("SELECT COUNT(log_id) FROM {$wpdb->prefix}advaipbl_logs WHERE level = 'critical' AND timestamp >= %s", $seven_days_ago)),
    56205660            'blocks_by_type_7d'       => $blocks_by_type_7d,
    56215661            'geoblock_country_count'  => count($this->options['geoblock_countries'] ?? []),
    56225662            'active_blocks_count'     => $this->get_blocked_count(),
     5663            // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching
    56235664            'ips_with_active_score'   => (int) $wpdb->get_var("SELECT COUNT(id) FROM {$wpdb->prefix}advaipbl_ip_scores"),
     5665            // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching
    56245666            'active_malicious_signatures' => (int) $wpdb->get_var($wpdb->prepare("SELECT COUNT(id) FROM {$wpdb->prefix}advaipbl_malicious_signatures WHERE expires_at > %d", time())),
    56255667            'geo_challenge_country_count' => count($this->options['geo_challenge_countries'] ?? []),
     
    56565698        check_ajax_referer( 'advaipbl_export_nonce', 'nonce' );
    56575699
    5658         $export_type = isset( $_POST['export_type'] ) && in_array( $_POST['export_type'], ['template', 'full_backup'] ) ? $_POST['export_type'] : 'template';
     5700        $export_type_raw = isset( $_POST['export_type'] ) ? sanitize_text_field(wp_unslash($_POST['export_type'])) : 'template';
     5701        $export_type = in_array( $export_type_raw, ['template', 'full_backup'] ) ? $export_type_raw : 'template';
    56595702
    56605703        global $wpdb;
     
    56695712        // 2. Exportar la tabla de IPs bloqueadas
    56705713        $table_name = $wpdb->prefix . 'advaipbl_blocked_ips';
    5671         // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared
     5714        // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared, WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, PluginCheck.Security.DirectDB.UnescapedDBParameter
    56725715        $blocked_ips_data = $wpdb->get_results("SELECT ip_range, block_type, timestamp, expires_at, reason FROM {$table_name}", ARRAY_A);
    56735716        if (!empty($blocked_ips_data)) {
     
    56805723                'recaptcha_site_key', 'recaptcha_secret_key',
    56815724                'api_key_ipapicom', 'api_key_ipstackcom', 'api_key_ipinfocom',
    5682                 'api_key_ip_apicom', 'maxmind_license_key', 'push_webhook_urls'
     5725                'api_key_ip_apicom', 'maxmind_license_key', 'push_webhook_urls',
     5726                'cf_api_token', 'cf_zone_id', 'abuseipdb_api_key'
    56835727            ];
    56845728            foreach ($sensitive_keys as $sensitive_key) {
     
    57105754    $type = 'error';
    57115755
    5712     if ( isset( $_FILES['advaipbl_import_file'] ) && UPLOAD_ERR_OK === $_FILES['advaipbl_import_file']['error'] ) {
    5713         $file_name = $_FILES['advaipbl_import_file']['name'];
     5756    $file_error = isset($_FILES['advaipbl_import_file']['error']) ? (int) $_FILES['advaipbl_import_file']['error'] : UPLOAD_ERR_NO_FILE;
     5757    if ( isset( $_FILES['advaipbl_import_file'] ) && UPLOAD_ERR_OK === $file_error ) {
     5758        $file_name = isset( $_FILES['advaipbl_import_file']['name'] ) ? sanitize_file_name(wp_unslash($_FILES['advaipbl_import_file']['name'])) : '';
    57145759        if ( 'json' !== pathinfo( $file_name, PATHINFO_EXTENSION ) ) {
    57155760            $message = __( 'Error: The uploaded file is not a .json file.', 'advanced-ip-blocker' );
    57165761            $this->log_event( sprintf( 'A failed settings import was attempted by %s (invalid file type).', $this->get_current_admin_username() ), 'error' );
    57175762        } else {
    5718             $file_content = file_get_contents( $_FILES['advaipbl_import_file']['tmp_name'] );
     5763            $tmp_name = isset( $_FILES['advaipbl_import_file']['tmp_name'] ) ? sanitize_text_field(wp_unslash($_FILES['advaipbl_import_file']['tmp_name'])) : '';
     5764            if (empty($tmp_name)) {
     5765                return;
     5766            }
     5767            $file_content = file_get_contents( $tmp_name );
    57195768            $settings_to_import = json_decode( $file_content, true );
    57205769
     
    57395788                        global $wpdb;
    57405789                        $table_name = $wpdb->prefix . 'advaipbl_blocked_ips';
    5741                         // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared
     5790                        // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared, WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, PluginCheck.Security.DirectDB.UnescapedDBParameter
    57425791                        $wpdb->query("TRUNCATE TABLE `{$table_name}`");
    57435792                       
     
    58975946    public function handle_login_action() {
    58985947        if ( ! isset( $_POST['advaipbl_2fa_login_step'] ) ) { return; }
    5899         $step = $_POST['advaipbl_2fa_login_step'];
     5948        $step = sanitize_text_field(wp_unslash($_POST['advaipbl_2fa_login_step']));
    59005949        $user_id = isset( $_POST['user_id'] ) ? absint( $_POST['user_id'] ) : 0;
    5901         $code = isset( $_POST['advaipbl_2fa_code'] ) ? trim( sanitize_text_field( $_POST['advaipbl_2fa_code'] ) ) : '';
    5902         $nonce = $_POST['_wpnonce'] ?? '';
     5950        $code = isset( $_POST['advaipbl_2fa_code'] ) ? trim( sanitize_text_field( wp_unslash($_POST['advaipbl_2fa_code']) ) ) : '';
     5951        $nonce = isset($_POST['_wpnonce']) ? sanitize_text_field(wp_unslash($_POST['_wpnonce'])) : '';
    59035952        $user = get_user_by( 'id', $user_id );
    59045953        if ( ! $user ) { wp_die( 'Authentication error: Invalid user.' ); }
     
    59215970        if ( $is_valid ) {
    59225971            wp_set_auth_cookie( $user->ID, isset( $_POST['rememberme'] ) );
    5923             $redirect_to = isset( $_REQUEST['redirect_to'] ) && !empty($_REQUEST['redirect_to']) ? wp_unslash( $_REQUEST['redirect_to'] ) : admin_url();
     5972            $redirect_to = (isset( $_REQUEST['redirect_to'] ) && !empty($_REQUEST['redirect_to'])) ? sanitize_text_field(wp_unslash( $_REQUEST['redirect_to'] )) : admin_url();
    59245973            wp_safe_redirect( $redirect_to );
    59255974            exit;
     
    59355984                'user_id' => $user->ID,
    59365985                'wp_auth_nonce' => wp_create_nonce( 'advaipbl-2fa-interim-' . $user->ID ),
    5937                 'redirect_to' => $_REQUEST['redirect_to'] ?? '',
     5986                'redirect_to' => isset($_REQUEST['redirect_to']) ? sanitize_text_field(wp_unslash($_REQUEST['redirect_to'])) : '',
    59385987            ], site_url( 'wp-login.php', 'login' ) );
    59395988            wp_safe_redirect( $redirect_url );
     
    59766025                'user_id' => $user->ID,
    59776026                'wp_auth_nonce' => wp_create_nonce( 'advaipbl-2fa-interim-' . $user->ID ),
    5978                 'redirect_to' => $_REQUEST['redirect_to'] ?? '',
    5979                 'rememberme' => $_REQUEST['rememberme'] ?? '',
     6027                // phpcs:ignore WordPress.Security.NonceVerification.Recommended
     6028                'redirect_to' => isset($_REQUEST['redirect_to']) ? sanitize_text_field(wp_unslash($_REQUEST['redirect_to'])) : '',
     6029                // phpcs:ignore WordPress.Security.NonceVerification.Recommended
     6030                'rememberme' => isset($_REQUEST['rememberme']) ? sanitize_text_field(wp_unslash($_REQUEST['rememberme'])) : '',
    59806031            ], site_url( 'wp-login.php', 'login' ) );
    59816032            wp_safe_redirect( $redirect_url );
     
    59976048        public function display_2fa_login_form_step_2() {
    59986049        $user_id = isset( $_GET['user_id'] ) ? absint( $_GET['user_id'] ) : 0;
    5999         $nonce = $_GET['wp_auth_nonce'] ?? '';
     6050        $nonce = isset($_GET['wp_auth_nonce']) ? sanitize_text_field(wp_unslash($_GET['wp_auth_nonce'])) : '';
    60006051
    60016052        if ( ! $user_id || ! wp_verify_nonce( $nonce, 'advaipbl-2fa-interim-' . $user_id ) ) {
     
    60056056        $message = '';
    60066057        if ( isset( $_COOKIE['advaipbl_login_error'] ) ) {
    6007             $message = '<div id="login_error" class="notice notice-error">' . wp_kses_post( $_COOKIE['advaipbl_login_error'] ) . '</div>';
     6058            $message = '<div id="login_error" class="notice notice-error">' . wp_kses_post( wp_unslash($_COOKIE['advaipbl_login_error']) ) . '</div>';
    60086059            // Borramos la cookie para que no se muestre de nuevo
    60096060            unset( $_COOKIE['advaipbl_login_error'] );
     
    60256076            </p>
    60266077            <input type="hidden" name="user_id" value="<?php echo esc_attr( $user_id ); ?>" />
    6027             <input type="hidden" name="redirect_to" value="<?php echo esc_attr( $_REQUEST['redirect_to'] ?? '' ); ?>" />
    6028             <input type="hidden" name="rememberme" value="<?php echo esc_attr( $_REQUEST['rememberme'] ?? '' ); ?>" />
     6078            <input type="hidden" name="redirect_to" value="<?php echo esc_attr( isset($_REQUEST['redirect_to']) ? sanitize_text_field(wp_unslash($_REQUEST['redirect_to'])) : '' ); ?>" />
     6079            <input type="hidden" name="rememberme" value="<?php echo esc_attr( isset($_REQUEST['rememberme']) ? sanitize_text_field(wp_unslash($_REQUEST['rememberme'])) : '' ); ?>" />
    60296080            <input type="hidden" name="advaipbl_2fa_login_step" value="2" />
    60306081            <?php wp_nonce_field( 'advaipbl-2fa-verify-' . $user_id ); ?>
     
    60406091                        'user_id' => $user_id,
    60416092                        'wp_auth_nonce' => $nonce,
    6042                         'redirect_to' => $_REQUEST['redirect_to'] ?? '',
     6093                        'redirect_to' => isset($_REQUEST['redirect_to']) ? sanitize_text_field(wp_unslash($_REQUEST['redirect_to'])) : '',
    60436094                    ], site_url( 'wp-login.php', 'login' ) ) );
    60446095                ?>">
     
    60576108        public function display_2fa_backup_code_form() {
    60586109        $user_id = isset( $_GET['user_id'] ) ? absint( $_GET['user_id'] ) : 0;
    6059         $nonce = $_GET['wp_auth_nonce'] ?? '';
     6110        $nonce = isset($_GET['wp_auth_nonce']) ? sanitize_text_field(wp_unslash($_GET['wp_auth_nonce'])) : '';
    60606111
    60616112        if ( ! $user_id || ! wp_verify_nonce( $nonce, 'advaipbl-2fa-interim-' . $user_id ) ) {
     
    60656116        $message = '';
    60666117        if ( isset( $_COOKIE['advaipbl_login_error'] ) ) {
    6067             $message = '<div id="login_error" class="notice notice-error">' . wp_kses_post( $_COOKIE['advaipbl_login_error'] ) . '</div>';
     6118            $message = '<div id="login_error" class="notice notice-error">' . wp_kses_post( wp_unslash($_COOKIE['advaipbl_login_error']) ) . '</div>';
    60686119            unset( $_COOKIE['advaipbl_login_error'] );
    60696120            setcookie( 'advaipbl_login_error', '', time() - 3600, COOKIEPATH, COOKIE_DOMAIN );
     
    60846135            </p>
    60856136            <input type="hidden" name="user_id" value="<?php echo esc_attr( $user_id ); ?>" />
    6086             <input type="hidden" name="redirect_to" value="<?php echo esc_attr( $_REQUEST['redirect_to'] ?? '' ); ?>" />
    6087             <input type="hidden" name="rememberme" value="<?php echo esc_attr( $_REQUEST['rememberme'] ?? '' ); ?>" />
     6137            <input type="hidden" name="redirect_to" value="<?php echo esc_attr( isset($_REQUEST['redirect_to']) ? sanitize_text_field(wp_unslash($_REQUEST['redirect_to'])) : '' ); ?>" />
     6138            <input type="hidden" name="rememberme" value="<?php echo esc_attr( isset($_REQUEST['rememberme']) ? sanitize_text_field(wp_unslash($_REQUEST['rememberme'])) : '' ); ?>" />
    60886139            <input type="hidden" name="advaipbl_2fa_login_step" value="backup" />
    60896140            <?php wp_nonce_field( 'advaipbl-2fa-verify-backup-' . $user_id ); ?>
     
    60996150                        'user_id' => $user_id,
    61006151                        'wp_auth_nonce' => $nonce,
    6101                         'redirect_to' => $_REQUEST['redirect_to'] ?? '',
     6152                        'redirect_to' => isset($_REQUEST['redirect_to']) ? sanitize_text_field(wp_unslash($_REQUEST['redirect_to'])) : '',
    61026153                    ], site_url( 'wp-login.php', 'login' ) ) );
    61036154                ?>">
     
    64026453     ) {
    64036454         // Increase limits for large file download/extraction
     6455         // phpcs:ignore Squiz.PHP.DiscouragedFunctions.Discouraged
    64046456         if (function_exists('set_time_limit')) { @set_time_limit(300); }
     6457         // phpcs:ignore Squiz.PHP.DiscouragedFunctions.Discouraged
    64056458         @ini_set('memory_limit', '256M');
    64066459         
     
    64696522        $table_name = $wpdb->prefix . 'advaipbl_blocked_ips';
    64706523       
    6471         // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared
     6524        // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared, WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, PluginCheck.Security.DirectDB.UnescapedDBParameter
    64726525        $is_blocked_in_db = $wpdb->get_var( $wpdb->prepare(
    64736526            "SELECT id FROM {$table_name} WHERE ip_range = %s AND (expires_at = 0 OR expires_at > %d)",
     
    65236576
    65246577        foreach ($options_to_optimize as $option_name) {
     6578            // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching
    65256579            $wpdb->query( $wpdb->prepare(
    65266580                "UPDATE {$wpdb->options} SET `autoload` = 'no' WHERE `option_name` = %s",
     
    65926646        static $request_method = null;
    65936647        if (is_null($request_method)) {
    6594             $request_method = sanitize_text_field($_SERVER['REQUEST_METHOD'] ?? 'GET');
     6648            $request_method_raw = isset($_SERVER['REQUEST_METHOD']) ? wp_unslash($_SERVER['REQUEST_METHOD']) : 'GET';
     6649            $request_method = sanitize_text_field($request_method_raw);
    65956650        }
    65966651        return $request_method;
     
    66166671        static $remote_addr = null;
    66176672        if (is_null($remote_addr)) {
    6618             $remote_addr = filter_var($_SERVER['REMOTE_ADDR'] ?? '', FILTER_VALIDATE_IP) ?: '';
     6673            $remote_addr_raw = isset($_SERVER['REMOTE_ADDR']) ? sanitize_text_field(wp_unslash($_SERVER['REMOTE_ADDR'])) : '';
     6674            $remote_addr = filter_var($remote_addr_raw, FILTER_VALIDATE_IP) ?: '';
    66196675        }
    66206676        return $remote_addr;
     
    66716727
    66726728            // Insertamos el lockdown en nuestra nueva tabla.
     6729            // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, PluginCheck.Security.DirectDB.UnescapedDBParameter
    66736730            $wpdb->insert(
    66746731                $lockdowns_table,
     
    66836740
    66846741            // Limpiamos el contador de la caché, ya que el lockdown está activo.
     6742            // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching
    66856743            $wpdb->delete($wpdb->prefix . 'advaipbl_cache', ['cache_key' => $cache_key]);
    66866744
     
    67346792
    67356793            // Verificamos que no haya ya un lockdown activo para este endpoint para evitar duplicados.
    6736             // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared
     6794            // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared, WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, PluginCheck.Security.DirectDB.UnescapedDBParameter
    67376795            $is_already_active = $wpdb->get_var($wpdb->prepare(
    67386796                "SELECT id FROM {$lockdowns_table} WHERE endpoint_key = %s AND expires_at > %d",
     
    67516809                $details = wp_json_encode(['triggering_ip_hashes' => $trigger_data['ip_hashes']]);
    67526810
     6811                // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, PluginCheck.Security.DirectDB.UnescapedDBParameter
    67536812                $wpdb->insert(
    67546813                    $lockdowns_table,
     
    67676826           
    67686827            // Limpiamos el contador de la caché, ya que el lockdown está activo.
     6828            // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching
    67696829            $wpdb->delete($wpdb->prefix . 'advaipbl_cache', ['cache_key' => $cache_key]);
    67706830        }
     
    67886848       
    67896849        // Procesa la respuesta del desafío si es para este tipo.
     6850        // phpcs:ignore WordPress.Security.NonceVerification.Missing
    67906851        if (isset($_POST['_advaipbl_challenge_type']) && $_POST['_advaipbl_challenge_type'] === 'endpoint') {
    67916852            // Un pase de 1 hora es suficiente para un endpoint crítico.
     
    68156876        global $wpdb;
    68166877        $lockdowns_table = $wpdb->prefix . 'advaipbl_endpoint_lockdowns';
    6817         // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared
     6878        // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared, WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, PluginCheck.Security.DirectDB.UnescapedDBParameter
    68186879        $is_lockdown_active = $wpdb->get_var($wpdb->prepare(
    68196880            "SELECT id FROM {$lockdowns_table} WHERE endpoint_key = %s AND expires_at > %d",
     
    68906951public function display_setup_wizard_notice() {
    68916952    // Solo mostrar el aviso si la bandera existe, el usuario puede gestionar opciones, y no estamos ya en el asistente.
     6953    // phpcs:ignore WordPress.Security.NonceVerification.Recommended
    68926954    if ( get_option( 'advaipbl_run_setup_wizard' ) && current_user_can( 'manage_options' ) && ( ! isset( $_GET['page'] ) || $_GET['page'] !== 'advaipbl-setup-wizard' ) ) {
    68936955        $wizard_url = admin_url( 'admin.php?page=advaipbl-setup-wizard' );
     
    70447106             
    70457107             // Check if already active
    7046              // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared
     7108             // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared, WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, PluginCheck.Security.DirectDB.UnescapedDBParameter
    70477109             $is_active = $wpdb->get_var($wpdb->prepare(
    70487110                 "SELECT id FROM {$lockdowns_table} WHERE endpoint_key = %s AND expires_at > %d",
     
    70687130                 $details = wp_json_encode($details_array);
    70697131
     7132                 // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, PluginCheck.Security.DirectDB.UnescapedDBParameter
    70707133                 $wpdb->insert(
    70717134                     $lockdowns_table,
     
    70847147             
    70857148             // Clear cache as lockdown is now active
     7149             // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching
    70867150             $wpdb->delete($wpdb->prefix . 'advaipbl_cache', ['cache_key' => $cache_key]);
    70877151        }
     
    70947158         global $wpdb;
    70957159         $lockdowns_table = $wpdb->prefix . 'advaipbl_endpoint_lockdowns';
    7096          // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared
     7160         // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared, WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, PluginCheck.Security.DirectDB.UnescapedDBParameter
    70977161         return $wpdb->get_var($wpdb->prepare(
    70987162             "SELECT id FROM {$lockdowns_table} WHERE endpoint_key = %s AND expires_at > %d",
     
    71027166
    71037167public function scanner_ping_endpoint() {
     7168    // phpcs:ignore WordPress.Security.NonceVerification.Recommended
    71047169    if (isset($_GET['advaipbl-ping']) && $_GET['advaipbl-ping'] === '1') {
    71057170       
     
    71207185        $expected_user_agent = base64_decode($encoded_user_agent);
    71217186       
    7122         $visitor_ip = $_SERVER['REMOTE_ADDR'] ?? '';
    7123         $request_user_agent = $_SERVER['HTTP_USER_AGENT'] ?? '';
     7187        $visitor_ip = isset($_SERVER['REMOTE_ADDR']) ? sanitize_text_field(wp_unslash($_SERVER['REMOTE_ADDR'])) : '';
     7188        $request_user_agent = isset($_SERVER['HTTP_USER_AGENT']) ? sanitize_text_field(wp_unslash($_SERVER['HTTP_USER_AGENT'])) : '';
    71247189
    71257190        if (in_array($visitor_ip, $allowed_ips, true) && hash_equals($expected_user_agent, $request_user_agent)) {
  • advanced-ip-blocker/trunk/includes/class-advaipbl-notification-manager.php

    r3464093 r3476940  
    5252        if (!empty($ids)) {
    5353            $ids_placeholder = implode(',', $ids);
    54             // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared, WordPress.DB.DirectDatabaseQuery.DirectQuery
     54            // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared, WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching
    5555            $wpdb->query("DELETE FROM $table_name WHERE id IN ($ids_placeholder)");
    5656        }
     
    9494        if (!empty($ids)) {
    9595            $ids_placeholder = implode(',', $ids);
    96             // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared, WordPress.DB.DirectDatabaseQuery.DirectQuery
     96            // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared, WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching
    9797            $wpdb->query("DELETE FROM $table_name WHERE id IN ($ids_placeholder)");
    9898        }
  • advanced-ip-blocker/trunk/includes/class-advaipbl-threat-score-manager.php

    r3419894 r3476940  
    3838        global $wpdb;
    3939       
    40         // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared
     40        // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared, WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, PluginCheck.Security.DirectDB.UnescapedDBParameter
    4141        $score = $wpdb->get_var($wpdb->prepare(
    4242            "SELECT score FROM {$this->table_name} WHERE ip = %s",
     
    7777       
    7878        // Obtenemos el log existente para poder añadir la nueva entrada.
    79         // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared
     79        // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared, WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, PluginCheck.Security.DirectDB.UnescapedDBParameter
    8080        $existing_log_json = $wpdb->get_var($wpdb->prepare(
    8181            "SELECT log_details FROM {$this->table_name} WHERE ip = %s",
     
    9999
    100100        // Usamos una única consulta eficiente para insertar o actualizar.
    101         // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared
     101        // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared, WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, PluginCheck.Security.DirectDB.UnescapedDBParameter
    102102        $wpdb->query($wpdb->prepare(
    103103            "INSERT INTO {$this->table_name} (ip, score, last_event_timestamp, log_details)
     
    140140        // 1. Reducimos la puntuación de las IPs inactivas.
    141141        // Usamos una consulta SQL para restar los puntos, asegurándonos de que nunca baje de 0.
    142         // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared
     142        // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared, WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, PluginCheck.Security.DirectDB.UnescapedDBParameter
    143143        $updated = $wpdb->query($wpdb->prepare(
    144144            "UPDATE {$this->table_name} 
    145              SET score = GREATEST(0, score - %d)
     145            SET score = GREATEST(0, score - %d)
    146146             WHERE last_event_timestamp < %d",
    147147            $decay_points,
     
    151151        // 2. Eliminamos las filas cuya puntuación ha llegado a 0.
    152152        // Esto mantiene la tabla limpia y eficiente.
    153         // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared
     153        // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared, WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, PluginCheck.Security.DirectDB.UnescapedDBParameter
    154154        $deleted = $wpdb->query(
    155155            "DELETE FROM {$this->table_name} WHERE score <= 0"
     
    172172        global $wpdb;
    173173       
     174        // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching
    174175        $result = $wpdb->delete(
    175176            $this->table_name,
     
    191192        global $wpdb;
    192193       
    193         // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared
     194        // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared, WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, PluginCheck.Security.DirectDB.UnescapedDBParameter
    194195        $log_json = $wpdb->get_var($wpdb->prepare(
    195196            "SELECT log_details FROM {$this->table_name} WHERE ip = %s",
  • advanced-ip-blocker/trunk/js/advaipbl-live-feed.js

    r3353165 r3476940  
    1 jQuery(document).ready(function($) {
     1jQuery(document).ready(function ($) {
    22
    33    const feedContainer = $('#advaipbl-live-feed-container');
     
    1010    const nonceUrl = window.advaipbl_feed_data.nonce_url || '';
    1111    const texts = window.advaipbl_feed_data.text || {};
    12    
     12
    1313    let lastId = 0;
    1414    let isFetching = false;
     
    2020        detailsHtml += `<div class="feed-label">${texts.method || 'Method'}</div><div class="feed-value"><code>${attack.method}</code></div>`;
    2121        detailsHtml += `<div class="feed-label">${texts.details || 'Details'}</div><div class="feed-value">${attack.details}</div>`;
    22         if (attack.uri) {
    23             detailsHtml += `<div class="feed-label">${texts.uri || 'URI'}</div><div class="feed-value"><code>${attack.uri}</code></div>`;
    24         }
    25         if (attack.user_agent && attack.user_agent !== 'N/A') {
    26             detailsHtml += `<div class="feed-label">${texts.user_agent || 'User Agent'}</div><div class="feed-value"><code>${attack.user_agent}</code></div>`;
    27         }
    2822        detailsHtml += '</div>';
    2923        return `
     
    5448
    5549        const url = `${apiUrl}?${params.toString()}`;
    56        
    57         $.get(url, function(response) {
     50
     51        $.get(url, function (response) {
    5852            if (response && response.attacks && response.attacks.length > 0) {
    5953                feedList.find('.placeholder').remove();
     
    6559                }
    6660            }
    67         }).always(function() {
     61        }).always(function () {
    6862            isFetching = false;
    6963        });
    7064    }
    71    
     65
    7266    function initializeFeed() {
    7367        if (!nonceUrl) {
     
    7670        }
    7771        // 1. Primero, obtenemos un nonce fresco que no esté cacheado.
    78         $.get(nonceUrl, function(response) {
     72        $.get(nonceUrl, function (response) {
    7973            if (response && response.nonce) {
    8074                freshNonce = response.nonce;
     
    8680                console.error('Live Feed: Failed to fetch a valid nonce.');
    8781            }
    88         }).fail(function() {
     82        }).fail(function () {
    8983            console.error('Live Feed: AJAX error while fetching nonce.');
    9084        });
  • advanced-ip-blocker/trunk/languages/advanced-ip-blocker.pot

    r3472969 r3476940  
    44msgid ""
    55msgstr ""
    6 "Project-Id-Version: Advanced IP Blocker 8.8.8\n"
     6"Project-Id-Version: Advanced IP Blocker 8.8.9\n"
    77"Report-Msgid-Bugs-To: https://wordpress.org/support/plugin/advanced-ip-blocker\n"
    88"POT-Creation-Date: 2025-07-22 14:47+0200\n"
  • advanced-ip-blocker/trunk/readme.txt

    r3472969 r3476940  
    66Requires at least: 6.7
    77Tested up to: 6.9
    8 Stable tag: 8.8.8
     8Stable tag: 8.8.9
    99Requires PHP: 8.1
    1010License: GPLv2 or later
     
    224224== Changelog ==
    225225
     226= 8.8.9 =
     227*   **SECURITY UPDATE:** Fixed an issue where the "Export Template" feature was inadvertently including sensitive API keys (`cf_api_token`, `cf_zone_id`, `abuseipdb_api_key`) in the generated JSON. Templates are now completely clean of private tokens.
     228*   **MAINTENANCE:** Cleaned up excessive developer comments in the frontend JS inclusion logic for better code readability.
     229*   **MAINTENANCE:** Analyzed and ensured that the background Cloudflare Sync task (`advaipbl_cloudflare_sync_event`) schedules properly.
     230
    226231= 8.8.8 =
    227232*   **CRITICAL FIX:** Resolved an issue where IPs imported via the Bulk Import tool were not immediately synchronized with the Server-Level Firewall (`.htaccess`). Synchronization is now instantaneous and safely batched.
     233*   **CRITICAL FIX:** Addressed a regression introduced in the `.htaccess` fix where Cloudflare Edge Firewalls stopped synchronizing imported IPs. Bulk Imports will now immediately trigger a background Cloudflare Sync Event to safely upload large IP batches without dropping connections.
    228234
    229235= 8.8.7 =
     
    399405== Upgrade Notice ==
    400406
     407= 8.8.9 =
     408**SECURITY UPDATE:** Patches a vulnerability in the Settings exporter where the "Template (No API Keys)" file was accidentally leaking Cloudflare and AbuseIPDB API keys. Update immediately if you plan to export your configuration templates to share with others.
     409
    401410= 8.8.8 =
    402 **CRITICAL UPDATE:** Fixes a `.htaccess` synchronization bug with the Bulk Import tool. Update immediately to ensure imported IPs are actively blocking threats at the server level.
     411**CRITICAL UPDATE:** Fixes a `.htaccess` synchronization bug with the Bulk Import tool. Resolves a regression where Bulk Imports stopped pushing new blocks to Cloudflare. Update immediately to ensure imported IPs are actively blocking threats at both the server level and the cloud edge.
    403412
    404413= 8.8.7 =
  • advanced-ip-blocker/trunk/uninstall.php

    r3464093 r3476940  
    3939    // phpcs:ignore WordPress.NamingConventions.PrefixAllGlobals.NonPrefixedVariableFound
    4040    foreach ( $tables_to_drop as $table_name ) {
    41         // phpcs:ignore WordPress.DB.DirectDatabaseQuery.NoCaching, WordPress.DB.PreparedSQL.NotPrepared
     41        // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.SchemaChange, WordPress.DB.DirectDatabaseQuery.NoCaching, WordPress.DB.PreparedSQL.NotPrepared
    4242        $wpdb->query( 'DROP TABLE IF EXISTS ' . $wpdb->prefix . $table_name );
    4343    }
Note: See TracChangeset for help on using the changeset viewer.