rails-ai-context

38 MCP tools that give AI agents live access to your Rails schema, models, routes & conventions.

View the Project on GitHub crisnahine/rails-ai-context

Security Model

Read-only by design. Defense in depth. Every tool is non-destructive.

Architecture · Configuration · Tools Reference · FAQ


[!CAUTION] This gem is designed for development environments. The query tool is disabled in production by default. Sensitive files are blocked. All 38 tools are read-only.

Design principles

  1. Read-only by design — All 38 tools are annotated as non-destructive in the MCP protocol
  2. Defense in depth — Multiple security layers, not single points of failure
  3. Sensitive data blocking — Configurable patterns prevent access to secrets
  4. Offline by default — No network calls except optional rails_search_docs with fetch: true
  5. Graceful degradation — Missing optional dependencies don’t expose errors or state

SQL query safety (4 layers)

The rails_query tool uses a 4-layer security model:

flowchart LR
    Q[SQL Query] --> L1{Layer 1\nRegex Validation}
    L1 -->|"Blocked:\nINSERT, DROP,\nUNION SELECT..."| R1[Rejected]
    L1 -->|SELECT only| L2{Layer 2\nDatabase Read-Only}
    L2 -->|"SET TRANSACTION\nREAD ONLY\n+ timeout"| L3{Layer 3\nRow Limit}
    L3 -->|"Cap: 1000 rows\nDefault: 100"| L4{Layer 4\nColumn Redaction}
    L4 -->|"password_digest\napi_key → [REDACTED]"| OK[Safe Result]

    style R1 fill:#e74c3c,stroke:#c0392b,color:#fff
    style OK fill:#27ae60,stroke:#1e8449,color:#fff
    style L1 fill:#e67e22,stroke:#d35400,color:#fff
    style L2 fill:#f39c12,stroke:#e67e22,color:#fff
    style L3 fill:#3498db,stroke:#2980b9,color:#fff
    style L4 fill:#9b59b6,stroke:#8e44ad,color:#fff

Layer 1 — SQL validation (regex-based)

Before any query reaches the database:

Layer 2 — Database-level read-only

After validation, the query runs inside a transaction:

Database Mechanism
PostgreSQL SET TRANSACTION READ ONLY + SET LOCAL statement_timeout
MySQL SET TRANSACTION READ ONLY + MAX_EXECUTION_TIME hint
SQLite PRAGMA query_only = ON + progress handler for timeout

All queries execute inside a transaction, then rollback (even if they could write, they can’t).

Layer 3 — Row limit

Layer 4 — Column redaction

Sensitive column values are replaced with [REDACTED]:

Default redacted patterns: password_digest, encrypted_password, password_hash, reset_password_token, confirmation_token, unlock_token, otp_secret, session_data, secret_key, api_key, api_secret, access_token, refresh_token, jti

Redaction matches by name and suffixSELECT password_digest AS pd still redacts pd because the column name is tracked through the query result.

Environment guard

[!WARNING] Disabled in production by default. Only enable with config.allow_query_in_production = true if you understand the implications.


Sensitive file blocking

The rails_search_code and file-reading tools block access to sensitive files:

Default patterns

.env*
*.key
*.pem
credentials.yml.enc
master.key
secret_key_base
config/secrets.yml
config/credentials/*

AI context file exclusions

Search also excludes generated AI context files to prevent circular references:

CLAUDE.md, .claude/, .mcp.json
.cursor/, .cursorrules
.github/copilot-instructions.md, .github/instructions/, .vscode/mcp.json
AGENTS.md, opencode.json
.codex/
.ai-context.json

Configuration

config.sensitive_patterns = %w[.env* *.key *.pem credentials.yml.enc]

Path traversal protection

All file-reading operations validate paths against Rails.root:

real_path = File.realpath(requested_path)
raise unless real_path.start_with?(Rails.root.to_s)

The VFS (rails-ai-context://views/{path}) applies the same protection for view template reads.


Command injection prevention

Search tools use array-based command execution (never shell strings):

# Safe: array form
Open3.capture2("rg", "--no-heading", pattern, "--", directory)

# Pattern injection prevented by -- separator

File type parameters accept only alphanumeric characters.


Regex injection prevention

User-supplied regex patterns have a 1-second timeout:

Regexp.new(pattern, timeout: 1)

Complex patterns that would cause catastrophic backtracking raise RegexpError instead of hanging.


Safe file reading

SafeFile.read provides drop-in safety for all file reads:


Log redaction

The rails_read_logs tool redacts sensitive data from log output:


Migration safety

The rails_migration_advisor tool validates input:


MCP HTTP transport

When using HTTP transport (Rack middleware or McpController):

The McpController uses thread-safe transport initialization with mutex synchronization.


Credential handling


Reporting vulnerabilities

Email crisjosephnahine@gmail.com. Response within 48 hours.

Supported versions: 4.0.x and later (4.2.1+ includes security hardening). See the repo root SECURITY.md for the full policy.


← Introspectors · CLI Reference →

Back to Home