From 511d2fefae0d8d1504245b3ffe78fc690db07dbe Mon Sep 17 00:00:00 2001 From: Javier Casares Date: Mon, 24 Aug 2026 08:18:14 +0000 Subject: [PATCH] v1.6.3 --- changelog.txt | 24 +++++++++++++ includes/admin/class-manager-notice.php | 30 +++++++++++----- includes/login/class-login-form-manager.php | 40 +++++++++++++++++++++ readme.txt | 29 +++++++-------- robotstxt-2fa.php | 4 +-- update.json | 22 ------------ vendor/composer/installed.php | 4 +-- 7 files changed, 103 insertions(+), 50 deletions(-) delete mode 100644 update.json diff --git a/changelog.txt b/changelog.txt index 5ba5490..5904ac3 100644 --- a/changelog.txt +++ b/changelog.txt @@ -1,5 +1,29 @@ == Changelog == += 1.6.3 = + +_Release date: 2026-08-24_ + +**Changed** + +* Manager detection now uses the ecosystem presence constant (`ROBOTSTXT_MANAGER_NOTICED`, defined by Manager 1.6.2+) with a fallback to the plugin-list scan for older Manager versions, so a stale plugin list can no longer produce false "Manager missing" notices. + +**Fixed** + +* Compatibility with the ALTCHA Spam Protection plugin: when "Protect login" was enabled, submitting the 2FA verification code failed with "[ALTCHA] Sorry, your request could not be processed.". The ALTCHA interceptor is now disabled while the verification screen is shown; the first login step keeps its ALTCHA check. + +**Compatibility** + +* WordPress: 5.6 – 7.1 +* PHP: 8.0 – 8.5 + +**Tests** + +* PHP Coding Standards: PHP_CodeSniffer 3.13.6 / WPCS 3.4.1 — 0 errors +* PHPStan: level 9 — 0 errors +* PHPCompatibility: 8.0–8.5 — 0 issues +* PHPUnit: 9.6.36 — 73 tests, 163 assertions + = 1.6.2 = _Release date: 2026-08-17_ diff --git a/includes/admin/class-manager-notice.php b/includes/admin/class-manager-notice.php index 567a166..7fb1e2d 100644 --- a/includes/admin/class-manager-notice.php +++ b/includes/admin/class-manager-notice.php @@ -20,11 +20,6 @@ if ( ! defined( 'ABSPATH' ) ) { */ class Manager_Notice { - /** - * Basename of the Manager plugin main file. - */ - private const MANAGER_BASENAME = 'robotstxt-manager/robotstxt-manager.php'; - /** * URL of the Manager plugin page. */ @@ -56,16 +51,35 @@ class Manager_Notice { /** * Whether the Manager (by ROBOTSTXT) plugin is active. * + * Uses the ecosystem presence constant (Manager 1.6.2+) and falls back + * to a plugin-list scan for older Manager versions. + * * @since 1.6.2 * - * @return bool True when the manager plugin is active. + * @return bool True when the Manager plugin is present and activated. */ public static function is_manager_active(): bool { - if ( ! function_exists( 'is_plugin_active' ) ) { + if ( defined( 'ROBOTSTXT_MANAGER_NOTICED' ) && ROBOTSTXT_MANAGER_NOTICED ) { + return true; + } + + if ( ! function_exists( 'get_plugins' ) ) { require_once ABSPATH . 'wp-admin/includes/plugin.php'; } - return is_plugin_active( self::MANAGER_BASENAME ); + foreach ( get_plugins() as $file => $data ) { + $slug = dirname( $file ); + + if ( '.' === $slug ) { + $slug = basename( $file, '.php' ); + } + + if ( 'robotstxt-manager' === $slug ) { + return is_plugin_active( $file ); + } + } + + return false; } /** diff --git a/includes/login/class-login-form-manager.php b/includes/login/class-login-form-manager.php index a859a0a..8150351 100644 --- a/includes/login/class-login-form-manager.php +++ b/includes/login/class-login-form-manager.php @@ -233,6 +233,46 @@ class Login_Form_Manager { add_filter( 'login_message', array( $this, 'filter_login_message' ) ); add_filter( 'authenticate', array( $this, 'maybe_complete_verification' ), 5, 3 ); add_filter( 'authenticate', array( $this, 'enforce_verification_challenge' ), 30, 3 ); + add_action( 'init', array( $this, 'maybe_remove_altcha_interceptor' ), 0 ); + } + + /** + * Disable the ALTCHA Spam Protection login interceptor during the 2FA stage. + * + * ALTCHA's "Protect login" feature rejects any wp-login.php POST that does + * not carry a fresh proof-of-work payload (HTTP 403). Its JavaScript only + * produces that payload for classic username + password submissions, while + * the verification stage intentionally omits the password field, so every + * legitimate 2FA submission would otherwise be blocked. Human verification + * already happened on the first login step; this stage is protected by the + * pending-stage token, the stage nonce, and the failed-attempts lockout. + * + * @since 1.6.2 + * + * @return void + */ + public function maybe_remove_altcha_interceptor(): void { + if ( ! $this->is_verification_stage() ) { + return; + } + + if ( ! has_action( 'init', 'altcha_interceptor' ) ) { + return; + } + + global $wp_filter; + + if ( ! isset( $wp_filter['init'] ) || ! $wp_filter['init'] instanceof \WP_Hook ) { + return; + } + + foreach ( array_keys( $wp_filter['init']->callbacks ) as $priority ) { + if ( isset( $wp_filter['init']->callbacks[ $priority ]['altcha_interceptor'] ) ) { + remove_action( 'init', 'altcha_interceptor', (int) $priority ); + + return; + } + } } /** diff --git a/readme.txt b/readme.txt index fbbe77f..f5d342c 100644 --- a/readme.txt +++ b/readme.txt @@ -4,7 +4,7 @@ Tags: security, two-factor authentication, login, otp Requires at least: 5.6 Tested up to: 7.0 Requires PHP: 8.0 -Stable tag: 1.6.2 +Stable tag: 1.6.3 License: GPLv3 or later License URI: https://www.gnu.org/licenses/gpl-3.0.html @@ -59,6 +59,18 @@ Yes. Activate the plugin at the network level. Network administrators can set an == Changelog == += 1.6.3 = + +_Release date: 2026-08-24_ + +**Changed** + +* Manager detection now uses the ecosystem presence constant (`ROBOTSTXT_MANAGER_NOTICED`, defined by Manager 1.6.2+) with a fallback to the plugin-list scan for older Manager versions. + +**Fixed** + +* Compatibility with the ALTCHA Spam Protection plugin: when "Protect login" was enabled, submitting the 2FA verification code failed with "[ALTCHA] Sorry, your request could not be processed.". The ALTCHA interceptor is now disabled while the verification screen is shown; the first login step keeps its ALTCHA check. + = 1.6.2 = _Release date: 2026-08-17_ @@ -81,21 +93,6 @@ _Release date: 2026-08-14_ * Fatal error during editor autosaves: the `[robotstxt_2fa_profile]` shortcode expanded when WordPress applied content filters to a post revision via REST (for example, an article that merely mentions the shortcode in its text). In that context the wp-admin render helpers are not loaded, causing a fatal error. The shortcode now bails out early on REST requests and loads the required wp-admin includes on demand elsewhere. -= 1.6.0 = - -_Release date: 2026-08-07_ - -**Added** - -* REST API for administrators (namespace `robotstxt-2fa/v1`, all endpoints require `manage_options`): - * `GET /wp-json/robotstxt-2fa/v1/settings` — read the full 2FA configuration. - * `PUT /wp-json/robotstxt-2fa/v1/settings` — update the configuration (reuses the same validation as the admin settings form). - * `GET /wp-json/robotstxt-2fa/v1/users?role=&status=` — list every user with their 2FA status: enabled, configured methods, role-required methods, forced flag, frequency, preferred method, whether OTP is set up, and unused recovery code count. No secrets are exposed. - -**Changed** - -* `wp 2fa list` now shows separate **Enabled**, **Methods** (configured), and **Required** (role-enforced) columns, plus a new `--required` filter to list only users whose role enforces 2FA. - = Previous versions = For the full changelog see the [changelog](https://www.robotstxt.software/plugins/robotstxt-2fa/) page. diff --git a/robotstxt-2fa.php b/robotstxt-2fa.php index 8bd4d4d..cb23599 100644 --- a/robotstxt-2fa.php +++ b/robotstxt-2fa.php @@ -4,7 +4,7 @@ * Plugin URI: https://www.robotstxt.software/plugins/robotstxt-2fa/ * Update URI: https://www.robotstxt.software/plugins/robotstxt-2fa/ * Description: Adds two-factor authentication to the WordPress login flow. - * Version: 1.6.2 + * Version: 1.6.3 * Author: ROBOTSTXT * Author URI: https://www.robotstxt.software/ * Text Domain: robotstxt-2fa @@ -25,7 +25,7 @@ if ( ! defined( 'ABSPATH' ) ) { } if ( ! defined( 'ROBOTSTXT_2FA_VERSION' ) ) { - define( 'ROBOTSTXT_2FA_VERSION', '1.6.2' ); + define( 'ROBOTSTXT_2FA_VERSION', '1.6.3' ); } if ( ! defined( 'ROBOTSTXT_2FA_FILE' ) ) { diff --git a/update.json b/update.json deleted file mode 100644 index 7543046..0000000 --- a/update.json +++ /dev/null @@ -1,22 +0,0 @@ -{ - "name": "2FA (by ROBOTSTXT)", - "slug": "robotstxt-2fa", - "version": "1.6.2", - "download_url": "https://git.robotstxt.es/ROBOTSTXT/robotstxt-2fa/releases/download/1.6.2/robotstxt-2fa-1.6.2.zip", - "requires": "6.4", - "requires_php": "8.0", - "tested": "7.1", - "last_updated": "2026-08-14", - "author": "ROBOTSTXT", - "author_profile": "https://www.robotstxt.es/", - "homepage": "https://www.robotstxt.es/plugins/robotstxt-2fa/", - "description": "Adds per-role two-factor authentication to the WordPress login flow. Supports email codes, authenticator apps (TOTP), and recovery codes.", - "changelog": "", - "sections": { - "description": "Adds per-role two-factor authentication to the WordPress login flow. Supports email codes, authenticator apps (TOTP), and recovery codes.", - "changelog": "" - }, - "banners": { "low": "", "high": "" }, - "icons": { "1x": "", "2x": "" } -} - diff --git a/vendor/composer/installed.php b/vendor/composer/installed.php index e9b72d6..144e152 100644 --- a/vendor/composer/installed.php +++ b/vendor/composer/installed.php @@ -3,7 +3,7 @@ 'name' => 'robotstxt/robotstxt-2fa', 'pretty_version' => 'dev-main', 'version' => 'dev-main', - 'reference' => '6ee18abad9ca997d00a8f2397aee3cc77a90a4e3', + 'reference' => '2f5ed132e25529d95b04f81bfd33dfdbcb0fc487', 'type' => 'wordpress-plugin', 'install_path' => __DIR__ . '/../../', 'aliases' => array(), @@ -40,7 +40,7 @@ 'robotstxt/robotstxt-2fa' => array( 'pretty_version' => 'dev-main', 'version' => 'dev-main', - 'reference' => '6ee18abad9ca997d00a8f2397aee3cc77a90a4e3', + 'reference' => '2f5ed132e25529d95b04f81bfd33dfdbcb0fc487', 'type' => 'wordpress-plugin', 'install_path' => __DIR__ . '/../../', 'aliases' => array(),