Documentation
¶
Overview ¶
Package gemfile provides parsing and analysis of Ruby Gemfile.lock files.
It handles:
- Parsing Gemfile.lock (and gems.locked) files to extract gem dependencies
- Extracting group information from Gemfile (and gems.rb) files
- Building dependency trees (forward and reverse dependencies)
- Analyzing gem health, outdated versions, and vulnerabilities
- Generating reports in multiple formats (text, CSV, JSON)
Index ¶
- Constants
- Variables
- func CalculateProjectSize(gems []*Gem, gemDirPath string) (int64, map[string]int64, error)
- func ClearUpgradeErrorLog() error
- func ClearVulnerabilityCache() error
- func ComputeGemsSignature(gems []*Gem) string
- func DetectFramework(gf *Gemfile) (framework string, version string)
- func DetectRubyManager(gemDirPath string) string
- func ExtractBundleVersion(path string) string
- func ExtractGitHubOwnerRepo(uri string) (owner, repo string, ok bool)
- func ExtractRubyVersion(path string) string
- func FindGemfile(dir string) string
- func FindLockFile(dir string) string
- func FormatBytes(bytes int64) string
- func GetCVECommentKey(vuln *Vulnerability) string
- func GetCacheAge(entry *CacheEntry) time.Duration
- func GetCacheDir() (string, error)
- func GetGemDirPath() (string, error)
- func GetGemInfo(gemName string) (string, error)
- func GetGemSize(gemName string, gemDirPath string) (int64, error)
- func GetReverseDependencies(gemName string, gemfile *Gemfile) []string
- func GetTimeUntilExpiry(entry *CacheEntry) time.Duration
- func GetUpgradeErrorLogPath() string
- func IsCacheValid(entry *CacheEntry) bool
- func ParseUpgradeErrors() []string
- func SaveCVEComments(projectDir string, comments *CVEComments) error
- func SaveVulnerabilityCache(gemsSignature string, entry *CacheEntry) error
- type AnalysisResult
- type CVEComment
- type CVECommentDecision
- type CVEComments
- type CacheEntry
- type ConstraintResolver
- type DependencyInfo
- type DependencyNode
- type DependencyResult
- type DependencyType
- type ErrCommandFailed
- type ErrRubyNotFound
- type Gem
- type GemHealth
- type GemStatus
- type Gemfile
- func (g *Gemfile) GetGemCount() int
- func (g *Gemfile) GetGemsAsList() []*Gem
- func (g *Gemfile) GetInsecureSourceGems() []*Gem
- func (g *Gemfile) LoadConstraintsFromGemfile(gemfilePath string) error
- func (g *Gemfile) LoadConstraintsFromGemspec(gemspecPath string) error
- func (g *Gemfile) LoadGroupsFromGemfile(gemfilePath string) error
- type HealthChecker
- type HealthScore
- type InstalledVersion
- type OSVBatchRequest
- type OSVBatchResponse
- type OSVClient
- type OSVPackage
- type OSVQueryRequest
- type OSVResult
- type OSVVulnerability
- type OutdatedChecker
- func (oc *OutdatedChecker) EnrichGemspecDependencies(gf *Gemfile) int
- func (oc *OutdatedChecker) GetDescription(gemName string) string
- func (oc *OutdatedChecker) GetHomepage(gemName string) string
- func (oc *OutdatedChecker) GetSourceCodeURI(gemName string) string
- func (oc *OutdatedChecker) GetVersionCreatedAt(gemName string) string
- func (oc *OutdatedChecker) IsOutdated(gemName, currentVersion string) (bool, string, error)
- type ParsedGemInfo
- type RepoOwnerPair
- type RubygemeInfo
- type RubygemesDependency
- type RubygemsDependencies
- type UpgradeResult
- type Vulnerability
Constants ¶
const ( CommentFileName = ".gemtracker_comments.json" CommentVersion = 1 )
const ( VulnerabilityCacheTTL = 1 * time.Hour CacheDir = "vulnerabilities" )
const (
OSVRequestTimeout = 30 * time.Second
)
Variables ¶
var ( OSVBatchEndpoint = "https://api.osv.dev/v1/querybatch" OSVVulnDetailEndpoint = "https://api.osv.dev/v1/vulns" )
Functions ¶
func CalculateProjectSize ¶ added in v1.2.0
CalculateProjectSize calculates the total size of all project gems and returns a map of gem name to size in bytes.
func ClearUpgradeErrorLog ¶ added in v1.2.9
func ClearUpgradeErrorLog() error
func ClearVulnerabilityCache ¶ added in v1.1.5
func ClearVulnerabilityCache() error
ClearVulnerabilityCache removes all cached vulnerability data from disk Called when user requests a refresh (--no-cache flag or 'r' key press)
func ComputeGemsSignature ¶ added in v1.1.5
ComputeGemsSignature creates a deterministic hash of all gems and their versions This ensures cache invalidation when gems change
func DetectFramework ¶ added in v1.0.6
DetectFramework detects the primary framework (Rails, Sinatra, etc.) from installed gems
func DetectRubyManager ¶ added in v1.2.0
DetectRubyManager extracts the Ruby version manager name from gem env gemdir output. Examples:
/Users/user/.frum/versions/3.4.4/lib/ruby/gems/3.4.0 → "frum" /Users/user/.rbenv/versions/3.4.4/lib/ruby/gems/3.4.0 → "rbenv" /Users/user/.rvm/gems/ruby-3.4.4 → "rvm" /usr/lib/ruby/gems/3.4.0 → "system"
func ExtractBundleVersion ¶ added in v1.0.6
ExtractBundleVersion extracts the Bundle version from Gemfile.lock
func ExtractGitHubOwnerRepo ¶ added in v1.1.0
ExtractGitHubOwnerRepo extracts the GitHub owner and repository name from a URI. It handles HTTPS, HTTP, and SSH-style URIs with optional .git suffix. Returns (owner, repo, true) if extraction succeeds, ("", "", false) otherwise.
func ExtractRubyVersion ¶ added in v1.0.6
ExtractRubyVersion extracts the Ruby version from Gemfile.lock
func FindGemfile ¶ added in v1.1.2
FindGemfile searches for a Ruby Gemfile in the given directory. It probes in priority order: gems.rb, Gemfile. Returns the absolute path to the Gemfile if found, empty string otherwise.
func FindLockFile ¶ added in v1.1.2
FindLockFile searches for a Ruby lock file in the given directory. It probes in priority order: gems.locked, Gemfile.lock. Returns the absolute path to the lock file if found, empty string otherwise.
func FormatBytes ¶ added in v1.2.0
FormatBytes converts bytes to human-readable format (KB, MB, GB).
func GetCVECommentKey ¶ added in v1.2.0
func GetCVECommentKey(vuln *Vulnerability) string
GetCVECommentKey returns the appropriate key for a vulnerability (prefer CVE, fall back to OSVId)
func GetCacheAge ¶ added in v1.1.5
func GetCacheAge(entry *CacheEntry) time.Duration
GetCacheAge returns how old the cache is
func GetCacheDir ¶ added in v1.1.5
GetCacheDir returns the vulnerability cache directory
func GetGemDirPath ¶ added in v1.2.0
GetGemDirPath executes `gem env gemdir` and returns the gem directory path. Returns ErrRubyNotFound if gem binary is not found in PATH.
func GetGemInfo ¶ added in v1.2.0
GetGemInfo executes `gem info <gemName>` and returns the sanitized output. Uses a timeout to prevent hanging if the gem command is slow or unresponsive. Returns ErrRubyNotFound if gem binary is not found in PATH.
func GetGemSize ¶ added in v1.2.0
GetGemSize calculates the total size of a gem directory in bytes. Returns 0 if the gem is not found, error if the calculation fails.
func GetReverseDependencies ¶
GetReverseDependencies returns a list of gems that directly depend on the given gem. This is a simple list of direct dependents, useful for quick lookups without building a tree.
func GetTimeUntilExpiry ¶ added in v1.1.5
func GetTimeUntilExpiry(entry *CacheEntry) time.Duration
GetTimeUntilExpiry returns how long until cache expires
func GetUpgradeErrorLogPath ¶ added in v1.2.9
func GetUpgradeErrorLogPath() string
func IsCacheValid ¶ added in v1.1.5
func IsCacheValid(entry *CacheEntry) bool
IsCacheValid checks if a cache entry is still valid (not expired)
func ParseUpgradeErrors ¶ added in v1.2.9
func ParseUpgradeErrors() []string
func SaveCVEComments ¶ added in v1.2.0
func SaveCVEComments(projectDir string, comments *CVEComments) error
SaveCVEComments saves CVE comments to the project directory
func SaveVulnerabilityCache ¶ added in v1.1.5
func SaveVulnerabilityCache(gemsSignature string, entry *CacheEntry) error
SaveVulnerabilityCache saves vulnerability data to disk cache atomically
Types ¶
type AnalysisResult ¶
type AnalysisResult struct {
// TotalGems is the total number of gems (first-level and transitive dependencies)
TotalGems int
// OutdatedGems is a list of gem names with available updates
OutdatedGems []string
// VulnerableGems is a list of gem names with known CVEs
VulnerableGems []string
// FirstLevelGems is a list of gem names directly required (in Gemfile/Gemfile.lock DEPENDENCIES)
FirstLevelGems []string
// AllGems is the complete list of parsed Gem objects
AllGems []*Gem
// GemStatuses is detailed status information for each gem (outdated, vulnerable, health, etc.)
GemStatuses []*GemStatus
// InsecureSourceGems is a list of gems sourced from insecure protocols (http://, git://)
InsecureSourceGems []*Gem
// Summary is a brief one-line summary of the analysis results
Summary string
// Details is a detailed report of all gems and their status
Details string
}
AnalysisResult contains the results of analyzing a Gemfile.lock for vulnerabilities, outdated gems, and other quality metrics.
func Analyze ¶
func Analyze(gemfile *Gemfile) *AnalysisResult
Analyze performs a complete security and version analysis of a parsed Gemfile. It identifies first-level dependencies and prepares gem statuses for analysis. Vulnerability checking is done asynchronously via OSV.dev (not here) to avoid blocking and to use the authoritative live vulnerability database. Outdated version checking is also done separately by the UI.
type CVEComment ¶ added in v1.2.0
type CVEComment struct {
Decision CVECommentDecision `json:"decision"`
Comment string `json:"comment"`
GemName string `json:"gem_name"`
GemVersion string `json:"gem_version"` // installed version at save time
CreatedAt time.Time `json:"created_at"`
UpdatedAt time.Time `json:"updated_at"`
}
CVEComment represents a user's comment and decision on a CVE advisory
type CVECommentDecision ¶ added in v1.2.0
type CVECommentDecision string
CVECommentDecision represents the user's decision on a CVE
const ( DecisionAcknowledged CVECommentDecision = "acknowledged" DecisionIgnored CVECommentDecision = "ignored" )
type CVEComments ¶ added in v1.2.0
type CVEComments struct {
Version int `json:"version"`
Entries map[string]*CVEComment `json:"entries"` // key = CVE ID (vuln.CVE or vuln.OSVId)
}
CVEComments holds all comment entries for a project
func LoadCVEComments ¶ added in v1.2.0
func LoadCVEComments(projectDir string) (*CVEComments, error)
LoadCVEComments loads CVE comments from the project directory
type CacheEntry ¶ added in v1.1.5
type CacheEntry struct {
GemsSignature string `json:"gems_signature"`
CachedAt time.Time `json:"cached_at"`
ScannedAt time.Time `json:"scanned_at"`
TTLSeconds int `json:"ttl_seconds"`
GemCount int `json:"gem_count"`
ScanStatus string `json:"scan_status"` // "success" or "error"
ErrorMessage string `json:"error_message,omitempty"`
Vulnerabilities []Vulnerability `json:"vulnerabilities"`
}
CacheEntry represents a cached vulnerability scan result
func LoadVulnerabilityCache ¶ added in v1.1.5
func LoadVulnerabilityCache(gemsSignature string) (*CacheEntry, error)
LoadVulnerabilityCache loads cached vulnerability data if it exists and is valid
type ConstraintResolver ¶ added in v1.2.9
type ConstraintResolver struct{}
ConstraintResolver resolves version constraints and finds compatible versions.
func NewConstraintResolver ¶ added in v1.2.9
func NewConstraintResolver() *ConstraintResolver
NewConstraintResolver creates a new ConstraintResolver.
func (*ConstraintResolver) ParseVersion ¶ added in v1.2.9
func (cr *ConstraintResolver) ParseVersion(versionStr string) []int
ParseVersion parses a semantic version string into integer parts. Handles pre-release versions by ignoring the pre-release suffix. E.g., "1.2.3" -> [1, 2, 3], "1.2.3-alpha.1" -> [1, 2, 3]
func (*ConstraintResolver) ResolveUpdateableVersion ¶ added in v1.2.9
func (cr *ConstraintResolver) ResolveUpdateableVersion(constraint, latestVersion, currentVersion string) string
ResolveUpdateableVersion finds the highest version that matches the constraint. If no constraint is provided, returns the latest version. If the latest version matches the constraint, returns it; otherwise returns the highest matching version.
type DependencyInfo ¶
type DependencyInfo struct {
// GemName is the selected gem name
GemName string
// Version is the selected gem's version
Version string
// ForwardDeps lists the gems that this gem depends on (direct dependencies only)
ForwardDeps []string
// ReverseDeps lists the gems that depend on this gem (direct dependents only)
ReverseDeps []string
// ForwardDepsCount is the count of direct forward dependencies
ForwardDepsCount int
// ReverseDepsCount is the count of direct reverse dependencies
ReverseDepsCount int
// ForwardTree is a tree structure showing transitive dependencies of this gem
ForwardTree *DependencyNode
// ReverseTree is a tree structure showing what depends on this gem (up to 3 levels)
ReverseTree *DependencyNode
}
DependencyInfo contains forward and reverse dependency information for a selected gem, including both simple lists and tree structures for visualization.
type DependencyNode ¶
type DependencyNode struct {
// Name is the gem name
Name string
// Version is the gem version at this node
Version string
// Children are the direct dependencies (or dependents for reverse trees)
Children []*DependencyNode
// Depth is the nesting level in the tree (0 for root, increments for each level)
Depth int
}
DependencyNode represents a node in a dependency tree, used for displaying forward and reverse dependency chains with version information and nesting depth.
type DependencyResult ¶
type DependencyResult struct {
// SelectedGem is the name of the gem being analyzed
SelectedGem string
// DependencyInfo contains the dependency analysis for the selected gem
DependencyInfo *DependencyInfo
// AllGems is a reference to the full gem map for version lookups
AllGems map[string]*Gem
}
DependencyResult contains the analysis result for a selected gem's dependencies.
func AnalyzeDependencies ¶
func AnalyzeDependencies(gemfile *Gemfile, selectedGemName string) *DependencyResult
AnalyzeDependencies analyzes forward and reverse dependencies for a given gem. It returns both lists of direct dependencies and tree structures showing transitive relationships. Trees are limited to prevent circular dependencies: forward tree is capped at depth 5, reverse tree is capped at depth 3.
type DependencyType ¶ added in v1.2.6
type DependencyType int
DependencyType distinguishes between runtime and development dependencies.
const ( // RuntimeDependency is a production runtime dependency RuntimeDependency DependencyType = iota // DevelopmentDependency is a development-only dependency DevelopmentDependency )
type ErrCommandFailed ¶ added in v1.2.7
ErrCommandFailed is returned when a command fails to execute
func (ErrCommandFailed) Error ¶ added in v1.2.7
func (e ErrCommandFailed) Error() string
type ErrRubyNotFound ¶ added in v1.2.7
type ErrRubyNotFound struct {
Binary string
}
ErrRubyNotFound is returned when the gem binary is not found in PATH
func (ErrRubyNotFound) Error ¶ added in v1.2.7
func (e ErrRubyNotFound) Error() string
type Gem ¶
type Gem struct {
// Name is the lowercase gem name
Name string
// Version is the installed version string (may include platform suffixes like "x86_64-linux")
Version string
// Dependencies is a list of gem names that this gem depends on
Dependencies []string
// Groups lists the bundle groups this gem belongs to (e.g., "default", "development", "test", "production")
Groups []string
// IsFirstLevel is true if this gem is in the DEPENDENCIES section (directly required)
IsFirstLevel bool
// Source indicates where the gem is sourced from (e.g., "rubygems.org", a git URL)
Source string
// InsecureSource is true if the gem is sourced from an insecure protocol (http://, git://)
InsecureSource bool
// Constraint is the version constraint from Gemfile/gems.rb/gemspec (e.g., "~> 7.2", ">= 1.0")
Constraint string
}
Gem represents a Ruby gem with its version, dependencies, and group assignments.
type GemHealth ¶ added in v1.1.0
type GemHealth struct {
// Score is the computed health tier (Healthy, Warning, Critical, Unknown)
Score HealthScore `json:"score"`
// LastRelease is the timestamp of the latest gem release from RubyGems
LastRelease time.Time `json:"last_release"`
// GitHubPushedAt is the timestamp of the last commit pushed to the repository
GitHubPushedAt time.Time `json:"github_pushed_at"`
// Stars is the number of GitHub stars on the repository
Stars int `json:"stars"`
// OpenIssues is the number of open issues on the repository
OpenIssues int `json:"open_issues"`
// Archived indicates whether the GitHub repository is archived
Archived bool `json:"archived"`
// Disabled indicates whether the GitHub repository is disabled
Disabled bool `json:"disabled"`
// MaintainerCount is the number of maintainers listed on RubyGems
MaintainerCount int `json:"maintainer_count"`
// RateLimited indicates if GitHub API rate limit was exceeded (partial data)
RateLimited bool `json:"rate_limited"`
// FetchedAt is the timestamp when this health data was fetched
FetchedAt time.Time `json:"fetched_at"`
}
GemHealth contains maintenance and activity metrics for a gem from RubyGems and GitHub.
type GemStatus ¶
type GemStatus struct {
// Name is the lowercase gem name
Name string
// Version is the currently installed version
Version string
// Groups lists the bundle groups this gem belongs to (e.g., "default", "development", "test")
Groups []string
// IsOutdated indicates whether a newer version is available
IsOutdated bool
// LatestVersion is the latest available version (only set if IsOutdated is true)
LatestVersion string
// IsVulnerable indicates whether known CVEs affect this gem version
IsVulnerable bool
// VulnerabilityInfo contains CVE ID and description (only set if IsVulnerable is true)
VulnerabilityInfo string
// VulnerabilityURL is the canonical OSV advisory URL (only set if IsVulnerable is true)
VulnerabilityURL string
// HomepageURL is the gem's homepage or source code repository URL
HomepageURL string
// Description is the gem description from rubygems.org
Description string
// Health contains gem maintenance status data (nil until fetched asynchronously)
Health *GemHealth
// OutdatedFailed is true if the outdated version check failed with an error
OutdatedFailed bool
// Constraint is the version constraint from Gemfile/gems.rb (e.g., "~> 7.2", ">= 1.0")
Constraint string
// UpdateableVersion is the highest version matching the constraint
UpdateableVersion string
}
GemStatus represents the current status and metadata of a gem, including its version, group assignments, and vulnerability/outdated status with additional information.
type Gemfile ¶
type Gemfile struct {
// Path is the absolute path to the Gemfile.lock file
Path string
// Gems is a map of all gems (by lowercase name) found in the lock file
Gems map[string]*Gem
// FirstLevelGems is a list of gem names that are directly required (in DEPENDENCIES section)
FirstLevelGems []string
}
Gemfile represents the parsed contents of a Gemfile.lock file.
func Parse ¶
Parse parses a Gemfile.lock file (or gems.locked) and returns the parsed Gemfile structure. It accepts either a file path or directory path; if a directory is provided, it searches for a lock file in that directory. Expands ~/ in paths. Returns an error if the file cannot be found, opened, or parsed.
func ParseGemspec ¶ added in v1.1.2
ParseGemspec parses a Ruby .gemspec file to extract gem dependencies declared via add_runtime_dependency, add_development_dependency, and add_dependency directives. It accepts either a file path or a directory path; if a directory is provided, it searches for the first .gemspec file in that directory. Version constraints from unresolved gemspec declarations are extracted but cannot be compared against actual installed versions without Gemfile.lock. Returns a Gemfile structure with all gems marked as first-level dependencies.
func (*Gemfile) GetGemCount ¶
GetGemCount returns the total number of gems in the parsed Gemfile.
func (*Gemfile) GetGemsAsList ¶
GetGemsAsList returns all gems in the Gemfile as a slice.
func (*Gemfile) GetInsecureSourceGems ¶ added in v1.2.0
GetInsecureSourceGems returns all gems that are sourced from insecure protocols (http://, git://)
func (*Gemfile) LoadConstraintsFromGemfile ¶ added in v1.2.9
LoadConstraintsFromGemfile parses the Gemfile (or gems.rb) to extract version constraints for gems. It processes gem declarations with version constraints (e.g., "gem 'rails', '~> 7.2'"). Handles multiple constraints: gem 'pg', '>= 1.1', '< 2.0' -> '>= 1.1, < 2.0' Returns an error if the Gemfile cannot be read; returns nil if the Gemfile is not found (graceful degradation).
func (*Gemfile) LoadConstraintsFromGemspec ¶ added in v1.2.9
LoadConstraintsFromGemspec parses .gemspec files to extract version constraints for gem dependencies. It looks for add_runtime_dependency and add_development_dependency declarations. Handles multiple constraints: spec.add_runtime_dependency "pg", ">= 1.1", "< 2.0" -> ">= 1.1, < 2.0" Returns an error if the gemspec cannot be read; returns nil if not found (graceful degradation).
func (*Gemfile) LoadGroupsFromGemfile ¶
LoadGroupsFromGemfile parses the Gemfile (or gems.rb) to extract group assignments for gems. It processes group blocks (e.g., "group :development do") and assigns those groups to gems defined within. Returns an error if the Gemfile cannot be read; returns nil if the Gemfile is not found (graceful degradation).
type HealthChecker ¶ added in v1.1.0
type HealthChecker struct {
// contains filtered or unexported fields
}
HealthChecker fetches and caches gem health data from the RubyGems and GitHub APIs. It supports batch GitHub queries via GraphQL and graceful handling of rate limiting.
func NewHealthChecker ¶ added in v1.1.0
func NewHealthChecker() *HealthChecker
NewHealthChecker creates a new HealthChecker with a 10-second HTTP timeout and empty caches.
func (*HealthChecker) FetchGitHubBatch ¶ added in v1.1.2
func (hc *HealthChecker) FetchGitHubBatch(pairs []RepoOwnerPair) error
FetchGitHubBatch fetches GitHub data for multiple repositories in batched GraphQL requests. It caches all results for use by FetchHealth. If GITHUB_TOKEN is not set, it silently returns without fetching (GitHub data is optional). Returns an error only if the API request fails.
func (*HealthChecker) FetchHealth ¶ added in v1.1.0
func (hc *HealthChecker) FetchHealth(gemName, sourceCodeURI, homepageURI, versionCreatedAtStr, ownersURL string) (*GemHealth, error)
FetchHealth fetches and computes health data for a gem from RubyGems and GitHub APIs. It uses cached GitHub data from FetchGitHubBatch when available, then falls back to individual REST calls. Returns (*GemHealth, error). If GitHub rate limited, returns partial data with RateLimited=true.
type HealthScore ¶ added in v1.1.0
type HealthScore int
HealthScore represents the maintenance health tier of a gem. Health is determined by last release date, maintainer count, activity, and repository status.
const ( // HealthUnknown indicates health data could not be fetched (rate limited, network error, etc.) HealthUnknown HealthScore = iota // HealthHealthy indicates active gem with regular releases and multiple maintainers (🟢) HealthHealthy // HealthWarning indicates stale gem with no recent activity or single maintainer (🟡) HealthWarning // HealthCritical indicates inactive gem, archived, or disabled repository (🔴) HealthCritical )
func ComputeHealthScore ¶ added in v1.1.0
func ComputeHealthScore(h *GemHealth) HealthScore
ComputeHealthScore computes a health tier from gem health metrics. Tiers: CRITICAL (archived/disabled/3+ yrs inactive), WARNING (1-3 yrs inactive or single maintainer), HEALTHY (active within 1 year with 2+ maintainers), UNKNOWN (rate limited or no data).
func (HealthScore) String ¶ added in v1.1.0
func (hs HealthScore) String() string
type InstalledVersion ¶ added in v1.2.0
InstalledVersion represents a single installed version of a gem and its location.
type OSVBatchRequest ¶ added in v1.1.5
type OSVBatchRequest struct {
Queries []OSVQueryRequest `json:"queries"`
}
OSVBatchRequest is the batch query request to OSV.dev
type OSVBatchResponse ¶ added in v1.1.5
type OSVBatchResponse struct {
Results []OSVResult `json:"results"`
}
OSVBatchResponse is the response from OSV.dev batch endpoint
type OSVClient ¶ added in v1.1.5
type OSVClient struct {
// contains filtered or unexported fields
}
OSVClient queries the OSV.dev API for vulnerability data
func NewOSVClient ¶ added in v1.1.5
func NewOSVClient() *OSVClient
NewOSVClient creates a new OSV.dev client
func (*OSVClient) EnrichVulnerabilitiesWithDetails ¶ added in v1.2.0
func (c *OSVClient) EnrichVulnerabilitiesWithDetails(ctx context.Context, vulns []*Vulnerability)
EnrichVulnerabilitiesWithDetails fetches detailed CVSS/Severity data and workarounds for vulnerabilities The batch endpoint doesn't include this data, so we query individual vulnerabilities Uses rate limiting to avoid overwhelming the OSV API (10 req/sec) Accepts pointers to allow modifying cached vulnerabilities
func (*OSVClient) QueryBatch ¶ added in v1.1.5
QueryBatch queries OSV.dev with a batch of gems Returns vulnerabilities found for gems that have them Filters out clean gems (those with no vulnerabilities)
type OSVPackage ¶ added in v1.1.5
OSVPackage represents the package info in a query
type OSVQueryRequest ¶ added in v1.1.5
type OSVQueryRequest struct {
Package OSVPackage `json:"package"`
Version string `json:"version"`
}
OSVQueryRequest represents a single query in the batch request
type OSVResult ¶ added in v1.1.5
type OSVResult struct {
Vulns []OSVVulnerability `json:"vulns"`
}
OSVResult is a single vulnerability result from OSV.dev
type OSVVulnerability ¶ added in v1.1.5
type OSVVulnerability struct {
ID string `json:"id"`
Summary string `json:"summary"`
Details string `json:"details"`
Published string `json:"published"`
Modified string `json:"modified"`
Severity []map[string]interface{} `json:"severity"` // Array of severity objects with type and score (CVSS string)
DatabaseSpecific map[string]interface{} `json:"database_specific"` // Contains severity for GitHub reviewed vulns
References []struct {
Type string `json:"type"`
URL string `json:"url"`
} `json:"references"`
Affected []struct {
Package struct {
Name string `json:"name"`
Ecosystem string `json:"ecosystem"`
} `json:"package"`
Ranges []struct {
Type string `json:"type"`
Events []struct {
Introduced string `json:"introduced"`
Fixed string `json:"fixed"`
} `json:"events"`
} `json:"ranges"`
EcosystemSpecific map[string]interface{} `json:"ecosystem_specific"` // Contains severity for some ecosystems
} `json:"affected"`
}
OSVVulnerability represents a vulnerability from OSV.dev
type OutdatedChecker ¶
type OutdatedChecker struct {
// contains filtered or unexported fields
}
OutdatedChecker checks if gems have newer versions available and fetches gem metadata from the rubygems.org API. It caches all results to minimize API calls.
func NewOutdatedChecker ¶
func NewOutdatedChecker() *OutdatedChecker
NewOutdatedChecker creates a new OutdatedChecker with a 10-second HTTP timeout and empty caches for gem metadata.
func (*OutdatedChecker) EnrichGemspecDependencies ¶ added in v1.2.6
func (oc *OutdatedChecker) EnrichGemspecDependencies(gf *Gemfile) int
EnrichGemspecDependencies fetches runtime and development dependencies from RubyGems for each gem in the parsed gemspec file. This resolves the full dependency tree that was not available in the gemspec file itself. Dependencies are cached to avoid duplicate API calls. Returns the number of gems successfully enriched.
func (*OutdatedChecker) GetDescription ¶
func (oc *OutdatedChecker) GetDescription(gemName string) string
GetDescription returns the gem's description from cache or fetches it if not cached. Returns an empty string if no description is available.
func (*OutdatedChecker) GetHomepage ¶
func (oc *OutdatedChecker) GetHomepage(gemName string) string
GetHomepage returns the homepage URL for a gem from cache or fetches it if not cached. Returns a fallback URL to rubygems.org if no homepage is available.
func (*OutdatedChecker) GetSourceCodeURI ¶ added in v1.1.0
func (oc *OutdatedChecker) GetSourceCodeURI(gemName string) string
GetSourceCodeURI returns the source code repository URL for a gem from cache or fetches it if not cached. Returns an empty string if no source code URI is available.
func (*OutdatedChecker) GetVersionCreatedAt ¶ added in v1.1.0
func (oc *OutdatedChecker) GetVersionCreatedAt(gemName string) string
GetVersionCreatedAt returns the release timestamp of the latest version from cache or fetches it if not cached. Returns an empty string if the timestamp is not available.
func (*OutdatedChecker) IsOutdated ¶
func (oc *OutdatedChecker) IsOutdated(gemName, currentVersion string) (bool, string, error)
IsOutdated checks if a gem has a newer version available. It handles platform suffixes and pre-release versions correctly (e.g., "1.6.3-x86_64-linux" is compared as "1.6.3"). Returns (isOutdated, latestVersion, error). If a gem is not found on rubygems.org (404), returns (false, "", nil) - not an error.
type ParsedGemInfo ¶ added in v1.2.0
type ParsedGemInfo struct {
Versions []InstalledVersion // Ordered list: newest first
}
ParsedGemInfo contains parsed information extracted from `gem info` output.
func ParseGemInfo ¶ added in v1.2.0
func ParseGemInfo(output string) *ParsedGemInfo
ParseGemInfo parses the output from `gem info <name>` to extract installed versions and paths. Example output format:
rack (3.2.6, 3.2.5, 3.2.4)
Author: ...
Installed at (3.2.6): /path/to/gems
(3.2.5): /path/to/gems
(3.2.4): /path/to/gems
Handles both output formats: Format A (legacy): "Installed at (VERSION): /path" with version in parentheses Format B (current): First line "gem (v1, v2)" + "Installed at: /path" without version
type RepoOwnerPair ¶ added in v1.1.2
type RepoOwnerPair struct {
// GemName is the gem name
GemName string
// Owner is the GitHub repository owner
Owner string
// Repo is the GitHub repository name
Repo string
}
RepoOwnerPair represents a gem and its GitHub repository for batch fetching. Used for efficient GraphQL batch queries to GitHub.
type RubygemeInfo ¶
type RubygemeInfo struct {
// Version is the latest available version of the gem
Version string `json:"version"`
// VersionCreatedAt is the timestamp when the latest version was released
VersionCreatedAt string `json:"version_created_at"`
// HomepageURI is the gem's official homepage URL
HomepageURI string `json:"homepage_uri"`
// SourceCodeURI is the source code repository URL
SourceCodeURI string `json:"source_code_uri"`
// Info is the gem's description
Info string `json:"info"`
}
RubygemeInfo represents gem metadata from the rubygems.org API.
type RubygemesDependency ¶ added in v1.2.6
type RubygemesDependency struct {
// Name is the name of the dependency gem
Name string `json:"name"`
// Requirements describes the version constraint(s) for this dependency
Requirements interface{} `json:"requirements"`
}
RubygemesDependency represents a dependency from the RubyGems API response.
type RubygemsDependencies ¶ added in v1.2.6
type RubygemsDependencies struct {
// Runtime dependencies (production gems required for the app to run)
Runtime []RubygemesDependency `json:"runtime"`
// Development dependencies (development and test gems)
Development []RubygemesDependency `json:"development"`
}
RubygemsDependencies groups runtime and development dependencies from the API.
type UpgradeResult ¶ added in v1.2.9
func UpgradeGems ¶ added in v1.2.9
func UpgradeGems(gemNames []string, projectPath string) ([]UpgradeResult, error)
type Vulnerability ¶
type Vulnerability struct {
// GemName is the affected gem (lowercase)
GemName string
// AffectedVersions is a list of version specs that are vulnerable (e.g., "< 6.1.4", ">= 6.0.0, < 6.0.5")
AffectedVersions []string
// Description is a brief summary of the vulnerability
Description string
// CVE is the CVE identifier (e.g., "CVE-2021-22942")
CVE string
// Severity is the vulnerability severity level (CRITICAL, HIGH, MODERATE, LOW)
Severity string
// CVSS is the CVSS score (0-10)
CVSS float64
// FixedVersion is the first version that fixes the vulnerability
FixedVersion string
// PublishedDate is when the vulnerability was published
PublishedDate time.Time
// References are links to additional information about the vulnerability
References []string
// OSVId is the OSV identifier (e.g., GHSA-xxxx or CVE-2021-xxxx)
OSVId string
// Source indicates where the vulnerability data came from (e.g., "osv.dev", "static")
Source string
// Workarounds are temporary mitigations if no upgrade is immediately available
Workarounds string
}
Vulnerability represents a known CVE affecting one or more versions of a gem.