PluginProbe
Vigilant – 100% Free Security Suite: Firewall, 2FA, Login, Headers, Scanner… / 3.0.2
Vigilant – 100% Free Security Suite: Firewall, 2FA, Login, Headers, Scanner… v3.0.2
3.0.5 3.0.4 3.0.3 3.0.2 3.0.1 3.0.0 2.11.12 2.11.11 2.11.10 2.11.9 2.11.7 2.11.8 2.11.6 2.11.5 2.11.4 2.11.3 2.11.1 2.11.2 2.11.0 2.10.5 2.10.4 2.10.3 2.10.2 2.10.1 2.10.0 All 93 releases
← All changes | includes/class-user-security.php +36 -31 2.11.10 → 3.0.2 View file →
@@ -284,9 +284,11 @@
284 284 * @return bool
285 285 */
286 286 private function is_insecure_username( $username ) {
287 287 $username = strtolower( trim( $username ) );
288 - $insecure_usernames = $this->options['insecure_usernames'] ?? array();
288 + // Vigilante_Settings::list_or_shipped(): an empty list of a setting with
289 + // no field on screen is a leftover, not a choice. See its docblock.
290 + $insecure_usernames = $this->get_insecure_usernames();
289 291
290 292 return in_array( $username, array_map( 'strtolower', $insecure_usernames ), true );
291 293 }
292 294
@@ -988,9 +990,14 @@
988 990 *
989 991 * @return array
990 992 */
991 993 public function get_insecure_usernames() {
992 - return $this->options['insecure_usernames'] ?? array();
994 + // The single reader of this list, so what blocks and what the screen
995 + // reports can never disagree.
996 + return Vigilante_Settings::list_or_shipped(
997 + $this->options['insecure_usernames'] ?? array(),
998 + array( 'user_security', 'insecure_usernames' )
999 + );
993 1000 }
994 1001
995 1002 /**
996 1003 * Check for existing insecure admin users
@@ -1249,22 +1256,27 @@
1249 1256 * @param string $password Password.
1250 1257 * @return WP_User|WP_Error|null
1251 1258 */
1252 1259 public function check_force_reset_on_login( $user, $username, $password ) {
1253 - // Resolve the target user. The flag must be evaluated whether the
1254 - // credentials matched (WP_User) or not (WP_Error).
1255 - if ( $user instanceof WP_User ) {
1256 - $login_user = $user;
1257 - } else {
1258 - $login_user = get_user_by( 'login', $username );
1259 - if ( ! $login_user ) {
1260 - $login_user = get_user_by( 'email', $username );
1261 - }
1260 + /*
1261 + * Only a login that would otherwise have succeeded is turned into this
1262 + * rejection. Wrong credentials are left exactly as WordPress reported
1263 + * them, and they are counted like any other failed login.
1264 + *
1265 + * Until 2.11.12 this ran for a WP_Error too, resolving the account from
1266 + * the username, and replaced an incorrect_password with the rejection
1267 + * below. A rejection of Vigilant's own is not counted towards the brute
1268 + * force lockout, so any account with a pending forced reset could be
1269 + * guessed at without limit: measured on 17 Sep 2026 against 2.11.11 and
1270 + * against the first build of 2.11.12, six wrong passwords in a row, none
1271 + * of them counted and no lockout at the end. The message this function
1272 + * exists to show belongs to whoever typed the right password.
1273 + */
1274 + if ( ! ( $user instanceof WP_User ) ) {
1275 + return $user;
1262 1276 }
1263 1277
1264 - if ( ! $login_user ) {
1265 - return $user;
1266 - }
1278 + $login_user = $user;
1267 1279
1268 1280 // Check if this user has a pending forced reset.
1269 1281 $force_reset = get_user_meta( $login_user->ID, 'vigilante_force_reset_pending', true );
1270 1282 if ( ! $force_reset ) {
@@ -1270,17 +1282,11 @@
1270 1282 if ( ! $force_reset ) {
1271 1283 return $user;
1272 1284 }
1273 1285
1274 - // If credentials were wrong with an error other than incorrect_password
1275 - // (e.g. a Vigilant lockout, pending approval), don't shadow it.
1276 - if ( is_wp_error( $user ) && ! in_array( 'incorrect_password', $user->get_error_codes(), true ) ) {
1277 - return $user;
1278 - }
1286 + // Not counted towards the brute force lockout: the rejection is
1287 + // recognised by its error code (Vigilante_Login_Security::CONTROLLED_REJECTIONS).
1279 1288
1280 - // Skip brute force counter for this controlled rejection.
1281 - add_filter( 'vigilante_skip_failed_login_count', '__return_true' );
1282 -
1283 1289 // Surface the controlled rejection in the activity log so the admin
1284 1290 // can tell apart "user fails login because they typed wrong password"
1285 1291 // from "user fails login because we are forcing a reset".
1286 1292 if ( $this->activity_log ) {
@@ -1342,9 +1348,14 @@
1342 1348 return;
1343 1349 }
1344 1350
1345 1351 $settings = $this->options['registration_approval'] ?? array();
1346 - $affected_roles = $settings['affected_roles'] ?? array( 'subscriber' );
1352 + // Vigilante_Settings::list_or_shipped(): an empty list of a setting with
1353 + // no field on screen is a leftover, not a choice. See its docblock.
1354 + $affected_roles = Vigilante_Settings::list_or_shipped(
1355 + $settings['affected_roles'] ?? array(),
1356 + array( 'user_security', 'registration_approval', 'affected_roles' )
1357 + );
1347 1358
1348 1359 // Check if user role requires approval
1349 1360 $user_roles = $user->roles;
1350 1361 $needs_approval = array_intersect( $user_roles, $affected_roles );
@@ -1390,11 +1401,8 @@
1390 1401 return $user;
1391 1402 }
1392 1403
1393 1404 if ( self::is_pending_anywhere( $user->ID ) ) {
1394 - // Mark this as a controlled rejection (not a brute force attempt)
1395 - add_filter( 'vigilante_skip_failed_login_count', '__return_true' );
1396 -
1397 1405 return new WP_Error(
1398 1406 'pending_approval',
1399 1407 __( '<strong>Account pending:</strong> Your account is awaiting administrator approval. You will receive an email once approved.', 'vigilante' )
1400 1408 );
@@ -2143,11 +2151,8 @@
2143 2151 'warning'
2144 2152 );
2145 2153 }
2146 2154
2147 - // Mark this as a controlled rejection (not a brute force attempt)
2148 - add_filter( 'vigilante_skip_failed_login_count', '__return_true' );
2149 -
2150 2155 return new WP_Error(
2151 2156 'session_limit_exceeded',
2152 2157 sprintf(
2153 2158 /* translators: %d: Maximum sessions allowed */
@@ -3239,9 +3244,9 @@
3239 3244
3240 3245 // Check if this user's role requires approval
3241 3246 $needs_approval = false;
3242 3247 if ( ! empty( $registration_approval['enabled'] ) ) {
3243 - $affected_roles = $registration_approval['affected_roles'] ?? array( 'subscriber' );
3248 + $affected_roles = Vigilante_Settings::list_or_shipped( $registration_approval['affected_roles'] ?? array(), array( 'user_security', 'registration_approval', 'affected_roles' ) );
3244 3249 $needs_approval = ! empty( array_intersect( $user->roles, $affected_roles ) );
3245 3250 }
3246 3251
3247 3252 // Check if email verification is enabled
@@ -3353,9 +3358,9 @@
3353 3358 if ( empty( $registration_approval['enabled'] ) ) {
3354 3359 return false;
3355 3360 }
3356 3361
3357 - $affected_roles = $registration_approval['affected_roles'] ?? array( 'subscriber' );
3362 + $affected_roles = Vigilante_Settings::list_or_shipped( $registration_approval['affected_roles'] ?? array(), array( 'user_security', 'registration_approval', 'affected_roles' ) );
3358 3363 return ! empty( array_intersect( $user->roles, $affected_roles ) );
3359 3364 }
3360 3365
3361 3366 /**