CrackedRuby CrackedRuby

Overview

Input validation examines data received from external sources to verify it conforms to expected criteria before the application processes or stores it. This defense mechanism prevents malicious or malformed data from compromising system integrity, corrupting data stores, or exposing security vulnerabilities.

Applications accept input from multiple sources: HTTP request parameters, form submissions, API payloads, file uploads, command-line arguments, environment variables, and database queries. Each input vector presents potential attack surfaces where adversaries inject malicious payloads, exploit parsing vulnerabilities, or trigger unintended application behavior.

Validation operates at the application boundary, acting as the first line of defense against injection attacks, data corruption, and business logic violations. Without proper validation, applications remain vulnerable to SQL injection, cross-site scripting (XSS), command injection, path traversal, and numerous other attack vectors that exploit unchecked input.

The validation process encompasses multiple dimensions: syntactic validation verifies data format and structure, semantic validation ensures data makes sense in context, type validation confirms data types match expectations, and business rule validation enforces domain-specific constraints. Each validation layer addresses different aspects of data integrity and security.

# Unvalidated input leading to SQL injection vulnerability
def find_user(username)
  User.find_by_sql("SELECT * FROM users WHERE username = '#{username}'")
end

# Validated and parameterized query
def find_user(username)
  return nil unless username.is_a?(String) && username.match?(/\A[a-zA-Z0-9_]+\z/)
  User.where(username: username).first
end

Modern web frameworks provide validation infrastructure, but developers must understand validation principles to apply them correctly. Framework abstractions hide complexity but can create false security confidence when misapplied or incompletely implemented.

Key Principles

Input validation follows the principle of explicit rejection: define what constitutes valid input and reject everything else. This whitelist approach proves more secure than blacklist-based rejection, which attempts to enumerate all possible invalid inputs and inevitably misses edge cases or novel attack vectors.

Validation occurs as early as possible in the data processing pipeline, ideally at the point where external data enters the application. Early validation prevents malicious data from propagating through the system, reducing the attack surface and simplifying security analysis. Each layer of the application stack can apply additional validation appropriate to its abstraction level.

Type coercion and validation remain distinct operations. Type coercion converts data from one type to another, potentially masking invalid input by forcing it into an expected format. Validation explicitly checks whether data meets requirements without automatic transformation. Performing validation before coercion maintains data integrity and prevents subtle security issues.

# Dangerous: coercion masks validation issues
age = params[:age].to_i  # "malicious" becomes 0
process_age(age) if age > 0  # Passes but may not reflect user intent

# Correct: validate before coercion
age_string = params[:age]
if age_string.match?(/\A\d+\z/)
  age = age_string.to_i
  process_age(age) if age > 0
else
  raise ValidationError, "Age must be a positive integer"
end

Context determines validation requirements. The same data may require different validation depending on how it will be used. A string validated for display differs from one validated for use in system commands or database queries. Understanding the data's destination and processing informs appropriate validation rules.

Validation failures require explicit handling rather than silent acceptance or default value substitution. Applications should reject invalid input with clear error messages that inform users without exposing implementation details attackers could exploit. Error messages balance usability with security, providing enough information for legitimate users while avoiding information disclosure.

Defense in depth applies to validation. Multiple validation layers at different architectural boundaries provide redundancy against validation bypass. Client-side validation improves user experience but never substitutes for server-side validation, as clients remain under attacker control and can bypass any client-side checks.

Canonical form validation addresses encoding variations and normalization attacks. Attackers exploit different encodings, Unicode normalization forms, or character representations to bypass validation. Converting input to a single canonical form before validation prevents these bypass techniques.

Security Implications

Input validation forms the foundation of application security, directly preventing the most prevalent web application vulnerabilities. SQL injection attacks exploit applications that concatenate unsanitized input into database queries, allowing attackers to execute arbitrary SQL commands. Proper validation combined with parameterized queries eliminates this entire vulnerability class.

Cross-site scripting (XSS) occurs when applications include unvalidated user input in HTML output without proper encoding. Attackers inject JavaScript code that executes in victim browsers, stealing credentials, hijacking sessions, or performing actions on behalf of users. Input validation restricts input to safe character sets and formats, while output encoding handles display concerns.

Command injection vulnerabilities arise when applications pass unvalidated input to system shell commands. Attackers inject command separators and additional commands, gaining unauthorized system access or executing malicious code. Strict validation combined with avoiding shell invocation when possible mitigates this risk.

Path traversal attacks manipulate file paths to access files outside intended directories. Attackers use sequences like ../ to navigate directory structures, potentially accessing sensitive configuration files, source code, or system files. Validating file paths against allowed patterns and canonicalizing paths before use prevents traversal attacks.

# Vulnerable to path traversal
def read_user_file(filename)
  File.read("uploads/#{filename}")
end

# Protected with validation
def read_user_file(filename)
  # Reject path separators and parent directory references
  raise SecurityError if filename.include?('/') || filename.include?('\\')
  raise SecurityError if filename.include?('..')
  
  # Whitelist allowed characters
  raise SecurityError unless filename.match?(/\A[a-zA-Z0-9._-]+\z/)
  
  path = File.expand_path(File.join('uploads', filename))
  raise SecurityError unless path.start_with?(File.expand_path('uploads'))
  
  File.read(path)
end

XML external entity (XXE) attacks exploit XML parsers that process external entity references in user-supplied XML. Attackers reference external files or network resources, potentially reading sensitive files or triggering denial-of-service conditions. Disabling external entity processing and validating XML structure prevents XXE attacks.

Buffer overflow vulnerabilities in languages with manual memory management occur when applications fail to validate input length, writing beyond allocated buffer boundaries. While Ruby's memory safety prevents traditional buffer overflows, validation still prevents resource exhaustion from excessively large inputs.

Business logic vulnerabilities result from insufficient semantic validation. Attackers manipulate prices, quantities, or other business parameters to exploit logic flaws. Validation must enforce not just data types and formats but also business rules and constraints specific to the application domain.

Mass assignment vulnerabilities occur in frameworks that automatically bind request parameters to object attributes. Attackers add unexpected parameters to modify protected attributes. Validation through explicit parameter filtering prevents unauthorized attribute modification.

Regular expression denial of service (ReDoS) exploits catastrophic backtracking in poorly designed regex patterns. Attackers provide input that causes exponential processing time, creating denial-of-service conditions. Careful regex design and input length limits mitigate ReDoS risks.

Ruby Implementation

Ruby provides multiple approaches to input validation, ranging from manual checks to framework-integrated validation systems. The standard library includes pattern matching, type checking, and string validation methods that form the foundation of custom validation logic.

Regular expressions validate string formats and patterns. Ruby's String#match? method performs pattern matching without creating match objects, improving performance for validation use cases. Character class shortcuts and anchors ensure complete string matching rather than partial matches.

# Email format validation
EMAIL_REGEX = /\A[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}\z/

def valid_email?(email)
  email.is_a?(String) && email.match?(EMAIL_REGEX)
end

# Phone number validation
PHONE_REGEX = /\A\+?[1-9]\d{1,14}\z/

def valid_phone?(phone)
  phone.is_a?(String) && phone.match?(PHONE_REGEX)
end

# Alphanumeric with length constraints
def valid_username?(username)
  username.is_a?(String) &&
    username.match?(/\A[a-zA-Z0-9_]{3,20}\z/)
end

Type validation uses Ruby's type system and introspection capabilities. The is_a? method checks class hierarchy membership, while kind_of? provides an alias for the same functionality. Duck typing validation checks for method presence using respond_to?.

def process_number(value)
  unless value.is_a?(Numeric)
    raise TypeError, "Expected Numeric, got #{value.class}"
  end
  
  unless value.positive?
    raise ArgumentError, "Value must be positive"
  end
  
  value * 2
end

# Duck typing validation
def process_enumerable(collection)
  unless collection.respond_to?(:each)
    raise TypeError, "Object must be enumerable"
  end
  
  collection.map { |item| item.to_s.upcase }
end

Rails Active Record validations provide declarative validation rules at the model layer. These validations execute before save operations, preventing invalid data from persisting to the database. Validation helpers cover common patterns like presence, format, uniqueness, and numericality.

class User < ApplicationRecord
  validates :email, presence: true, 
                   format: { with: URI::MailTo::EMAIL_REGEXP },
                   uniqueness: { case_sensitive: false }
  
  validates :age, numericality: { only_integer: true,
                                  greater_than_or_equal_to: 0,
                                  less_than_or_equal_to: 150 }
  
  validates :username, format: { with: /\A[a-zA-Z0-9_]+\z/ },
                      length: { minimum: 3, maximum: 20 },
                      uniqueness: true
  
  validate :password_complexity
  
  private
  
  def password_complexity
    return if password.blank?
    
    unless password.match?(/[A-Z]/)
      errors.add(:password, "must contain uppercase letter")
    end
    
    unless password.match?(/[a-z]/)
      errors.add(:password, "must contain lowercase letter")
    end
    
    unless password.match?(/[0-9]/)
      errors.add(:password, "must contain digit")
    end
  end
end

Strong parameters in Rails controllers prevent mass assignment vulnerabilities by requiring explicit parameter whitelisting. Controllers define permitted parameters, and the framework raises exceptions when unpermitted parameters are accessed.

class UsersController < ApplicationController
  def create
    @user = User.new(user_params)
    if @user.save
      redirect_to @user
    else
      render :new
    end
  end
  
  private
  
  def user_params
    params.require(:user).permit(:username, :email, :age)
  end
end

Custom validators encapsulate complex validation logic for reuse across models. Validators inherit from ActiveModel::Validator or ActiveModel::EachValidator depending on whether they validate entire models or individual attributes.

class EmailDomainValidator < ActiveModel::EachValidator
  def validate_each(record, attribute, value)
    return if value.blank?
    
    domain = value.split('@').last
    allowed_domains = options[:domains]
    
    unless allowed_domains.include?(domain)
      record.errors.add(attribute, 
                       "must be from allowed domains: #{allowed_domains.join(', ')}")
    end
  end
end

class User < ApplicationRecord
  validates :email, email_domain: { domains: ['company.com', 'partner.com'] }
end

The dry-validation gem provides a functional approach to validation with composable rules and detailed error messages. Contracts define schemas with type coercion, predicates, and custom rules.

require 'dry-validation'

UserContract = Dry::Validation.Contract do
  params do
    required(:username).filled(:string)
    required(:email).filled(:string)
    required(:age).filled(:integer)
  end
  
  rule(:email) do
    unless /\A[^@\s]+@[^@\s]+\z/.match?(value)
      key.failure('must be valid email format')
    end
  end
  
  rule(:age) do
    key.failure('must be non-negative') if value < 0
    key.failure('must be realistic') if value > 150
  end
end

# Usage
result = UserContract.call(username: 'john', email: 'invalid', age: -5)
result.success? # => false
result.errors.to_h # => {:email=>["must be valid email format"], :age=>["must be non-negative"]}

Practical Examples

User registration forms require comprehensive validation across multiple fields with different requirements. Email validation checks format, username validation enforces character restrictions and length limits, and password validation ensures sufficient complexity.

class RegistrationValidator
  EMAIL_REGEX = /\A[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}\z/
  USERNAME_REGEX = /\A[a-zA-Z0-9_]+\z/
  
  def self.validate(params)
    errors = {}
    
    # Email validation
    email = params[:email].to_s.strip
    if email.empty?
      errors[:email] = "Email is required"
    elsif !email.match?(EMAIL_REGEX)
      errors[:email] = "Email format is invalid"
    elsif email.length > 255
      errors[:email] = "Email is too long"
    end
    
    # Username validation
    username = params[:username].to_s.strip
    if username.empty?
      errors[:username] = "Username is required"
    elsif !username.match?(USERNAME_REGEX)
      errors[:username] = "Username can only contain letters, numbers, and underscores"
    elsif username.length < 3
      errors[:username] = "Username must be at least 3 characters"
    elsif username.length > 20
      errors[:username] = "Username cannot exceed 20 characters"
    end
    
    # Password validation
    password = params[:password].to_s
    if password.empty?
      errors[:password] = "Password is required"
    elsif password.length < 8
      errors[:password] = "Password must be at least 8 characters"
    elsif !password.match?(/[A-Z]/)
      errors[:password] = "Password must contain an uppercase letter"
    elsif !password.match?(/[a-z]/)
      errors[:password] = "Password must contain a lowercase letter"
    elsif !password.match?(/[0-9]/)
      errors[:password] = "Password must contain a digit"
    elsif !password.match?(/[^a-zA-Z0-9]/)
      errors[:password] = "Password must contain a special character"
    end
    
    # Password confirmation
    if params[:password] != params[:password_confirmation]
      errors[:password_confirmation] = "Passwords do not match"
    end
    
    errors
  end
end

# Controller usage
def create
  errors = RegistrationValidator.validate(params)
  
  if errors.empty?
    user = User.create!(params.permit(:email, :username, :password))
    redirect_to user
  else
    @errors = errors
    render :new
  end
end

API request validation handles JSON payloads with nested structures, arrays, and optional fields. Validation must handle missing keys, type mismatches, and constraint violations while providing detailed error information.

class ApiRequestValidator
  def self.validate_create_order(payload)
    errors = []
    
    # Required top-level fields
    unless payload.is_a?(Hash)
      return ["Request body must be a JSON object"]
    end
    
    unless payload['customer_id'].is_a?(Integer)
      errors << "customer_id must be an integer"
    end
    
    unless payload['items'].is_a?(Array)
      errors << "items must be an array"
    else
      # Validate each item
      payload['items'].each_with_index do |item, index|
        unless item.is_a?(Hash)
          errors << "items[#{index}] must be an object"
          next
        end
        
        unless item['product_id'].is_a?(Integer)
          errors << "items[#{index}].product_id must be an integer"
        end
        
        unless item['quantity'].is_a?(Integer) && item['quantity'] > 0
          errors << "items[#{index}].quantity must be a positive integer"
        end
        
        if item['price']
          unless item['price'].is_a?(Numeric) && item['price'] >= 0
            errors << "items[#{index}].price must be a non-negative number"
          end
        end
      end
    end
    
    # Optional shipping address
    if payload['shipping_address']
      address = payload['shipping_address']
      
      ['street', 'city', 'country'].each do |field|
        unless address[field].is_a?(String) && !address[field].empty?
          errors << "shipping_address.#{field} is required"
        end
      end
      
      if address['postal_code']
        unless address['postal_code'].match?(/\A[A-Z0-9\s-]{3,10}\z/i)
          errors << "shipping_address.postal_code format is invalid"
        end
      end
    end
    
    errors
  end
end

# API controller
def create_order
  errors = ApiRequestValidator.validate_create_order(request_payload)
  
  if errors.empty?
    order = Order.create_from_api(request_payload)
    render json: { order: order }, status: :created
  else
    render json: { errors: errors }, status: :unprocessable_entity
  end
end

File upload validation prevents security vulnerabilities from malicious files. Validation checks file size, content type, filename safety, and file content to ensure uploaded files meet security requirements.

class FileUploadValidator
  MAX_SIZE = 10.megabytes
  ALLOWED_CONTENT_TYPES = ['image/jpeg', 'image/png', 'image/gif', 'application/pdf']
  SAFE_FILENAME_REGEX = /\A[a-zA-Z0-9._-]+\z/
  
  def self.validate(uploaded_file)
    errors = []
    
    unless uploaded_file.respond_to?(:read)
      return ["Invalid file upload"]
    end
    
    # Size validation
    if uploaded_file.size > MAX_SIZE
      errors << "File size exceeds maximum of #{MAX_SIZE / 1.megabyte}MB"
    end
    
    # Content type validation
    unless ALLOWED_CONTENT_TYPES.include?(uploaded_file.content_type)
      errors << "File type #{uploaded_file.content_type} is not allowed"
    end
    
    # Filename validation
    filename = File.basename(uploaded_file.original_filename)
    unless filename.match?(SAFE_FILENAME_REGEX)
      errors << "Filename contains invalid characters"
    end
    
    if filename.length > 255
      errors << "Filename is too long"
    end
    
    # Magic byte validation for images
    if uploaded_file.content_type.start_with?('image/')
      magic_bytes = uploaded_file.read(8)
      uploaded_file.rewind
      
      valid_image = case uploaded_file.content_type
      when 'image/jpeg'
        magic_bytes.start_with?("\xFF\xD8\xFF")
      when 'image/png'
        magic_bytes.start_with?("\x89PNG")
      when 'image/gif'
        magic_bytes.start_with?("GIF87a") || magic_bytes.start_with?("GIF89a")
      else
        false
      end
      
      unless valid_image
        errors << "File content does not match declared content type"
      end
    end
    
    errors
  end
end

Common Pitfalls

Partial regex matching creates validation bypass vulnerabilities when developers forget anchors. Without start anchor \A and end anchor \z, regex matches any substring, allowing attackers to append or prepend malicious content that passes validation.

# Vulnerable: matches "user@example.com" anywhere in string
def vulnerable_email?(email)
  email.match?(/[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}/)
end

# Attack: vulnerable_email?("attacker<script>@evil.com") => false
# Attack: vulnerable_email?("valid@example.com<script>alert(1)</script>") => true (passes!)

# Secure: requires entire string to match
def secure_email?(email)
  email.match?(/\A[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}\z/)
end

Validating after type coercion obscures invalid input by converting unexpected data into default values. String-to-integer coercion converts non-numeric strings to zero, causing validation logic to accept invalid input.

# Dangerous: "malicious" coerces to 0, passing validation
age = params[:age].to_i
if age >= 0
  process_age(age)  # Processes 0 for invalid input
end

# Correct: validate before coercion
if params[:age].match?(/\A\d+\z/)
  age = params[:age].to_i
  process_age(age) if age >= 0
else
  raise ValidationError, "Invalid age format"
end

Client-side validation alone provides no security value, as attackers control client environments and bypass any client-side checks. Client-side validation improves user experience but never substitutes for server-side validation.

Blacklist-based validation fails to account for encoding variations, case sensitivity, and novel attack vectors. Attackers find creative ways to represent malicious content that bypasses blacklist filters.

# Inadequate blacklist approach
def sanitize_dangerous(input)
  input.gsub(/script|javascript|onerror/i, '')
end

# Bypassed by: "<scr<script>ipt>alert(1)</script>"
# Bypassed by: "java&#115;cript:alert(1)"

# Better: whitelist allowed characters
def validate_safe_input(input)
  input.match?(/\A[a-zA-Z0-9\s.,!?-]+\z/)
end

Length validation on byte count rather than character count creates issues with multibyte UTF-8 characters. Database column limits operate on character counts, but byte-based validation may accept strings that exceed database limits.

# Incorrect: byte length vs character length mismatch
def validate_length(text)
  text.bytesize <= 100  # May allow >100 characters with multibyte chars
end

# Correct: validate character length
def validate_length(text)
  text.length <= 100
end

Insufficient semantic validation accepts syntactically valid but meaningless data. Date validation that accepts February 30th, quantity validation that accepts negative values, or price validation that accepts zero demonstrate semantic validation failures.

# Syntactically valid but semantically invalid
def create_order(quantity, price)
  unless quantity.is_a?(Integer)
    raise TypeError, "Quantity must be integer"
  end
  
  # Missing semantic validation
  # Should reject: quantity <= 0, price < 0
  
  Order.create(quantity: quantity, price: price)
end

# Complete validation
def create_order(quantity, price)
  unless quantity.is_a?(Integer) && quantity > 0
    raise ArgumentError, "Quantity must be positive integer"
  end
  
  unless price.is_a?(Numeric) && price >= 0
    raise ArgumentError, "Price must be non-negative"
  end
  
  Order.create(quantity: quantity, price: price)
end

Trusting deserialized data without validation assumes serialization provides integrity guarantees. Attackers manipulate serialized data before submission, requiring validation after deserialization.

Unicode normalization bypass occurs when validation and application logic use different Unicode normalization forms. Attackers exploit normalization differences to bypass validation filters.

Error message information disclosure reveals validation logic details that assist attackers. Overly specific error messages expose database schema, field constraints, or internal logic that attackers use to craft attacks.

Error Handling & Edge Cases

Validation failures require informative error messages that help legitimate users correct problems without revealing sensitive implementation details. Error messages should identify the field, describe the problem, and suggest corrections without exposing database schema, query structure, or internal validation logic.

class ValidationError < StandardError
  attr_reader :field, :message_type
  
  def initialize(field, message_type, details = nil)
    @field = field
    @message_type = message_type
    super(format_message(details))
  end
  
  private
  
  def format_message(details)
    case @message_type
    when :required
      "#{@field} is required"
    when :format
      "#{@field} format is invalid"
    when :length
      "#{@field} length must be between #{details[:min]} and #{details[:max]} characters"
    when :type
      "#{@field} must be a #{details[:expected_type]}"
    else
      "#{@field} is invalid"
    end
  end
end

Null and undefined value handling requires explicit checking before validation. Ruby's nil values and empty strings represent absence differently from invalid input, requiring separate handling paths.

def validate_optional_field(value)
  return true if value.nil?  # Optional field, absence is valid
  return false if value.empty?  # Present but empty is invalid
  
  value.match?(/\A[a-zA-Z0-9]+\z/)  # Validate format when present
end

def validate_required_field(value)
  return false if value.nil? || value.empty?  # Both nil and empty are invalid
  
  value.match?(/\A[a-zA-Z0-9]+\z/)
end

Whitespace handling affects validation depending on field semantics. Leading and trailing whitespace may represent invalid input for some fields while being acceptable for others. Explicit whitespace handling policy prevents inconsistent behavior.

def validate_username(username)
  # Usernames should not contain whitespace
  return false if username.nil?
  return false if username.match?(/\s/)
  
  username.match?(/\A[a-zA-Z0-9_]{3,20}\z/)
end

def validate_display_name(name)
  # Display names allow internal whitespace but not leading/trailing
  return false if name.nil?
  
  trimmed = name.strip
  return false if trimmed.empty?
  
  trimmed.match?(/\A[a-zA-Z0-9\s]{1,50}\z/)
end

Boundary condition testing validates input at extreme values. Minimum and maximum length values, numeric limits, and empty collections represent common boundary conditions that expose validation edge cases.

RSpec.describe Validator do
  describe '#validate_age' do
    it 'accepts valid ages' do
      expect(Validator.validate_age(25)).to be true
    end
    
    it 'rejects negative ages' do
      expect(Validator.validate_age(-1)).to be false
    end
    
    it 'accepts zero age' do
      expect(Validator.validate_age(0)).to be true
    end
    
    it 'accepts maximum reasonable age' do
      expect(Validator.validate_age(150)).to be true
    end
    
    it 'rejects unrealistic ages' do
      expect(Validator.validate_age(151)).to be false
    end
  end
end

Encoding validation prevents encoding-based attacks. Input should be validated for proper UTF-8 encoding, with invalid byte sequences rejected before processing.

def validate_encoding(input)
  unless input.valid_encoding?
    raise ValidationError.new(:input, :encoding, "Invalid UTF-8 encoding")
  end
  
  # Additional validation after encoding check
  validate_content(input)
end

Array and collection validation requires checking collection type, element count constraints, and validating each element individually. Validation short-circuits on first error or accumulates all errors depending on requirements.

def validate_items(items)
  errors = []
  
  unless items.is_a?(Array)
    return ["Items must be an array"]
  end
  
  if items.empty?
    errors << "At least one item is required"
  end
  
  if items.length > 100
    errors << "Cannot exceed 100 items"
  end
  
  items.each_with_index do |item, index|
    item_errors = validate_item(item)
    item_errors.each do |error|
      errors << "Item #{index}: #{error}"
    end
  end
  
  errors
end

Reference

Common Validation Patterns

Pattern Regex Use Case
Email /\A[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+.[a-zA-Z]{2,}\z/ Email addresses
Username /\A[a-zA-Z0-9_]{3,20}\z/ Alphanumeric usernames
UUID /\A[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}\z/i UUID identifiers
Hex Color /\A#[0-9a-f]{6}\z/i Hex color codes
ISO Date /\A\d{4}-\d{2}-\d{2}\z/ YYYY-MM-DD dates
Phone (E.164) /\A+?[1-9]\d{1,14}\z/ International phone
Slug /\A[a-z0-9-]+\z/ URL-safe slugs
IPv4 /\A(?:[0-9]{1,3}.){3}[0-9]{1,3}\z/ IPv4 addresses

Rails Validation Helpers

Helper Parameters Description
validates_presence_of :field Ensures field is not nil or empty
validates_length_of :field, minimum:, maximum: Validates string length
validates_numericality_of :field, greater_than:, less_than: Validates numeric values
validates_format_of :field, with: Validates against regex pattern
validates_inclusion_of :field, in: Validates value in allowed set
validates_exclusion_of :field, in: Rejects values in blacklist
validates_uniqueness_of :field, scope: Ensures database uniqueness
validates_confirmation_of :field Validates confirmation field match

Type Checking Methods

Method Returns Example
is_a?(Class) Boolean value.is_a?(String)
kind_of?(Class) Boolean value.kind_of?(Numeric)
instance_of?(Class) Boolean value.instance_of?(Integer)
respond_to?(method) Boolean value.respond_to?(:each)
String#match?(pattern) Boolean str.match?(/\d+/)
valid_encoding? Boolean str.valid_encoding?

Input Sanitization Functions

Function Purpose Example
String#strip Remove leading/trailing whitespace input.strip
String#gsub Pattern replacement input.gsub(/[^\w]/, '')
String#tr Character translation input.tr('^A-Za-z0-9', '')
String#encode Encoding conversion input.encode('UTF-8', invalid: :replace)
CGI.escapeHTML HTML entity encoding CGI.escapeHTML(user_input)
URI.encode_www_form_component URL encoding URI.encode_www_form_component(param)

Security Validation Checklist

Check Purpose Implementation
Type validation Ensure correct data type Use is_a? or type coercion with validation
Format validation Match expected pattern Regular expressions with anchors
Length constraints Prevent buffer issues Check string/array length bounds
Range validation Enforce numeric limits Compare against min/max values
Whitelist characters Allow only safe characters Match against approved character set
Encoding validation Prevent encoding attacks Check valid_encoding?
Canonical form Prevent bypass via encoding Normalize before validation
Business rules Enforce domain constraints Custom validation logic

Error Response Structure

Field Type Description
status String Error status code
errors Array List of validation errors
field String Field name with error
message String Human-readable error message
code String Machine-readable error code
details Object Additional error context

Validation Timing

Stage Location Purpose
Input reception Controller/API Reject malformed requests early
Type coercion Parameter parsing Convert to expected types
Business rules Service layer Enforce domain constraints
Persistence Model layer Final validation before save
Output rendering View layer Escape for safe display