rubion 0.3.0 → 0.3.2
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/Gemfile +2 -0
- data/LICENSE +2 -0
- data/README.md +14 -9
- data/bin/rubion +2 -0
- data/lib/rubion/reporter.rb +113 -30
- data/lib/rubion/scanner.rb +70 -9
- data/lib/rubion/version.rb +1 -1
- data/lib/rubion.rb +26 -8
- metadata +6 -3
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: a34f7102afe1491a751b94e0d11e22fe854f20bb1c1f5a322473447282bd665a
|
|
4
|
+
data.tar.gz: a7dc977d51a43a5657445ee42afc730be67dd2fe6006e35b5153f47ae13fa30d
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 13e0b27d669216a58580c02dc8f2e5d26a35a0102e9ac7537bb6d6aa6caea7d42e115b4c12ad6cecc4cdd61add4829a0e549b01578c23d150ce90da4ae859001
|
|
7
|
+
data.tar.gz: f09035851f40e23cdac6f3c594f3f99f4579438ea6421c9007295e1cde0707d689b95675e7435c8da17878defe51bec2ad8427b1ec09fc476727cb026ace9859
|
data/Gemfile
CHANGED
data/LICENSE
CHANGED
data/README.md
CHANGED
|
@@ -1,13 +1,15 @@
|
|
|
1
|
-
#
|
|
1
|
+
# Rubion
|
|
2
2
|
|
|
3
|
-
**Rubion** is a security and version scanner for Ruby and JavaScript projects. It helps you identify vulnerabilities and outdated dependencies in your Ruby gems and NPM packages.
|
|
3
|
+
**Rubion** is a security and version scanner for Ruby and JavaScript projects. It helps you identify vulnerabilities and outdated dependencies in your Ruby gems and NPM/JavaScript packages.
|
|
4
|
+
|
|
5
|
+
<img width="1237" height="671" alt="Screenshot 2025-11-14 at 10 48 12 am" src="https://github.com/user-attachments/assets/a3d93452-c442-416a-9697-de59746e16ad" />
|
|
4
6
|
|
|
5
7
|
## Features
|
|
6
8
|
|
|
7
9
|
- 📛 **Gem Vulnerabilities**: Scans for known security vulnerabilities in Ruby gems using `bundle-audit`
|
|
8
10
|
- 📦 **Gem Versions**: Identifies outdated Ruby gems with release dates and version counts
|
|
9
|
-
- 📛 **Package Vulnerabilities**: Scans for known security vulnerabilities in NPM packages using `npm audit`
|
|
10
|
-
- 📦 **Package Versions**: Identifies outdated NPM packages with release dates and version counts
|
|
11
|
+
- 📛 **Package Vulnerabilities**: Scans for known security vulnerabilities in NPM/JavaScript packages using `npm audit` or `yarn audit`
|
|
12
|
+
- 📦 **Package Versions**: Identifies outdated NPM/JavaScript packages with release dates and version counts
|
|
11
13
|
- 📊 **Beautiful Reports**: Organized table output with severity icons (🔴 Critical, 🟠 High, 🟡 Medium, 🟢 Low, ⚪ Unknown)
|
|
12
14
|
- 🚀 **Fast & Efficient**: Parallel API processing (10 concurrent threads) for quick results
|
|
13
15
|
- ⚡ **Incremental Output**: Shows gem results immediately, then scans packages
|
|
@@ -44,8 +46,8 @@ rubion scan
|
|
|
44
46
|
This will scan your project for:
|
|
45
47
|
- Ruby gem vulnerabilities (if `Gemfile.lock` exists)
|
|
46
48
|
- Outdated Ruby gems with release dates
|
|
47
|
-
- NPM package vulnerabilities (if `package.json` exists)
|
|
48
|
-
- Outdated NPM packages with release dates
|
|
49
|
+
- NPM/JavaScript package vulnerabilities (if `package.json` exists)
|
|
50
|
+
- Outdated NPM/JavaScript packages with release dates
|
|
49
51
|
|
|
50
52
|
### Scan options
|
|
51
53
|
|
|
@@ -126,9 +128,11 @@ Package Versions:
|
|
|
126
128
|
|
|
127
129
|
- Ruby 2.6 or higher
|
|
128
130
|
- Bundler (for Ruby gem scanning)
|
|
129
|
-
- NPM (optional, for
|
|
131
|
+
- NPM or Yarn (optional, for JavaScript package scanning)
|
|
130
132
|
- `bundler-audit` (optional, for enhanced gem vulnerability detection)
|
|
131
133
|
|
|
134
|
+
**Note:** If both npm and yarn are available, Rubion will prompt you to choose which one to use.
|
|
135
|
+
|
|
132
136
|
### Installing bundler-audit (recommended)
|
|
133
137
|
|
|
134
138
|
```bash
|
|
@@ -172,10 +176,11 @@ Rubion uses a modular architecture:
|
|
|
172
176
|
1. **Scanner** (`lib/rubion/scanner.rb`): Executes various commands to scan for vulnerabilities and outdated versions
|
|
173
177
|
- `bundle-audit check` for gem vulnerabilities
|
|
174
178
|
- `bundle outdated --parseable` for gem versions
|
|
175
|
-
- `npm audit --json` for package vulnerabilities
|
|
176
|
-
- `npm outdated --json` for package versions
|
|
179
|
+
- `npm audit --json` or `yarn audit --json` for package vulnerabilities (auto-detects which is available)
|
|
180
|
+
- `npm outdated --json` or `yarn outdated --json` for package versions (auto-detects which is available)
|
|
177
181
|
- Fetches release dates and version data from RubyGems.org and NPM registry APIs
|
|
178
182
|
- Uses parallel processing (10 concurrent threads) for fast API calls
|
|
183
|
+
- Prompts user to choose between npm and yarn if both are available
|
|
179
184
|
|
|
180
185
|
2. **Reporter** (`lib/rubion/reporter.rb`): Formats scan results into beautiful terminal tables using `terminal-table`
|
|
181
186
|
- Adds severity icons (🔴 🟠 🟡 🟢 ⚪)
|
data/bin/rubion
CHANGED
data/lib/rubion/reporter.rb
CHANGED
|
@@ -4,8 +4,9 @@ require 'terminal-table'
|
|
|
4
4
|
|
|
5
5
|
module Rubion
|
|
6
6
|
class Reporter
|
|
7
|
-
def initialize(scan_result)
|
|
7
|
+
def initialize(scan_result, sort_by: nil)
|
|
8
8
|
@result = scan_result
|
|
9
|
+
@sort_by = sort_by
|
|
9
10
|
end
|
|
10
11
|
|
|
11
12
|
def report
|
|
@@ -36,31 +37,6 @@ module Rubion
|
|
|
36
37
|
|
|
37
38
|
private
|
|
38
39
|
|
|
39
|
-
def _print_gem_vulnerabilities
|
|
40
|
-
puts "Gem Vulnerabilities:\n\n"
|
|
41
|
-
|
|
42
|
-
if @result.gem_vulnerabilities.empty?
|
|
43
|
-
puts " ✅ No vulnerabilities found!\n\n"
|
|
44
|
-
return
|
|
45
|
-
end
|
|
46
|
-
|
|
47
|
-
table = Terminal::Table.new do |t|
|
|
48
|
-
t.headings = %w[Level Name Version Vulnerability]
|
|
49
|
-
|
|
50
|
-
@result.gem_vulnerabilities.each do |vuln|
|
|
51
|
-
t.add_row [
|
|
52
|
-
severity_with_icon(vuln[:severity]),
|
|
53
|
-
vuln[:gem],
|
|
54
|
-
vuln[:version],
|
|
55
|
-
truncate(vuln[:title], 50)
|
|
56
|
-
]
|
|
57
|
-
end
|
|
58
|
-
end
|
|
59
|
-
|
|
60
|
-
puts table
|
|
61
|
-
puts "\n"
|
|
62
|
-
end
|
|
63
|
-
|
|
64
40
|
def print_header
|
|
65
41
|
# Simplified header
|
|
66
42
|
puts "\n"
|
|
@@ -97,10 +73,14 @@ module Rubion
|
|
|
97
73
|
return
|
|
98
74
|
end
|
|
99
75
|
|
|
76
|
+
# Sort if sort_by is specified
|
|
77
|
+
versions = @result.gem_versions.dup
|
|
78
|
+
versions = sort_versions(versions, :gem) if @sort_by
|
|
79
|
+
|
|
100
80
|
table = Terminal::Table.new do |t|
|
|
101
81
|
t.headings = ['Name', 'Current', 'Date', 'Latest', 'Date', 'Behind By(Time)', 'Behind By(Versions)']
|
|
102
82
|
|
|
103
|
-
|
|
83
|
+
versions.each do |gem|
|
|
104
84
|
t.add_row [
|
|
105
85
|
gem[:gem],
|
|
106
86
|
gem[:current],
|
|
@@ -150,10 +130,14 @@ module Rubion
|
|
|
150
130
|
return
|
|
151
131
|
end
|
|
152
132
|
|
|
133
|
+
# Sort if sort_by is specified
|
|
134
|
+
versions = @result.package_versions.dup
|
|
135
|
+
versions = sort_versions(versions, :package) if @sort_by
|
|
136
|
+
|
|
153
137
|
table = Terminal::Table.new do |t|
|
|
154
|
-
t.headings = ['Name', 'Current', 'Date', 'Latest', 'Date', 'Behind By', 'Versions']
|
|
138
|
+
t.headings = ['Name', 'Current', 'Date', 'Latest', 'Date', 'Behind By(Time)', 'Behind By(Versions)']
|
|
155
139
|
|
|
156
|
-
|
|
140
|
+
versions.each do |pkg|
|
|
157
141
|
t.add_row [
|
|
158
142
|
pkg[:package],
|
|
159
143
|
pkg[:current],
|
|
@@ -218,7 +202,7 @@ module Rubion
|
|
|
218
202
|
def truncate(text, length = 50)
|
|
219
203
|
return text if text.length <= length
|
|
220
204
|
|
|
221
|
-
"#{text[0..length - 3]}..."
|
|
205
|
+
"#{text[0..(length - 3)]}..."
|
|
222
206
|
end
|
|
223
207
|
|
|
224
208
|
def version_difference(current, latest)
|
|
@@ -242,5 +226,104 @@ module Rubion
|
|
|
242
226
|
rescue StandardError
|
|
243
227
|
'unknown'
|
|
244
228
|
end
|
|
229
|
+
|
|
230
|
+
# Sort versions array based on the specified column
|
|
231
|
+
def sort_versions(versions, name_key)
|
|
232
|
+
return versions unless @sort_by
|
|
233
|
+
|
|
234
|
+
column = @sort_by.strip.downcase
|
|
235
|
+
name_key_sym = name_key # :gem or :package
|
|
236
|
+
|
|
237
|
+
# Normalize column name - default to 'name' if not recognized
|
|
238
|
+
normalized_column = case column
|
|
239
|
+
when 'name', 'current', 'date', 'latest',
|
|
240
|
+
'behind by(time)', 'behind by time', 'time',
|
|
241
|
+
'behind by(versions)', 'behind by versions', 'versions'
|
|
242
|
+
column
|
|
243
|
+
else
|
|
244
|
+
'name' # Default to name sorting
|
|
245
|
+
end
|
|
246
|
+
|
|
247
|
+
versions.sort_by do |item|
|
|
248
|
+
case normalized_column
|
|
249
|
+
when 'name'
|
|
250
|
+
item[name_key_sym].to_s.downcase
|
|
251
|
+
when 'current'
|
|
252
|
+
parse_version_for_sort(item[:current])
|
|
253
|
+
when 'date'
|
|
254
|
+
# Sort by current_date (first Date column)
|
|
255
|
+
parse_date_for_sort(item[:current_date])
|
|
256
|
+
when 'latest'
|
|
257
|
+
parse_version_for_sort(item[:latest])
|
|
258
|
+
when 'behind by(time)', 'behind by time', 'time'
|
|
259
|
+
parse_time_for_sort(item[:time_diff])
|
|
260
|
+
when 'behind by(versions)', 'behind by versions', 'versions'
|
|
261
|
+
parse_version_count_for_sort(item[:version_count])
|
|
262
|
+
end
|
|
263
|
+
end
|
|
264
|
+
end
|
|
265
|
+
|
|
266
|
+
# Parse version string for sorting (handles semantic versions)
|
|
267
|
+
def parse_version_for_sort(version_str)
|
|
268
|
+
return [0, 0, 0, ''] if version_str.nil? || version_str == 'N/A' || version_str == 'unknown'
|
|
269
|
+
|
|
270
|
+
# Handle version strings like "1.2.3", "1.2.3.4", "1.2.3-beta", etc.
|
|
271
|
+
parts = version_str.to_s.split(/[.-]/)
|
|
272
|
+
major = parts[0].to_i
|
|
273
|
+
minor = parts[1].to_i
|
|
274
|
+
patch = parts[2].to_i
|
|
275
|
+
suffix = parts[3..-1].join('') if parts.length > 3
|
|
276
|
+
|
|
277
|
+
[major, minor, patch, suffix || '']
|
|
278
|
+
end
|
|
279
|
+
|
|
280
|
+
# Parse date string for sorting (handles M/D/YYYY format)
|
|
281
|
+
def parse_date_for_sort(date_str)
|
|
282
|
+
return [0, 0, 0] if date_str.nil? || date_str == 'N/A'
|
|
283
|
+
|
|
284
|
+
begin
|
|
285
|
+
parts = date_str.split('/').map(&:to_i)
|
|
286
|
+
return [parts[2] || 0, parts[0] || 0, parts[1] || 0] if parts.length == 3
|
|
287
|
+
rescue StandardError
|
|
288
|
+
# If parsing fails, return a date that sorts last
|
|
289
|
+
end
|
|
290
|
+
|
|
291
|
+
[0, 0, 0]
|
|
292
|
+
end
|
|
293
|
+
|
|
294
|
+
# Parse time difference string for sorting (e.g., "1 year", "3 months", "5 days")
|
|
295
|
+
def parse_time_for_sort(time_str)
|
|
296
|
+
return [0, 0] if time_str.nil? || time_str == 'N/A'
|
|
297
|
+
|
|
298
|
+
time_str = time_str.to_s.downcase.strip
|
|
299
|
+
|
|
300
|
+
# Extract number and unit
|
|
301
|
+
match = time_str.match(/(\d+(?:\.\d+)?)\s*(year|month|day|years|months|days)/)
|
|
302
|
+
return [0, 0] unless match
|
|
303
|
+
|
|
304
|
+
value = match[1].to_f
|
|
305
|
+
unit = match[2].to_s.downcase
|
|
306
|
+
|
|
307
|
+
# Convert to days for comparison
|
|
308
|
+
days = case unit
|
|
309
|
+
when /year/
|
|
310
|
+
value * 365
|
|
311
|
+
when /month/
|
|
312
|
+
value * 30
|
|
313
|
+
when /day/
|
|
314
|
+
value
|
|
315
|
+
else
|
|
316
|
+
0
|
|
317
|
+
end
|
|
318
|
+
|
|
319
|
+
[days.to_i, value]
|
|
320
|
+
end
|
|
321
|
+
|
|
322
|
+
# Parse version count for sorting
|
|
323
|
+
def parse_version_count_for_sort(count)
|
|
324
|
+
return 0 if count.nil? || count == 'N/A' || count == 'unknown'
|
|
325
|
+
|
|
326
|
+
count.to_i
|
|
327
|
+
end
|
|
245
328
|
end
|
|
246
329
|
end
|
data/lib/rubion/scanner.rb
CHANGED
|
@@ -21,9 +21,11 @@ module Rubion
|
|
|
21
21
|
end
|
|
22
22
|
end
|
|
23
23
|
|
|
24
|
-
def initialize(project_path: Dir.pwd)
|
|
24
|
+
def initialize(project_path: Dir.pwd, package_manager: nil)
|
|
25
25
|
@project_path = project_path
|
|
26
26
|
@result = ScanResult.new
|
|
27
|
+
@package_manager = package_manager
|
|
28
|
+
@package_manager_detected = false
|
|
27
29
|
end
|
|
28
30
|
|
|
29
31
|
def scan
|
|
@@ -35,7 +37,7 @@ module Rubion
|
|
|
35
37
|
@result
|
|
36
38
|
end
|
|
37
39
|
|
|
38
|
-
def scan_incremental(options = { gems: true, packages: true })
|
|
40
|
+
def scan_incremental(options = { gems: true, packages: true, sort_by: nil })
|
|
39
41
|
puts "🔍 Scanning project at: #{@project_path}\n\n"
|
|
40
42
|
|
|
41
43
|
# Scan and display Ruby gems first (if enabled)
|
|
@@ -44,7 +46,7 @@ module Rubion
|
|
|
44
46
|
|
|
45
47
|
# Print gem results immediately
|
|
46
48
|
puts "\n"
|
|
47
|
-
reporter = Reporter.new(@result)
|
|
49
|
+
reporter = Reporter.new(@result, sort_by: options[:sort_by])
|
|
48
50
|
reporter.print_gem_vulnerabilities
|
|
49
51
|
reporter.print_gem_versions
|
|
50
52
|
end
|
|
@@ -74,10 +76,21 @@ module Rubion
|
|
|
74
76
|
package_json = File.join(@project_path, 'package.json')
|
|
75
77
|
return unless File.exist?(package_json)
|
|
76
78
|
|
|
77
|
-
#
|
|
79
|
+
# Detect package manager if not already set
|
|
80
|
+
unless @package_manager_detected
|
|
81
|
+
@package_manager = @package_manager || detect_package_manager
|
|
82
|
+
@package_manager_detected = true
|
|
83
|
+
end
|
|
84
|
+
|
|
85
|
+
unless @package_manager
|
|
86
|
+
puts " ⚠️ Neither npm nor yarn is available. Skipping package scanning."
|
|
87
|
+
return
|
|
88
|
+
end
|
|
89
|
+
|
|
90
|
+
# Check for vulnerabilities using package manager audit
|
|
78
91
|
check_npm_vulnerabilities
|
|
79
92
|
|
|
80
|
-
# Check for outdated versions using
|
|
93
|
+
# Check for outdated versions using package manager outdated (will show progress)
|
|
81
94
|
check_npm_versions
|
|
82
95
|
end
|
|
83
96
|
|
|
@@ -113,7 +126,10 @@ module Rubion
|
|
|
113
126
|
end
|
|
114
127
|
|
|
115
128
|
def check_npm_vulnerabilities
|
|
116
|
-
|
|
129
|
+
return unless @package_manager
|
|
130
|
+
|
|
131
|
+
command = "#{@package_manager} audit --json 2>&1"
|
|
132
|
+
stdout, stderr, status = Open3.capture3(command, chdir: @project_path)
|
|
117
133
|
|
|
118
134
|
begin
|
|
119
135
|
data = JSON.parse(stdout)
|
|
@@ -122,12 +138,15 @@ module Rubion
|
|
|
122
138
|
@result.package_vulnerabilities = []
|
|
123
139
|
end
|
|
124
140
|
rescue => e
|
|
125
|
-
puts " ⚠️ Could not run
|
|
141
|
+
puts " ⚠️ Could not run #{@package_manager} audit (#{e.message}). Skipping package vulnerability check."
|
|
126
142
|
@result.package_vulnerabilities = []
|
|
127
143
|
end
|
|
128
144
|
|
|
129
145
|
def check_npm_versions
|
|
130
|
-
|
|
146
|
+
return unless @package_manager
|
|
147
|
+
|
|
148
|
+
command = "#{@package_manager} outdated --json 2>&1"
|
|
149
|
+
stdout, stderr, status = Open3.capture3(command, chdir: @project_path)
|
|
131
150
|
|
|
132
151
|
begin
|
|
133
152
|
data = JSON.parse(stdout) unless stdout.empty?
|
|
@@ -136,7 +155,7 @@ module Rubion
|
|
|
136
155
|
@result.package_versions = []
|
|
137
156
|
end
|
|
138
157
|
rescue => e
|
|
139
|
-
puts " ⚠️ Could not run
|
|
158
|
+
puts " ⚠️ Could not run #{@package_manager} outdated (#{e.message}). Skipping package version check."
|
|
140
159
|
@result.package_versions = []
|
|
141
160
|
end
|
|
142
161
|
|
|
@@ -532,6 +551,48 @@ module Rubion
|
|
|
532
551
|
end
|
|
533
552
|
end
|
|
534
553
|
|
|
554
|
+
# Detect which package manager is available (npm or yarn)
|
|
555
|
+
def detect_package_manager
|
|
556
|
+
npm_available = check_command_available('npm')
|
|
557
|
+
yarn_available = check_command_available('yarn')
|
|
558
|
+
|
|
559
|
+
if npm_available && yarn_available
|
|
560
|
+
# Both available - prompt user
|
|
561
|
+
prompt_package_manager_choice
|
|
562
|
+
elsif npm_available
|
|
563
|
+
'npm'
|
|
564
|
+
elsif yarn_available
|
|
565
|
+
'yarn'
|
|
566
|
+
else
|
|
567
|
+
nil
|
|
568
|
+
end
|
|
569
|
+
end
|
|
570
|
+
|
|
571
|
+
# Check if a command is available in the system
|
|
572
|
+
def check_command_available(command)
|
|
573
|
+
_, _, status = Open3.capture3("which #{command} 2>&1")
|
|
574
|
+
status.success?
|
|
575
|
+
rescue
|
|
576
|
+
false
|
|
577
|
+
end
|
|
578
|
+
|
|
579
|
+
# Prompt user to choose between npm and yarn when both are available
|
|
580
|
+
def prompt_package_manager_choice
|
|
581
|
+
puts "\n Both npm and yarn are available. Which would you like to use?"
|
|
582
|
+
print " Enter 'npm' or 'yarn' (default: npm): "
|
|
583
|
+
|
|
584
|
+
choice = $stdin.gets.chomp.strip.downcase
|
|
585
|
+
|
|
586
|
+
if choice.empty? || choice == 'npm'
|
|
587
|
+
'npm'
|
|
588
|
+
elsif choice == 'yarn'
|
|
589
|
+
'yarn'
|
|
590
|
+
else
|
|
591
|
+
puts " ⚠️ Invalid choice. Using npm as default."
|
|
592
|
+
'npm'
|
|
593
|
+
end
|
|
594
|
+
end
|
|
595
|
+
|
|
535
596
|
# Fetch all NPM package version info (dates and version list) from NPM registry in one call
|
|
536
597
|
def fetch_npm_all_versions(package_name)
|
|
537
598
|
return { versions: {}, version_list: [] } if package_name.nil?
|
data/lib/rubion/version.rb
CHANGED
data/lib/rubion.rb
CHANGED
|
@@ -28,7 +28,7 @@ module Rubion
|
|
|
28
28
|
end
|
|
29
29
|
|
|
30
30
|
def self.parse_scan_options(args)
|
|
31
|
-
options = { gems: true, packages: true }
|
|
31
|
+
options = { gems: true, packages: true, sort_by: nil }
|
|
32
32
|
|
|
33
33
|
# Check for --gems-only or --packages-only flags
|
|
34
34
|
if args.include?('--gems-only') || args.include?('-g')
|
|
@@ -43,20 +43,28 @@ module Rubion
|
|
|
43
43
|
options[:packages] = args.include?('--packages')
|
|
44
44
|
end
|
|
45
45
|
|
|
46
|
+
# Parse --sort-by or -s option
|
|
47
|
+
sort_index = args.index('--sort-by') || args.index('-s')
|
|
48
|
+
if sort_index && args[sort_index + 1]
|
|
49
|
+
options[:sort_by] = args[sort_index + 1]
|
|
50
|
+
end
|
|
51
|
+
|
|
46
52
|
options
|
|
47
53
|
end
|
|
48
54
|
|
|
49
|
-
def self.scan(options = { gems: true, packages: true })
|
|
55
|
+
def self.scan(options = { gems: true, packages: true, sort_by: nil })
|
|
50
56
|
project_path = Dir.pwd
|
|
51
57
|
|
|
52
58
|
scanner = Scanner.new(project_path: project_path)
|
|
53
59
|
result = scanner.scan_incremental(options)
|
|
54
60
|
|
|
55
61
|
# Results are already printed incrementally based on options
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
#
|
|
62
|
+
# Package results are printed in scan_incremental, but we need to ensure
|
|
63
|
+
# they use the same reporter instance with sort_by
|
|
64
|
+
# Actually, scan_incremental handles gem printing, but package printing
|
|
65
|
+
# happens here, so we need a reporter for packages
|
|
59
66
|
if options[:packages]
|
|
67
|
+
reporter = Reporter.new(result, sort_by: options[:sort_by])
|
|
60
68
|
reporter.print_package_vulnerabilities
|
|
61
69
|
reporter.print_package_versions
|
|
62
70
|
end
|
|
@@ -76,13 +84,14 @@ module Rubion
|
|
|
76
84
|
--gems, --gem, -g Scan only Ruby gems (skip NPM packages)
|
|
77
85
|
--packages, --npm, -p Scan only NPM packages (skip Ruby gems)
|
|
78
86
|
--all, -a Scan both gems and packages (default)
|
|
87
|
+
--sort-by COLUMN, -s COLUMN Sort results by column (Name, Current, Date, Latest, Behind By(Time), Behind By(Versions))
|
|
79
88
|
|
|
80
89
|
DESCRIPTION:
|
|
81
90
|
Rubion scans your project for:
|
|
82
91
|
- Ruby gem vulnerabilities (using bundler-audit)
|
|
83
92
|
- Outdated Ruby gems (using bundle outdated)
|
|
84
|
-
- NPM package vulnerabilities (using npm audit)
|
|
85
|
-
- Outdated NPM packages (using npm outdated)
|
|
93
|
+
- NPM/JavaScript package vulnerabilities (using npm audit or yarn audit)
|
|
94
|
+
- Outdated NPM/JavaScript packages (using npm outdated or yarn outdated)
|
|
86
95
|
|
|
87
96
|
OUTPUT:
|
|
88
97
|
Results are displayed in organized tables with:
|
|
@@ -101,14 +110,23 @@ module Rubion
|
|
|
101
110
|
# Scan only NPM packages
|
|
102
111
|
rubion scan --packages
|
|
103
112
|
|
|
113
|
+
# Sort by name
|
|
114
|
+
rubion scan --sort-by Name
|
|
115
|
+
|
|
116
|
+
# Sort by versions behind
|
|
117
|
+
rubion scan -s "Behind By(Versions)"
|
|
118
|
+
|
|
104
119
|
# Get help
|
|
105
120
|
rubion help
|
|
106
121
|
|
|
107
122
|
REQUIREMENTS:
|
|
108
123
|
- Ruby 2.6+
|
|
109
124
|
- Bundler (for gem scanning)
|
|
110
|
-
- NPM (for package scanning, optional)
|
|
125
|
+
- NPM or Yarn (for package scanning, optional)
|
|
111
126
|
- bundler-audit (optional, install with: gem install bundler-audit)
|
|
127
|
+
|
|
128
|
+
NOTE:
|
|
129
|
+
If both npm and yarn are available, you will be prompted to choose which one to use.
|
|
112
130
|
|
|
113
131
|
HELP
|
|
114
132
|
end
|
metadata
CHANGED
|
@@ -1,13 +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.2
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- bipashant
|
|
8
|
+
autorequire:
|
|
8
9
|
bindir: bin
|
|
9
10
|
cert_chain: []
|
|
10
|
-
date:
|
|
11
|
+
date: 2025-11-14 00:00:00.000000000 Z
|
|
11
12
|
dependencies:
|
|
12
13
|
- !ruby/object:Gem::Dependency
|
|
13
14
|
name: terminal-table
|
|
@@ -92,6 +93,7 @@ metadata:
|
|
|
92
93
|
source_code_uri: https://github.com/bipashant/rubion
|
|
93
94
|
changelog_uri: https://github.com/bipashant/rubion/blob/main/CHANGELOG.md
|
|
94
95
|
bug_tracker_uri: https://github.com/bipashant/rubion/issues
|
|
96
|
+
post_install_message:
|
|
95
97
|
rdoc_options: []
|
|
96
98
|
require_paths:
|
|
97
99
|
- lib
|
|
@@ -106,7 +108,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
|
106
108
|
- !ruby/object:Gem::Version
|
|
107
109
|
version: '0'
|
|
108
110
|
requirements: []
|
|
109
|
-
rubygems_version: 3.
|
|
111
|
+
rubygems_version: 3.4.10
|
|
112
|
+
signing_key:
|
|
110
113
|
specification_version: 4
|
|
111
114
|
summary: Security and version scanner for Ruby and JavaScript projects
|
|
112
115
|
test_files: []
|