Ruby on Rails Security Checklist

Nguyen Phu Cuong
3 min readMay 25, 2021

Check for Unauthorized Access

Always verify that the user is authorized to do the action he’s doing.

Example: A user owns a list of projects, he should not see projects of the others. Instead of @project = Project.find(params[:id]) . We should use

@project = @current_user.projects.find(params[:id])

Authentication

I usually use Rails’ built-in has_secure_password for my own authentication system. It uses bcrypt to hash the password. When authenticating a user, get the hash of the password and compare it with the hash on the database.

Never save password in clear text.

Besides that you can use existing gems like devise or authlogic to do the same way.

Strong parameters

By using strong parameters, I whitelist the values that can be used

params.require(:person).permit(:name, :age)

We’re telling Rails that only name and age can be changed. A user can’t not change easily the data when he try to add more data than required data on Front-end form.

Throttling Requests

On some pages like login page, I want to throttle my users to a few requests per minute. This prevents bots from trying thousands of passwords quickly

Rack Attack is a Rack middleware that provides throttling among other features.

Rack::Attack.throttle('logins/email', :limit => 6, :period => 60.seconds) do |req|
req.params['email'] if req.path == '/login' && req.post?
end

Protecting my Users

Use a generic message if the username or password are wrong. Don’t let the attacker have a chance to compile a list of error messages and emails of our users.

Use HTTPS

If we use HTTP for a login page, anyone sniffing the network of our user will see the password in clear text.

On config/environments/production.rb, you can redirect all requests to HTTPS.

config.force_ssl = true

No credentials in the Repository

The secret key base, database credentials and other sensitive data should not be committed to our repository.

In theory, there’s nothing wrong with storing any type of credential in a private repository but keeping it as secret as possible is still better.

Bundler Audit

To check if any of gem you’re using has a vulnerability issue, install the bundler-audit gem.

Run Brakeman

Brakeman is static analysis security vulnerability scanner for Rails application. While bundler-audit checks the Gemfile.lock only, brakeman checks my code.

SQL Injection

Some ActiveRecord methods doesn’t escape arguments so you have to be careful when using them with the user input. For example:

e = params[:email]
User.where("email = '#{e}'")

if e is set to "') OR 1-- ", the query will become

SELECT `users`.* FROM `users` WHERE (email = '') OR 1-- ')

Anything after -- is a comment. OR 1 will select all the records from the users table.

There are 2 safe versions that you can apply in this case

e = params[:email]
User.where(email: e)

or

e = params[:email]
User.where("email = ?", e)

Now, it’s your turn to build your security checklist. I only suggest common issues that I usually face with. You should notice about your security checklist from early stage of the project because it will cost a lot of time to change when your project grows up.

--

--