rubion 0.3.0

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 ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: f3dc20ad2e0d8a10c9819577c5370327e860d1406b866fa02504e472dbb1e673
4
+ data.tar.gz: b7954923cc22c872f7a20520db5bf2496af0615886978d2701188357b1e3cdf2
5
+ SHA512:
6
+ metadata.gz: c8997bc21f73e51e7e904e8372fd779d85f5b162ff0d7b7187ce4136571343913d6362d61a2cb2839d3c8333f91b3af8724192a6b7bff9ae361c357975d8dce6
7
+ data.tar.gz: 8e18d1257ef3cc883c7dba88355c3c7928c60f31bb17d20135b19954ad4ac055b2aeb21338d9453156959330ad3432aa36ab2e7772c315ec9bc8bb81a9946ab2
data/Gemfile ADDED
@@ -0,0 +1,11 @@
1
+ # frozen_string_literal: true
2
+
3
+ source "https://rubygems.org"
4
+
5
+ # Specify your gem's dependencies in rubion.gemspec
6
+ gemspec
7
+
8
+ gem "rake", "~> 13.0"
9
+ gem "rspec", "~> 3.0"
10
+ gem "rubocop", "~> 1.21"
11
+
data/LICENSE ADDED
@@ -0,0 +1,22 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2025 [Your Name]
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
22
+
data/README.md ADDED
@@ -0,0 +1,273 @@
1
+ # 🔒 Rubion
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.
4
+
5
+ ## Features
6
+
7
+ - 📛 **Gem Vulnerabilities**: Scans for known security vulnerabilities in Ruby gems using `bundle-audit`
8
+ - 📦 **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
+ - 📊 **Beautiful Reports**: Organized table output with severity icons (🔴 Critical, 🟠 High, 🟡 Medium, 🟢 Low, ⚪ Unknown)
12
+ - 🚀 **Fast & Efficient**: Parallel API processing (10 concurrent threads) for quick results
13
+ - ⚡ **Incremental Output**: Shows gem results immediately, then scans packages
14
+ - 📅 **Release Dates**: Fetches actual release dates from RubyGems.org and NPM registry
15
+ - 🔢 **Version Analysis**: Shows how many versions behind and time difference
16
+
17
+ ## Installation
18
+
19
+ ### Install from RubyGems (when published)
20
+
21
+ ```bash
22
+ gem install rubion
23
+ ```
24
+
25
+ ### Install from source
26
+
27
+ ```bash
28
+ git clone https://github.com/yourusername/rubion.git
29
+ cd rubion
30
+ bundle install
31
+ rake install_local
32
+ ```
33
+
34
+ ## Usage
35
+
36
+ ### Scan your project
37
+
38
+ Navigate to your project directory and run:
39
+
40
+ ```bash
41
+ rubion scan
42
+ ```
43
+
44
+ This will scan your project for:
45
+ - Ruby gem vulnerabilities (if `Gemfile.lock` exists)
46
+ - Outdated Ruby gems with release dates
47
+ - NPM package vulnerabilities (if `package.json` exists)
48
+ - Outdated NPM packages with release dates
49
+
50
+ ### Scan options
51
+
52
+ ```bash
53
+ # Scan only Ruby gems (skip NPM packages)
54
+ rubion scan --gems-only
55
+ # or
56
+ rubion scan -g
57
+
58
+ # Scan only NPM packages (skip Ruby gems)
59
+ rubion scan --packages-only
60
+ # or
61
+ rubion scan -p
62
+
63
+ # Scan both (default)
64
+ rubion scan
65
+ ```
66
+
67
+ ### View help
68
+
69
+ ```bash
70
+ rubion help
71
+ ```
72
+
73
+ ### Check version
74
+
75
+ ```bash
76
+ rubion version
77
+ # or
78
+ rubion -v
79
+ ```
80
+
81
+ ## Output Example
82
+
83
+ ```
84
+ 🔍 Scanning project at: /path/to/project
85
+
86
+ 📦 Checking Ruby gems... 139/139 ✓
87
+
88
+ Gem Vulnerabilities:
89
+
90
+ +----------+--------+---------+------------------------------------------+
91
+ | Level | Name | Version | Vulnerability |
92
+ +----------+--------+---------+------------------------------------------+
93
+ | 🔴 Critical | rexml | 3.4.1 | REXML has DoS condition when parsing... |
94
+ | 🟠 High | rack | 2.0.8 | Denial of Service vulnerability |
95
+ +----------+--------+---------+------------------------------------------+
96
+
97
+ Gem Versions:
98
+
99
+ +----------+---------+-----------+---------+-----------+-----------+----------+
100
+ | Name | Current | Date | Latest | Date | Behind By | Versions |
101
+ +----------+---------+-----------+---------+-----------+-----------+----------+
102
+ | sidekiq | 7.30 | 3/5/2024 | 8.1 | 11/11/2025| 1 year | 15 |
103
+ | fastimage| 2.2.7 | 2/2/2025 | 2.3.2 | 9/9/2025 | 7 months | 3 |
104
+ +----------+---------+-----------+---------+-----------+-----------+----------+
105
+
106
+ 📦 Checking NPM packages... 45/45 ✓
107
+
108
+ Package Vulnerabilities:
109
+
110
+ +----------+--------+---------+------------------------------------------+
111
+ | Level | Name | Version | Vulnerability |
112
+ +----------+--------+---------+------------------------------------------+
113
+ | 🟠 High | moment | 1.2.3 | Wrong timezone date calculation |
114
+ +----------+--------+---------+------------------------------------------+
115
+
116
+ Package Versions:
117
+
118
+ +----------+---------+-----------+---------+-----------+-----------+----------+
119
+ | Name | Current | Date | Latest | Date | Behind By | Versions |
120
+ +----------+---------+-----------+---------+-----------+-----------+----------+
121
+ | jquery | 3.7.1 | 4/5/2024 | 3.9.1 | 10/11/2025| 1 year | 8 |
122
+ +----------+---------+-----------+---------+-----------+-----------+----------+
123
+ ```
124
+
125
+ ## Requirements
126
+
127
+ - Ruby 2.6 or higher
128
+ - Bundler (for Ruby gem scanning)
129
+ - NPM (optional, for NPM package scanning)
130
+ - `bundler-audit` (optional, for enhanced gem vulnerability detection)
131
+
132
+ ### Installing bundler-audit (recommended)
133
+
134
+ ```bash
135
+ gem install bundler-audit
136
+ ```
137
+
138
+ **Note:** Without `bundler-audit`, gem vulnerability scanning will be skipped.
139
+
140
+ ## Development
141
+
142
+ After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake spec` to run the tests. You can also run `bin/console` for an interactive prompt.
143
+
144
+ ### Running tests
145
+
146
+ ```bash
147
+ rake spec
148
+ ```
149
+
150
+ ### Running RuboCop
151
+
152
+ ```bash
153
+ rake rubocop
154
+ ```
155
+
156
+ ### Building the gem
157
+
158
+ ```bash
159
+ gem build rubion.gemspec
160
+ ```
161
+
162
+ ### Installing locally
163
+
164
+ ```bash
165
+ rake install_local
166
+ ```
167
+
168
+ ## How It Works
169
+
170
+ Rubion uses a modular architecture:
171
+
172
+ 1. **Scanner** (`lib/rubion/scanner.rb`): Executes various commands to scan for vulnerabilities and outdated versions
173
+ - `bundle-audit check` for gem vulnerabilities
174
+ - `bundle outdated --parseable` for gem versions
175
+ - `npm audit --json` for package vulnerabilities
176
+ - `npm outdated --json` for package versions
177
+ - Fetches release dates and version data from RubyGems.org and NPM registry APIs
178
+ - Uses parallel processing (10 concurrent threads) for fast API calls
179
+
180
+ 2. **Reporter** (`lib/rubion/reporter.rb`): Formats scan results into beautiful terminal tables using `terminal-table`
181
+ - Adds severity icons (🔴 🟠 🟡 🟢 ⚪)
182
+ - Formats dates, time differences, and version counts
183
+ - Supports incremental output (gems first, then packages)
184
+
185
+ 3. **CLI** (`lib/rubion.rb`): Provides the command-line interface
186
+ - Parses command-line options (`--gems-only`, `--packages-only`)
187
+ - Coordinates scanning and reporting
188
+
189
+ For detailed information about data collection and mapping, see [HOW_IT_WORKS.md](HOW_IT_WORKS.md).
190
+
191
+ ## Extending Rubion
192
+
193
+ Rubion is designed to be easily extensible. To add new scanners:
194
+
195
+ 1. Add a new method in `lib/rubion/scanner.rb`
196
+ 2. Add a corresponding report method in `lib/rubion/reporter.rb`
197
+ 3. Update the scan flow in `Scanner#scan`
198
+
199
+ Example:
200
+
201
+ ```ruby
202
+ # In scanner.rb
203
+ def scan_python_packages
204
+ # Your scanning logic here
205
+ @result.python_vulnerabilities = check_pip_vulnerabilities
206
+ end
207
+
208
+ # In reporter.rb
209
+ def print_python_vulnerabilities
210
+ # Your reporting logic here
211
+ end
212
+ ```
213
+
214
+ ## Contributing
215
+
216
+ Bug reports and pull requests are welcome on GitHub at https://github.com/yourusername/rubion.
217
+
218
+ 1. Fork it
219
+ 2. Create your feature branch (`git checkout -b feature/my-new-feature`)
220
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
221
+ 4. Push to the branch (`git push origin feature/my-new-feature`)
222
+ 5. Create new Pull Request
223
+
224
+ ## License
225
+
226
+ The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
227
+
228
+ ## Code of Conduct
229
+
230
+ Everyone interacting in the Rubion project's codebases, issue trackers, chat rooms and mailing lists is expected to follow the code of conduct.
231
+
232
+ ## Support
233
+
234
+ If you have any questions or need help, please:
235
+ - Open an issue on GitHub
236
+ - Check the documentation
237
+ - Contact the maintainers
238
+
239
+ ## Performance
240
+
241
+ Rubion is optimized for speed:
242
+
243
+ - **Parallel API Processing**: Uses 10 concurrent threads to fetch version data from RubyGems.org and NPM registry
244
+ - **Single API Call Per Package**: Fetches all necessary data (dates, version list) in one request
245
+ - **Incremental Output**: Shows gem results immediately, then scans packages (better UX)
246
+ - **Progress Indicators**: Shows real-time progress like "Checking Ruby gems... 10/54"
247
+
248
+ Typical scan times:
249
+ - Gems only: ~4-5 seconds (for ~140 gems)
250
+ - Packages only: ~3-4 seconds (for ~50 packages)
251
+ - Both: ~7-9 seconds total
252
+
253
+ ## Roadmap
254
+
255
+ Future features planned:
256
+ - [ ] Sorting options (by severity, name, date, etc.)
257
+ - [ ] Filtering options (by severity, outdated threshold, etc.)
258
+ - [ ] Export formats (JSON, CSV, HTML)
259
+ - [ ] Summary statistics
260
+ - [ ] Update command suggestions
261
+ - [ ] Support for Python (pip) packages
262
+ - [ ] Support for PHP (composer) packages
263
+ - [ ] Support for Go modules
264
+ - [ ] CI/CD integration flags
265
+ - [ ] Configurable severity thresholds
266
+ - [ ] Auto-fix suggestions
267
+ - [ ] Historical tracking of vulnerabilities
268
+
269
+ ## Acknowledgments
270
+
271
+ - Built with [terminal-table](https://github.com/tj/terminal-table)
272
+ - Inspired by tools like `bundle-audit` and `npm audit`
273
+
data/bin/rubion ADDED
@@ -0,0 +1,7 @@
1
+ #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
3
+
4
+ require_relative '../lib/rubion'
5
+
6
+ Rubion::CLI.start(ARGV)
7
+
@@ -0,0 +1,246 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'terminal-table'
4
+
5
+ module Rubion
6
+ class Reporter
7
+ def initialize(scan_result)
8
+ @result = scan_result
9
+ end
10
+
11
+ def report
12
+ print_header
13
+ _print_gem_vulnerabilities
14
+ _print_gem_versions
15
+ _print_package_vulnerabilities
16
+ _print_package_versions
17
+ print_summary
18
+ end
19
+
20
+ # Public methods for incremental reporting
21
+ def print_gem_vulnerabilities
22
+ _print_gem_vulnerabilities
23
+ end
24
+
25
+ def print_gem_versions
26
+ _print_gem_versions
27
+ end
28
+
29
+ def print_package_vulnerabilities
30
+ _print_package_vulnerabilities
31
+ end
32
+
33
+ def print_package_versions
34
+ _print_package_versions
35
+ end
36
+
37
+ private
38
+
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
+ def print_header
65
+ # Simplified header
66
+ puts "\n"
67
+ end
68
+
69
+ def _print_gem_vulnerabilities
70
+ if @result.gem_vulnerabilities.empty?
71
+ puts " ✅ No vulnerabilities found!\n\n"
72
+ return
73
+ end
74
+
75
+ table = Terminal::Table.new do |t|
76
+ t.headings = %w[Level Name Version Vulnerability]
77
+
78
+ @result.gem_vulnerabilities.each do |vuln|
79
+ t.add_row [
80
+ severity_with_icon(vuln[:severity]),
81
+ vuln[:gem],
82
+ vuln[:version],
83
+ truncate(vuln[:title], 50)
84
+ ]
85
+ end
86
+ end
87
+
88
+ puts table
89
+ puts "\n"
90
+ end
91
+
92
+ def _print_gem_versions
93
+ puts "Gem Versions:\n\n"
94
+
95
+ if @result.gem_versions.empty?
96
+ puts " ✅ All gems are up to date!\n\n"
97
+ return
98
+ end
99
+
100
+ table = Terminal::Table.new do |t|
101
+ t.headings = ['Name', 'Current', 'Date', 'Latest', 'Date', 'Behind By(Time)', 'Behind By(Versions)']
102
+
103
+ @result.gem_versions.each do |gem|
104
+ t.add_row [
105
+ gem[:gem],
106
+ gem[:current],
107
+ gem[:current_date] || 'N/A',
108
+ gem[:latest],
109
+ gem[:latest_date] || 'N/A',
110
+ gem[:time_diff] || 'N/A',
111
+ gem[:version_count] || 'N/A'
112
+ ]
113
+ end
114
+ end
115
+
116
+ puts table
117
+ puts "\n"
118
+ end
119
+
120
+ def _print_package_vulnerabilities
121
+ puts "Package Vulnerabilities:\n\n"
122
+
123
+ if @result.package_vulnerabilities.empty?
124
+ puts " ✅ No vulnerabilities found!\n\n"
125
+ return
126
+ end
127
+
128
+ table = Terminal::Table.new do |t|
129
+ t.headings = %w[Level Name Version Vulnerability]
130
+
131
+ @result.package_vulnerabilities.each do |vuln|
132
+ t.add_row [
133
+ severity_with_icon(vuln[:severity]),
134
+ vuln[:package],
135
+ vuln[:version],
136
+ truncate(vuln[:title], 50)
137
+ ]
138
+ end
139
+ end
140
+
141
+ puts table
142
+ puts "\n"
143
+ end
144
+
145
+ def _print_package_versions
146
+ puts "Package Versions:\n\n"
147
+
148
+ if @result.package_versions.empty?
149
+ puts " ✅ All packages are up to date!\n\n"
150
+ return
151
+ end
152
+
153
+ table = Terminal::Table.new do |t|
154
+ t.headings = ['Name', 'Current', 'Date', 'Latest', 'Date', 'Behind By', 'Versions']
155
+
156
+ @result.package_versions.each do |pkg|
157
+ t.add_row [
158
+ pkg[:package],
159
+ pkg[:current],
160
+ pkg[:current_date] || 'N/A',
161
+ pkg[:latest],
162
+ pkg[:latest_date] || 'N/A',
163
+ pkg[:time_diff] || 'N/A',
164
+ pkg[:version_count] || 'N/A'
165
+ ]
166
+ end
167
+ end
168
+
169
+ puts table
170
+ puts "\n"
171
+ end
172
+
173
+ def print_summary
174
+ # Minimal summary at the end
175
+ puts "\n"
176
+ end
177
+
178
+ # Helpers
179
+
180
+ def severity_with_icon(severity)
181
+ severity_str = severity.to_s.capitalize
182
+
183
+ case severity.to_s.downcase
184
+ when 'critical'
185
+ "🔴 #{severity_str}"
186
+ when 'high'
187
+ "🟠 #{severity_str}"
188
+ when 'medium', 'moderate'
189
+ "🟡 #{severity_str}"
190
+ when 'low'
191
+ "🟢 #{severity_str}"
192
+ when 'unknown'
193
+ "⚪ #{severity_str}"
194
+ else
195
+ severity_str
196
+ end
197
+ end
198
+
199
+ def colorize_severity(severity)
200
+ case severity.to_s.downcase
201
+ when 'critical'
202
+ "🔴 #{severity}"
203
+ when 'high'
204
+ "🟠 #{severity}"
205
+ when 'medium', 'moderate'
206
+ "🟡 #{severity}"
207
+ when 'low'
208
+ "🟢 #{severity}"
209
+ else
210
+ severity
211
+ end
212
+ end
213
+
214
+ def colorize_count(count)
215
+ count > 0 ? "🔴 #{count}" : "✅ #{count}"
216
+ end
217
+
218
+ def truncate(text, length = 50)
219
+ return text if text.length <= length
220
+
221
+ "#{text[0..length - 3]}..."
222
+ end
223
+
224
+ def version_difference(current, latest)
225
+ # Simple version difference calculation
226
+ current_parts = current.split('.').map(&:to_i)
227
+ latest_parts = latest.split('.').map(&:to_i)
228
+
229
+ major_diff = (latest_parts[0] || 0) - (current_parts[0] || 0)
230
+ minor_diff = (latest_parts[1] || 0) - (current_parts[1] || 0)
231
+ patch_diff = (latest_parts[2] || 0) - (current_parts[2] || 0)
232
+
233
+ if major_diff > 0
234
+ "#{major_diff} major"
235
+ elsif minor_diff > 0
236
+ "#{minor_diff} minor"
237
+ elsif patch_diff > 0
238
+ "#{patch_diff} patch"
239
+ else
240
+ 'up to date'
241
+ end
242
+ rescue StandardError
243
+ 'unknown'
244
+ end
245
+ end
246
+ end