Skip to content

[BUG] Fix Cloudflare Turnstile widget not loading on Vercel production #45

@gensecai-dev

Description

@gensecai-dev

Problem

The Cloudflare Turnstile bot protection widget is not loading on Vercel production deployment. The widget shows "Security verification bypassed - widget failed to load" message instead of rendering properly.

Current Status: Turnstile validation has been temporarily disabled (commit 7dfe511) to unblock user flow, but all implementation code remains intact for future fixes.

Environment

  • Platform: Vercel (Production)
  • Mode: Non-interactive Turnstile
  • Environment Variables: ✅ Properly configured in Vercel dashboard
    • TURNSTILE_SECRET_KEY (All Environments)
    • NEXT_PUBLIC_TURNSTILE_SITE_KEY (All Environments)

What's Already Implemented

Frontend (src/components/PrivacyAnalyzer.tsx)

  • ✅ Native Cloudflare Turnstile JavaScript API integration
  • ✅ Explicit widget rendering with window.turnstile.render()
  • ✅ Proper callbacks (success, error, expired, timeout)
  • ✅ Non-interactive mode configuration (appearance: 'interaction-only')
  • ✅ Runtime environment variable loading via useEffect
  • ✅ Widget lifecycle management (render, reset, cleanup)

Backend (src/app/api/analyze/route.ts)

  • ✅ Server-side token verification against Cloudflare API
  • ✅ Hostname validation
  • ✅ Proper error handling with specific error messages
  • ✅ Fraud detection with remoteip parameter

Script Loading (src/app/layout.tsx)

  • ✅ Turnstile script loaded: https://challenges.cloudflare.com/turnstile/v0/api.js

Issue Details

Despite correct implementation according to official Cloudflare documentation, the widget fails to load on Vercel production. Local environment was not tested.

Attempted Fixes

  1. ✅ Replaced third-party React wrapper with native API
  2. ✅ Fixed environment variable loading (build-time → runtime)
  3. ✅ Fixed infinite re-render issues in useEffect
  4. ✅ Configured non-interactive mode
  5. ✅ Enhanced server-side validation
  6. ✅ Added comprehensive error handling and logging

Disabled Code

The validation check is currently commented out (lines 186-191 in PrivacyAnalyzer.tsx):

// TURNSTILE DISABLED - Keep code for future use
// if (TURNSTILE_SITE_KEY && !turnstileToken && !turnstileBypass) {
//   setError('Please complete the security verification');
//   return;
// }

Potential Root Causes to Investigate

  1. Vercel-specific configuration issues

    • Content Security Policy blocking Cloudflare script
    • Next.js build/runtime configuration conflicts
    • Environment variable propagation timing
  2. Network/CDN issues

    • Turnstile script not loading from Cloudflare CDN
    • CORS or network policy blocking requests
  3. Widget initialization timing

    • Script loading race conditions
    • React hydration conflicts

Expected Behavior

The Turnstile widget should:

  1. Load and render automatically in non-interactive mode
  2. Show a loading bar while challenge runs
  3. Generate a token upon successful completion
  4. Allow form submission with valid token

Acceptance Criteria

  • Turnstile widget renders correctly on Vercel production
  • Widget completes verification in non-interactive mode
  • Token is generated and validated server-side
  • Form submission works with valid token
  • Error states handled gracefully
  • Uncomment validation check in PrivacyAnalyzer.tsx (lines 186-191)

Documentation References

Files to Review

  • src/components/PrivacyAnalyzer.tsx - Frontend widget integration
  • src/app/api/analyze/route.ts - Backend verification (lines 310-361)
  • src/app/layout.tsx - Script loading (line 108)
  • .env.example - Environment variable documentation

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't workinghelp wantedExtra attention is needed

    Type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions