diff --git a/lib/admin_auth.rb b/lib/admin_auth.rb index c7af28e..acb9ea2 100644 --- a/lib/admin_auth.rb +++ b/lib/admin_auth.rb @@ -1,4 +1,5 @@ require 'rack/auth/basic' +require 'rack/utils' # Rack middleware that gates everything under /admin/* behind HTTP Basic. # Credentials come from ENV at boot; missing vars fail closed (401 always). @@ -14,7 +15,7 @@ class AdminAuth return @app.call(env) unless path == '/admin' || path.start_with?('/admin/') auth = Rack::Auth::Basic::Request.new(env) - if @user && @pass && auth.provided? && auth.basic? && auth.credentials == [@user, @pass] + if @user && @pass && auth.provided? && auth.basic? && credentials_match?(auth.credentials) @app.call(env) else [401, @@ -22,4 +23,13 @@ class AdminAuth ["Unauthorized\n"]] end end + + private + + def credentials_match?(creds) + user, pass = creds + # Single & so both comparisons always run (no short-circuit timing signal). + Rack::Utils.secure_compare(@user, user.to_s) & + Rack::Utils.secure_compare(@pass, pass.to_s) + end end