Skip to content

Recovery flow returns 403 CSRF error instead of 410 Gone when max submissions exceeded #4510

@johnbolsonito

Description

@johnbolsonito

Preflight checklist

Ory Network Project

No response

Describe the bug

The recovery flow with code strategy never reaches the max submissions check because the CSRF token becomes stale after failed code submissions. When users exceed the max submission limit (default 5), the 6th attempt fails with a 403 CSRF error instead of returning 410 Gone (as the verification flow does).

Root cause:

  1. CSRF validation happens before the max submissions check in strategy_recovery.go:178
  2. By the 6th attempt, the CSRF token is stale/invalid, causing CSRF validation to fail first
  3. The max submissions check (which would return 400/410) never executes because CSRF fails earlier

Reproducing the bug

  1. Initiate a recovery flow with code strategy
  2. Submit 5 incorrect recovery codes (attempts 1-5)
  3. On the 6th attempt, submit another incorrect code
  4. Observe the response

Expected: 410 Gone status with use_flow_id in the response (new flow created)
Actual: 403 Forbidden status with CSRF error message: "the request was rejected to protect you from Cross-Site-Request-Forgery"

Code flow:
strategy_recovery.go:178 - CSRF check happens first
strategy_recovery.go:197 - recoveryUseCode() is called (only if CSRF passes)
strategy_recovery.go:344 - Max submissions check happens inside UseRecoveryCode()
Since CSRF fails at line 178, line 344 is never reached

Relevant log output

[Log]
{
  error: "the request was rejected to protect you from Cross-Site-Request-Forgery"
}

Relevant configuration

selfservice:
  methods:
    code:
      enabled: true
      config:
        passwordless_enabled: false

Version

25.4.0

On which operating system are you observing this issue?

None

In which environment are you deploying?

None

Additional Context

No response

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething is not working.

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions