CrackedRuby CrackedRuby

Overview

Static code analysis examines source code without executing the program to identify potential defects, security vulnerabilities, code smells, and violations of coding standards. The analysis operates on the abstract syntax tree (AST) or intermediate representations of code, applying pattern matching, data flow analysis, and control flow analysis to detect issues that might escape runtime testing.

The practice emerged in the 1970s with tools like Lint for C, which found suspicious code constructs that compilers would accept but likely contained errors. Modern static analysis tools have expanded beyond simple pattern matching to include sophisticated techniques like taint analysis for security vulnerabilities, symbolic execution for logic errors, and machine learning-based anomaly detection.

Static analysis differs from dynamic analysis (testing) in that it examines all possible code paths without executing the program. This characteristic makes it particularly effective for finding issues in rarely-executed error handling code, security vulnerabilities in edge cases, and inconsistencies across large codebases. The analysis occurs at various stages: during editing (IDE integration), before commits (pre-commit hooks), during code review (pull request checks), or as part of continuous integration pipelines.

# Code that static analysis can check without execution
def transfer_funds(from_account, to_account, amount)
  # Detects: Unused variable 'transaction_id'
  transaction_id = generate_id
  
  # Detects: Potential nil reference if 'from_account' is nil
  from_account.balance -= amount
  
  # Detects: SQL injection vulnerability
  execute("SELECT * FROM accounts WHERE id = #{to_account.id}")
end

The analysis provides immediate feedback during development rather than waiting for runtime failures or security incidents. This shift-left approach to quality assurance reduces the cost of fixing defects by catching them early in the development cycle.

Key Principles

Static analysis operates through several fundamental mechanisms that examine code structure, semantics, and patterns. The analysis begins with parsing source code into an abstract syntax tree, which represents the syntactic structure of the program in a tree format where each node denotes a language construct. This AST becomes the foundation for all subsequent analysis passes.

Lexical Analysis examines individual tokens and patterns in the source code without understanding program semantics. This level detects formatting inconsistencies, naming convention violations, and suspicious patterns like duplicated code or commented-out sections. Lexical analysis requires no understanding of program flow or data relationships.

Syntax Analysis verifies that code conforms to language grammar rules and coding standards. This analysis identifies deprecated APIs, incorrect method signatures, missing error handling, and violations of established style guides. The analysis operates on the structure of code rather than its runtime behavior.

Data Flow Analysis tracks how data moves through the program by examining assignments, method calls, and variable usage patterns. The analyzer builds a graph representing possible data transformations and identifies issues like uninitialized variables, unused assignments, potential null pointer dereferences, and information leakage through insecure data channels. Control flow analysis works in tandem by examining the order of statement execution, identifying unreachable code, infinite loops, missing return statements, and complex conditional logic.

Type Analysis examines type compatibility and conversions, detecting type mismatches that might cause runtime errors, unsafe type casting, and implicit conversions that could lose precision or introduce bugs. Ruby's dynamic nature requires static analyzers to infer types through pattern analysis and method signatures rather than explicit declarations.

Taint Analysis tracks potentially malicious or untrusted data as it flows through the application. The analyzer marks data from untrusted sources (user input, external APIs, file systems) as "tainted" and traces its propagation through the codebase. When tainted data reaches a sensitive operation (database query, system command, template rendering) without proper sanitization, the analyzer flags a potential security vulnerability.

# Taint analysis example
def search_users(query)
  # 'query' is marked as tainted (user input)
  sanitized = sanitize_sql(query)  # Removes taint
  
  # Safe: uses sanitized data
  User.where("name LIKE ?", sanitized)
  
  # Unsafe: uses tainted data directly
  User.where("name LIKE '#{query}'")  # Analyzer flags this
end

Pattern Matching identifies known problematic code constructs by comparing code against a database of anti-patterns, security vulnerabilities, and bug patterns. This includes detection of SQL injection patterns, cross-site scripting vulnerabilities, race conditions, resource leaks, and common programming mistakes specific to the language or framework.

The analysis produces findings with severity classifications (error, warning, information), precise source locations, descriptions of the issue, and often suggested fixes. False positives occur when the analyzer flags correct code as problematic, typically due to limitations in understanding complex program semantics or intentional use of advanced language features. False negatives occur when the analyzer misses actual defects, usually in dynamically-evaluated code or patterns not covered by the analyzer's rules.

Ruby Implementation

Ruby static analysis tools operate by parsing Ruby source code into an AST using the parser gem or Ruby's built-in Ripper library. The tools then apply various checks against this AST, examining node patterns, method calls, variable usage, and code structure.

RuboCop serves as the primary static analyzer for Ruby code, enforcing both syntactic rules and semantic patterns. The tool operates through a cop-based architecture where each cop (checker) examines specific aspects of code. Cops can auto-correct violations, generate offense reports, and integrate with editors and CI systems.

# .rubocop.yml configuration
AllCops:
  NewCops: enable
  TargetRubyVersion: 3.2

Style/StringLiterals:
  EnforcedStyle: double_quotes

Metrics/MethodLength:
  Max: 20
  Exclude:
    - 'db/migrate/*'

Naming/VariableName:
  EnforcedStyle: snake_case

The tool provides extensive configuration options for enabling, disabling, or modifying cop behavior. Custom cops can be created to enforce organization-specific rules:

# Custom cop for enforcing service object naming
module CustomCops
  class ServiceObjectNaming < RuboCop::Cop::Base
    MSG = "Service objects must end with 'Service'"
    
    def on_class(node)
      class_name = node.identifier.source
      return if class_name.end_with?('Service')
      return unless inherits_from_base_service?(node)
      
      add_offense(node.identifier)
    end
    
    private
    
    def inherits_from_base_service?(node)
      return false unless node.parent_class
      
      node.parent_class.source == 'BaseService'
    end
  end
end

Reek focuses specifically on code smells, detecting issues like long parameter lists, complex conditionals, duplicate code, and poor abstraction. Unlike RuboCop's focus on style and correctness, Reek examines design quality:

# Reek detects code smells
class UserProcessor
  # Smell: Too many instance variables
  def initialize(user, validator, notifier, logger, cache)
    @user = user
    @validator = validator
    @notifier = notifier
    @logger = logger
    @cache = cache
  end
  
  # Smell: Long method
  # Smell: Feature envy (using methods from user extensively)
  def process
    return false unless @validator.valid?(@user)
    
    @user.status = 'active'
    @user.processed_at = Time.now
    @user.save!
    
    @notifier.send_welcome(@user)
    @logger.info("Processed user #{@user.id}")
    @cache.delete("pending_users")
    
    true
  end
end

Brakeman specializes in security analysis for Rails applications, detecting vulnerabilities like SQL injection, cross-site scripting, command injection, and insecure configurations:

# Brakeman detects security issues
class ArticlesController < ApplicationController
  def search
    # SQL injection vulnerability
    @articles = Article.where("title LIKE '%#{params[:query]}%'")
    
    # Cross-site scripting vulnerability
    @message = params[:message].html_safe
    
    # Mass assignment vulnerability
    @user = User.new(params[:user])
  end
  
  def secure_search
    # Safe parameterized query
    @articles = Article.where("title LIKE ?", "%#{params[:query]}%")
    
    # Escaped output
    @message = sanitize(params[:message])
    
    # Strong parameters
    @user = User.new(user_params)
  end
  
  private
  
  def user_params
    params.require(:user).permit(:name, :email)
  end
end

Ruby-specific analysis must account for metaprogramming, dynamic method definitions, and runtime code evaluation. Analyzers use heuristics and pattern matching to handle these dynamic features:

# Challenges for static analysis
class DynamicModel
  # Dynamic method definition
  [:name, :email, :phone].each do |attr|
    define_method(attr) do
      instance_variable_get("@#{attr}")
    end
    
    define_method("#{attr}=") do |value|
      instance_variable_set("@#{attr}", value)
    end
  end
  
  # Runtime code evaluation
  def execute_code(code)
    eval(code)  # Analyzer flags security risk
  end
  
  # send usage can bypass access control
  def invoke_method(method_name)
    send(method_name)  # Analyzer may warn about dynamic dispatch
  end
end

Implementation Approaches

Static analysis integrates into development workflows at multiple points, each offering different trade-offs between feedback speed, thoroughness, and developer disruption.

IDE Integration provides real-time feedback as developers write code. Modern editors like RubyMine, VS Code with Ruby LSP, and Vim with ALE display static analysis warnings inline with syntax highlighting. This immediate feedback loop catches issues at the earliest possible moment:

# VS Code settings.json for Ruby analysis
{
  "ruby.lint": {
    "rubocop": true,
    "reek": true
  },
  "ruby.format": "rubocop",
  "editor.formatOnSave": true,
  "ruby.intellisense": "rubyLocate"
}

The approach minimizes context switching since developers see issues without leaving their editor. However, IDE integration typically runs lighter analysis to maintain editor responsiveness, potentially missing deeper issues that require more computation time.

Pre-commit Hooks run analysis before changes enter version control. Git hooks execute static analysis tools and block commits that contain violations, ensuring only clean code reaches the repository:

# .git/hooks/pre-commit
#!/usr/bin/env ruby

# Get list of Ruby files changed in this commit
changed_files = `git diff --cached --name-only --diff-filter=ACM`
  .split("\n")
  .select { |file| file.end_with?('.rb') }

exit 0 if changed_files.empty?

puts "Running static analysis on changed files..."

# Run RuboCop on changed files
system("bundle exec rubocop #{changed_files.join(' ')}")
rubocop_result = $?.exitstatus

# Run Reek on changed files
system("bundle exec reek #{changed_files.join(' ')}")
reek_result = $?.exitstatus

# Exit with failure if any analyzer failed
exit 1 if rubocop_result != 0 || reek_result != 0

Pre-commit analysis prevents problematic code from entering the repository but can slow down the commit process. Developers may disable hooks when rushing, bypassing the safety mechanism. Tools like Overcommit provide a framework for managing Git hooks with better developer experience.

Pull Request Analysis runs comprehensive checks on proposed changes before merging. CI systems execute full analysis suites, post results as PR comments, and block merges based on quality gates:

# .github/workflows/static_analysis.yml
name: Static Analysis
on: [pull_request]

jobs:
  analyze:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v2
      - uses: ruby/setup-ruby@v1
        with:
          ruby-version: 3.2
          bundler-cache: true
      
      - name: Run RuboCop
        run: bundle exec rubocop --format json --out rubocop-results.json
      
      - name: Run Brakeman
        run: bundle exec brakeman -o brakeman-results.json --no-pager
      
      - name: Run Reek
        run: bundle exec reek --format json > reek-results.json
      
      - name: Upload results
        uses: github/codeql-action/upload-sarif@v2
        with:
          sarif_file: combined-results.sarif

This approach provides thorough analysis without disrupting individual developer workflows. The analysis runs in parallel with human code review, catching issues before they reach production. PR-based analysis allows for stricter rules than pre-commit hooks since failures don't interrupt local development.

Continuous Monitoring tracks code quality metrics over time, identifying trends and hotspots. Tools like Code Climate, SonarQube, and Coveralls aggregate analysis results across commits and branches:

# config/quality_gates.yml
maintainability:
  threshold: 'B'
  block_on_failure: true

security:
  max_vulnerabilities:
    critical: 0
    high: 2
    medium: 10

coverage:
  minimum: 85
  allow_coverage_decrease: false

complexity:
  max_method_complexity: 10
  max_class_complexity: 50

Continuous monitoring provides visibility into code quality evolution and helps teams prioritize technical debt. Historical data reveals which areas of the codebase accumulate issues most frequently, guiding refactoring efforts.

Incremental Analysis examines only changed code rather than the entire codebase, reducing analysis time for large projects. This approach requires careful cache management to ensure accuracy:

# Rakefile for incremental analysis
namespace :analyze do
  desc 'Run analysis on changed files since main branch'
  task :incremental do
    # Find files changed compared to main branch
    changed_files = `git diff --name-only origin/main...HEAD`
      .split("\n")
      .select { |f| f.end_with?('.rb') }
    
    if changed_files.any?
      puts "Analyzing #{changed_files.size} changed files..."
      system("rubocop #{changed_files.join(' ')}")
    else
      puts "No Ruby files changed"
    end
  end
end

Tools & Ecosystem

The Ruby ecosystem provides specialized static analysis tools targeting different aspects of code quality, security, and maintainability.

RuboCop serves as the most comprehensive style and quality checker for Ruby. The tool includes over 400 cops organized into departments (Style, Layout, Lint, Metrics, Naming, Security). Extensions add framework-specific rules:

Extension Purpose Key Features
rubocop-rails Rails conventions ActiveRecord patterns, controller checks, view helpers
rubocop-rspec RSpec best practices Spec organization, expectation styles, test structure
rubocop-performance Performance optimization N+1 queries, inefficient iterations, object allocations
rubocop-thread_safety Concurrency safety Thread-unsafe operations, race conditions, shared state

RuboCop's auto-correction capability fixes many violations automatically, though complex issues require manual intervention. The tool supports multiple output formats (JSON, JUnit, HTML) for integration with various CI systems and reporting tools.

Reek identifies code smells through heuristic analysis. The tool detects design issues that don't violate syntax rules but indicate potential maintenance problems:

Smell Category Detection Impact
Uncommunicative Name Short or unclear identifiers Reduced readability
Long Parameter List Methods with 4+ parameters High coupling, testing difficulty
Data Clump Same parameters appearing together Missing abstraction
Feature Envy Methods using another class extensively Misplaced responsibility
Utility Function Public methods not using instance state Poor encapsulation

Reek operates with lower precision than RuboCop, producing more false positives since code smell detection involves subjective judgment about design quality.

Brakeman specializes in security vulnerability detection for Rails applications. The scanner identifies common web application security issues without requiring a running application:

# Running Brakeman with options
bundle exec brakeman \
  --confidence-level 2 \
  --ignore-config config/brakeman.ignore \
  --output brakeman-report.html \
  --no-exit-on-warn

Brakeman detects vulnerabilities including SQL injection, cross-site scripting, command injection, unsafe redirects, mass assignment, and insecure dependencies. The tool produces confidence ratings (high, medium, low) for each finding based on analysis certainty.

Bundler Audit scans Gemfile.lock against a database of known vulnerable gem versions. The tool integrates into CI pipelines to catch security vulnerabilities in dependencies:

# Running bundle-audit
bundle audit check --update  # Update vulnerability database
bundle audit check --ignore CVE-2024-1234  # Ignore specific CVE

Fasterer suggests performance improvements by detecting inefficient Ruby patterns and suggesting faster alternatives:

# Fasterer detects performance issues
array.shuffle.first  # Suggests: array.sample
array.select { |e| condition }.size  # Suggests: array.count { |e| condition }
hash.keys.each { |k| process(hash[k]) }  # Suggests: hash.each { |k, v| process(v) }

Debride finds unused methods through static analysis of method definitions and calls. The tool helps identify dead code that can be safely removed:

# debride output
path/to/file.rb:
  unused_method_1  # Defined but never called
  unused_method_2  # Defined but never called

Integration frameworks like Pronto aggregate results from multiple analyzers and present them as unified code review comments on pull requests. This centralized approach reduces noise by deduplicating findings and provides a single interface for multiple analysis tools.

Security Implications

Static analysis identifies security vulnerabilities before code execution, catching issues that testing might miss. Security-focused analysis examines how untrusted data flows through applications, detecting patterns that enable attacks.

SQL Injection Detection identifies database queries constructed through string interpolation rather than parameterized statements. Analyzers trace user input from controllers or API endpoints to database queries, flagging any path where tainted data enters a query without proper escaping:

# Insecure patterns detected by analysis
class UserController
  def search
    # Direct interpolation - High severity
    query = "SELECT * FROM users WHERE name = '#{params[:name]}'"
    
    # String concatenation - High severity
    query = "SELECT * FROM users WHERE " + build_where_clause(params)
    
    # Conditional query building - Medium severity
    User.where("status = '#{params[:status]}'") if params[:status]
  end
  
  def secure_search
    # Parameterized query - Safe
    User.where("name = ?", params[:name])
    
    # Hash conditions - Safe
    User.where(name: params[:name])
    
    # Arel - Safe
    User.where(User.arel_table[:name].eq(params[:name]))
  end
end

Cross-Site Scripting (XSS) Prevention detects unsafe rendering of user-provided content. Analyzers flag calls to html_safe, raw, or render with user input without proper sanitization:

# XSS vulnerabilities detected
class CommentsController
  def show
    # Unsafe: marks user input as safe HTML
    @comment_text = params[:comment].html_safe
    
    # Unsafe: raw bypasses escaping
    @formatted = raw(markdown_to_html(params[:content]))
    
    # Unsafe: dynamic rendering with user input
    render inline: params[:template]
  end
  
  def secure_show
    # Safe: automatically escaped by default
    @comment_text = params[:comment]
    
    # Safe: sanitize removes dangerous HTML
    @formatted = sanitize(markdown_to_html(params[:content]))
    
    # Safe: render predefined template
    render :show
  end
end

Command Injection Detection identifies system calls constructed from user input. Analyzers flag uses of system, backticks, exec, and open with tainted data:

# Command injection vulnerabilities
def process_file(filename)
  # Unsafe: shell interpolation
  system("convert #{filename} output.pdf")
  
  # Unsafe: backtick execution
  result = `cat #{filename}`
  
  # Unsafe: pipe open
  IO.popen("process_data #{params[:input]}")
end

def secure_process_file(filename)
  # Safe: array form avoids shell interpolation
  system("convert", filename, "output.pdf")
  
  # Safe: explicit array
  result = IO.popen(["cat", filename]).read
  
  # Safe: input validation
  raise ArgumentError unless filename.match?(/\A[\w.-]+\z/)
  system("convert #{filename} output.pdf")
end

Path Traversal Prevention detects file operations using unsanitized user input that could access files outside intended directories:

# Path traversal vulnerabilities
def download_file
  # Unsafe: allows ../../../etc/passwd
  send_file("/uploads/#{params[:filename]}")
  
  # Unsafe: join doesn't prevent traversal
  path = File.join("/uploads", params[:path])
  send_file(path)
end

def secure_download_file
  # Safe: validates against whitelist
  allowed_files = ["document.pdf", "image.png"]
  raise SecurityError unless allowed_files.include?(params[:filename])
  send_file("/uploads/#{params[:filename]}")
  
  # Safe: expand_path and check prefix
  base = File.expand_path("/uploads")
  path = File.expand_path(File.join(base, params[:filename]))
  raise SecurityError unless path.start_with?(base)
  send_file(path)
end

Mass Assignment Protection identifies controller actions that pass user parameters directly to model constructors or update methods:

# Mass assignment vulnerabilities
def create
  # Unsafe: all parameters passed through
  @user = User.create(params[:user])
  
  # Unsafe: permit! allows everything
  @user = User.create(params.require(:user).permit!)
end

def secure_create
  # Safe: strong parameters whitelist
  @user = User.create(user_params)
end

private

def user_params
  params.require(:user).permit(:name, :email)
end

Security analyzers also detect insecure cryptographic practices, weak random number generation, hardcoded secrets, and insecure session configuration. The analysis provides remediation guidance alongside vulnerability reports.

Common Pitfalls

Static analysis tools require careful configuration and interpretation to provide value without creating excessive noise or developer friction.

Ignoring All Warnings defeats the purpose of static analysis. Teams that suppress all warnings or disable analyzers due to initial overwhelming output lose the security and quality benefits. The correct approach involves progressively addressing violations:

# Bad: Blanket disable
# .rubocop.yml
AllCops:
  Enabled: false

# Good: Targeted configuration with plan to improve
Metrics/MethodLength:
  Max: 30  # Current state
  # TODO: Reduce to 20 over next quarter
  
Layout/LineLength:
  Exclude:
    - 'db/migrate/*.rb'  # Specific exclusion with reason

Effective analysis requires establishing baseline configurations that reflect current code quality, then progressively tightening rules as the codebase improves.

Configuration Drift occurs when teams copy analysis configurations between projects without adaptation. Each project's context determines appropriate rules:

# Anti-pattern: Same config everywhere
# Project A: API service
# Project B: Background jobs
# Project C: Admin interface
# All use identical RuboCop config

# Better: Context-specific rules
# API service emphasizes security and performance
Security/YAMLLoad:
  Enabled: true
Performance/UnfreezeString:
  Enabled: true

# Background jobs emphasize reliability and monitoring
Lint/SuppressedException:
  Enabled: true
  AllowComments: false

False Positive Fatigue happens when developers encounter too many incorrect warnings. This erodes trust in analysis tools and leads to ignoring legitimate issues. Address false positives through better configuration rather than blanket suppression:

# Problem: Analyzer incorrectly flags valid code
def calculate_checksum(data)
  # Reek: Unused variable 'checksum'
  # But it's actually used in rescue clause
  checksum = 0
  
  data.each do |byte|
    checksum = (checksum + byte) & 0xFF
  end
rescue
  logger.error("Checksum calculation failed: #{checksum}")
end

# Solution: Inline suppression with explanation
def calculate_checksum(data)
  checksum = 0  # reek:UnusedVariable (used in rescue)
  
  data.each do |byte|
    checksum = (checksum + byte) & 0xFF
  end
rescue
  logger.error("Checksum calculation failed: #{checksum}")
end

Ignoring Context applies rules mechanically without considering their purpose. Static analysis provides starting points for discussion, not absolute mandates:

# Metrics/CyclomaticComplexity: Reports complexity of 12 (max 10)
def process_payment(payment, options = {})
  return false unless payment.valid?
  return false unless sufficient_funds?(payment)
  return false if payment.duplicate?
  
  if options[:priority]
    process_priority_payment(payment)
  elsif payment.recurring?
    process_recurring_payment(payment)
  elsif payment.international?
    process_international_payment(payment)
  else
    process_standard_payment(payment)
  end
  
  notify_payment_complete(payment)
  true
end

# Blindly reducing complexity can worsen code
# Extract methods just to satisfy metric
def process_payment(payment, options = {})
  return false unless valid_payment?(payment)
  route_payment(payment, options)
  notify_payment_complete(payment)
  true
end

The complexity metric correctly identifies code that merits review, but the solution depends on whether the complexity reflects essential business logic or poor design.

Performance Cost Neglect runs expensive analysis too frequently. Comprehensive security scans or deep program analysis can take minutes on large codebases:

# Anti-pattern: Run everything on every save
# .vscode/settings.json
{
  "ruby.lint": {
    "rubocop": true,
    "reek": true,
    "brakeman": true,  # Too slow for real-time
    "bundler-audit": true  # Network calls on every save
  }
}

# Better: Tier analysis by speed
# Real-time: Fast checks only
# Pre-commit: Medium depth
# CI: Comprehensive analysis

Dependency on Single Tool limits detection scope. Different analyzers find different issues:

# Incomplete: RuboCop only
# Misses: Security vulnerabilities, code smells, performance issues

# Comprehensive: Multiple tools
- rubocop: Style, syntax, basic security
- reek: Design smells
- brakeman: Security vulnerabilities
- fasterer: Performance patterns
- bundle-audit: Dependency vulnerabilities

Effective static analysis requires orchestrating multiple tools, each specialized for different detection capabilities.

Reference

Analysis Tool Comparison

Tool Primary Focus Language Support Auto-fix Configuration Complexity
RuboCop Style and correctness Ruby Extensive Medium
Reek Code smells Ruby None Low
Brakeman Security Ruby/Rails None Low
Bundler Audit Dependencies Gemfile None Minimal
Fasterer Performance Ruby None Minimal
Debride Dead code Ruby None Minimal

Common Vulnerability Categories

Vulnerability Detection Method Severity Auto-fix Available
SQL Injection Data flow analysis Critical No
XSS Output encoding check High No
Command Injection System call analysis Critical No
Path Traversal File operation analysis High No
Mass Assignment Parameter analysis Medium No
Weak Crypto API pattern matching Medium Sometimes
CSRF Protection verification High No
Insecure Cookies Configuration check Medium No

Integration Points

Integration Feedback Speed Thoroughness Developer Impact
IDE Real-time Light Minimal
Pre-commit Seconds Medium Medium
Pull Request Minutes Comprehensive Low
Continuous Varies Comprehensive None

RuboCop Department Overview

Department Purpose Example Cops
Style Code style conventions StringLiterals, TrailingComma, HashSyntax
Layout Code formatting LineLength, IndentationWidth, EmptyLines
Lint Error-prone patterns UnusedVariable, UselessAssignment, Void
Metrics Complexity measures MethodLength, CyclomaticComplexity, ClassLength
Naming Identifier conventions MethodName, VariableName, ClassAndModuleCamelCase
Security Security vulnerabilities YAMLLoad, JSONLoad, Eval

Analysis Metrics

Metric Measures Threshold Guidance
Cyclomatic Complexity Decision paths Methods: 10, Classes: 50
Method Length Lines per method 20 lines
Class Length Lines per class 100 lines
Parameter Count Method parameters 4 parameters
ABC Metric Assignments, branches, calls 15
Perceived Complexity Nested control flow 8

Configuration Template

# .rubocop.yml - Starter configuration
AllCops:
  NewCops: enable
  TargetRubyVersion: 3.2
  Exclude:
    - 'vendor/**/*'
    - 'db/schema.rb'
    - 'bin/**/*'
    - 'node_modules/**/*'

Style/Documentation:
  Enabled: false

Metrics/MethodLength:
  Max: 20
  CountComments: false

Metrics/BlockLength:
  Exclude:
    - 'spec/**/*'
    - 'config/routes.rb'

Layout/LineLength:
  Max: 120
  AllowedPatterns:
    - '\s+# '

Naming/VariableNumber:
  EnforcedStyle: normalcase

Brakeman Scan Options

Option Purpose Usage
--confidence-level Filter by confidence 1 (high only), 2 (high/medium), 3 (all)
--ignore-config Suppression file Path to brakeman.ignore
--quiet Reduce output Flag for CI environments
--format Output format json, html, tabs, csv
--skip-files Exclude files Comma-separated patterns