How RuboCop can secure your Ruby and Rails Applications

In the last two posts, we covered setting up bundler-audit to identify vulnerable dependencies and brakeman for static code analysis. In this post, we will focus on using RuboCop as static code analyzer for security checks.

While RuboCop is known as a linter and formatter, it also comes with some security rules and can be extended with more.

Let us get started by installing RuboCop first. For this add the following to your Gemfile:

gem 'rubocop', require: false

and then run our old friend:

bundle install

Once this has finished, you can run the rubocop command.

If you have never used RuboCop before you will likely see a lot of warnings appearing in your terminal. This is because out of the box all default rules are enabled. For this post, we are not interested in the linting and formatting capabilities of RuboCop. So let’s make sure we only run the relevant security rules instead.

Create a .rubocop.yml configuration file in the root of your project and copy the following into it.

AllCops:
DisabledByDefault: true

Rails/OutputSafety:
Enabled: true
Bundler/InsecureProtocolSource:
Enabled: true
Security/Eval:
Enabled: true
Security/JSONLoad:
Enabled: true
Security/MarshalLoad:
Enabled: true
Security/Open:
Enabled: true
Security/YAMLLoad:
Enabled: true

This disables all the style and linting rules and enables only security-related rules. If you use RuboCop for its normal purpose you might want to keep two different configuration files. One for code style linting and one for security testing.

Running the rubocop command now should only show security findings.

The following output has been generated by using the RailsGoat project.

output simple rubocop run

This was a good start already, but we can still enhance this a bit.

We will use a custom ruleset curated by the GitLab team.

Add the following to your Gemfile: gem 'rubocop-gitlab-security' and run bundle install again.

Next update the rubycop.yml configuration file and add:

require: rubocop-gitlab-security
GitlabSecurity/DeepMunge:
Enabled: true
GitlabSecurity/JsonSerialization:
Enabled: true
GitlabSecurity/RedirectToParamsUpdate:
Enabled: true
GitlabSecurity/SendFileParams:
Enabled: true
GitlabSecurity/SqlInjection:
Enabled: true
GitlabSecurity/SystemCommandInjection:
Enabled: true

With this setup, we can find more security issues in the RailsGoat project. output rubocop run with GitLab rules

To configure the RakeTasks, add this to your Rakefile and run rake rubocop.

require 'rubocop/rake_task'
RuboCop::RakeTask.new do |task|
  task.requires << 'rubocop-gitlab-security'
end

Fixing Findings

The RuboCop SAST (Static Application Security Testing) setup we have created is a very generic one. You can apply this to any Ruby and Rails application you have.

RuboCop issues don’t have a notion of severity. This may make it difficult for you to resolve the issues by using the approach we discussed for Brakeman. Ideally, you look into every single finding and make sure you can either fix the code, mitigate the issue in some other way or consider it a false positive.

Once you fixed all the issues that you identified as real threats, you will have to suppress the false positives. You can do this automatically by running rubocop --auto-gen-config or by manually marking the lines in the source code.

A Better Way

Feels like that would be a lot of work to set up for all your apps? You’re right, it is. Good news, we have already done the hard work for you and integrated RuboCop into GuardRails.

GuardRails filters noisy findings and delivers the results with actionable advice in your PRs. Every finding we report is of importance and you don’t have to spend time figuring out what to fix and what ignore. If by any chance we missed something you can mark it as false positive and it will not show up anymore in your scans.

GuardRails takes care of the heavy lifting so you can focus on delivering a great and secure product.

Give GuardRails a try so that you can move fast and be safe.

try guardrails