[Security] Unauthorised account access via token prediction

46 views
Skip to first unread message

Gareth Rees

unread,
Mar 25, 2026, 6:00:34 AMMar 25
to alavet...@googlegroups.com
We've discovered and patched an issue where user accounts can potentially be compromised via token prediction.

We've released fixes for all known operational Alavetelis.

Summary and Impact:
===================

Password reset tokens are generated using Ruby's rand(), which is not cryptographically secure. An attacker can observe tokens leaked in login redirect URLs, and under the right circumstances (one process running Alaveteli, little other uses of rand on the device it runs on) may be able to predict future password reset tokens, and thus gain access to change the password of a user account, given the email address (unless it is protected by two factor authentication).

Fix:
====

The fix is to commonlib/rblib/util.rb. As MySociety::Util.generate_token has been using rand() instead of SecureRandom, the fix is to have it use SecureRandom.

We have released fixed versions for all known operational Alaveteli installs. These are listed below.

We also attach a generic patch file that should work with any version of Alaveteli since the vulnerability was introduced. Note that as the vulnerability resides in the commonlib git submodule, you will need to apply it by changing into the commonlib directory and then apply the patch:

cd path/to/alaveteli
cd commonlib
git am Ruby-Use-SecureRandom.hex-in-generate_token.patch

Here's the diff:

diff --git a/rblib/util.rb b/rblib/util.rb
index 8db3644..3e968fd 100644
--- a/rblib/util.rb
+++ b/rblib/util.rb
@@ -7,16 +7,13 @@
 #
 #
 require 'openssl'
+require 'securerandom'
 module MySociety

   module Util
     # Makes a random token, suitable for using in URLs e.g confirmation messages.
     def self.generate_token
-      bits = 12 * 8
-      # Make range from value to double value, so number of digits in base 36
-      # encoding is quite long always.
-      rand_num = rand(max = 2**(bits+1)) + 2**bits
-      rand_num.to_s(base=36)
+      SecureRandom.hex(14)
     end

     # breaks a list of items into a hash keyed by first letter of their descriptor block

Note that in later versions we've used SecureRandom.alphanumeric. This is unavailable before Ruby 2.5, which affects some Alaveteli installs. If you're on an older install and need to patch instead of upgrade to one of the new releases, then hex is more generally compatible until you can get to a later version. We strongly recommend upgrading to more recent versions of Ruby and Alaveteli, as other security issues will have been patched.

Affected versions:
==================

This vulnerability was introduced in 2007, and all versions are affected.

Fixed versions:
===============

We have published hotfix releases for the below series of Alaveteli and merged a fix to the master branch.

https://github.com/mysociety/alaveteli/releases/tag/0.46.2.1
https://github.com/mysociety/alaveteli/releases/tag/0.46.1.2
https://github.com/mysociety/alaveteli/releases/tag/0.46.0.3
https://github.com/mysociety/alaveteli/releases/tag/0.44.0.3
https://github.com/mysociety/alaveteli/releases/tag/0.43.2.2
https://github.com/mysociety/alaveteli/releases/tag/0.42.0.2
https://github.com/mysociety/alaveteli/releases/tag/0.41.1.2
https://github.com/mysociety/alaveteli/releases/tag/0.38.4.5
https://github.com/mysociety/alaveteli/releases/tag/0.38.1.3
https://github.com/mysociety/alaveteli/releases/tag/0.24.1.14
https://github.com/mysociety/alaveteli/releases/tag/0.23.2.8

As ever, reach out if you have any questions.

Best,

Gareth

--
Gareth Rees
Ruby-Use-SecureRandom.hex-in-generate_token.patch

Gareth Rees

unread,
Mar 25, 2026, 8:46:47 AMMar 25
to Alaveteli Dev
We've also now released a hotfix for the previous release:

Reply all
Reply to author
Forward
0 new messages