Automatically validates security best practices and prevents vulnerabilities
Validates Rails security best practices and prevents vulnerabilities in controllers and models.
/plugin marketplace add nbarthel/claudy/plugin install rails-workflow@claudyThis skill inherits all available tools. When active, it can use any tool Claude has access to.
Auto-validates security best practices and blocks common vulnerabilities.
Automatic Security Checks:
When It Activates:
Checks:
create and update action uses strong parametersparams usage in model instantiationpermit calls include only expected attributesExample Violation:
# 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:
❌ 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)
Checks:
where clausesExample Violation:
# 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:
❌ 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)
Checks:
Example:
# app/controllers/posts_controller.rb
class PostsController < ApplicationController
before_action :authenticate_user! # ✅ Auth required
def index
# ...
end
end
Skill Output (if missing):
⚠️ 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!
Checks:
Example:
# 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:
⚠️ 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
Checks:
Example Violation:
# BAD
API_KEY = "sk_live_abc123..." # ❌ Hardcoded secret
# GOOD
API_KEY = ENV['STRIPE_API_KEY'] # ✅ Environment variable
Skill Output:
❌ 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
This skill works with the pre-commit hook to block unsafe commits:
Automatic blocks:
Warnings (allow commit):
Create .rails-security.yml to customize:
# .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
Token-based:
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
Pattern:
# Always scope to current_user when possible
@posts = current_user.posts
@post = current_user.posts.find(params[:id])
# Prevents accessing other users' resources
Recommendation:
# 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
This skill runs automatically and blocks security vulnerabilities before they reach production.
This skill should be used when the user asks to "create an agent", "add an agent", "write a subagent", "agent frontmatter", "when to use description", "agent examples", "agent tools", "agent colors", "autonomous agent", or needs guidance on agent structure, system prompts, triggering conditions, or agent development best practices for Claude Code plugins.
This skill should be used when the user asks to "create a slash command", "add a command", "write a custom command", "define command arguments", "use command frontmatter", "organize commands", "create command with file references", "interactive command", "use AskUserQuestion in command", or needs guidance on slash command structure, YAML frontmatter fields, dynamic arguments, bash execution in commands, user interaction patterns, or command development best practices for Claude Code.
This skill should be used when the user asks to "create a hook", "add a PreToolUse/PostToolUse/Stop hook", "validate tool use", "implement prompt-based hooks", "use ${CLAUDE_PLUGIN_ROOT}", "set up event-driven automation", "block dangerous commands", or mentions hook events (PreToolUse, PostToolUse, Stop, SubagentStop, SessionStart, SessionEnd, UserPromptSubmit, PreCompact, Notification). Provides comprehensive guidance for creating and implementing Claude Code plugin hooks with focus on advanced prompt-based hooks API.