still_active 3.0.0.rc6 → 3.0.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 +4 -4
- data/CHANGELOG.md +39 -2
- data/README.md +27 -2
- data/lib/still_active/artifactory_client.rb +1 -1
- data/lib/still_active/cli.rb +91 -29
- data/lib/still_active/compact_index_client.rb +1 -1
- data/lib/still_active/config.rb +2 -0
- data/lib/still_active/config_file.rb +3 -2
- data/lib/still_active/deps_dev_client.rb +24 -3
- data/lib/still_active/ecosystem_lens.rb +19 -7
- data/lib/still_active/ecosystems_client.rb +1 -1
- data/lib/still_active/forgejo_client.rb +1 -1
- data/lib/still_active/gitlab_client.rb +1 -1
- data/lib/{helpers → still_active/helpers}/activity_helper.rb +1 -1
- data/lib/{helpers → still_active/helpers}/cyclonedx_helper.rb +85 -7
- data/lib/{helpers → still_active/helpers}/libyear_helper.rb +1 -1
- data/lib/{helpers → still_active/helpers}/markdown_helper.rb +19 -0
- data/lib/{helpers → still_active/helpers}/sarif_helper.rb +17 -2
- data/lib/still_active/helpers/sbom_graph.rb +166 -0
- data/lib/{helpers → still_active/helpers}/status_helper.rb +23 -5
- data/lib/{helpers → still_active/helpers}/terminal_helper.rb +15 -0
- data/lib/{helpers → still_active/helpers}/version_helper.rb +14 -2
- data/lib/still_active/options.rb +6 -3
- data/lib/still_active/osv_client.rb +2 -2
- data/lib/still_active/poison_security_correlator.rb +3 -3
- data/lib/still_active/pypi_client.rb +1 -1
- data/lib/still_active/sarif/rules.rb +15 -0
- data/lib/still_active/sbom_reader.rb +117 -2
- data/lib/still_active/sbom_workflow.rb +4 -4
- data/lib/still_active/suppressions.rb +5 -3
- data/lib/still_active/version.rb +1 -1
- data/lib/still_active/workflow.rb +17 -11
- metadata +34 -33
- /data/lib/{helpers → still_active/helpers}/alternatives_helper.rb +0 -0
- /data/lib/{helpers → still_active/helpers}/ansi_helper.rb +0 -0
- /data/lib/{helpers → still_active/helpers}/bot_context.rb +0 -0
- /data/lib/{helpers → still_active/helpers}/bundler_helper.rb +0 -0
- /data/lib/{helpers → still_active/helpers}/catalog_index.rb +0 -0
- /data/lib/{helpers → still_active/helpers}/constraint_helper.rb +0 -0
- /data/lib/{helpers → still_active/helpers}/cvss_helper.rb +0 -0
- /data/lib/{helpers → still_active/helpers}/dependency_helper.rb +0 -0
- /data/lib/{helpers → still_active/helpers}/diff_markdown_helper.rb +0 -0
- /data/lib/{helpers → still_active/helpers}/dotnet_helper.rb +0 -0
- /data/lib/{helpers → still_active/helpers}/emoji_helper.rb +0 -0
- /data/lib/{helpers → still_active/helpers}/endoflife_helper.rb +0 -0
- /data/lib/{helpers → still_active/helpers}/http_helper.rb +0 -0
- /data/lib/{helpers → still_active/helpers}/lockfile_dependency_parser.rb +0 -0
- /data/lib/{helpers → still_active/helpers}/lockfile_indexer.rb +0 -0
- /data/lib/{helpers → still_active/helpers}/markdown_escape.rb +0 -0
- /data/lib/{helpers → still_active/helpers}/pep440_helper.rb +0 -0
- /data/lib/{helpers → still_active/helpers}/python_helper.rb +0 -0
- /data/lib/{helpers → still_active/helpers}/ruby_advisory_db.rb +0 -0
- /data/lib/{helpers → still_active/helpers}/ruby_helper.rb +0 -0
- /data/lib/{helpers → still_active/helpers}/runtime_ceiling_helper.rb +0 -0
- /data/lib/{helpers → still_active/helpers}/semver_satisfaction.rb +0 -0
- /data/lib/{helpers → still_active/helpers}/summary_helper.rb +0 -0
- /data/lib/{helpers → still_active/helpers}/vulnerability_helper.rb +0 -0
|
@@ -4,6 +4,8 @@ require "json"
|
|
|
4
4
|
require "uri"
|
|
5
5
|
require "package_url"
|
|
6
6
|
|
|
7
|
+
require_relative "helpers/sbom_graph"
|
|
8
|
+
|
|
7
9
|
module StillActive
|
|
8
10
|
# Reads a CycloneDX SBOM (e.g. produced by Syft) into a clean, normalized
|
|
9
11
|
# dependency set -- the breadth input for non-Ruby ecosystems, where the
|
|
@@ -63,12 +65,19 @@ module StillActive
|
|
|
63
65
|
|
|
64
66
|
deps = []
|
|
65
67
|
unassessable = []
|
|
68
|
+
entries_by_ref = {}
|
|
66
69
|
components.each do |component|
|
|
67
70
|
kind, entry = classify(component)
|
|
68
71
|
entry[:production] = !dev_signal?(component) if kind == :dependency && marks_dev
|
|
69
|
-
|
|
72
|
+
if kind == :dependency
|
|
73
|
+
ref = component["bom-ref"]
|
|
74
|
+
entries_by_ref[ref] = entry if ref.is_a?(String)
|
|
75
|
+
deps << entry
|
|
76
|
+
end
|
|
70
77
|
unassessable << entry if kind == :unassessable
|
|
71
78
|
end
|
|
79
|
+
drop_project_components(doc, deps, entries_by_ref)
|
|
80
|
+
attach_dependency_graph(doc, deps, entries_by_ref)
|
|
72
81
|
# uniq collapses a package that a generator lists more than once (e.g. Syft's
|
|
73
82
|
# per-location entries); `production` is derived from each component's own
|
|
74
83
|
# signal, so duplicates of the same name+version dedup cleanly unless a
|
|
@@ -80,6 +89,92 @@ module StillActive
|
|
|
80
89
|
|
|
81
90
|
private
|
|
82
91
|
|
|
92
|
+
# A Syft SBOM lists the scanned project as an ordinary library component with a
|
|
93
|
+
# purl, so it was classified as one of its own dependencies and assessed: no
|
|
94
|
+
# registry entry, therefore no releases, therefore reported as critically stale.
|
|
95
|
+
# That is a confident false verdict about the user's own code, on the workflow
|
|
96
|
+
# the README recommends, and it trips --fail-if-critical.
|
|
97
|
+
#
|
|
98
|
+
# The project is dropped rather than surfaced as unassessable: it is not a
|
|
99
|
+
# dependency we failed to assess, it is not a dependency, which is the same
|
|
100
|
+
# treatment CI actions and opaque binaries already get. Nothing changes for an
|
|
101
|
+
# SBOM with no dependency graph, and the rule needs the project to actually
|
|
102
|
+
# depend on something, so a dependency with a missing parent edge is never
|
|
103
|
+
# dropped for looking parentless.
|
|
104
|
+
def drop_project_components(doc, deps, entries_by_ref)
|
|
105
|
+
return if entries_by_ref.empty?
|
|
106
|
+
|
|
107
|
+
roots = SbomGraph.project_refs(dependencies: doc["dependencies"], library_refs: entries_by_ref.keys.to_set)
|
|
108
|
+
return if roots.empty?
|
|
109
|
+
|
|
110
|
+
# Compared by identity, not value: two components can classify to equal
|
|
111
|
+
# hashes, and only the one the graph named as a root should be dropped.
|
|
112
|
+
dropped = roots.filter_map { |ref| entries_by_ref.delete(ref)&.object_id }.to_set
|
|
113
|
+
deps.reject! { |entry| dropped.include?(entry.object_id) }
|
|
114
|
+
end
|
|
115
|
+
|
|
116
|
+
# Place each package in the CycloneDX dependency graph, so a cross-ecosystem
|
|
117
|
+
# audit can say which packages you actually declared and, for the rest, the
|
|
118
|
+
# declared package that pulls each one in. Same contract as the native path:
|
|
119
|
+
# `direct` is a boolean, and `dependency_path` is present only for a transitive
|
|
120
|
+
# package, head-first so it names the dependency a maintainer can act on.
|
|
121
|
+
#
|
|
122
|
+
# Both fields are attached ONLY to packages the graph actually places. A
|
|
123
|
+
# generator can emit a near-empty graph (a Syft directory scan of a Ruby project
|
|
124
|
+
# produced one edge across 789 components), and stamping `direct: false` on
|
|
125
|
+
# everything it failed to mention would be the positive claim "none of these are
|
|
126
|
+
# yours" about a document that never said. Absent means unknown, which the
|
|
127
|
+
# renderers already treat correctly: they test `direct == false`, not falsiness.
|
|
128
|
+
def attach_dependency_graph(doc, deps, entries_by_ref)
|
|
129
|
+
return if entries_by_ref.empty?
|
|
130
|
+
|
|
131
|
+
placements = SbomGraph.resolve(
|
|
132
|
+
dependencies: doc["dependencies"],
|
|
133
|
+
root_ref: doc.dig("metadata", "component", "bom-ref"),
|
|
134
|
+
library_refs: entries_by_ref.keys.to_set
|
|
135
|
+
)
|
|
136
|
+
return if placements.nil?
|
|
137
|
+
|
|
138
|
+
identities = entries_by_ref.transform_values { |entry| "#{entry[:ecosystem]}/#{entry[:name]}" }
|
|
139
|
+
# Fold per package identity first. A generator may list one package under
|
|
140
|
+
# several bom-refs (Syft emits a component per location), and those copies are
|
|
141
|
+
# collapsed by `uniq` below; if they carried different placements they would
|
|
142
|
+
# stop being equal and the package would appear twice in the audit.
|
|
143
|
+
best = {}
|
|
144
|
+
entries_by_ref.each do |ref, entry|
|
|
145
|
+
placement = placements[ref]
|
|
146
|
+
next if placement.nil?
|
|
147
|
+
|
|
148
|
+
key = identity_key(entry)
|
|
149
|
+
best[key] = better_placement(best[key], placement)
|
|
150
|
+
end
|
|
151
|
+
|
|
152
|
+
deps.each do |entry|
|
|
153
|
+
placement = best[identity_key(entry)]
|
|
154
|
+
next if placement.nil?
|
|
155
|
+
|
|
156
|
+
entry[:direct] = placement[:direct]
|
|
157
|
+
next if placement[:direct]
|
|
158
|
+
|
|
159
|
+
path = Array(placement[:path]).filter_map { |ref| identities[ref] }
|
|
160
|
+
entry[:dependency_path] = path unless path.empty?
|
|
161
|
+
end
|
|
162
|
+
end
|
|
163
|
+
|
|
164
|
+
def identity_key(entry)
|
|
165
|
+
[entry[:ecosystem], entry[:name], entry[:version]]
|
|
166
|
+
end
|
|
167
|
+
|
|
168
|
+
# Declared beats pulled-in (you can act on it directly), and among transitive
|
|
169
|
+
# placements the shorter path wins, matching the native path's shortest-path BFS.
|
|
170
|
+
def better_placement(current, candidate)
|
|
171
|
+
return candidate if current.nil?
|
|
172
|
+
return current if current[:direct]
|
|
173
|
+
return candidate if candidate[:direct]
|
|
174
|
+
|
|
175
|
+
(Array(candidate[:path]).length < Array(current[:path]).length) ? candidate : current
|
|
176
|
+
end
|
|
177
|
+
|
|
83
178
|
# Whether a component is marked dev/test-only. CycloneDX `scope` (excluded =
|
|
84
179
|
# not part of the product, optional = not needed at runtime) is the standard;
|
|
85
180
|
# tools that don't set scope may instead emit a property (cyclonedx-npm's
|
|
@@ -146,7 +241,12 @@ module StillActive
|
|
|
146
241
|
return [:unassessable, {ecosystem: ecosystem, name: full_name, version: parsed.version, reason: :private_registry, repository_url: repository_url}]
|
|
147
242
|
end
|
|
148
243
|
|
|
149
|
-
|
|
244
|
+
# The input's own PURL, kept verbatim rather than parsed-and-rebuilt. An
|
|
245
|
+
# enriched SBOM re-emits it unchanged, so whatever a consumer matched on
|
|
246
|
+
# the input it matches on our output, and no per-ecosystem PURL
|
|
247
|
+
# reconstruction (npm scopes, maven group:artifact, go module paths) can
|
|
248
|
+
# get it subtly wrong.
|
|
249
|
+
[:dependency, {ecosystem: ecosystem, name: full_name, version: parsed.version, purl: preserved_purl(purl)}]
|
|
150
250
|
elsif NOISE_TYPES.include?(type)
|
|
151
251
|
nil # CI actions / opaque binaries: not a package dependency
|
|
152
252
|
else
|
|
@@ -161,6 +261,21 @@ module StillActive
|
|
|
161
261
|
[:unassessable, {ecosystem: nil, name: name, reason: :malformed_purl}]
|
|
162
262
|
end
|
|
163
263
|
|
|
264
|
+
# The input's PURL, kept for re-emission in an enriched SBOM, with Syft's
|
|
265
|
+
# `package-id` qualifier removed. That qualifier is Syft's internal per-location
|
|
266
|
+
# bookkeeping rather than part of the package's identity, and it is why the same
|
|
267
|
+
# package can appear twice under two different PURLs; dropping it is what lets
|
|
268
|
+
# those copies still collapse. Everything else is left byte-identical rather than
|
|
269
|
+
# re-serialized through PackageURL, so a consumer that matched the input PURL
|
|
270
|
+
# matches ours, with no chance of a normalization changing the encoding.
|
|
271
|
+
def preserved_purl(purl)
|
|
272
|
+
base, separator, query = purl.partition("?")
|
|
273
|
+
return purl if separator.empty?
|
|
274
|
+
|
|
275
|
+
kept = query.split("&").reject { |pair| pair.start_with?("package-id=") }
|
|
276
|
+
kept.empty? ? base : "#{base}?#{kept.join("&")}"
|
|
277
|
+
end
|
|
278
|
+
|
|
164
279
|
# Whether a repository_url points at a known public registry. We only read the
|
|
165
280
|
# host; we never connect to it (a lockfile/SBOM-derived URL is untrusted). An
|
|
166
281
|
# unparseable or non-public host reads as private, failing safe.
|
|
@@ -3,8 +3,8 @@
|
|
|
3
3
|
require_relative "ecosystem_lens"
|
|
4
4
|
require_relative "ceiling_reconciler"
|
|
5
5
|
require_relative "poison_security_correlator"
|
|
6
|
-
require_relative "
|
|
7
|
-
require_relative "
|
|
6
|
+
require_relative "helpers/python_helper"
|
|
7
|
+
require_relative "helpers/dotnet_helper"
|
|
8
8
|
require "async"
|
|
9
9
|
require "async/barrier"
|
|
10
10
|
require "async/semaphore"
|
|
@@ -62,7 +62,7 @@ module StillActive
|
|
|
62
62
|
# otherwise): absent stays "unknown", never a false that reads as test-only.
|
|
63
63
|
result["#{dep[:ecosystem]}/#{dep[:name]}@#{dep[:version]}"] =
|
|
64
64
|
EcosystemLens.assess(ecosystem: dep[:ecosystem], name: dep[:name], version: dep[:version], constraint_cache: constraint_cache, runtime_ranges: runtime_ranges)
|
|
65
|
-
.merge(dep.slice(:production))
|
|
65
|
+
.merge(dep.slice(:production, :direct, :dependency_path, :purl))
|
|
66
66
|
rescue => e
|
|
67
67
|
# One dependency's failure must not abort the audit, but it must not
|
|
68
68
|
# disappear either: record it as an unassessable entry (same shape as
|
|
@@ -70,7 +70,7 @@ module StillActive
|
|
|
70
70
|
# production rides along (when known, via slice) so a failed prod dep
|
|
71
71
|
# stays distinguishable from a failed dev one.
|
|
72
72
|
failures << {ecosystem: dep[:ecosystem], name: dep[:name], version: dep[:version], reason: :assessment_error, error: "#{e.class}: #{e.message}"}
|
|
73
|
-
.merge(dep.slice(:production))
|
|
73
|
+
.merge(dep.slice(:production, :direct, :dependency_path, :purl))
|
|
74
74
|
warn("error assessing #{dep[:ecosystem]}/#{dep[:name]}@#{dep[:version]}: #{e.class}\n\t#{e.message}")
|
|
75
75
|
ensure
|
|
76
76
|
completed += 1
|
|
@@ -16,7 +16,7 @@ module StillActive
|
|
|
16
16
|
# name an explicit advisory id, so a newly disclosed CVE on the same gem is
|
|
17
17
|
# never pre-silenced.
|
|
18
18
|
class Suppressions
|
|
19
|
-
GATEABLE_SIGNALS = [:activity, :vulnerability, :libyear, :poison, :language_ceiling].freeze
|
|
19
|
+
GATEABLE_SIGNALS = [:activity, :vulnerability, :libyear, :poison, :language_ceiling, :deprecated].freeze
|
|
20
20
|
|
|
21
21
|
Entry = Struct.new(:gem, :advisory, :signal, :reason, :expires, keyword_init: true) do
|
|
22
22
|
def whole_gem?
|
|
@@ -76,14 +76,16 @@ module StillActive
|
|
|
76
76
|
return false
|
|
77
77
|
end
|
|
78
78
|
if signal && !GATEABLE_SIGNALS.include?(signal)
|
|
79
|
-
|
|
79
|
+
# Listed from the constant rather than spelled out: the hand-written
|
|
80
|
+
# version had already drifted (it never mentioned language_ceiling).
|
|
81
|
+
warnings << "ignoring suppression for #{label}: unknown signal #{signal.inspect} (expected #{GATEABLE_SIGNALS.join(", ")})"
|
|
80
82
|
return false
|
|
81
83
|
end
|
|
82
84
|
if signal == :vulnerability && advisory.nil?
|
|
83
85
|
warnings << "ignoring vulnerability suppression for #{label}: must name an advisory id so newly disclosed advisories still surface"
|
|
84
86
|
return false
|
|
85
87
|
end
|
|
86
|
-
if [:activity, :libyear, :poison].include?(signal) && gem.nil?
|
|
88
|
+
if [:activity, :libyear, :poison, :deprecated].include?(signal) && gem.nil?
|
|
87
89
|
warnings << "ignoring #{signal} suppression: must name a gem"
|
|
88
90
|
return false
|
|
89
91
|
end
|
data/lib/still_active/version.rb
CHANGED
|
@@ -12,17 +12,17 @@ require_relative "forgejo_client"
|
|
|
12
12
|
require_relative "github_client"
|
|
13
13
|
require_relative "gitlab_client"
|
|
14
14
|
require_relative "repository"
|
|
15
|
-
require_relative "
|
|
16
|
-
require_relative "
|
|
17
|
-
require_relative "
|
|
18
|
-
require_relative "
|
|
19
|
-
require_relative "
|
|
20
|
-
require_relative "
|
|
21
|
-
require_relative "
|
|
22
|
-
require_relative "
|
|
23
|
-
require_relative "
|
|
24
|
-
require_relative "
|
|
25
|
-
require_relative "
|
|
15
|
+
require_relative "helpers/activity_helper"
|
|
16
|
+
require_relative "helpers/alternatives_helper"
|
|
17
|
+
require_relative "helpers/catalog_index"
|
|
18
|
+
require_relative "helpers/constraint_helper"
|
|
19
|
+
require_relative "helpers/http_helper"
|
|
20
|
+
require_relative "helpers/libyear_helper"
|
|
21
|
+
require_relative "helpers/ruby_advisory_db"
|
|
22
|
+
require_relative "helpers/ruby_helper"
|
|
23
|
+
require_relative "helpers/runtime_ceiling_helper"
|
|
24
|
+
require_relative "helpers/version_helper"
|
|
25
|
+
require_relative "helpers/vulnerability_helper"
|
|
26
26
|
require "async"
|
|
27
27
|
require "async/barrier"
|
|
28
28
|
require "async/semaphore"
|
|
@@ -390,6 +390,12 @@ module StillActive
|
|
|
390
390
|
{
|
|
391
391
|
scorecard_score: scorecard&.dig(:score),
|
|
392
392
|
scorecard_maintained: scorecard&.dig(:maintained),
|
|
393
|
+
# The maintainer's own "stop using this" declaration, from the same
|
|
394
|
+
# response as the advisories. RubyGems has no deprecation mechanism, so
|
|
395
|
+
# this is effectively always false for gems today; it is threaded anyway
|
|
396
|
+
# so the field means the same thing on both paths.
|
|
397
|
+
deprecated: info&.dig(:deprecated) == true,
|
|
398
|
+
deprecation_reason: info&.dig(:deprecation_reason),
|
|
393
399
|
vulnerability_count: vulnerabilities.length,
|
|
394
400
|
vulnerabilities: vulnerabilities
|
|
395
401
|
}
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: still_active
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 3.0.0
|
|
4
|
+
version: 3.0.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Sean Floyd
|
|
@@ -133,38 +133,6 @@ files:
|
|
|
133
133
|
- LICENSE.txt
|
|
134
134
|
- README.md
|
|
135
135
|
- bin/still_active
|
|
136
|
-
- lib/helpers/activity_helper.rb
|
|
137
|
-
- lib/helpers/alternatives_helper.rb
|
|
138
|
-
- lib/helpers/ansi_helper.rb
|
|
139
|
-
- lib/helpers/bot_context.rb
|
|
140
|
-
- lib/helpers/bundler_helper.rb
|
|
141
|
-
- lib/helpers/catalog_index.rb
|
|
142
|
-
- lib/helpers/constraint_helper.rb
|
|
143
|
-
- lib/helpers/cvss_helper.rb
|
|
144
|
-
- lib/helpers/cyclonedx_helper.rb
|
|
145
|
-
- lib/helpers/dependency_helper.rb
|
|
146
|
-
- lib/helpers/diff_markdown_helper.rb
|
|
147
|
-
- lib/helpers/dotnet_helper.rb
|
|
148
|
-
- lib/helpers/emoji_helper.rb
|
|
149
|
-
- lib/helpers/endoflife_helper.rb
|
|
150
|
-
- lib/helpers/http_helper.rb
|
|
151
|
-
- lib/helpers/libyear_helper.rb
|
|
152
|
-
- lib/helpers/lockfile_dependency_parser.rb
|
|
153
|
-
- lib/helpers/lockfile_indexer.rb
|
|
154
|
-
- lib/helpers/markdown_escape.rb
|
|
155
|
-
- lib/helpers/markdown_helper.rb
|
|
156
|
-
- lib/helpers/pep440_helper.rb
|
|
157
|
-
- lib/helpers/python_helper.rb
|
|
158
|
-
- lib/helpers/ruby_advisory_db.rb
|
|
159
|
-
- lib/helpers/ruby_helper.rb
|
|
160
|
-
- lib/helpers/runtime_ceiling_helper.rb
|
|
161
|
-
- lib/helpers/sarif_helper.rb
|
|
162
|
-
- lib/helpers/semver_satisfaction.rb
|
|
163
|
-
- lib/helpers/status_helper.rb
|
|
164
|
-
- lib/helpers/summary_helper.rb
|
|
165
|
-
- lib/helpers/terminal_helper.rb
|
|
166
|
-
- lib/helpers/version_helper.rb
|
|
167
|
-
- lib/helpers/vulnerability_helper.rb
|
|
168
136
|
- lib/still_active.rb
|
|
169
137
|
- lib/still_active/artifactory_client.rb
|
|
170
138
|
- lib/still_active/ceiling_reconciler.rb
|
|
@@ -181,6 +149,39 @@ files:
|
|
|
181
149
|
- lib/still_active/forgejo_client.rb
|
|
182
150
|
- lib/still_active/github_client.rb
|
|
183
151
|
- lib/still_active/gitlab_client.rb
|
|
152
|
+
- lib/still_active/helpers/activity_helper.rb
|
|
153
|
+
- lib/still_active/helpers/alternatives_helper.rb
|
|
154
|
+
- lib/still_active/helpers/ansi_helper.rb
|
|
155
|
+
- lib/still_active/helpers/bot_context.rb
|
|
156
|
+
- lib/still_active/helpers/bundler_helper.rb
|
|
157
|
+
- lib/still_active/helpers/catalog_index.rb
|
|
158
|
+
- lib/still_active/helpers/constraint_helper.rb
|
|
159
|
+
- lib/still_active/helpers/cvss_helper.rb
|
|
160
|
+
- lib/still_active/helpers/cyclonedx_helper.rb
|
|
161
|
+
- lib/still_active/helpers/dependency_helper.rb
|
|
162
|
+
- lib/still_active/helpers/diff_markdown_helper.rb
|
|
163
|
+
- lib/still_active/helpers/dotnet_helper.rb
|
|
164
|
+
- lib/still_active/helpers/emoji_helper.rb
|
|
165
|
+
- lib/still_active/helpers/endoflife_helper.rb
|
|
166
|
+
- lib/still_active/helpers/http_helper.rb
|
|
167
|
+
- lib/still_active/helpers/libyear_helper.rb
|
|
168
|
+
- lib/still_active/helpers/lockfile_dependency_parser.rb
|
|
169
|
+
- lib/still_active/helpers/lockfile_indexer.rb
|
|
170
|
+
- lib/still_active/helpers/markdown_escape.rb
|
|
171
|
+
- lib/still_active/helpers/markdown_helper.rb
|
|
172
|
+
- lib/still_active/helpers/pep440_helper.rb
|
|
173
|
+
- lib/still_active/helpers/python_helper.rb
|
|
174
|
+
- lib/still_active/helpers/ruby_advisory_db.rb
|
|
175
|
+
- lib/still_active/helpers/ruby_helper.rb
|
|
176
|
+
- lib/still_active/helpers/runtime_ceiling_helper.rb
|
|
177
|
+
- lib/still_active/helpers/sarif_helper.rb
|
|
178
|
+
- lib/still_active/helpers/sbom_graph.rb
|
|
179
|
+
- lib/still_active/helpers/semver_satisfaction.rb
|
|
180
|
+
- lib/still_active/helpers/status_helper.rb
|
|
181
|
+
- lib/still_active/helpers/summary_helper.rb
|
|
182
|
+
- lib/still_active/helpers/terminal_helper.rb
|
|
183
|
+
- lib/still_active/helpers/version_helper.rb
|
|
184
|
+
- lib/still_active/helpers/vulnerability_helper.rb
|
|
184
185
|
- lib/still_active/options.rb
|
|
185
186
|
- lib/still_active/osv_client.rb
|
|
186
187
|
- lib/still_active/poison_security_correlator.rb
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|