rubion 0.3.15 → 0.3.17

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 99ef1ebceccefcea4bf5c67725d1ca01f0b96d93fc6f241f454d87036f66ca82
4
- data.tar.gz: 0cc8829b4732831a6b4abde663adc9e03e6b8cd44036e53ba74a0786596f6c57
3
+ metadata.gz: 1d382653589bad6b28b68444b231efafa582f375cf1d4c7284d8df5faae04d50
4
+ data.tar.gz: 3edfba9269ed3024943544887422101b7512cd4309c5e689fbd6f8a7cf655a60
5
5
  SHA512:
6
- metadata.gz: 5cc9368809677f92ab9943fa1b46aa29c34bf387965cdad7be2c4a7ccafd3937b5aa594d6306d64cb74dc0fd08fb3a51d5ebf0f4c7fc12f110fc128c7a6fa40b
7
- data.tar.gz: 8ba9129d965c90617f8c867b1f3289eafbecf8cea776f43f06e5244e04d7983e78f57c8dbc8bed43cf283405c0b84bce7a8df8041e703697f4a84fc5878fc1f5
6
+ metadata.gz: a5f3c72e3d1f257c426e0df25efb3b1ae62751527324bd5a8991986dd12aa6652cb0ca81aecd2941c3b00a19a5ceff090d1718ff5d540e59c0ddbc509707dd73
7
+ data.tar.gz: bc17b9ebd3c5081cb040deba4358eae42f4a941169fa7a5db919ea9ef92065dfa33fcb11dcc0a2925e58a62ebbb9ea4dad3364c69ff46133b7a2f79447885503
@@ -106,8 +106,10 @@ module Rubion
106
106
  # Exit code 0 means no vulnerabilities found
107
107
  # Any other exit code or error means the command failed
108
108
  if status.exitstatus.nil? || status.exitstatus == 127 || stderr.include?('command not found') || stdout.include?('command not found')
109
- # Command not found - try to install bundler-audit automatically
110
- install_bundler_audit_and_retry
109
+ # Command not found - show friendly message and skip vulnerability check
110
+ puts "\n ℹ️ bundle-audit is not installed. Skipping gem vulnerability check."
111
+ puts " To enable vulnerability scanning, install it with: gem install bundler-audit\n"
112
+ @result.gem_vulnerabilities = []
111
113
  elsif status.exitstatus == 1 || status.success? || (!stdout.empty? && (stdout.include?('vulnerabilities found') || stdout.include?('Name:')))
112
114
  # Exit code 1 (vulnerabilities found) or 0 (no vulnerabilities) - parse output
113
115
  # Also try to parse if output looks valid even if exit code is unexpected
@@ -120,37 +122,20 @@ module Rubion
120
122
  end
121
123
  end
122
124
 
123
- def install_bundler_audit_and_retry
124
- puts "\n ⚠️ bundle-audit is not installed."
125
- print ' Attempting to install bundler-audit... '
126
- $stdout.flush
127
-
128
- _install_stdout, install_stderr, install_status = Open3.capture3('gem install bundler-audit 2>&1')
129
-
130
- if install_status.success?
131
- puts "✓ Successfully installed bundler-audit\n"
132
- puts " Retrying gem vulnerability check...\n\n"
133
- # Retry the check after installation
134
- check_gem_vulnerabilities
135
- else
136
- puts '✗ Failed to install bundler-audit'
137
- raise "bundle-audit is not installed and automatic installation failed.\n" \
138
- "Please install it manually by running: gem install bundler-audit\n" \
139
- "Installation error: #{install_stderr}"
140
- end
141
- end
142
-
143
125
  def check_gem_versions
144
126
  stdout, stderr, status = Open3.capture3('bundle outdated --parseable', chdir: @project_path)
145
127
 
146
- if status.success?
147
- # Command succeeded - parse output (may be empty if all gems are up to date)
128
+ # bundle outdated returns exit code 1 when outdated gems are found (expected behavior)
129
+ # Exit code 0 means no outdated gems or command succeeded
130
+ # Exit code 1 means outdated gems found - this is success, not an error
131
+ if status.success? || status.exitstatus == 1
132
+ # Command succeeded or outdated gems found - parse output
148
133
  parse_bundle_outdated_output(stdout)
149
134
  elsif status.exitstatus.nil?
150
135
  # Command not found or failed to execute
151
136
  raise "bundle outdated command failed or is not available. Error: #{stderr}"
152
137
  else
153
- # Command failed with non-zero exit code
138
+ # Command failed with unexpected non-zero exit code
154
139
  raise "bundle outdated failed with exit code #{status.exitstatus}. Output: #{stdout}#{unless stderr.empty?
155
140
  "\nError: #{stderr}"
156
141
  end}"
@@ -166,16 +151,22 @@ module Rubion
166
151
  if status.exitstatus.nil?
167
152
  # Command not found or failed to execute
168
153
  raise "#{@package_manager} audit command failed or is not available. Error: #{stderr}"
169
- elsif !status.success? && status.exitstatus != 1
170
- # Exit code 1 is expected when vulnerabilities are found, other non-zero codes are errors
154
+ elsif !status.success? && status.exitstatus != 1 && status.exitstatus != 4
155
+ # Exit code 1 (npm) or 4 (yarn) is expected when vulnerabilities are found
156
+ # Other non-zero codes are errors
171
157
  raise "#{@package_manager} audit failed with exit code #{status.exitstatus}. Output: #{stdout}#{unless stderr.empty?
172
158
  "\nError: #{stderr}"
173
159
  end}"
174
160
  end
175
161
 
176
162
  begin
177
- data = JSON.parse(stdout)
178
- parse_npm_audit_output(data)
163
+ # Yarn audit outputs JSON line by line, need to parse each line
164
+ if @package_manager == 'yarn'
165
+ parse_yarn_audit_output(stdout)
166
+ else
167
+ data = JSON.parse(stdout)
168
+ parse_npm_audit_output(data)
169
+ end
179
170
  rescue JSON::ParserError => e
180
171
  raise "Failed to parse #{@package_manager} audit JSON output: #{e.message}. Raw output: #{stdout}"
181
172
  end
@@ -382,6 +373,55 @@ module Rubion
382
373
  @result.package_vulnerabilities = vulnerabilities
383
374
  end
384
375
 
376
+ def parse_yarn_audit_output(output)
377
+ vulnerabilities = []
378
+ seen_advisories = {}
379
+
380
+ # Yarn audit outputs JSON line by line
381
+ output.each_line do |line|
382
+ next if line.strip.empty?
383
+
384
+ begin
385
+ json_obj = JSON.parse(line)
386
+ next unless json_obj.is_a?(Hash)
387
+
388
+ # Parse auditAdvisory type
389
+ if json_obj['type'] == 'auditAdvisory' && json_obj['data'] && json_obj['data']['advisory']
390
+ advisory = json_obj['data']['advisory']
391
+ advisory_id = advisory['id']
392
+
393
+ # Skip if we've already seen this advisory
394
+ next if seen_advisories[advisory_id]
395
+
396
+ seen_advisories[advisory_id] = true
397
+
398
+ # Extract package name and version from findings
399
+ if advisory['findings'] && advisory['findings'].is_a?(Array) && advisory['findings'].first
400
+ finding = advisory['findings'].first
401
+ version = finding['version'] || 'unknown'
402
+ else
403
+ version = 'unknown'
404
+ end
405
+
406
+ # Get severity (yarn uses lowercase)
407
+ severity = (advisory['severity'] || 'unknown').downcase
408
+
409
+ vulnerabilities << {
410
+ package: advisory['module_name'] || 'unknown',
411
+ version: version,
412
+ severity: severity,
413
+ title: advisory['title'] || advisory['overview'] || 'Vulnerability detected'
414
+ }
415
+ end
416
+ rescue JSON::ParserError
417
+ # Skip invalid JSON lines
418
+ next
419
+ end
420
+ end
421
+
422
+ @result.package_vulnerabilities = vulnerabilities
423
+ end
424
+
385
425
  def parse_npm_outdated_output(data)
386
426
  versions = []
387
427
 
@@ -807,7 +847,14 @@ module Rubion
807
847
  puts "\n Both npm and yarn are available. Which would you like to use?"
808
848
  print " Enter 'n' for npm or 'y' for yarn (default: npm): "
809
849
 
810
- choice = $stdin.gets.chomp.strip.downcase
850
+ input = $stdin.gets
851
+ if input.nil?
852
+ # stdin not available (e.g., running through bundle exec in non-interactive mode)
853
+ puts " (stdin not available, using npm as default)\n"
854
+ return 'npm'
855
+ end
856
+
857
+ choice = input.chomp.strip.downcase
811
858
 
812
859
  if choice.empty? || choice == 'n' || choice == 'npm'
813
860
  'npm'
@@ -1,6 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Rubion
4
- VERSION = "0.3.15"
4
+ VERSION = "0.3.17"
5
5
  end
6
6
 
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: rubion
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.3.15
4
+ version: 0.3.17
5
5
  platform: ruby
6
6
  authors:
7
7
  - bipashant