Module: StillActive::SemverSatisfaction
- Extended by:
- SemverSatisfaction
- Included in:
- SemverSatisfaction
- Defined in:
- lib/helpers/semver_satisfaction.rb
Overview
Does a concrete version satisfy a declared requirement, at PATCH precision, for npm and cargo? This is the primitive the cross-ecosystem below-the-fix signal needs: a CVE's fix is usually a same-major patch bump, so "can this fix be reached within the package's constraint" cannot be answered by the coarse, major-precision ConstraintHelper. node-semver's caret/tilde/OR/prerelease rules are a correctness minefield, so we lean on the semantic_range gem (a node-semver port) rather than reimplement them.
npm ranges are node-semver as-is. cargo's VersionReq agrees with node-semver on
every operator form, and diverges on ANY operator-less bare version: cargo treats
a bare version as a caret (1.2.3 = ^1.2.3, 1.2 = ^1.2 = >=1.2.0 <2.0.0,
1 = ^1), while node-semver reads a bare full version as an exact pin and a
partial 1.2 as the narrower 1.2.x (<1.3.0). Per the Cargo Book's caret
table, node-semver's caret expands identically to cargo's for every one of these
forms, so the whole shim is: prefix ^ to a bare version before evaluating.
Getting it wrong (e.g. leaving 1.2 unshimmed) reads a reachable fix as
unreachable and fabricates a below-the-fix security finding.
Constant Summary collapse
- BARE_VERSION =
An operator-less bare version, 1 to 3 numeric components, optional prerelease and/or build tail (
1,1.2,1.2.3,0.10.38,1.2.3-alpha+001). cargo reads any of these as a caret; node-semver does not, so cargo shims them. /\A\s*v?\d+(?:\.\d+){0,2}(?:-[0-9A-Za-z.-]+)?(?:\+[0-9A-Za-z.-]+)?\s*\z/
Instance Method Summary collapse
-
#evaluate(requirement:, version:, ecosystem:) ⇒ Object
Does
versionsatisfyrequirement? true / false when decidable; nil when the requirement or version isn't valid semver for the ecosystem, or the ecosystem isn't one we model.
Instance Method Details
#evaluate(requirement:, version:, ecosystem:) ⇒ Object
Does version satisfy requirement? true / false when decidable; nil when the
requirement or version isn't valid semver for the ecosystem, or the ecosystem
isn't one we model. The tri-state is deliberate (hence a plain verb, not a
? predicate): semantic_range returns false for garbage, and a false would read
as "the fix can't be reached" in a wall test and fabricate a below-the-fix flag.
The caller must treat nil as "cannot establish a wall", never as unreachable.
37 38 39 40 41 42 43 |
# File 'lib/helpers/semver_satisfaction.rb', line 37 def evaluate(requirement:, version:, ecosystem:) range = range_for(requirement, ecosystem) return if range.nil? # undecidable: unmodelled ecosystem or unparseable requirement return if SemanticRange.valid(version.to_s).nil? # undecidable: unparseable version SemanticRange.satisfies?(version.to_s, range) end |