Files
gh-geoffjay-claude-plugins-…/commands/sinatra-review.md
2025-11-29 18:28:07 +08:00

14 KiB

description
description
Review Sinatra code for security issues, performance problems, route conflicts, and framework best practices

Sinatra Review Command

Performs comprehensive code review of Sinatra applications, identifying security vulnerabilities, performance issues, routing conflicts, and deviations from best practices.

Arguments

  • $1: path (optional) - Path to review (defaults to current directory)

Usage Examples

# Review current directory
/sinatra-review

# Review specific directory
/sinatra-review /path/to/sinatra-app

# Review specific file
/sinatra-review app/controllers/users_controller.rb

Workflow

Step 1: Scan and Identify Application Files

Discovery Phase:

  1. Locate config.ru to identify Rack application
  2. Find Sinatra application files (controllers, routes)
  3. Identify application structure (classic vs modular)
  4. Scan for middleware configuration
  5. Locate view templates and helpers
  6. Find configuration files
  7. Identify database and model files

File Patterns to Search:

# Application files
*.rb files inheriting from Sinatra::Base
config.ru
app.rb (classic style)
app/controllers/*.rb
lib/**/*.rb

# View templates
views/**/*.erb
views/**/*.haml
views/**/*.slim

# Configuration
config/*.rb
Gemfile
.env files

Step 2: Analyze Route Definitions

Route Conflict Detection:

Check for:

  1. Duplicate routes with same path and HTTP method
  2. Overlapping routes where order matters (specific before generic)
  3. Missing route constraints leading to ambiguous matching
  4. Wildcard route conflicts

Examples of Issues:

# ISSUE: Route order conflict
get '/users/new' do
  # Never reached because of wildcard below
end

get '/users/:id' do
  # This catches /users/new
end

# FIX: Specific routes before wildcards
get '/users/new' do
  # Now reached first
end

get '/users/:id' do
  # Only catches other IDs
end

# ISSUE: Duplicate routes
get '/api/users' do
  # First definition
end

get '/api/users' do
  # Overwrites first - only this runs
end

# ISSUE: Missing validation
get '/users/:id' do
  user = User.find(params[:id])  # What if id is not numeric?
end

# FIX: Add validation
get '/users/:id', id: /\d+/ do
  user = User.find(params[:id])
end

Route Analysis Report:

Route Analysis:
  Total routes: 25
  GET: 15, POST: 5, PUT: 3, DELETE: 2

  ⚠ Warnings:
    - Route order issue in app/controllers/users_controller.rb:15
      GET /users/:id should be after GET /users/new

    - Missing parameter validation in app/controllers/posts_controller.rb:32
      Route GET /posts/:id should validate :id is numeric

Step 3: Security Analysis

Security Checklist:

1. CSRF Protection:

# CHECK: Is CSRF protection enabled?
use Rack::Protection
# or
use Rack::Protection::AuthenticityToken

# ISSUE: Missing CSRF for POST/PUT/DELETE
post '/users' do
  User.create(params[:user])  # Vulnerable to CSRF
end

# FIX: Ensure Rack::Protection is enabled

2. XSS Prevention:

# CHECK: Are templates auto-escaping HTML?
# ERB: Use <%= %> (escapes) not <%== %> (raw)

# ISSUE: Raw user input in template
<div><%== @user.bio %></div>

# FIX: Escape user input
<div><%= @user.bio %></div>

# CHECK: JSON responses properly encoded
# ISSUE: Manual JSON creation
get '/api/users' do
  "{ \"name\": \"#{user.name}\" }"  # XSS if name contains quotes
end

# FIX: Use JSON library
get '/api/users' do
  json({ name: user.name })
end

3. SQL Injection:

# ISSUE: String interpolation in queries
DB["SELECT * FROM users WHERE email = '#{params[:email]}'"]

# FIX: Use parameterized queries
DB["SELECT * FROM users WHERE email = ?", params[:email]]

# ISSUE: Unsafe ActiveRecord
User.where("email = '#{params[:email]}'")

# FIX: Use hash conditions
User.where(email: params[:email])

4. Authentication & Authorization:

# CHECK: Protected routes have authentication
# ISSUE: Admin route without auth check
delete '/users/:id' do
  User.find(params[:id]).destroy  # No auth check!
end

# FIX: Add authentication
before '/admin/*' do
  halt 401 unless current_user&.admin?
end

# CHECK: Session security
# ISSUE: Weak session configuration
use Rack::Session::Cookie, secret: 'easy'

# FIX: Strong secret and secure flags
use Rack::Session::Cookie,
  secret: ENV['SESSION_SECRET'],  # Long random string
  same_site: :strict,
  httponly: true,
  secure: production?

5. Mass Assignment:

# ISSUE: Accepting all params
User.create(params)

# FIX: Whitelist allowed attributes
def user_params
  params.slice(:name, :email, :bio)
end

User.create(user_params)

6. File Upload Security:

# ISSUE: Unrestricted file uploads
post '/upload' do
  File.write("uploads/#{params[:file][:filename]}", params[:file][:tempfile].read)
end

# FIX: Validate file type and sanitize filename
post '/upload' do
  file = params[:file]

  # Validate content type
  halt 400 unless ['image/jpeg', 'image/png'].include?(file[:type])

  # Sanitize filename
  filename = File.basename(file[:filename]).gsub(/[^a-zA-Z0-9\._-]/, '')

  # Save with random name
  secure_name = "#{SecureRandom.hex}-#{filename}"
  File.write("uploads/#{secure_name}", file[:tempfile].read)
end

7. Information Disclosure:

# ISSUE: Detailed error messages in production
configure :production do
  set :show_exceptions, true  # Exposes stack traces
end

# FIX: Hide errors in production
configure :production do
  set :show_exceptions, false
  set :dump_errors, false
end

error do
  log_error(env['sinatra.error'])
  json({ error: 'Internal server error' }, 500)
end

Security Report:

Security Analysis:
  ✓ CSRF protection enabled (Rack::Protection)
  ✓ Session configured securely
  ⚠ Potential Issues:
    - SQL injection risk in app/models/user.rb:45
    - Raw HTML output in views/profile.erb:12
    - Missing authentication check in app/controllers/admin_controller.rb:23
    - Weak session secret detected

  Critical: 1
  High: 2
  Medium: 3
  Low: 2

Step 4: Review Middleware Configuration

Middleware Analysis:

Check for:

  1. Missing essential middleware (Protection, CommonLogger)
  2. Incorrect ordering (e.g., session after auth)
  3. Performance issues (e.g., no compression)
  4. Security middleware properly configured

Common Issues:

# ISSUE: Missing compression
# FIX: Add Rack::Deflater
use Rack::Deflater

# ISSUE: Session middleware after authentication
use TokenAuth
use Rack::Session::Cookie  # Session needed by auth!

# FIX: Session before authentication
use Rack::Session::Cookie
use TokenAuth

# ISSUE: No security headers
# FIX: Add Rack::Protection
use Rack::Protection, except: [:session_hijacking]

# ISSUE: Static file serving after application
run MyApp
use Rack::Static  # Never reached!

# FIX: Static before application
use Rack::Static, urls: ['/css', '/js'], root: 'public'
run MyApp

Middleware Report:

Middleware Configuration:
  ✓ Rack::CommonLogger (logging)
  ✓ Rack::Session::Cookie (sessions)
  ✓ Rack::Protection (security)
  ⚠ Warnings:
    - Missing Rack::Deflater (compression)
    - Middleware order issue: Session should be before CustomAuth
    - Consider adding Rack::Attack for rate limiting

Step 5: Performance Assessment

Performance Patterns to Check:

1. Database Query Optimization:

# ISSUE: N+1 queries
get '/users' do
  users = User.all
  users.map { |u| { name: u.name, posts: u.posts.count } }
  # Queries DB for each user's posts
end

# FIX: Eager load or use counter cache
get '/users' do
  users = User.eager(:posts).all
  users.map { |u| { name: u.name, posts: u.posts.count } }
end

# ISSUE: Loading entire collection
get '/users' do
  json User.all.map(&:to_hash)  # Load all users in memory
end

# FIX: Paginate
get '/users' do
  page = params[:page]&.to_i || 1
  per_page = 50

  users = User.limit(per_page).offset((page - 1) * per_page)
  json users.map(&:to_hash)
end

2. Caching Opportunities:

# ISSUE: Expensive operation on every request
get '/stats' do
  json calculate_expensive_stats  # Takes 2 seconds
end

# FIX: Add caching
get '/stats' do
  stats = cache.fetch('stats', expires_in: 300) do
    calculate_expensive_stats
  end
  json stats
end

# ISSUE: No HTTP caching headers
get '/public/data' do
  json PublicData.all
end

# FIX: Add cache control
get '/public/data' do
  cache_control :public, max_age: 3600
  json PublicData.all
end

3. Response Optimization:

# ISSUE: Rendering large response synchronously
get '/large-export' do
  csv = generate_large_csv  # Blocks for 30 seconds
  send_file csv
end

# FIX: Stream or queue as background job
get '/large-export' do
  stream do |out|
    CSV.generate(out) do |csv|
      User.find_each do |user|
        csv << user.to_csv_row
      end
    end
  end
end

Performance Report:

Performance Analysis:
  ⚠ Issues Detected:
    - Potential N+1 query in app/controllers/users_controller.rb:42
    - Missing pagination in GET /api/posts (returns all records)
    - No caching headers on GET /api/public/data
    - Expensive operation in GET /stats without caching

  Recommendations:
    - Add database query optimization (eager loading)
    - Implement pagination for collection endpoints
    - Add HTTP caching headers for static content
    - Consider Redis caching for expensive operations

Step 6: Error Handling Review

Error Handling Patterns:

# ISSUE: No error handlers defined
get '/users/:id' do
  User.find(params[:id])  # Raises if not found, shows stack trace
end

# FIX: Add error handlers
error ActiveRecord::RecordNotFound do
  json({ error: 'Not found' }, 404)
end

error 404 do
  json({ error: 'Endpoint not found' }, 404)
end

error 500 do
  json({ error: 'Internal server error' }, 500)
end

# ISSUE: Not handling exceptions in routes
post '/users' do
  User.create!(params)  # Raises on validation error
end

# FIX: Handle exceptions
post '/users' do
  user = User.create(params)
  if user.persisted?
    json(user.to_hash, 201)
  else
    json({ errors: user.errors }, 422)
  end
end

Step 7: Testing Coverage

Test Analysis:

Check for:

  1. Test files exist
  2. Route coverage
  3. Error case testing
  4. Integration vs unit tests
  5. Test quality and patterns

Report:

Testing Analysis:
  Framework: RSpec
  Total specs: 45
  Coverage: 78%

  ⚠ Missing Tests:
    - No tests for POST /api/users
    - Error cases not tested in app/controllers/posts_controller.rb
    - Missing integration tests for authentication flow

  Recommendations:
    - Add tests for all POST/PUT/DELETE routes
    - Test error scenarios (404, 422, 500)
    - Increase coverage to 90%+

Step 8: Generate Comprehensive Report

Final Report Structure:

================================================================================
SINATRA CODE REVIEW REPORT
================================================================================

Project: my-sinatra-app
Path: /path/to/app
Date: 2024-01-15
Reviewer: Sinatra Review Tool

--------------------------------------------------------------------------------
SUMMARY
--------------------------------------------------------------------------------
  Total Issues: 15
    Critical: 2
    High: 4
    Medium: 6
    Low: 3

  Categories:
    Security: 5 issues
    Performance: 4 issues
    Best Practices: 6 issues

--------------------------------------------------------------------------------
CRITICAL ISSUES
--------------------------------------------------------------------------------

1. SQL Injection Vulnerability
   Location: app/models/user.rb:45
   Severity: Critical

   Issue:
     DB["SELECT * FROM users WHERE email = '#{email}'"]

   Fix:
     DB["SELECT * FROM users WHERE email = ?", email]

   Impact: Attacker can execute arbitrary SQL queries

2. Missing Authentication on Admin Route
   Location: app/controllers/admin_controller.rb:23
   Severity: Critical

   Issue:
     delete '/users/:id' do
       User.find(params[:id]).destroy
     end

   Fix:
     before '/admin/*' do
       authenticate_admin!
     end

   Impact: Unauthorized users can delete records

--------------------------------------------------------------------------------
HIGH PRIORITY ISSUES
--------------------------------------------------------------------------------

[List high priority issues...]

--------------------------------------------------------------------------------
RECOMMENDATIONS
--------------------------------------------------------------------------------

Security:
  - Enable Rack::Protection::AuthenticityToken for CSRF
  - Rotate session secret to strong random value
  - Implement rate limiting with Rack::Attack
  - Add Content-Security-Policy headers

Performance:
  - Add Rack::Deflater for response compression
  - Implement caching strategy (Redis or Memcached)
  - Add pagination to collection endpoints
  - Optimize database queries (N+1 issues)

Testing:
  - Increase test coverage to 90%+
  - Add integration tests for critical flows
  - Test error scenarios
  - Add security-focused tests

Best Practices:
  - Extract business logic to service objects
  - Use helpers for repeated code
  - Implement proper error handling
  - Add API documentation

--------------------------------------------------------------------------------
DETAILED FINDINGS
--------------------------------------------------------------------------------

[Full list of all issues with locations, descriptions, and fixes]

================================================================================
END REPORT
================================================================================

Review Categories

Security

  • CSRF protection
  • XSS prevention
  • SQL injection
  • Authentication/Authorization
  • Session security
  • Mass assignment
  • File upload security
  • Information disclosure
  • Secure headers

Performance

  • Database query optimization
  • N+1 queries
  • Caching opportunities
  • Response optimization
  • Static asset handling
  • Connection pooling

Best Practices

  • Route organization
  • Error handling
  • Code organization
  • Helper usage
  • Configuration management
  • Logging
  • Documentation

Testing

  • Test coverage
  • Test quality
  • Missing tests
  • Test organization

Output Format

  • Console output with colored severity indicators
  • Detailed report with file locations and line numbers
  • Suggested fixes with code examples
  • Priority-sorted issue list
  • Summary statistics

Error Handling

  • Handle non-Sinatra Ruby applications gracefully
  • Report when application structure cannot be determined
  • Skip non-readable files
  • Handle parse errors in Ruby files