You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Two real bugs surfaced by Codex's review of the Basic-auth migration:
P1.1: app-password collision (production-breaking, conditional)
On any site where `WP_Application_Passwords::is_in_use()` returns true
(i.e. any merchant has ever provisioned an app password — for any user,
any plugin), `wp_validate_application_password` runs at
`determine_current_user` priority 20 against our `ck_xxx` username.
`get_user_by('login', 'ck_xxx')` returns false → WP fires
`application_password_failed_authentication` with an `invalid_username`
WP_Error → `rest_application_password_collect_status` stores it on
`$wp_rest_application_password_status` → `rest_application_password_check_errors`
returns 401 from `rest_authentication_errors` before our route
permission callback ever runs.
The original smoke test passed because the wp-env had zero app
passwords, so `is_in_use()` returned false and the chain short-
circuited. A ticking time bomb.
Fix: filter `application_password_is_api_request` to return false for
`/wp-json/hey-woo/mcp`. Inside `wp_authenticate_application_password`,
the `! $is_api_request` early-return then prevents the error global
from ever being set. Surgical — every other REST route keeps WP's
normal app-password handling.
Verified against a live wp-env with an app password provisioned:
Basic Auth + read-only WC key + MCP initialize returns 200, not 401.
P1.2: route-scope bypass on mod_php (real, exploitable)
`enforce_setup_key_route_scope` calls `extract_request_credential`,
which only read `HTTP_AUTHORIZATION`. On Apache + mod_php (and many
fastcgi setups) Apache strips the raw header and populates
`PHP_AUTH_USER` / `PHP_AUTH_PW` directly. WC's auth reads the split
form, so it would authenticate the setup credential against any WC
REST surface (e.g. /wc/v3/orders), but our scope filter would see ''
and skip the restriction — defeating the credential's privacy
boundary on those SAPIs.
Fix: add a `PHP_AUTH_USER` / `PHP_AUTH_PW` branch at the top of
`extract_request_credential`, before the raw-header parse.
Tests:
- 2 new tests on `test-rest-api-key.php` pin the deny + allow paths
for the route-scope filter via the PHP_AUTH split form. These would
have caught the P1.2 bug; the existing tests only exercised
HTTP_AUTHORIZATION.
- 4 new tests on `test-wc-auth-route-scoping.php`: pin that
`enable_wc_auth_for_our_routes` excludes the MCP route (which the
recent narrowing introduced); pin that
`exclude_mcp_route_from_app_password_auth` denies the MCP route,
passes through every other REST route, and is a no-op when the
incoming value is already false.
288 PHPUnit tests pass (up from 282). PHPCS clean.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
0 commit comments