rubion 0.3.16 → 0.3.18
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 +4 -4
- data/lib/rubion/scanner.rb +77 -8
- data/lib/rubion/version.rb +1 -1
- metadata +2 -2
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 25866a240d194626328073cc8f0e78b970dd1e8389563f8a2a636a23ccc545e3
|
|
4
|
+
data.tar.gz: bc7061c95fe6a24fd7cc464bf3671f26bc9d1a53eb248512d7b15c1c67efdbf6
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: aa33bfe89c56497e77cb63b9e518fe4f57673c53440971ee50b3ebe56f82f83ea39af26e74b5bd3e38036ef85270be2a778b900afce56027234e50c80acb7603
|
|
7
|
+
data.tar.gz: 536c26c682881e1516baeeb9833214fb3a761fa0c65df777961d434da28a4e4ba5a39c6e6013251e3b27a6baca3ba9b424e7465282832ed298d061564c859959
|
data/lib/rubion/scanner.rb
CHANGED
|
@@ -125,14 +125,17 @@ module Rubion
|
|
|
125
125
|
def check_gem_versions
|
|
126
126
|
stdout, stderr, status = Open3.capture3('bundle outdated --parseable', chdir: @project_path)
|
|
127
127
|
|
|
128
|
-
|
|
129
|
-
|
|
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
|
|
130
133
|
parse_bundle_outdated_output(stdout)
|
|
131
134
|
elsif status.exitstatus.nil?
|
|
132
135
|
# Command not found or failed to execute
|
|
133
136
|
raise "bundle outdated command failed or is not available. Error: #{stderr}"
|
|
134
137
|
else
|
|
135
|
-
# Command failed with non-zero exit code
|
|
138
|
+
# Command failed with unexpected non-zero exit code
|
|
136
139
|
raise "bundle outdated failed with exit code #{status.exitstatus}. Output: #{stdout}#{unless stderr.empty?
|
|
137
140
|
"\nError: #{stderr}"
|
|
138
141
|
end}"
|
|
@@ -148,16 +151,26 @@ module Rubion
|
|
|
148
151
|
if status.exitstatus.nil?
|
|
149
152
|
# Command not found or failed to execute
|
|
150
153
|
raise "#{@package_manager} audit command failed or is not available. Error: #{stderr}"
|
|
151
|
-
elsif !status.success? && status.exitstatus != 1
|
|
152
|
-
#
|
|
154
|
+
elsif @package_manager == 'npm' && !status.success? && status.exitstatus != 1
|
|
155
|
+
# For npm, exit code 1 means vulnerabilities were found; any other non-zero code is an error
|
|
153
156
|
raise "#{@package_manager} audit failed with exit code #{status.exitstatus}. Output: #{stdout}#{unless stderr.empty?
|
|
154
157
|
"\nError: #{stderr}"
|
|
155
158
|
end}"
|
|
159
|
+
elsif @package_manager == 'yarn' && !status.success?
|
|
160
|
+
# For Yarn (classic), any non-zero exit code is a bitmask of severities:
|
|
161
|
+
# 1=info, 2=low, 4=moderate, 8=high, 16=critical. The exit code is the sum of severities found.
|
|
162
|
+
# Non-zero here indicates vulnerabilities were found; we'll still try to parse the JSON output below.
|
|
163
|
+
# Do not raise here so that vulnerabilities are handled gracefully.
|
|
156
164
|
end
|
|
157
165
|
|
|
158
166
|
begin
|
|
159
|
-
|
|
160
|
-
|
|
167
|
+
# Yarn audit outputs JSON line by line, need to parse each line
|
|
168
|
+
if @package_manager == 'yarn'
|
|
169
|
+
parse_yarn_audit_output(stdout)
|
|
170
|
+
else
|
|
171
|
+
data = JSON.parse(stdout)
|
|
172
|
+
parse_npm_audit_output(data)
|
|
173
|
+
end
|
|
161
174
|
rescue JSON::ParserError => e
|
|
162
175
|
raise "Failed to parse #{@package_manager} audit JSON output: #{e.message}. Raw output: #{stdout}"
|
|
163
176
|
end
|
|
@@ -364,6 +377,55 @@ module Rubion
|
|
|
364
377
|
@result.package_vulnerabilities = vulnerabilities
|
|
365
378
|
end
|
|
366
379
|
|
|
380
|
+
def parse_yarn_audit_output(output)
|
|
381
|
+
vulnerabilities = []
|
|
382
|
+
seen_advisories = {}
|
|
383
|
+
|
|
384
|
+
# Yarn audit outputs JSON line by line
|
|
385
|
+
output.each_line do |line|
|
|
386
|
+
next if line.strip.empty?
|
|
387
|
+
|
|
388
|
+
begin
|
|
389
|
+
json_obj = JSON.parse(line)
|
|
390
|
+
next unless json_obj.is_a?(Hash)
|
|
391
|
+
|
|
392
|
+
# Parse auditAdvisory type
|
|
393
|
+
if json_obj['type'] == 'auditAdvisory' && json_obj['data'] && json_obj['data']['advisory']
|
|
394
|
+
advisory = json_obj['data']['advisory']
|
|
395
|
+
advisory_id = advisory['id']
|
|
396
|
+
|
|
397
|
+
# Skip if we've already seen this advisory
|
|
398
|
+
next if seen_advisories[advisory_id]
|
|
399
|
+
|
|
400
|
+
seen_advisories[advisory_id] = true
|
|
401
|
+
|
|
402
|
+
# Extract package name and version from findings
|
|
403
|
+
if advisory['findings'] && advisory['findings'].is_a?(Array) && advisory['findings'].first
|
|
404
|
+
finding = advisory['findings'].first
|
|
405
|
+
version = finding['version'] || 'unknown'
|
|
406
|
+
else
|
|
407
|
+
version = 'unknown'
|
|
408
|
+
end
|
|
409
|
+
|
|
410
|
+
# Get severity (yarn uses lowercase)
|
|
411
|
+
severity = (advisory['severity'] || 'unknown').downcase
|
|
412
|
+
|
|
413
|
+
vulnerabilities << {
|
|
414
|
+
package: advisory['module_name'] || 'unknown',
|
|
415
|
+
version: version,
|
|
416
|
+
severity: severity,
|
|
417
|
+
title: advisory['title'] || advisory['overview'] || 'Vulnerability detected'
|
|
418
|
+
}
|
|
419
|
+
end
|
|
420
|
+
rescue JSON::ParserError
|
|
421
|
+
# Skip invalid JSON lines
|
|
422
|
+
next
|
|
423
|
+
end
|
|
424
|
+
end
|
|
425
|
+
|
|
426
|
+
@result.package_vulnerabilities = vulnerabilities
|
|
427
|
+
end
|
|
428
|
+
|
|
367
429
|
def parse_npm_outdated_output(data)
|
|
368
430
|
versions = []
|
|
369
431
|
|
|
@@ -789,7 +851,14 @@ module Rubion
|
|
|
789
851
|
puts "\n Both npm and yarn are available. Which would you like to use?"
|
|
790
852
|
print " Enter 'n' for npm or 'y' for yarn (default: npm): "
|
|
791
853
|
|
|
792
|
-
|
|
854
|
+
input = $stdin.gets
|
|
855
|
+
if input.nil?
|
|
856
|
+
# stdin not available (e.g., running through bundle exec in non-interactive mode)
|
|
857
|
+
puts " (stdin not available, using npm as default)\n"
|
|
858
|
+
return 'npm'
|
|
859
|
+
end
|
|
860
|
+
|
|
861
|
+
choice = input.chomp.strip.downcase
|
|
793
862
|
|
|
794
863
|
if choice.empty? || choice == 'n' || choice == 'npm'
|
|
795
864
|
'npm'
|
data/lib/rubion/version.rb
CHANGED
metadata
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: rubion
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.3.
|
|
4
|
+
version: 0.3.18
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- bipashant
|
|
8
8
|
autorequire:
|
|
9
9
|
bindir: bin
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date: 2025-11-
|
|
11
|
+
date: 2025-11-21 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: terminal-table
|