AI & Agent Dev Bug Sandbox logo
AI & Agent Dev Bug Sandbox
Back to Radar

SMS Test OTP Not Honored With Twilio Verify Provider Due To Phone Normalization Mismatch And Provider-Specific Bypass

Supabase Auth ignores configured SMS test OTP entries when Phone Auth uses Twilio Verify. The test OTP map stores phone numbers without a leading '+', but internal phone numbers are normalized to E.164 with '+'. The comparison in send and verify paths uses exact string equality, causing the match to fail. Additionally, the test OTP bypass is likely restricted to legacy Twilio and is not consulted for Twilio Verify, so both OTP send and verify routes use the real Twilio Verify API, leading to otp_expired.

highConfidence 75%Supabase Auth (GoTrue)

Origin Analysis

The test OTP configuration map keys are stored without a leading '+', while the incoming phone number is normalized to E.164 with a leading '+' before comparison. The existing test OTP lookup uses exact string equality and does not strip the '+'. Furthermore, the test OTP bypass logic appears to be provider-specific and does not apply to Twilio Verify, causing the sending path to call Twilio Verify instead of returning 'test-otp' and the verification path to reject the fixed test code.
1. Enable Phone Auth in a hosted or self-hosted Supabase project with SMS provider set to Twilio Verify. 2. Add a test OTP entry in the dashboard or config with format '12125550124=000000' (phone without leading '+'). 3. Ensure 'sms_test_otp_valid_until' is set to a future date. 4. Request an OTP via POST /auth/v1/otp with phone '+12125550124'. 5. Verify using the configured test OTP '000000' via POST /auth/v1/verify. 6. Observe that verification fails with 403 and error code 'otp_expired', and the OTP send response includes 'message_id: null' instead of 'test-otp'.

Fixing Code Block

Edge Case Audit

This fix requires updating both the send and verify call sites; if only one path is patched, test OTPs may be accepted while real messages are still sent, or vice versa. The helper uses the global config map; ensure thread safety if configuration is ever hot-reloaded (currently GoTrue configuration is immutable per process, but if reload support is added later, protect the map with a mutex or atomic reference). Constant-time comparison avoids timing leaks. Rollback: revert these helper functions and remove their calls from send and verify paths; no data migration is needed.

Ecosystem Topology