Skip to content

Commit 5afe4fb

Browse files
Make secure_compare handle empty strings comparison correctly
Used Rails' secure_compare method inside the definition of secure_compare. This will handle the empty strings comparison and return true when both the parameters are empty strings. Fixes #4441, #4829
1 parent 47e8716 commit 5afe4fb

File tree

3 files changed

+10
-8
lines changed

3 files changed

+10
-8
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@
4646
* Use `OmniAuth.config.allowed_request_methods` as routing verbs for the auth path [#5508](https://github.com/heartcombo/devise/pull/5508)
4747
* Handle `on` and `ON` as true values to check params [#5514](https://github.com/heartcombo/devise/pull/5514)
4848
* Fix passing `format` option to `devise_for` [#5732](https://github.com/heartcombo/devise/pull/5732)
49+
* Use `ActiveRecord::SecurityUtils.secure_compare` in `Devise.secure_compare` to match two empty strings correctly. [#4829](https://github.com/heartcombo/devise/pull/4829)
4950
5051
5152
Please check [4-stable](https://github.com/heartcombo/devise/blob/4-stable/CHANGELOG.md)

lib/devise.rb

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -517,12 +517,8 @@ def self.friendly_token(length = 20)
517517

518518
# constant-time comparison algorithm to prevent timing attacks
519519
def self.secure_compare(a, b)
520-
return false if a.blank? || b.blank? || a.bytesize != b.bytesize
521-
l = a.unpack "C#{a.bytesize}"
522-
523-
res = 0
524-
b.each_byte { |byte| res |= byte ^ l.shift }
525-
res == 0
520+
return false if a.nil? || b.nil?
521+
ActiveSupport::SecurityUtils.secure_compare(a, b)
526522
end
527523

528524
def self.deprecator

test/devise_test.rb

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -86,15 +86,20 @@ class DeviseTest < ActiveSupport::TestCase
8686
Devise::CONTROLLERS.delete(:kivi)
8787
end
8888

89-
test 'should complain when comparing empty or different sized passes' do
89+
test 'Devise.secure_compare fails when comparing different strings or nil' do
9090
[nil, ""].each do |empty|
9191
assert_not Devise.secure_compare(empty, "something")
9292
assert_not Devise.secure_compare("something", empty)
93-
assert_not Devise.secure_compare(empty, empty)
9493
end
94+
assert_not Devise.secure_compare(nil, nil)
9595
assert_not Devise.secure_compare("size_1", "size_four")
9696
end
9797

98+
test 'Devise.secure_compare passes when strings are the same, even two empty strings' do
99+
assert Devise.secure_compare("", "")
100+
assert Devise.secure_compare("something", "something")
101+
end
102+
98103
test 'Devise.email_regexp should match valid email addresses' do
99104
100105
non_valid_emails = ["rex", "test [email protected]", "test_user@example server.com"]

0 commit comments

Comments
 (0)