Rails Security Patterns Skill
Auto-validates security best practices and blocks common vulnerabilities.
What This Skill Does
Automatic Security Checks:
- •Strong parameters in controllers (prevents mass assignment)
- •SQL injection prevention (parameterized queries)
- •CSRF token handling (API mode considerations)
- •Authentication presence
- •Authorization checks
When It Activates:
- •Controller files created or modified
- •Model files with database queries modified
- •Authentication-related changes
Security Checks
1. Strong Parameters
Checks:
- •Every
createandupdateaction uses strong parameters - •No direct
paramsusage in model instantiation - •
permitcalls include only expected attributes
Example Violation:
ruby
# BAD def create @user = User.create(params[:user]) # ❌ Mass assignment end # GOOD def create @user = User.create(user_params) # ✅ Strong params end private def user_params params.require(:user).permit(:name, :email) end
Skill Output:
code
❌ Security: Mass assignment vulnerability Location: app/controllers/users_controller.rb:15 Issue: params[:user] used directly without strong parameters Fix: Define strong parameters method: private def user_params params.require(:user).permit(:name, :email, :role) end Then use: @user = User.create(user_params)
2. SQL Injection Prevention
Checks:
- •No string interpolation in
whereclauses - •Parameterized queries used
- •No raw SQL without placeholders
Example Violation:
ruby
# BAD
User.where("email = '#{params[:email]}'") # ❌ SQL injection
User.where("name LIKE '%#{params[:query]}%'") # ❌ SQL injection
# GOOD
User.where("email = ?", params[:email]) # ✅ Parameterized
User.where("name LIKE ?", "%#{params[:query]}%") # ✅ Safe
User.where(email: params[:email]) # ✅ Hash syntax
Skill Output:
code
❌ Security: SQL injection vulnerability
Location: app/models/user.rb:45
Issue: String interpolation in SQL query
Vulnerable code:
User.where("email = '#{email}'")
Fix: Use parameterized query:
User.where("email = ?", email)
Or use hash syntax:
User.where(email: email)
3. Authentication Checks
Checks:
- •Controllers have authentication filters
- •Sensitive actions require authentication
- •Token-based auth for API endpoints
Example:
ruby
# app/controllers/posts_controller.rb
class PostsController < ApplicationController
before_action :authenticate_user! # ✅ Auth required
def index
# ...
end
end
Skill Output (if missing):
code
⚠️ Security: No authentication found Location: app/controllers/admin/users_controller.rb Issue: Admin controller without authentication Recommendation: Add authentication: before_action :authenticate_user! before_action :require_admin!
4. Authorization Checks
Checks:
- •Update/destroy actions verify ownership
- •Role-based access control present
- •Resource-level authorization
Example:
ruby
# BAD def destroy @post = Post.find(params[:id]) @post.destroy # ❌ No ownership check end # GOOD def destroy @post = current_user.posts.find(params[:id]) # ✅ Scoped to user @post.destroy end # BETTER def destroy @post = Post.find(params[:id]) authorize @post # ✅ Using Pundit/CanCanCan @post.destroy end
Skill Output:
code
⚠️ Security: Missing authorization check Location: app/controllers/posts_controller.rb:42 Issue: destroy action without ownership verification Recommendation: Add authorization: Option 1 (scope to user): @post = current_user.posts.find(params[:id]) Option 2 (use authorization gem): authorize @post # Pundit authorize! :destroy, @post # CanCanCan
5. Sensitive Data Exposure
Checks:
- •No passwords in logs
- •API keys not hardcoded
- •Secrets use environment variables
Example Violation:
ruby
# BAD API_KEY = "sk_live_abc123..." # ❌ Hardcoded secret # GOOD API_KEY = ENV['STRIPE_API_KEY'] # ✅ Environment variable
Skill Output:
code
❌ Security: Hardcoded secret detected Location: config/initializers/stripe.rb:3 Issue: API key hardcoded in source Fix: Use environment variable: API_KEY = ENV['STRIPE_API_KEY'] Add to .env (don't commit): STRIPE_API_KEY=sk_live_your_key_here
Integration with Pre-commit Hook
This skill works with the pre-commit hook to block unsafe commits:
Automatic blocks:
- •SQL injection vulnerabilities
- •Missing strong parameters in create/update actions
- •Hardcoded secrets/API keys
- •Mass assignment vulnerabilities
Warnings (allow commit):
- •Missing authentication (might be intentional for public endpoints)
- •Missing authorization (might use custom logic)
- •Complex queries (performance concern, not security)
Configuration
Create .rails-security.yml to customize:
yaml
# .rails-security.yml
strong_parameters:
enforce: true
block_commit: true
sql_injection:
enforce: true
block_commit: true
authentication:
require_for_controllers: true
exceptions:
- Api::V1::PublicController
- PagesController
authorization:
warn_on_missing: true
block_commit: false
secrets:
detect_patterns:
- "sk_live_"
- "api_key"
- "password"
- "secret"
block_commit: true
Common Patterns
API Authentication
Token-based:
ruby
class Api::BaseController < ActionController::API
before_action :authenticate_token!
private
def authenticate_token!
token = request.headers['Authorization']&.split(' ')&.last
@current_user = User.find_by(api_token: token)
render json: { error: 'Unauthorized' }, status: :unauthorized unless @current_user
end
end
Scope to User
Pattern:
ruby
# Always scope to current_user when possible @posts = current_user.posts @post = current_user.posts.find(params[:id]) # Prevents accessing other users' resources
Rate Limiting
Recommendation:
ruby
# Gemfile
gem 'rack-attack'
# config/initializers/rack_attack.rb
Rack::Attack.throttle('api/ip', limit: 100, period: 1.minute) do |req|
req.ip if req.path.start_with?('/api/')
end
References
- •OWASP Top 10: https://owasp.org/www-project-top-ten/
- •Rails Security Guide: https://guides.rubyonrails.org/security.html
- •Pattern Library: /patterns/authentication-patterns.md
This skill runs automatically and blocks security vulnerabilities before they reach production.