スキル一覧に戻る
GangWooLee

security-audit

by GangWooLee

0🍴 0📅 2026年1月25日
GitHubで見るManusで実行

SKILL.md


name: security-audit description: Security vulnerability scanning and audit. Use when user needs security check, dependency updates, vulnerability scan, or says "check security", "audit code", "security vulnerabilities", "update gems", "CVE check".

Security Audit

보안 취약점 스캔, 의존성 검사, 환경 변수 관리 등 애플리케이션 보안 감사를 수행합니다.

Quick Start

Task Progress (copy and check off):
- [ ] 1. Run security scan
- [ ] 2. Review vulnerabilities
- [ ] 3. Update dependencies
- [ ] 4. Fix security issues
- [ ] 5. Re-scan to verify

Security Tools

1. Brakeman (Static Analysis)

Rails 보안 취약점을 자동으로 감지합니다.

Installation:

# Gemfile
group :development do
  gem 'brakeman', require: false
end

Usage:

# Run security scan
bundle exec brakeman

# Output to file
bundle exec brakeman -o brakeman_report.html

# Quiet mode (only show warnings)
bundle exec brakeman -q

# Check specific files
bundle exec brakeman app/controllers/

Common Vulnerabilities Detected:

  • SQL Injection
  • Cross-Site Scripting (XSS)
  • Cross-Site Request Forgery (CSRF)
  • Mass Assignment
  • Command Injection
  • Unsafe Redirects

2. Bundler Audit (Dependency Vulnerabilities)

Gem 의존성의 알려진 취약점을 검사합니다.

Installation:

# Gemfile
group :development do
  gem 'bundler-audit', require: false
end

Usage:

# Update vulnerability database
bundle exec bundler-audit update

# Check for vulnerabilities
bundle exec bundler-audit check

# Auto-update vulnerable gems (use with caution)
bundle exec bundler-audit check --update

Fix Vulnerabilities:

# Update specific gem
bundle update gem_name

# Update all gems (risky)
bundle update

3. Rails Security Checklist

Authentication & Authorization:

# ✅ Use has_secure_password
class User < ApplicationRecord
  has_secure_password
  validates :password, length: { minimum: 8 }
end

# ✅ Use before_action for authorization
class PostsController < ApplicationController
  before_action :require_login
  before_action :authorize_user, only: [:edit, :update, :destroy]

  private

  def authorize_user
    @post = Post.find(params[:id])
    redirect_to root_path unless @post.user == current_user
  end
end

SQL Injection Prevention:

# ❌ Vulnerable to SQL injection
User.where("email = '#{params[:email]}'")

# ✅ Use parameterized queries
User.where("email = ?", params[:email])
User.where(email: params[:email])

XSS Prevention:

<%# ❌ Vulnerable to XSS %>
<%= raw @post.content %>
<%= @post.content.html_safe %>

<%# ✅ Safe (auto-escaped) %>
<%= @post.content %>

<%# ✅ If HTML is needed, sanitize %>
<%= sanitize @post.content, tags: %w[p br strong em] %>

CSRF Protection:

# ApplicationController (enabled by default)
class ApplicationController < ActionController::Base
  protect_from_forgery with: :exception
end

# For API controllers, use null_session
class Api::V1::BaseController < ApplicationController
  protect_from_forgery with: :null_session
end

Mass Assignment Protection:

# ✅ Use strong parameters
class UsersController < ApplicationController
  def create
    @user = User.new(user_params)
    # ...
  end

  private

  def user_params
    params.require(:user).permit(:email, :name, :password)
    # Never permit :admin, :role without authorization check
  end
end

4. Environment Variables Security

Never commit secrets:

# ❌ Never do this
class ApiClient
  API_KEY = "sk_live_123456789"  # Hard-coded secret!
end

# ✅ Use environment variables
class ApiClient
  API_KEY = ENV['API_KEY']
end

Use Rails credentials (Rails 5.2+):

# Edit credentials
EDITOR=nano rails credentials:edit

# Access in code
Rails.application.credentials.api_key
Rails.application.credentials.dig(:aws, :access_key_id)

Check for exposed secrets:

# .gitignore should include:
/.env
/config/master.key
/config/credentials/*.key

5. Session Security

Secure session configuration:

# config/initializers/session_store.rb
Rails.application.config.session_store :cookie_store,
  key: '_app_session',
  secure: Rails.env.production?,  # HTTPS only in production
  httponly: true,                 # Not accessible via JavaScript
  same_site: :lax                 # CSRF protection

Session timeout:

# app/controllers/application_controller.rb
before_action :check_session_timeout

private

def check_session_timeout
  if session[:last_seen_at] && session[:last_seen_at] < 30.minutes.ago
    reset_session
    redirect_to login_path, alert: "Session expired"
  end
  session[:last_seen_at] = Time.current
end

6. File Upload Security

Validate file types:

class User < ApplicationRecord
  has_one_attached :avatar

  validate :acceptable_avatar

  private

  def acceptable_avatar
    return unless avatar.attached?

    unless avatar.content_type.in?(%w[image/jpeg image/png image/gif])
      errors.add(:avatar, "must be a JPEG, PNG, or GIF")
    end

    if avatar.byte_size > 5.megabytes
      errors.add(:avatar, "is too large (max 5MB)")
    end
  end
end

Secure file storage:

# config/storage.yml
production:
  service: S3
  access_key_id: <%= Rails.application.credentials.dig(:aws, :access_key_id) %>
  secret_access_key: <%= Rails.application.credentials.dig(:aws, :secret_access_key) %>
  region: us-east-1
  bucket: your-bucket-name
  public: false  # Important: Files not publicly accessible

7. Rate Limiting

Using Rack Attack (recommended):

# Gemfile
gem 'rack-attack'

# config/initializers/rack_attack.rb
Rack::Attack.throttle("requests by ip", limit: 300, period: 5.minutes) do |req|
  req.ip
end

Rack::Attack.throttle("logins/ip", limit: 5, period: 20.seconds) do |req|
  req.ip if req.path == '/login' && req.post?
end

# Block bad actors
Rack::Attack.blocklist("block bad IPs") do |req|
  # Check against your blocklist
  Redis.current.sismember("blocked_ips", req.ip)
end

8. Database Security

Use database-level constraints:

# Migration
def change
  add_index :users, :email, unique: true  # Prevent duplicates
  add_foreign_key :posts, :users         # Referential integrity

  # NOT NULL constraints
  change_column_null :users, :email, false
end

Encrypted attributes (for sensitive data):

# Gemfile
gem 'attr_encrypted'

# Model
class User < ApplicationRecord
  attr_encrypted :ssn,
    key: Rails.application.credentials.encryption_key,
    algorithm: 'aes-256-gcm'
end

9. Headers Security

Security headers (use gem):

# Gemfile
gem 'secure_headers'

# config/initializers/secure_headers.rb
SecureHeaders::Configuration.default do |config|
  config.x_frame_options = "DENY"
  config.x_content_type_options = "nosniff"
  config.x_xss_protection = "1; mode=block"
  config.referrer_policy = "strict-origin-when-cross-origin"

  config.csp = {
    default_src: %w['self'],
    script_src: %w['self' 'unsafe-inline'],
    style_src: %w['self' 'unsafe-inline'],
    img_src: %w['self' data: https:],
    font_src: %w['self' data:]
  }
end

10. Logging & Monitoring

Never log sensitive data:

# config/initializers/filter_parameter_logging.rb
Rails.application.config.filter_parameters += [
  :password,
  :password_confirmation,
  :credit_card,
  :ssn,
  :api_key,
  :token
]

Monitor failed login attempts:

# app/controllers/sessions_controller.rb
def create
  user = User.find_by(email: params[:email])

  if user&.authenticate(params[:password])
    session[:user_id] = user.id
    redirect_to root_path
  else
    # Log failed attempt
    Rails.logger.warn "Failed login attempt for #{params[:email]} from #{request.remote_ip}"
    flash.now[:alert] = "Invalid credentials"
    render :new
  end
end

Automation Script

Security Audit Runner

# Run via: ruby .claude/skills/security-audit/scripts/security_audit.rb

The script runs:

  1. Brakeman security scan
  2. Bundler-audit dependency check
  3. Environment variables check
  4. Credentials security check
  5. Security headers verification

Common Vulnerabilities & Fixes

1. Weak Passwords

Problem: Short or simple passwords

Fix:

class User < ApplicationRecord
  has_secure_password

  validates :password,
    length: { minimum: 12 },
    format: {
      with: /\A(?=.*[a-z])(?=.*[A-Z])(?=.*\d)/,
      message: "must include uppercase, lowercase, and number"
    },
    if: :password_digest_changed?
end

2. Insecure Direct Object Reference (IDOR)

Problem: Users can access other users' data

Fix:

# ❌ Vulnerable
def show
  @post = Post.find(params[:id])  # Any post!
end

# ✅ Scope to current user
def show
  @post = current_user.posts.find(params[:id])
end

3. Missing Authorization

Problem: No permission checks

Fix:

# Use Pundit or CanCanCan
class PostPolicy < ApplicationPolicy
  def update?
    user == record.user || user.admin?
  end
end

# In controller
authorize @post

4. Timing Attack on Authentication

Problem: Different response times leak information

Fix:

# Use secure_compare for password/token comparison
def valid_token?(provided_token)
  ActiveSupport::SecurityUtils.secure_compare(
    provided_token,
    expected_token
  )
end

Security Best Practices

  1. Keep Rails and gems updated

    bundle update --conservative rails
    
  2. Run security audits regularly

    bundle exec brakeman
    bundle exec bundler-audit check
    
  3. Use HTTPS in production (force SSL)

    # config/environments/production.rb
    config.force_ssl = true
    
  4. Implement proper authentication

    • Use Devise or has_secure_password
    • Multi-factor authentication for sensitive operations
    • Password strength requirements
  5. Authorization on every action

    • Never trust user input
    • Always scope queries to current user
    • Use authorization gems (Pundit, CanCanCan)
  6. Secure file uploads

    • Validate file types and sizes
    • Scan for malware (ClamAV)
    • Store in secure location (S3 private buckets)
  7. API Security

    • Use authentication tokens
    • Rate limiting
    • CORS configuration
    • API versioning
  8. Regular backups

    • Automated database backups
    • Encrypted backup storage
    • Tested restore procedures

CI/CD Integration

Add security checks to your CI pipeline:

# .github/workflows/security.yml
name: Security Audit

on: [push, pull_request]

jobs:
  security:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v3
      - uses: ruby/setup-ruby@v1
        with:
          bundler-cache: true
      - name: Run Brakeman
        run: bundle exec brakeman --no-pager
      - name: Run Bundler Audit
        run: |
          bundle exec bundler-audit update
          bundle exec bundler-audit check

Checklist

  • Brakeman scan passed
  • No vulnerable dependencies (bundler-audit)
  • Secrets not in version control
  • Strong parameters used everywhere
  • SQL injection protected (parameterized queries)
  • XSS protected (proper escaping)
  • CSRF protection enabled
  • Proper authorization on all actions
  • File uploads validated
  • Rate limiting configured
  • Security headers set
  • HTTPS enforced in production
  • Sensitive data filtered from logs
  • Regular security audits scheduled

スコア

総合スコア

50/100

リポジトリの品質指標に基づく評価

SKILL.md

SKILL.mdファイルが含まれている

+20
LICENSE

ライセンスが設定されている

0/10
説明文

100文字以上の説明がある

0/10
人気

GitHub Stars 100以上

0/15
最近の活動

3ヶ月以内に更新がある

0/10
フォーク

10回以上フォークされている

0/5
Issue管理

オープンIssueが50未満

+5
言語

プログラミング言語が設定されている

+5
タグ

1つ以上のタグが設定されている

0/5

レビュー

💬

レビュー機能は近日公開予定です