Class: Cabriolet::PluginValidator
- Inherits:
-
Object
- Object
- Cabriolet::PluginValidator
- Defined in:
- lib/cabriolet/plugin_validator.rb
Overview
Validates plugin classes and configurations
The PluginValidator provides comprehensive validation for plugins including inheritance checks, metadata validation, version compatibility, and safety scanning.
Constant Summary collapse
- REQUIRED_METADATA =
Required metadata fields
i[name version description cabriolet_version].freeze
- DANGEROUS_METHODS =
Dangerous method names to check for
%w[ system exec spawn ` fork eval instance_eval class_eval module_eval binding const_set remove_const send __send__ method_missing respond_to_missing? ].freeze
Class Method Summary collapse
-
.check_safety(plugin_class) ⇒ Array<String>
Check plugin for potentially dangerous code.
-
.validate(plugin_class) ⇒ Hash
Validate a plugin class.
-
.validate_dependencies(dependencies) ⇒ Array<String>
Validate plugin dependencies.
-
.validate_inheritance(plugin_class) ⇒ Array<String>
Validate plugin inheritance.
-
.validate_metadata(metadata) ⇒ Array<String>
Validate plugin metadata.
-
.validate_version_compatibility(plugin_version, cabriolet_version) ⇒ Array<String>
Validate version compatibility.
Class Method Details
.check_safety(plugin_class) ⇒ Array<String>
Check plugin for potentially dangerous code
Scans the plugin’s source code for dangerous method calls that might pose security risks.
311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 |
# File 'lib/cabriolet/plugin_validator.rb', line 311 def check_safety(plugin_class) warnings = [] # Get source location begin methods_to_check = i[setup activate ] methods_to_check.each do |method_name| next unless plugin_class.method_defined?(method_name, false) method_obj = plugin_class.instance_method(method_name) source_location = method_obj.source_location if source_location && File.exist?(source_location[0]) source = File.read(source_location[0]) DANGEROUS_METHODS.each do |dangerous| pattern = /\b#{Regexp.escape(dangerous)}\b/ if source&.match?(pattern) warnings << "Plugin uses potentially dangerous method " \ "'#{dangerous}' " \ "in #{source_location[0]}" end end end end rescue StandardError => e warnings << "Could not perform safety check: #{e.message}" end warnings end |
.validate(plugin_class) ⇒ Hash
Validate a plugin class
Performs comprehensive validation including inheritance, metadata, version compatibility, and safety checks.
48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 |
# File 'lib/cabriolet/plugin_validator.rb', line 48 def validate(plugin_class) errors = [] warnings = [] # Check inheritance inherit_errors = validate_inheritance(plugin_class) errors.concat(inherit_errors) # If inheritance fails, stop here return { valid: false, errors: errors, warnings: warnings } unless inherit_errors.empty? # Create instance to check metadata begin instance = plugin_class.new(nil) = instance. # Validate metadata = () errors.concat() # Check version compatibility if [:cabriolet_version] version_errors = validate_version_compatibility( [:cabriolet_version], Cabriolet::VERSION, ) errors.concat(version_errors) end # Validate dependencies if [:dependencies] dep_warnings = validate_dependencies([:dependencies]) warnings.concat(dep_warnings) end rescue NotImplementedError => e errors << "Plugin does not implement required method: " \ "#{e.message}" rescue StandardError => e errors << "Failed to instantiate plugin: #{e.message}" end # Safety checks safety_warnings = check_safety(plugin_class) warnings.concat(safety_warnings) { valid: errors.empty?, errors: errors, warnings: warnings, } end |
.validate_dependencies(dependencies) ⇒ Array<String>
Validate plugin dependencies
Checks if dependency specifications are valid. This performs format validation only; actual dependency resolution happens at load time.
270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 |
# File 'lib/cabriolet/plugin_validator.rb', line 270 def validate_dependencies(dependencies) warnings = [] unless dependencies.is_a?(Array) warnings << "Dependencies must be an array" return warnings end dependencies.each do |dep| unless dep.is_a?(String) warnings << "Each dependency must be a string" next end parts = dep.split if parts.empty? warnings << "Empty dependency specification" elsif !/^[a-z0-9_-]+$/.match?(parts[0]) warnings << "Invalid dependency name: #{parts[0]}" end end warnings end |
.validate_inheritance(plugin_class) ⇒ Array<String>
Validate plugin inheritance
Checks that the plugin class properly inherits from Cabriolet::Plugin.
117 118 119 120 121 122 123 124 125 126 127 128 129 130 |
# File 'lib/cabriolet/plugin_validator.rb', line 117 def validate_inheritance(plugin_class) errors = [] unless plugin_class.is_a?(Class) errors << "Plugin must be a class, got #{plugin_class.class}" return errors end unless plugin_class < Plugin errors << "Plugin must inherit from Cabriolet::Plugin" end errors end |
.validate_metadata(metadata) ⇒ Array<String>
Validate plugin metadata
Checks that all required metadata fields are present and valid.
148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 |
# File 'lib/cabriolet/plugin_validator.rb', line 148 def () errors = [] unless .is_a?(Hash) errors << "Metadata must be a Hash" return errors end # Check required fields missing = REQUIRED_METADATA - .keys unless missing.empty? errors << "Missing required metadata: #{missing.join(', ')}" end # Validate field types and formats if [:name] unless [:name].is_a?(String) && ![:name].empty? errors << "Plugin name must be a non-empty string" end if [:name].is_a?(String) && [:name] =~ /^[a-z0-9_-]+$/ # Valid format - do nothing elsif [:name].is_a?(String) errors << "Plugin name must contain only lowercase letters, " \ "numbers, hyphens, and underscores" end end if [:version] && !valid_version?([:version]) errors << "Plugin version must be a valid semantic version " \ "(e.g., '1.0.0')" end if [:author] && !([:author].is_a?(String) && ![:author].empty?) errors << "Plugin author must be a non-empty string" end if [:description] && !([:description].is_a?(String) && ![:description].empty?) errors << "Plugin description must be a non-empty string" end # Optional fields validation if [:homepage] && ![:homepage].empty? && !valid_url?([:homepage]) errors << "Plugin homepage must be a valid URL" end if [:dependencies] && ![:dependencies].is_a?(Array) errors << "Plugin dependencies must be an array" end if [:tags] && ![:tags].is_a?(Array) errors << "Plugin tags must be an array" end errors end |
.validate_version_compatibility(plugin_version, cabriolet_version) ⇒ Array<String>
Validate version compatibility
Checks if the plugin’s required Cabriolet version matches the current version.
226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 |
# File 'lib/cabriolet/plugin_validator.rb', line 226 def validate_version_compatibility(plugin_version, cabriolet_version) errors = [] # Parse version requirement if plugin_version.start_with?("~>") # Pessimistic version constraint required = plugin_version.sub("~>", "").strip unless version_compatible?(cabriolet_version, required, :pessimistic) errors << "Plugin requires Cabriolet version ~> #{required}, " \ "but #{cabriolet_version} is installed" end elsif plugin_version.start_with?(">=") # Minimum version required = plugin_version.sub(">=", "").strip unless version_compatible?(cabriolet_version, required, :gte) errors << "Plugin requires Cabriolet version >= #{required}, " \ "but #{cabriolet_version} is installed" end elsif plugin_version.start_with?("=") # Exact version required = plugin_version.sub("=", "").strip unless cabriolet_version == required errors << "Plugin requires exact Cabriolet version #{required}, " \ "but #{cabriolet_version} is installed" end end errors end |