Module: Kettle::Rb::GemFloors
- Defined in:
- lib/kettle/rb/gem_floors.rb,
lib/kettle/rb/gem_floors/data.rb,
lib/kettle/rb/gem_floors/generator.rb
Overview
Security floors for tracked gems, one entry per minor series.
For each series the floor is the newest released patch that keeps the series' original minimum Ruby, never below an advisory's patched version. Advisories that still affect the floor (a series with no fixed release) are recorded as unpatched so consumers can decide how to treat it.
The data lives in gem_floors/data.rb and is regenerated from the
rubygems.org versions API and ruby-advisory-db by
rake kettle:rb:gem_floors:generate (see Generator).
Defined Under Namespace
Constant Summary collapse
- ENTRIES =
begin entries = {} ROWS.each do |row| entry = Entry.new(*row) entry.patched_advisories.freeze entry.unpatched_advisories.freeze entry.freeze entries[[entry.gem_name, entry.series]] = entry end entries.freeze end
- GENERATED_ON =
"2026-09-15"- ADVISORY_DB_COMMIT =
"f08b5bf5b277"- TRACKED_GEMS =
["activemodel", "activerecord", "activesupport", "sqlite3"].freeze
- ROWS =
[ ["activemodel", "5.2", "5.2.8.1", ">= 2.2.2", [], []], ["activemodel", "6.0", "6.0.6.1", ">= 2.5.0", [], []], ["activemodel", "6.1", "6.1.7.10", ">= 2.5.0", [], []], ["activemodel", "7.0", "7.0.10", ">= 2.7.0", [], []], ["activemodel", "7.1", "7.1.6", ">= 2.7.0", [], []], ["activemodel", "7.2", "7.2.3.2", ">= 3.1.0", [], []], ["activemodel", "8.0", "8.0.5.1", ">= 3.2.0", [], []], ["activemodel", "8.1", "8.1.3.1", ">= 3.2.0", [], []], ["activerecord", "5.2", "5.2.8.1", ">= 2.2.2", ["CVE-2021-22880", "CVE-2022-32224", "CVE-2022-44566"], ["CVE-2025-55193"]], ["activerecord", "6.0", "6.0.6.1", ">= 2.5.0", ["CVE-2021-22880", "CVE-2022-32224", "CVE-2023-22794"], ["CVE-2022-44566", "CVE-2025-55193"]], ["activerecord", "6.1", "6.1.7.10", ">= 2.5.0", ["CVE-2021-22880", "CVE-2022-32224", "CVE-2022-44566", "CVE-2023-22794"], ["CVE-2025-55193"]], ["activerecord", "7.0", "7.0.10", ">= 2.7.0", ["CVE-2022-32224", "CVE-2022-44566", "CVE-2023-22794"], ["CVE-2025-55193"]], ["activerecord", "7.1", "7.1.6", ">= 2.7.0", ["CVE-2025-55193"], []], ["activerecord", "7.2", "7.2.3.2", ">= 3.1.0", ["CVE-2025-55193"], []], ["activerecord", "8.0", "8.0.5.1", ">= 3.2.0", ["CVE-2025-55193"], []], ["activerecord", "8.1", "8.1.3.1", ">= 3.2.0", [], []], ["activesupport", "5.2", "5.2.8.1", ">= 2.2.2", ["CVE-2020-8165", "CVE-2023-22796"], ["CVE-2023-28120", "CVE-2023-38037", "CVE-2026-33169", "CVE-2026-33170", "CVE-2026-33176"]], ["activesupport", "6.0", "6.0.6.1", ">= 2.5.0", ["CVE-2020-8165"], ["CVE-2023-22796", "CVE-2023-28120", "CVE-2023-38037", "CVE-2026-33169", "CVE-2026-33170", "CVE-2026-33176"]], ["activesupport", "6.1", "6.1.7.10", ">= 2.5.0", ["CVE-2023-22796", "CVE-2023-28120", "CVE-2023-38037"], ["CVE-2026-33169", "CVE-2026-33170", "CVE-2026-33176"]], ["activesupport", "7.0", "7.0.10", ">= 2.7.0", ["CVE-2023-22796", "CVE-2023-28120", "CVE-2023-38037"], ["CVE-2026-33169", "CVE-2026-33170", "CVE-2026-33176"]], ["activesupport", "7.1", "7.1.6", ">= 2.7.0", [], ["CVE-2026-33169", "CVE-2026-33170", "CVE-2026-33176"]], ["activesupport", "7.2", "7.2.3.2", ">= 3.1.0", ["CVE-2026-33169", "CVE-2026-33170", "CVE-2026-33176"], []], ["activesupport", "8.0", "8.0.5.1", ">= 3.2.0", ["CVE-2026-33169", "CVE-2026-33170", "CVE-2026-33176"], []], ["activesupport", "8.1", "8.1.3.1", ">= 3.2.0", ["CVE-2026-33169", "CVE-2026-33170", "CVE-2026-33176"], []], ["sqlite3", "1.3", "1.3.13", ">= 1.8.7", [], ["CVE-2026-54619"]], ["sqlite3", "1.4", "1.4.4", ">= 1.8.7", [], ["CVE-2026-54619", "GHSA-mwm8-39rw-8826"]], ["sqlite3", "1.5", "1.5.4", ">= 1.9.2", ["GHSA-mgvv-5mxp-xq67"], ["CVE-2026-54619", "GHSA-mwm8-39rw-8826"]], ["sqlite3", "1.6", "1.6.9", ">= 1.9.2", [], ["CVE-2026-54619", "GHSA-mwm8-39rw-8826"]], ["sqlite3", "1.7", "1.7.3", ">= 2.7", [], ["CVE-2026-54619", "GHSA-mwm8-39rw-8826"]], ["sqlite3", "2.0", "2.0.4", ">= 3.0", [], ["CVE-2026-54619", "GHSA-mwm8-39rw-8826"]], ["sqlite3", "2.1", "2.1.1", ">= 3.1", [], ["CVE-2026-54619", "CVE-2026-54620", "GHSA-mwm8-39rw-8826"]], ["sqlite3", "2.2", "2.2.0", ">= 3.1", [], ["CVE-2026-54619", "CVE-2026-54620", "GHSA-mwm8-39rw-8826"]], ["sqlite3", "2.3", "2.3.1", ">= 3.1", [], ["CVE-2026-54619", "CVE-2026-54620", "GHSA-mwm8-39rw-8826"]], ["sqlite3", "2.4", "2.4.1", ">= 3.1", [], ["CVE-2026-54619", "CVE-2026-54620", "GHSA-mwm8-39rw-8826"]], ["sqlite3", "2.5", "2.5.0", ">= 3.1", [], ["CVE-2026-54619", "CVE-2026-54620", "GHSA-mwm8-39rw-8826"]], ["sqlite3", "2.6", "2.6.0", ">= 3.1", [], ["CVE-2026-54619", "CVE-2026-54620", "GHSA-mwm8-39rw-8826"]], ["sqlite3", "2.7", "2.7.4", ">= 3.1", [], ["CVE-2026-54619", "CVE-2026-54620", "GHSA-mwm8-39rw-8826"]], ["sqlite3", "2.8", "2.8.1", ">= 3.1", [], ["CVE-2026-54619", "CVE-2026-54620", "GHSA-mwm8-39rw-8826"]], ["sqlite3", "2.9", "2.9.6", ">= 3.2", ["CVE-2026-54619", "CVE-2026-54620", "GHSA-mwm8-39rw-8826"], []] ].freeze
Class Method Summary collapse
-
.entries_for(gem_name) ⇒ Array<Entry>
Entries for
gem_name, oldest series first. - .entry(gem_name, version) ⇒ Entry?
-
.floor(gem_name, version) ⇒ String?
The security floor for the series containing
version. -
.requirements(gem_name, version) ⇒ Array<String>
Requirements that pin the series and enforce its floor.
-
.series_for(version) ⇒ String?
The "major.minor" series, or nil when it cannot be determined.
-
.tracked?(gem_name) ⇒ Boolean
Whether floors are tracked for
gem_name. -
.unpatched_advisories(gem_name, version) ⇒ Array<String>
Advisory identifiers still affecting the series' floor.
Class Method Details
.entries_for(gem_name) ⇒ Array<Entry>
57 58 59 60 61 |
# File 'lib/kettle/rb/gem_floors.rb', line 57 def entries_for(gem_name) ENTRIES.values .select { |entry| entry.gem_name == gem_name.to_s } .sort_by { |entry| Gem::Version.new(entry.series) } end |
.entry(gem_name, version) ⇒ Entry?
50 51 52 53 |
# File 'lib/kettle/rb/gem_floors.rb', line 50 def entry(gem_name, version) series = series_for(version) series && ENTRIES[[gem_name.to_s, series]] end |
.floor(gem_name, version) ⇒ String?
64 65 66 67 |
# File 'lib/kettle/rb/gem_floors.rb', line 64 def floor(gem_name, version) found = entry(gem_name, version) found && found.floor end |
.requirements(gem_name, version) ⇒ Array<String>
Requirements that pin the series and enforce its floor.
74 75 76 77 78 79 |
# File 'lib/kettle/rb/gem_floors.rb', line 74 def requirements(gem_name, version) found = entry(gem_name, version) return [] unless found ["~> #{found.series}.0", ">= #{found.floor}"] end |
.series_for(version) ⇒ String?
89 90 91 92 93 94 95 96 |
# File 'lib/kettle/rb/gem_floors.rb', line 89 def series_for(version) segments = Gem::Version.new(version.to_s).segments return nil if segments.size < 2 "#{segments[0]}.#{segments[1]}" rescue ArgumentError nil end |
.tracked?(gem_name) ⇒ Boolean
43 44 45 |
# File 'lib/kettle/rb/gem_floors.rb', line 43 def tracked?(gem_name) TRACKED_GEMS.include?(gem_name.to_s) end |
.unpatched_advisories(gem_name, version) ⇒ Array<String>
82 83 84 85 |
# File 'lib/kettle/rb/gem_floors.rb', line 82 def unpatched_advisories(gem_name, version) found = entry(gem_name, version) found ? found.unpatched_advisories : [] end |