Left arrow
Practices / Tech

Exploring Security Measures in Ruby on Rails 7

Clock icon 9 min read
Top right decor Bottom left decor

With cyber threats becoming increasingly sophisticated, developers must proactively implement robust security measures to protect sensitive data and maintain user trust.

Ensuring the security of your Ruby on Rails is paramount.

In this comprehensive guide, we’ll explore seven key security practices that are essential for fortifying your Ruby on Rails 7 applications.

1. Secure Query Construction with ActiveRecord

In Rails, developers are encouraged to utilize ActiveRecord’s robust query methods or ActiveRecord::QueryMethods for constructing SQL queries. These methods provide built-in protection against SQL injection attacks by automatically escaping user input, ensuring the integrity and security of database interactions.

class User < ApplicationRecord
  def find_by_name(name)
    where("name = ?", name).first
  end
end

2. Safeguard Against Cross-Site Scripting (XSS) Attacks

Cross-Site Scripting (XSS) remains a pervasive security threat in web applications, allowing attackers to inject malicious scripts into pages viewed by unsuspecting users.  These scripts execute within the victim’s browser context, potentially leading to data theft, session hijacking, and other harmful exploits. 

To mitigate XSS risks, Rails fortifies applications with automatic output escaping as its default behavior. Moreover, Rails equips developers with helper methods like sanitize to further sanitize the data when necessary. 
In the example below, the @user.name variable might contain user-generated content, including HTML or JavaScript. Rails automatically escapes such content by default, rendering any potential XSS scripts harmless.

<h1><%= @user.name %></h1>
<p><%= @user.email %></p>

If it contains the following:

 <script>alert('XSS attack!');</script>

Rails will escape it before rendering:

As a result, the browser treats it as plain text (<script>alert(‘XSS attack!’);</script>) rather than executing it as JavaScript.

3. Bolstering Cross-Site Request Forgery (CSRF) Defenses

Imagine a scenario: a banking website facilitates money transfers between accounts through a straightforward HTML form:

<form action="https://examplebank.com/transfer" method="post">
    <input type="hidden" name="fromAccount" value="123456">
    <input type="hidden" name="toAccount" value="987654">
    <input type="hidden" name="amount" value="1000">
    <input type="submit" value="Transfer">
</form>

In this setup:

  • fromAccount denotes the initiating user’s account number.
  • toAccount represents the recipient’s account number.
  • amount specifies the sum being transferred.

Now, imagine a malicious website designed by an attacker. It replicates the banking form but alters the toAccount value to the attacker’s account and inflates the amount. This form is similar to the one on the banking website, but notice that the toAccount value has been changed to the attacker’s account, and the amount is significantly higher.

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Malicious Website</title>
</head>
<body>
    <h1>Click the Button!</h1>
    <form action="https://examplebank.com/transfer" method="post">
        <input type="hidden" name="fromAccount" value="123456">
        <input type="hidden" name="toAccount" value="attackersAccount">
        <input type="hidden" name="amount" value="1000000">
        <input type="submit" value="Click Me">
    </form>
</body>
</html>

If a logged-in user inadvertently clicks the form on the malicious site, the transfer occurs without consent. This exploit thrives because the user’s browser, still authenticated with the bank, automatically forwards cookies, including the session cookie, to the banking domain.

Rails combats CSRF threats by default, employing unique session-based tokens embedded within forms. These tokens thwart unauthorized requests by verifying their source against the application’s origin. 

Consider a form for creating a new product in our Rails app:

<%= form_with(model: @product, local: true) do |form| %>
  <%= form.label :title %>
  <%= form.text_field :title %>

  <%= form.label :description %>
  <%= form.text_area :description %>

  <%= form.submit %>
<% end %>

Rails automatically includes a CSRF token within such forms:

<form action="/products" method="post">
  <input type="hidden" name="authenticity_token" value="<%= form_authenticity_token %>">
  <!-- Other form fields -->
</form>

Upon submission, Rails validates the authenticity token, ensuring request integrity. The protect_from_forgery method in the ApplicationController further fortifies all controller actions against CSRF exploits:

class ApplicationController < ActionController::Base
  protect_from_forgery with: :exception
end

4. Reinforcing Security with Strong Parameters

Rails introduced Strong Parameters to the handling of user input within controller actions, mitigating the risk of mass assignment vulnerabilities.

class ItemsController < ApplicationController
  def create
    @item = Item.new(create_params)

    if @item.save
      redirect_to @item, notice: 'Item was successfully created.'
    else
      render :new
    end
  end

  private

  def create_params
    params.require(:item).permit(:title, :description)
  end
end

In the create action of the ItemsController, we employ Strong Parameters to whitelist permissible parameters for mass assignment, using the permit method. Here, we exclusively allow :title and :description attributes.

{
  product: {
    title: 'New Item',
    description: 'This is the description of the new item.'
  }
}

5. Strengthening Web Security with HTTP Headers

In Rails, bolstering web security through the configuration of HTTP headers is both seamless and effective. By setting headers such as Content Security Policy (CSP), X-Content-Type-Options, X-Frame-Options, and X-XSS-Protection, you can significantly enhance your application’s overall security posture.

To accomplish this, you can utilize middleware to uniformly apply security headers to all responses within your Rails application. 

Below is an example of creating a custom middleware class to define and implement these headers:

class SecurityHeadersMiddleware
  def initialize(app)
    @app = app
  end

  def call(env)
    status, headers, response = @app.call(env)
    
    # Set security headers
    headers['X-Content-Type-Options'] = 'nosniff'
    headers['X-Frame-Options'] = 'SAMEORIGIN'
    headers['X-XSS-Protection'] = '1; mode=block'
    headers['Content-Security-Policy'] = "default-src 'self'"

    [status, headers, response]
  end
end

After defining the middleware class, integrate it into your Rails application by configuring it within the config/application.rb file

# config/application.rb
config.middleware.use SecurityHeadersMiddleware

With this setup, every response generated by your Rails application will be fortified with essential security headers like X-Content-Type-Options, X-Frame-Options, X-XSS-Protection, and Content-Security-Policy. These headers collectively serve as robust defenses against a myriad of web security threats, ensuring the integrity and resilience of your application.

6. Secrets Management

In Rails, safeguarding information like API keys, database credentials, and encryption keys is critical for maintaining robust security practices. This is typically achieved through the secure management of environment variables or encrypted credentials.
Rails conveniently stores secrets in the config/secrets.yml file, where different environments, such as development or production, each have their own set of keys. Below is an example illustrating how secrets are managed in Rails:

development:
  secret_key_base: <%= ENV['SECRET_KEY_BASE'] %>
  api_key: <%= ENV['API_KEY'] %>
production:
  secret_key_base: <%= ENV['SECRET_KEY_BASE'] %>
  api_key: <%= ENV['API_KEY'] %>

7. Ensuring Ongoing Security

Maintaining the security of your Rails application requires a proactive approach, which includes regularly updating your application with the latest patches and security fixes. The Rails team diligently releases security patches to address vulnerabilities and strengthen the framework’s defenses against emerging threats.

Safeguarding Your Ruby on Rails 7 Application

By implementing the security measures outlined in this guide, you fortify your application against vulnerabilities, protect sensitive data, and maintain user trust.

From secure query construction to robust CSRF protection, each measure contributes to your application’s resilience. By embracing strong parameters, meticulous secrets management, and regular updates, you establish a proactive defense strategy against evolving threats. 

Incorporate these practices into your development workflow, adhere to best practices, and stay vigilant against emerging threats to ensure the ongoing security of your Ruby Rails on 7 application.

Next Articles

Load more

Have a task with an important mission? Let’s discuss it!

    Thank you for getting in touch!

    We appreciate you contacting us. One of our colleagues will get back in touch with you soon!

    Have a great day!

    Thank you for getting in touch!

    Your form data is saved and will be sent to the site administrator as soon as your network is stable.