Module: DebugMcp::CodeSafetyAnalyzer
- Defined in:
- lib/debug_mcp/code_safety_analyzer.rb
Constant Summary collapse
- DANGEROUS_PATTERNS =
{ file_operations: [ [/\bFile\s*\.\s*(write|delete|unlink|rename|chmod|chown)\b/, "File.write/delete/unlink/rename"], [/\bFileUtils\b/, "FileUtils"], [/\bIO\s*\.\s*(write|binwrite)\b/, "IO.write"], [/\bDir\s*\.\s*(mkdir|rmdir|delete|unlink)\b/, "Dir.mkdir/rmdir"], ], system_commands: [ [/\bsystem\s*\(/, "system()"], [/\bexec\s*\(/, "exec()"], [/\bspawn\s*\(/, "spawn()"], [/`[^`]+`/, "backtick command"], [/%x\{/, "%x{}"], [/%x\[/, "%x[]"], [/%x\(/, "%x()"], [/\bOpen3\b/, "Open3"], [/\bIO\s*\.\s*popen\b/, "IO.popen"], ], process_manipulation: [ [/\bProcess\s*\.\s*(kill|fork|exit)\b/, "Process.kill/fork/exit"], [/\bfork\s*[\s({]/, "fork"], [/\bexit!/, "exit!"], [/\babort\b/, "abort"], ], network_operations: [ [/\bNet::HTTP\b/, "Net::HTTP"], [/\bTCPSocket\b/, "TCPSocket"], [/\bUDPSocket\b/, "UDPSocket"], [/\bFaraday\b/, "Faraday"], [/\bHTTParty\b/, "HTTParty"], [/\bopen-uri\b/, "open-uri"], [/\bURI\s*\.\s*open\b/, "URI.open"], [/\bRestClient\b/, "RestClient"], ], destructive_data: [ [/\.destroy_all\b/, ".destroy_all"], [/\.delete_all\b/, ".delete_all"], [/\.update_all\b/, ".update_all"], [/\b(DROP|TRUNCATE)\s+(TABLE|DATABASE)\b/i, "DROP/TRUNCATE SQL"], ], mutation_operations: [ [/\.save!/, ".save!"], [/\.save\b(?![!?])/, ".save"], [/\.update![\s(]/, ".update!"], [/\.update[\s(]/, ".update"], [/\.create![\s(]/, ".create!"], [/\.create[\s(]/, ".create"], [/\.destroy!/, ".destroy!"], [/\.destroy\b(?![_!])/, ".destroy"], [/\.touch\b/, ".touch"], [/\.increment!/, ".increment!"], [/\.decrement!/, ".decrement!"], [/\.toggle!/, ".toggle!"], ], }.freeze
- CATEGORY_LABELS =
{ file_operations: "File system operations", system_commands: "System command execution", process_manipulation: "Process manipulation", network_operations: "Network operations", destructive_data: "Destructive data operations", mutation_operations: "Data mutation (modifies database records)", }.freeze
Class Method Summary collapse
-
.analyze(code) ⇒ Object
Analyze code for dangerous patterns.
-
.filter_acknowledged(warnings, acknowledged_categories) ⇒ Object
Filter out warnings whose categories have been acknowledged.
-
.format_warnings(warnings) ⇒ Object
Format warnings into human-readable text.
Class Method Details
.analyze(code) ⇒ Object
Analyze code for dangerous patterns. Returns an array of warnings: [{ category:, label:, matches: }]
70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 |
# File 'lib/debug_mcp/code_safety_analyzer.rb', line 70 def self.analyze(code) warnings = [] DANGEROUS_PATTERNS.each do |category, patterns| matches = [] patterns.each do |regexp, label| matches << label if code.match?(regexp) end next if matches.empty? warnings << { category: category, matches: matches } end warnings end |
.filter_acknowledged(warnings, acknowledged_categories) ⇒ Object
Filter out warnings whose categories have been acknowledged.
62 63 64 65 66 |
# File 'lib/debug_mcp/code_safety_analyzer.rb', line 62 def self.filter_acknowledged(warnings, acknowledged_categories) return warnings if acknowledged_categories.nil? || acknowledged_categories.empty? warnings.reject { |w| acknowledged_categories.include?(w[:category]) } end |
.format_warnings(warnings) ⇒ Object
Format warnings into human-readable text. Returns nil if no warnings. Uses a compact “Note:” format when only mutation_operations are present, and a verbose “WARNING:” format when other categories are involved.
99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 |
# File 'lib/debug_mcp/code_safety_analyzer.rb', line 99 def self.format_warnings(warnings) return nil if warnings.empty? # Compact format for mutation-only warnings if warnings.all? { |w| w[:category] == :mutation_operations } matches = warnings.flat_map { |w| w[:matches] } return "Note: Data mutation detected (#{matches.join(", ")}). " \ "Use acknowledge_mutations to suppress this notice." end # Verbose format for dangerous operations lines = [] lines << "WARNING: Potentially dangerous operations detected in code." lines << "evaluate_code should only be used for investigating runtime state." lines << "Use the agent's own tools for file/system/network operations." lines << "" warnings.each do |w| label = CATEGORY_LABELS[w[:category]] || w[:category].to_s lines << " #{label}: #{w[:matches].join(", ")}" end lines.join("\n") end |