Ruby on Rails Security Audit Checklist 2025: 23 Proven Steps to Secure Your App [Free Template]
Table of contents
- 1. Keep Ruby and Rails Versions Up-to-Date
- 2. Validate User Input
- 3. Enforce Secure Passwords
- 4. Implement HTTPS
- 5. Protect Against Cross-Site Request Forgery (CSRF)
- 6. Use Secure Headers
- 7. Prevent SQL Injection
- 8. Sanitize Data for Views
- 9. Restrict Mass Assignment
- 10. Encrypt Sensitive Data
- 11. Protect Against Brute Force Attacks
- 12. Use Secure Cookies
- 13. Disable Unused Gems
- 14. Restrict Admin Panel Access
- 15. Monitor Logs for Suspicious Activity
- 16. Avoid Exposing Stack Traces
- 17. Secure File Uploads
- 18. Enable Rate Limiting
- 19. Audit and Secure Dependencies
- 20. Implement Role-Based Access Control (RBAC)
- 21. Perform Regular Security Scans
- 22. Backup Data Securely
- 23. Train Your Team
- FREE Template
- FAQ
Ensuring the security of web applications is paramount in today’s digital landscape.
Ruby on Rails (RoR), known for its developer-friendly nature and robust features, powers thousands of applications globally.
However, like any framework, it is susceptible to various vulnerabilities if not properly secured.
This comprehensive guide outlines a 23-point security audit checklist for Ruby on Rails applications in 2025.
With detailed explanations and actionable steps, including code examples, you'll be equipped to audit and fortify your RoR application effectively.
1. Keep Ruby and Rails Versions Up-to-Date
Why It Matters:
Staying updated ensures your application benefits from the latest security patches.
Both Ruby and Rails receive regular updates addressing vulnerabilities and performance improvements.
Steps:
Use a version manager like
rbenv
orrvm
to manage Ruby versions. I personally usemise
these days.Regularly check Rails release notes for updates.
Code Example:
Update your Gemfile
to specify the latest version:
# Gemfile
ruby '3.3.5' # Example latest Ruby version
gem 'rails', '~> 8.0.0'
Then, run:
bundle install
2. Validate User Input
Why It Matters:
Input validation ensures data integrity but does not prevent vulnerabilities like SQL Injection or XSS. Use it to enforce constraints like format or range.
Steps:
Use Rails' built-in strong parameters for input validation.
Validate the data input
Sanitize user input where necessary.
Code Example 1:
Prevent mass assignment vulnerabilities by explicitly permitting required attributes in controllers.:
class UsersController < ApplicationController
def create
user = User.new(user_params)
if user.save
redirect_to user, notice: 'User successfully created.'
else
render :new
end
end
private
def user_params
params.require(:user).permit(:name, :email, :password)
end
end
Code Example 2:
Validate that age is a positive integer:
validates :age, numericality: { greater_than: 0 }
Code Example 3:
Rails escapes input in views by default. Use sanitize
for rendering user-generated HTML after stripping harmful tags:
<%= sanitize(comment.body) %>
This protects against XSS when raw HTML input is necessary. Avoid sanitization unless required and always validate input first.
3. Enforce Secure Passwords
Why It Matters:
Weak passwords are a common entry point for attackers. Secure password enforcement reduces this risk.
Steps:
Use the
bcrypt
gem to hash passwords.Enforce complexity and length rules.
Code Example:
Model-level password validation:
class User < ApplicationRecord
has_secure_password
validates :password, length: { minimum: 12 }, format: { with: /\A(?=.*[a-z])(?=.*[A-Z])(?=.*\d).*\z/, message: "must include at least one uppercase letter, one lowercase letter, and one digit" }
end
4. Implement HTTPS
Why It Matters:
HTTPS encrypts data in transit, protecting sensitive information like login credentials and personal data.
Steps:
Use SSL certificates (e.g., from Let’s Encrypt).
Force HTTPS in Rails using
config.force_ssl
.
Code Example:
Enable HTTPS in config/environments/production.rb
:
Rails.application.configure do
config.force_ssl = true
end
5. Protect Against Cross-Site Request Forgery (CSRF)
Why It Matters:
CSRF attacks trick users into performing unintended actions on a website.
Steps:
Enable Rails’ default CSRF protection.
Ensure forms include authenticity tokens.
Code Example:
Rails automatically includes CSRF protection, but verify it's in your ApplicationController
:
class ApplicationController < ActionController::Base
protect_from_forgery with: :exception
end
6. Use Secure Headers
Why It Matters:
HTTP headers like Content-Security-Policy
and Strict-Transport-Security
mitigate attacks such as XSS and protocol downgrade attacks.
Steps:
- Use the
secure_headers
gem to manage security headers.
Code Example:
Add this to your Gemfile
:
gem 'secure_headers'
Enhance web application security with Content Security Policies (CSP). Configure headers in config/initializers/secure_headers.rb
:
SecureHeaders::Configuration.default do |config|
config.csp = {
default_src: ["'self'"],
script_src: ["'self'", "'unsafe-inline'", "https://trusted-scripts.com"],
object_src: ["'none'"],
frame_ancestors: ["'none'"]
}
config.hsts = "max-age=31536000; includeSubDomains"
end
7. Prevent SQL Injection
Why It Matters:
SQL Injection attacks manipulate database queries to access or destroy data. Prevent SQL Injection by using parameterized queries in Active Record. Never directly interpolate user input in SQL strings.
Steps:
Use Active Record query methods instead of raw SQL.
Sanitize inputs.
Code Example:
Instead of:
User.where("email = '#{params[:email]}'")
Use:
User.where("email = ?", params[:email])
8. Sanitize Data for Views
Why It Matters:
Rendering unsanitized user data can lead to XSS attacks.
Steps:
Use Rails’
html_safe
method cautiously.Utilize the
sanitize
helper for user-generated content.
Code Example:
<%= sanitize(user.bio) %>
Note: The sanitize
helper is only necessary for raw user-provided HTML and that Rails' default output escaping is sufficient for general XSS protection. Be cautious when relying on sanitize
and consider validating or rejecting unsafe input at earlier stages.
9. Restrict Mass Assignment
Why It Matters:
Mass assignment allows attackers to set protected attributes if not restricted.
Steps:
Use strong parameters.
Avoid
attr_accessible
andattr_protected
.
10. Encrypt Sensitive Data
Why It Matters:
Encrypting sensitive fields ensures data remains secure even if compromised.
Steps:
- Use the
attr_encrypted
gem for field-level encryption.
Code Example:
Add this to your model:
class User < ApplicationRecord
attr_encrypted :ssn, key: Rails.application.secrets.encryption_key
end
11. Protect Against Brute Force Attacks
Why It Matters:
Brute force attacks guess credentials until successful. Introduce rate limiting techniques using tools like Rack::Attack or built-in Rails features to prevent brute force and credential stuffing attacks.
Steps:
Use enhanced password hashing practices (e.g., use of
bcrypt
orargon2
).Use account lockouts after multiple failed attempts.
Implement Rate limiting to combat brute force or credential stuffing attacks.
Implement CAPTCHA for sensitive actions.
Code Example:
To mitigate brute force and credential stuffing attacks, implement rate limiting using middleware like Rack::Attack
. Here’s an example configuration to limit login attempts:
Rack::Attack.throttle("logins/ip", limit: 5, period: 60.seconds) do |req|
req.ip if req.path == "/login" && req.post?
end
Additionally, consider locking user accounts after multiple failed attempts and incorporating Two-Factor Authentication (2FA) to secure logins.
12. Use Secure Cookies
Why It Matters:
Cookies are vulnerable to theft and manipulation.
Steps:
Mark cookies as secure and HttpOnly.
Use Rails’ encrypted cookies.
Code Example:
Rails.application.config.session_store :cookie_store, key: '_your_app_session', secure: Rails.env.production?, httponly: true
13. Disable Unused Gems
Why It Matters:
Unused gems increase the attack surface.
Steps:
- Audit and remove unnecessary gems from the
Gemfile
.
14. Restrict Admin Panel Access
Why It Matters:
Admin panels are high-value targets for attackers.
Steps:
- Restrict access by IP or using authentication.
15. Monitor Logs for Suspicious Activity
Why It Matters:
Logs can reveal attempted or successful attacks.
Steps:
Use tools like
lograge
for structured logging.Monitor for unusual patterns.
16. Avoid Exposing Stack Traces
Why It Matters:
Stack traces reveal sensitive information about your application.
Steps:
- Disable full error reports in production.
17. Secure File Uploads
Why It Matters:
Improper file uploads can lead to remote code execution or data leaks.
Steps:
Use libraries like
ActiveStorage
orCarrierWave
.Validate file types and sizes.
18. Enable Rate Limiting
Why It Matters:
Rate limiting prevents abuse by controlling the frequency of requests. Mitigate brute force and credential stuffing attacks with Rack::Attack
. Throttle login attempts and consider Two-Factor Authentication (2FA).
Steps:
- Use Rack middleware like
rack-attack
.
19. Audit and Secure Dependencies
Why It Matters:
Vulnerable gems can compromise your application.
Steps:
- Use tools like
bundler-audit
to scan for vulnerabilities.
Code Example:
Bundler Audit does not directly detect vulnerabilities in your application code but scans for vulnerable dependencies in your Gemfile.lock using the Ruby Advisory Database. Install Bundler Audit and run:
gem install bundler-audit
bundle audit
Regularly update your dependencies to fix known vulnerabilities flagged by the tool.
20. Implement Role-Based Access Control (RBAC)
Why It Matters:
RBAC ensures users only access resources they’re authorized for.
Steps:
- Use gems like
pundit
for authorization.
21. Perform Regular Security Scans
Why It Matters:
Periodic scans identify vulnerabilities before attackers exploit them.
Steps:
- Use tools like
Brakeman
for static analysis.
22. Backup Data Securely
Why It Matters:
Regular backups ensure recovery in case of data loss or corruption.
Steps:
- Use encrypted backups and store them securely.
23. Train Your Team
Why It Matters:
Security is a shared responsibility. Training ensures best practices are followed.
Steps:
- Conduct regular security training and awareness sessions.
Conclusion
The 23-point framework provided here is a robust foundation for auditing the security of Ruby on Rails applications.
Regularly reviewing and updating your practices in light of evolving threats will keep your applications secure.
Use the provided template to systematically assess vulnerabilities and fortify your RoR applications.
FREE Template
Download the FREE Template to Audit the Security of your Ruby on Rails application.
We also provide a FREE Ruby on Rails Application Audit service that will basically audit your Rails app by using this 23-points template and give you a FREE Report.
Contact us now if you want your Rails App audited for its security.
FAQ
What makes Ruby on Rails 8 secure for web application development?
Rails 8 integrates built-in security measures against common vulnerabilities like SQL injection, cross-site scripting (XSS), and cross-site request forgery (CSRF). With new Active Record enhancements and simplified authentication setup, Rails 8 improves overall security.What’s new in the authentication system of Rails 8?
Rails 8 introduces a built-in authentication generator that creates all essential files, such as controllers, models, views, and mailers, for a secure session-based system. This eliminates reliance on third-party gems for basic authentication setups.How does Rails 8 handle CSRF protection?
CSRF protection in Rails 8 is automatic, using tokens embedded in forms to verify requests and prevent unauthorized actions. This is standard for all form submissions and API calls.How does the Rails framework protect against SQL injection in version 8?
Rails 8 continues to use parameterized queries in Active Record to prevent SQL injection. Developers are encouraged to use methods likewhere
with placeholders or hashes to handle user input safely.What improvements in logging practices are available in Rails 8?
Rails 8 introduces query log tags by default in development mode, making it easier to trace SQL statements to their origins in application code. Additionally, sensitive data in logs can be filtered usingfilter_parameters
.What are strong parameters, and how do they enhance security in Rails 8?
Strong parameters prevent mass assignment vulnerabilities by explicitly defining permitted attributes for updates and creations, ensuring no unintended changes are made by user inputs.What new tools in Rails 8 help developers secure their applications?
The built-in authentication generator.
Query log tags for better debugging.
Simplified asset management via Propshaft, which minimizes dependencies and attack vectors.
Does Rails 8 provide better support for encryption?
Yes, Rails 8 builds on encrypted attributes, allowing developers to store sensitive data securely in the database without additional setup.How does Rails 8 improve protection against XSS attacks?
By default, Rails 8 escapes untrusted user inputs in views, preventing script injection attacks. It also supports helper methods likesanitize
for additional control over raw HTML handling.What are the key reasons to upgrade from Rails 7 to Rails 8?
Upgrading to Rails 8 is essential to leverage:Built-in authentication.
Propshaft for modern asset management.
Enhanced Active Record features like PostgreSQL partitioning.
Improved SQLite support for production environments.
These features align Rails 8 with modern web application needs.
What database systems are best supported in Rails 8?
Rails 8 enhances compatibility with PostgreSQL, MySQL 5.6.4+, and SQLite. New features include PostgreSQL table inheritance, improved fixture bulk inserts, and better schema migrations.What are the highlights of the new Propshaft asset pipeline in Rails 8?
Propshaft focuses on simplicity by managing core asset tasks like file digestion and caching. It works seamlessly with modern JavaScript tools like Esbuild or Vite, making it a lightweight replacement for Sprockets.Can Rails 8 protect against session hijacking?
Yes, Rails 8 uses secure, encrypted cookies withHttpOnly
andsecure
flags. Additionally, its built-in authentication handles session expiry and password reset functionalities.How has Rails 8 improved Active Record for performance and security?
Rails 8 adds reversible schema changes, support for PostgreSQL partitioning, and enhanced concurrency handling in SQLite, reducing downtime risks and improving data integrity.What is the
bin/rails generate script
command in Rails 8?
This command creates reusable scripts stored in thescript/
directory, streamlining operations like data migrations or cleanup tasks. It keeps scripts organized and separate from core application logic.How does Rails 8 ensure HTTPS usage?
Enablingconfig.force_ssl
in Rails 8 applications enforces HTTPS, encrypting all client-server communications. This prevents data interception and man-in-the-middle attacks.Does Rails 8 simplify Progressive Web App (PWA) development?
Yes, Rails 8 enhances PWA support with built-in configurations for service workers, enabling features like offline caching and better performance for mobile-first applications.What are the deployment improvements in Rails 8?
Rails 8 includes Kamal, a deployment tool that simplifies configuration and reduces complexity in production environments. It integrates seamlessly with Docker-based setups.How can automated tools like Brakeman be used with Rails 8?
Brakeman can scan Rails 8 codebases for vulnerabilities, including issues related to deprecated methods or insecure practices. Running tools likebrakeman -A
ensures proactive security measures are in place.How has SQLite support evolved in Rails 8?
SQLite can now be used effectively for production workloads in Rails 8, supporting caching, Action Cable, and background jobs. Improved error handling and transaction management make it more reliable.What are the prerequisites for using Rails 8?
Rails 8 requires Ruby 3.3+ and updated database versions (PostgreSQL 10+ or MySQL 5.6.4+). Ensure all dependencies meet the minimum requirements before upgrading.
Subscribe to my newsletter
Read articles from Chetan Mittal directly inside your inbox. Subscribe to the newsletter, and don't miss out.
Written by
Chetan Mittal
Chetan Mittal
I stumbled upon Ruby on Rails beta version in 2005 and has been using it since then. I have also trained multiple Rails developers all over the globe. Currently, providing consulting and advising companies on how to upgrade, secure, optimize, monitor, modernize, and scale their Rails apps.