Module: RailsMcpServer::PathValidator
- Defined in:
- lib/rails-mcp-server/utilities/path_validator.rb
Constant Summary collapse
- SENSITIVE_PATTERNS =
Sensitive file patterns - files that should never be read or listed
[ /\.env(\..*)?$/i, # .env, .env.local, .env.production /\.key$/i, # *.key files /\.pem$/i, # SSL certificates /\.crt$/i, # SSL certificates /\.p12$/i, # PKCS12 certificates /credentials\.yml(\.enc)?$/i, # Rails credentials (encrypted or not) /secrets\.yml(\.enc)?$/i, # Rails secrets /master\.key$/i, # Rails master key /config\/credentials/i, # credentials directory /config\/secrets/i, # secrets directory /\.secret$/i, # generic secret files /password/i, # password files /\.ssh\//i, # SSH directory /id_rsa/i, # SSH keys /id_ed25519/i, # SSH keys /id_ecdsa/i, # SSH keys /\.gnupg\//i, # GPG directory /\.netrc$/i, # netrc credentials /\.pgpass$/i, # PostgreSQL passwords /database\.yml$/i, # Database configuration /storage\.yml$/i # Active Storage config (may contain keys) ].freeze
- EXCLUDED_DIRECTORIES =
Directories that should be excluded from listing
%w[ .git/ .bundle/ node_modules/ vendor/bundle/ vendor/cache/ tmp/ log/ storage/ .ruby-lsp/ ].freeze
Class Method Summary collapse
-
.excluded_directory?(path) ⇒ Boolean
Check if path is in excluded directory.
-
.filter_sensitive_files(files, project_root) ⇒ Object
Filter a list of files, removing sensitive ones.
-
.safe_path?(path, project_root) ⇒ Boolean
Reject paths that resolve to project_root itself (e.g., ".", "..").
-
.sensitive_path?(path) ⇒ Boolean
Check if a path matches sensitive patterns.
-
.shell_escape(str) ⇒ Object
Escape a string for safe shell usage.
- .valid_identifier?(name) ⇒ Boolean
-
.valid_table_name?(name) ⇒ Boolean
Validate table names (alphanumeric and underscores only).
-
.validate_path(path, project_root) ⇒ Object
Validate and return safe absolute path, or nil if unsafe.
Class Method Details
.excluded_directory?(path) ⇒ Boolean
Check if path is in excluded directory
96 97 98 |
# File 'lib/rails-mcp-server/utilities/path_validator.rb', line 96 def excluded_directory?(path) EXCLUDED_DIRECTORIES.any? { |dir| path.start_with?(dir) } end |
.filter_sensitive_files(files, project_root) ⇒ Object
Filter a list of files, removing sensitive ones
88 89 90 91 92 93 |
# File 'lib/rails-mcp-server/utilities/path_validator.rb', line 88 def filter_sensitive_files(files, project_root) files.reject do |file| relative_path = file.sub("#{project_root}/", "") sensitive_path?(relative_path) end end |
.safe_path?(path, project_root) ⇒ Boolean
Reject paths that resolve to project_root itself (e.g., ".", "..")
52 53 54 55 56 57 |
# File 'lib/rails-mcp-server/utilities/path_validator.rb', line 52 def safe_path?(path, project_root) return false if path.nil? || path.empty? = File.(path, project_root) .start_with?(project_root + "/") end |
.sensitive_path?(path) ⇒ Boolean
Check if a path matches sensitive patterns
46 47 48 49 |
# File 'lib/rails-mcp-server/utilities/path_validator.rb', line 46 def sensitive_path?(path) normalized = path.to_s.downcase SENSITIVE_PATTERNS.any? { |pattern| normalized.match?(pattern) } end |
.shell_escape(str) ⇒ Object
Escape a string for safe shell usage
70 71 72 |
# File 'lib/rails-mcp-server/utilities/path_validator.rb', line 70 def shell_escape(str) Shellwords.escape(str.to_s) end |
.valid_identifier?(name) ⇒ Boolean
74 75 76 77 78 |
# File 'lib/rails-mcp-server/utilities/path_validator.rb', line 74 def valid_identifier?(name) return false if name.nil? || name.empty? name.match?(/\A[a-zA-Z_][a-zA-Z0-9_]*(::[a-zA-Z_][a-zA-Z0-9_]*)*\z/) end |
.valid_table_name?(name) ⇒ Boolean
Validate table names (alphanumeric and underscores only)
81 82 83 84 85 |
# File 'lib/rails-mcp-server/utilities/path_validator.rb', line 81 def valid_table_name?(name) return false if name.nil? || name.empty? name.match?(/\A[a-zA-Z_][a-zA-Z0-9_]*\z/) end |
.validate_path(path, project_root) ⇒ Object
Validate and return safe absolute path, or nil if unsafe
60 61 62 63 64 65 66 67 |
# File 'lib/rails-mcp-server/utilities/path_validator.rb', line 60 def validate_path(path, project_root) return nil unless safe_path?(path, project_root) = File.(path, project_root) return nil if sensitive_path?(.sub(project_root + "/", "")) end |