Skip to content

Conversation

miketheman
Copy link
Member

Limits specifically calls to the 2FA-related actions:

  • checking a recovery code
  • checking a TOTP value
  • checking a Webauthn value

The rate limits were selected to be a balance of usability vs how long it would take a slow-roll actor to continue trying.

Metrics are emitted for monitoring and alerting purposes.

Refs: #8456

Limits specifically calls to the 2FA-related actions:

- checking a recovery code
- checking a TOTP value
- checking a Webauthn value

The rate limits were selected to be a balance of usability vs how long
it would take a slow-roll actor to continue trying.

Metrics are emitted for monitoring and alerting purposes.

Refs: pypi#8456

Signed-off-by: Mike Fiedler <miketheman@gmail.com>
@miketheman miketheman requested a review from a team as a code owner August 22, 2025 14:34
@miketheman miketheman added security Security-related issues and pull requests 2FA labels Aug 22, 2025
@miketheman miketheman mentioned this pull request Aug 22, 2025
Copy link
Contributor

@ewjoachim ewjoachim left a comment

Choose a reason for hiding this comment

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

The change in the ratelimit, unless I'm mistaken, means attacks will be 2.4 times slower (so >50% chance of success in 7 months)

The new metrics will surely help measuring the normal "noise" level of users failing to 2FA (assuming those kinds of attacks are rare) (maybe we're about to discover something huge :D )

This will definitely help setting the right thresholds when later pulling out the effective measures that have been discussed (exponential backoff, auto-lockout, ...)

👍 for me and thanks for taking the time to act on this 5-year-old issue :) (issue birthday was just a few days ago) <3

@miketheman
Copy link
Member Author

@ewjoachim Thanks for the review!

The change in the ratelimit, unless I'm mistaken, means attacks will be 2.4 times slower (so >50% chance of success in 7 months)

By my math, the "50 per day" is the most restrictive, so you'd need some 20k days to hit all combinations, so even if we assume that you get there in half of the entries, that's still some ~25 years. Unless I can't do math?

@ewjoachim
Copy link
Contributor

ewjoachim commented Sep 3, 2025

I trust your maths more than I trust mine. I think I saw the 50/h and missed the 50/d, but let's redo the maths :)

There are 1M possible TOTP codes (000000 to 999999)
Each code counts as 3 codes because we check the 30 secs before and after, so each code has 1/333333 chances to be right (you could actually try the code 000000 every half hour instead of trying to hit them all)
The probability of having 0 success on n tries is (333332/333333)^n which goes under 50% after n=math.ceil(math.log(0.5)/math.log(333332/333333))=231049 tries, which divided by 50 makes 4620 days which is 12.6 years. So an attacker would get >50% of success after 12.6 years.

@ewdurbin ewdurbin merged commit 70085e8 into pypi:main Sep 4, 2025
20 checks passed
@miketheman miketheman deleted the miketheman/8456-2fa-bruteforce branch September 5, 2025 13:49
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

2FA security Security-related issues and pull requests

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants