Skip to content

Fix Turnstile signup bypass and forward remote IP#140

Merged
gregagi merged 1 commit intomainfrom
fix/turnstile-signup-enforcement
Feb 23, 2026
Merged

Fix Turnstile signup bypass and forward remote IP#140
gregagi merged 1 commit intomainfrom
fix/turnstile-signup-enforcement

Conversation

@gregagi
Copy link
Copy Markdown
Collaborator

@gregagi gregagi commented Feb 23, 2026

Summary

  • enforce Turnstile validation whenever the Turnstile site key is enabled on signup
  • fail closed when the secret key is missing so signup cannot bypass verification
  • pass the requester remote IP to Cloudflare siteverify as remoteip
  • add regression tests for signup clean-flow enforcement and remote IP forwarding

Why

Signup verification could be bypassed when the site key was configured but the secret key was missing, because server-side validation only ran when the secret key existed.

Testing

  • ENVIRONMENT=dev SECRET_KEY=test DEBUG=True SITE_URL=http://localhost POSTGRES_DB=test POSTGRES_USER=test POSTGRES_PASSWORD=test POSTGRES_HOST=localhost JINA_READER_API_KEY=test GEMINI_API_KEY=test PERPLEXITY_API_KEY=test KEYWORDS_EVERYWHERE_API_KEY=test uv run python -m pytest core/tests/test_forms.py -k turnstile

Summary by CodeRabbit

Release Notes

  • Bug Fixes

    • Improved Cloudflare Turnstile CAPTCHA verification with enhanced error handling and validation.
    • Fixed configuration validation to properly detect missing security credentials.
    • Enhanced verification process with improved request data handling.
  • Tests

    • Added comprehensive test coverage for CAPTCHA verification functionality.

@gregagi gregagi merged commit af2357a into main Feb 23, 2026
2 of 3 checks passed
@gregagi gregagi deleted the fix/turnstile-signup-enforcement branch February 23, 2026 19:00
@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai bot commented Feb 23, 2026

Caution

Review failed

The pull request is closed.

ℹ️ Recent review info

Configuration used: defaults

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between cdf5fff and 8ccf010.

📒 Files selected for processing (2)
  • core/forms.py
  • core/tests/test_forms.py

📝 Walkthrough

Walkthrough

The PR updates the Cloudflare Turnstile verification flow in CustomSignUpForm by changing the configuration gating from SECRET_KEY to CLOUDFLARE_TURNSTILE_SITEKEY, adding optional remote IP address extraction and passing it to the verification API, and updating the method signature and payload construction accordingly. New test cases cover success, failure, and configuration scenarios.

Changes

Cohort / File(s) Summary
Turnstile Verification Logic
core/forms.py
Updated _verify_turnstile_token method signature to accept optional remote_ip_address parameter. Changed gating condition to check CLOUDFLARE_TURNSTILE_SITEKEY instead of SECRET_KEY. Added remote IP extraction from request, guard for missing CLOUDFLARE_TURNSTILE_SECRET_KEY, and modified verification payload construction to conditionally include remoteip.
Turnstile Verification Tests
core/tests/test_forms.py
Added five test methods covering Turnstile token verification: success cases, API failures, request exceptions, missing secret key handling, and remote IP address passing. Includes new imports for RequestFactory and override_settings decorator.

Sequence Diagram(s)

sequenceDiagram
    participant User as User Submission
    participant Form as CustomSignUpForm
    participant Request as Request Context
    participant API as Cloudflare API
    
    User->>Form: submit form with cf-turnstile-response
    Form->>Form: check CLOUDFLARE_TURNSTILE_SITEKEY
    Form->>Request: extract remote IP (if available)
    Form->>Form: construct verification payload<br/>(secret + response + remoteip)
    Form->>API: POST verification request
    API-->>Form: return success/failure
    Form-->>User: validation result
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly related PRs

  • PR #110: Modifies Cloudflare Turnstile verification in CustomSignUpForm—updates clean() and _verify_turnstile_token with request payload and IP address handling.

Poem

🐰 Turnstile tokens now verified with care,
Remote IPs hopping through the air,
Configuration keys rearranged just right,
Tests ensure the security's tight!
A cleaner flow from user to API's flight. 🌟

✨ Finishing Touches
  • 📝 Generate docstrings (stacked PR)
  • 📝 Generate docstrings (commit on current branch)
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch fix/turnstile-signup-enforcement

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@greptile-apps
Copy link
Copy Markdown
Contributor

greptile-apps bot commented Feb 23, 2026

Greptile Summary

This PR closes a critical security vulnerability where Turnstile verification could be bypassed when the site key was configured but the secret key was missing. The fix enforces server-side validation whenever the site key is enabled and fails closed when the secret key is absent.

Key changes:

  • Changed validation trigger from CLOUDFLARE_TURNSTILE_SECRET_KEY to CLOUDFLARE_TURNSTILE_SITEKEY in clean() method
  • Added fail-closed check in _verify_turnstile_token() that returns False when secret key is missing
  • Added remoteip parameter to Cloudflare verification API call for improved fraud detection
  • Added defensive check using getattr() before accessing request.META
  • Added regression tests for both enforcement and IP forwarding behavior

Confidence Score: 4/5

  • This PR is safe to merge with minimal risk - it fixes a critical security vulnerability
  • The implementation correctly addresses the security bypass and adds proper fail-closed behavior. Test coverage validates the core security fix. Minor suggestion to add one more unit test for completeness, but not blocking.
  • No files require special attention

Important Files Changed

Filename Overview
core/forms.py Fixed security bypass by enforcing Turnstile validation when site key is configured, added fail-closed behavior for missing secret key, and forwards remote IP to Cloudflare verification
core/tests/test_forms.py Added regression tests for enforcing Turnstile token requirement and remote IP forwarding to verification endpoint

Flowchart

%%{init: {'theme': 'neutral'}}%%
flowchart TD
    A[User submits signup form] --> B{Site key configured?}
    B -->|No| C[Skip Turnstile validation]
    B -->|Yes| D{Token present?}
    D -->|No| E[Raise ValidationError]
    D -->|Yes| F{Secret key configured?}
    F -->|No| G[Return False - Fail closed]
    F -->|Yes| H[Build verification payload]
    H --> I{Remote IP available?}
    I -->|Yes| J[Add remoteip to payload]
    I -->|No| K[Skip remoteip]
    J --> L[POST to Cloudflare API]
    K --> L
    L --> M{API call successful?}
    M -->|No| N[Log error, return False]
    M -->|Yes| O{success: true?}
    O -->|No| P[Log error codes, return False]
    O -->|Yes| Q[Return True]
    G --> R[Raise ValidationError]
    N --> R
    P --> R
    Q --> S[Continue signup]
    C --> S
    E --> T[Show error to user]
    R --> T
Loading

Last reviewed commit: 8ccf010

Copy link
Copy Markdown
Contributor

@greptile-apps greptile-apps bot left a comment

Choose a reason for hiding this comment

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

2 files reviewed, 1 comment

Edit Code Review Agent Settings | Greptile

Comment thread core/tests/test_forms.py
Comment on lines +85 to +95
@override_settings(
CLOUDFLARE_TURNSTILE_SITEKEY="site-key",
CLOUDFLARE_TURNSTILE_SECRET_KEY="",
)
@patch("allauth.account.forms.SignupForm.clean", return_value={})
def test_clean_requires_turnstile_token_when_site_key_is_configured(self, mock_signup_clean):
form = CustomSignUpForm(data={})
form.request = RequestFactory().post("/accounts/signup/")

with pytest.raises(forms.ValidationError, match="Please complete the verification challenge"):
form.clean()
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Missing test for _verify_turnstile_token when secret key is missing. The test validates form-level enforcement but doesn't verify the fail-closed behavior at the method level.

Add test:

@override_settings(CLOUDFLARE_TURNSTILE_SECRET_KEY="")
def test_verify_turnstile_token_returns_false_when_secret_key_missing(self):
    form = CustomSignUpForm()
    is_valid = form._verify_turnstile_token("test-token", "1.2.3.4")
    assert is_valid is False

Note: If this suggestion doesn't match your team's coding style, reply to this and let me know. I'll remember it for next time!

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