Skip to content

fix(security): captcha bypass via predictable test account patterns#2462

Open
failsafesecurity wants to merge 1 commit intoWeb3Auth:masterfrom
failsafesecurity:security-fix/captcha-bypass-via-predictable-test-account
Open

fix(security): captcha bypass via predictable test account patterns#2462
failsafesecurity wants to merge 1 commit intoWeb3Auth:masterfrom
failsafesecurity:security-fix/captcha-bypass-via-predictable-test-account

Conversation

@failsafesecurity
Copy link
Copy Markdown
Contributor

@failsafesecurity failsafesecurity commented Apr 22, 2026

Security Finding: Captcha Bypass via Predictable Test Account Patterns

Severity: MEDIUM
Reported by: FailSafe Research Team
Component: packages/modal/src/ui/containers/Login/Login.tsx:188

Description

The passwordless login flow in the Web3Auth UI components includes a conditional check that bypasses HCaptcha execution if the user's login identifier (email or phone number) matches a predefined 'test account pattern'. This bypass is implemented via the 'isTestAccountPattern' helper function. While intended to facilitate automated integration testing, allowing such a bypass in production environments creates a significant security hole. Attackers can identify the patterns used for test accounts (e.g., identifiers ending in '@example.com' or specific number ranges) and use them to programmatically trigger the 'sendVerificationCode' endpoint without solving a captcha. This bypasses the primary defense against automated bot attacks and allows for large-scale abuse of the notification infrastructure.

 183            authConnection,
 184            authBuildEnv,
 185          });
 186    
 187          let token: string | undefined = undefined;
 188>>>       if (!isTestAccountPattern(authConnection, loginHint)) {
 189            const res = await captchaRef.current?.execute({ async: true });
 190            if (!res) {
 191              throw WalletLoginError.connectionError("Captcha token is required");
 192            }
 193            token = res.response;

Fix

Remove the client-side captcha bypass for test accounts in production builds. If test accounts are required for automated testing, ensure the bypass is only active in non-production environments using environment variables.

Code sample:

// Ensure bypass only happens outside of production
const isDev = process.env.NODE_ENV !== 'production';
const requiresCaptcha = !(isDev && isTestAccountPattern(loginId));

if (requiresCaptcha) {
 await executeCaptcha();
}

Additionally, enforce captcha validation strictly on the backend, ensuring that any test account bypass is securely managed and not exposed to production users.


Note

Medium Risk
Changes the passwordless login captcha gating logic; mistakes could either reintroduce a captcha bypass in production or inadvertently require captcha in automated/dev test flows.

Overview
Closes a production captcha-bypass in the passwordless login flow by making the test-account exception conditional on NODE_ENV !== "production".

handleCustomLogin now requires HCaptcha for all production logins (including those matching isTestAccountPattern), while still allowing the bypass for test patterns in non-production environments.

Reviewed by Cursor Bugbot for commit 14c1d02. Bugbot is set up for automated code reviews on this repo. Configure here.

@vercel
Copy link
Copy Markdown

vercel Bot commented Apr 22, 2026

@failsafesecurity is attempting to deploy a commit to the Consensys Team on Vercel.

A member of the Team first needs to authorize it.

@failsafesecurity failsafesecurity marked this pull request as ready for review April 22, 2026 06:54
@failsafesecurity failsafesecurity requested a review from a team as a code owner April 22, 2026 06:54
Copy link
Copy Markdown

@cursor cursor Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cursor Bugbot has reviewed your changes and found 1 potential issue.

Fix All in Cursor

Reviewed by Cursor Bugbot for commit 14c1d02. Configure here.

let token: string | undefined = undefined;
if (!isTestAccountPattern(authConnection, loginHint)) {
const isDev = process.env.NODE_ENV !== "production";
const requiresCaptcha = !(isDev && isTestAccountPattern(authConnection, loginHint));
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Captcha bypass persists when NODE_ENV is undefined

High Severity

The process.env.NODE_ENV check is unreliable for this library because the package's own rollup build config only replaces process.env.WEB3AUTH_VERSION, not process.env.NODE_ENV. The raw string is shipped to consumers, and if their bundler doesn't substitute it (or if process.env is undefined in the browser), then undefined !== "production" evaluates to true, making isDev true and keeping the captcha bypass active in production. This undermines the security fix entirely for affected environments.

Fix in Cursor Fix in Web

Reviewed by Cursor Bugbot for commit 14c1d02. Configure here.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant