Skip to content

Add rate limiting to activation, activation code request, and TOTP setup endpoints#6232

Merged
apata merged 11 commits into
masterfrom
rate-limit-forms
May 15, 2026
Merged

Add rate limiting to activation, activation code request, and TOTP setup endpoints#6232
apata merged 11 commits into
masterfrom
rate-limit-forms

Conversation

@cnkk
Copy link
Copy Markdown
Member

@cnkk cnkk commented Apr 6, 2026

Adds rate limiting to previously unprotected authentication endpoints:

  • POST /activate — brute-force of 4-digit codes (1000–9999)
  • POST /activate/request-code — activation email spam prevention
  • POST /2fa/setup/verify — TOTP code brute-force during enrolment

@cnkk
Copy link
Copy Markdown
Member Author

cnkk commented Apr 6, 2026

@cubic-dev-ai

@cubic-dev-ai
Copy link
Copy Markdown

cubic-dev-ai Bot commented Apr 6, 2026

@cubic-dev-ai

@cnkk I have started the AI code review. It will take a few minutes to complete.

Copy link
Copy Markdown

@cubic-dev-ai cubic-dev-ai Bot left a comment

Choose a reason for hiding this comment

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

No issues found across 3 files

Comment thread lib/plausible/auth/auth.ex
@cnkk cnkk added this pull request to the merge queue Apr 10, 2026
@github-merge-queue github-merge-queue Bot removed this pull request from the merge queue due to failed status checks Apr 10, 2026
@cnkk
Copy link
Copy Markdown
Member Author

cnkk commented May 13, 2026

@coderabbitai full review

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented May 13, 2026

✅ Actions performed

Full review triggered.

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented May 13, 2026

Review Change Stack

📝 Walkthrough

Walkthrough

This PR renames the public super-admin predicate function from is_super_admin?/1 to super_admin?/1, updates environment-based rate-limit configuration in the Auth module, implements rate limiting for three authentication flows, and updates all 12 call sites across authorization, controllers, and views to use the renamed function.

Changes

Super Admin Rename and Rate Limiting

Layer / File(s) Summary
Auth Module: Function Rename and Rate Limit Configuration
lib/plausible/auth/auth.ex
is_super_admin?/1 is renamed to super_admin?/1 across all clauses. Environment-based rate-limit configuration replaces a single conditional with a Mix.env() case statement for :e2e_test, :test/:ce_test, and other environments. The @rate_limits map is extended with activation and TOTP setup rate-limit entries.
Rate Limiting in Authentication Flows
lib/plausible_web/controllers/auth_controller.ex, test/plausible_web/controllers/auth_controller_test.exs
activate/2 wraps execution in rate-limit checks (IP and user), rendering 429 on throttle or delegating to do_activate/3 on success. request_activation_code/2 applies rate limiting before issuing activation codes, redirecting with error flash on throttle. verify_2fa_setup/2 rate-limits TOTP setup attempts before enabling 2FA, rendering 429 on throttle. A new test verifies activation is limited to 10 requests per 5 minutes per IP.
Function Call Updates Across Codebase
extra/lib/plausible_web/live/verification.ex, lib/plausible/sites.ex, lib/plausible_web/controllers/api/internal_controller.ex, lib/plausible_web/controllers/stats_controller.ex, lib/plausible_web/plugs/authorize_public_api.ex, lib/plausible_web/plugs/authorize_site_access.ex, lib/plausible_web/plugs/super_admin_only_plug.ex, lib/plausible_web/templates/layout/_header.html.heex
All 12 call sites switch from is_super_admin?/1 to super_admin?/1, including authorization plugs, site access/query logic, API controllers, stats rendering, and UI templates.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Suggested labels

preview

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title accurately and specifically describes the main change: adding rate limiting to three authentication endpoints (activation, activation code request, and TOTP setup).
Description check ✅ Passed The description directly relates to the changeset by listing the three specific endpoints receiving rate limiting and explaining their purpose (brute-force and spam prevention).
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch rate-limit-forms

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.

Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 2

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@lib/plausible_web/controllers/auth_controller.ex`:
- Around line 424-435: The rate-limit error branch currently conflates the IP
1-minute and user 5-minute throttles (Auth.rate_limit(:totp_setup_ip, conn) and
Auth.rate_limit(:totp_setup_user, user)) and renders a misleading message;
update the {:error, {:rate_limit, _}} branch to use a neutral message such as
"Too many attempts. Wait a few minutes before trying again." or, if you prefer
more accuracy, pattern-match the returned limit type from Auth.rate_limit
(inspect the {:error, {:rate_limit, limit_type}} value) and call render_error
with "Wait a minute..." for :totp_setup_ip and "Wait a few minutes..." for
:totp_setup_user so the render_error call reflects the actual throttle.

In `@lib/plausible/auth/auth.ex`:
- Around line 28-35: The test env block sets `@activation_ip_limit`,
`@totp_setup_ip_limit`, and `@activation_request_limit` to 100_000 which disables
IP-based throttling branches; change those three module attributes in the env
when env in [:test, :ce_test] branch to small limits (e.g., 5 or 10) so tests
exercise IP-based paths, and if any specific tests require higher headroom,
override the limits only within those tests or use a tagged setup to temporarily
increase them.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: 9be5c5dd-7e30-45a6-b107-06fa7b3937e4

📥 Commits

Reviewing files that changed from the base of the PR and between 19002bc and c2f7067.

📒 Files selected for processing (11)
  • extra/lib/plausible_web/live/verification.ex
  • lib/plausible/auth/auth.ex
  • lib/plausible/sites.ex
  • lib/plausible_web/controllers/api/internal_controller.ex
  • lib/plausible_web/controllers/auth_controller.ex
  • lib/plausible_web/controllers/stats_controller.ex
  • lib/plausible_web/plugs/authorize_public_api.ex
  • lib/plausible_web/plugs/authorize_site_access.ex
  • lib/plausible_web/plugs/super_admin_only_plug.ex
  • lib/plausible_web/templates/layout/_header.html.heex
  • test/plausible_web/controllers/auth_controller_test.exs

Comment thread lib/plausible_web/controllers/auth_controller.ex
Comment thread lib/plausible/auth/auth.ex
@apata apata added this pull request to the merge queue May 15, 2026
Merged via the queue into master with commit ff14198 May 15, 2026
23 checks passed
@apata apata deleted the rate-limit-forms branch May 15, 2026 07:39
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.

3 participants