0.0
The project is in a healthy, maintained state
Analyses your Gemfile.lock for dependency health across the full transitive graph: whether each gem is actively maintained (last activity on GitHub, GitLab, or Codeberg/Forgejo, plus release recency), outdated versions, archived repos, OpenSSF Scorecard scores, known vulnerabilities (deps.dev merged with ruby-advisory-db), and libyear drift. Ruby version freshness with EOL detection. Handles rubygems, git, path, GitHub Packages, and JFrog Artifactory sources. Outputs coloured terminal tables, markdown, JSON (with a versioned, contract-tested schema), SARIF for GitHub code scanning, and a CycloneDX SBOM. CI quality gates (--fail-if-critical / -warning / -vulnerable / -outdated) with granular, committed suppression via .still_active.yml. A comprehensive alternative to running bundle outdated, bundler-audit, and libyear-bundler separately.
2005
2006
2007
2008
2009
2010
2011
2012
2013
2014
2015
2016
2017
2018
2019
2020
2021
2022
2023
2024
2025
2026
 Dependencies
 Project Readme

still_active

How do you know the dependencies you ship are still maintained?

Install · Quick start · GitHub Action & CI · Cross-ecosystem · Configuration · Rules

Your package manager tells you what's outdated and what has a known CVE. Neither tells you whether anyone's still working on the thing. An abandoned dependency is a quiet liability: when it finally breaks or a vulnerability lands, there's no release coming and no one to ping, and you find out at the worst time.

still_active flags that risk before it bites, across your whole dependency graph: archived repos, no release in years, low OpenSSF scores, unfixable vulnerabilities, and the poison-pill case where a dormant package holds one of your deps below its own security patch. Native on Ruby gems; npm, PyPI, Cargo, Go, Maven, and NuGet via a CycloneDX SBOM.

Name            Version          Activity  OpenSSF  Vulns  License
────────────────────────────────────────────────────────────────────
backbone-rails  1.2.3 (latest)   archived  2.6/10   0      -
nokogiri        1.19.4 (latest)  ok        5.9/10   0      MIT
paperclip       6.1.0 (latest)   archived  2/10     0      MIT
  ↳ poison: caps terrapin ~> 0.6.0 (1 major behind, latest 1.x)
rake            13.4.2 (latest)  ok        5.5/10   0      MIT

4 gems: 4 up to date · 2 active, 2 archived · 0 vulnerabilities · 1 poison-pill
Ruby 4.0.5 (latest)

Why still_active?

No package ecosystem's standard tooling answers "is anyone still maintaining this?" npm audit, cargo audit, pip-audit, and bundler-audit find known CVEs; the outdated commands find version drift. None tell you a dependency's upstream is archived, hasn't shipped in three years, or is holding one of your deps below its security fix. That maintenance gap is what still_active fills. It's complementary to, not a replacement for, the tools you already run.

On Ruby, where it runs natively:

bundle outdated bundler-audit libyear-bundler still_active
Outdated versions Yes - Yes Yes
Known vulnerabilities (CVEs) - Yes (ruby-advisory-db) - Yes (deps.dev + OSV + ruby-advisory-db)
Libyear drift - - Yes Yes
Last-commit activity - - - Yes
Archived repo detection - - - Yes
OpenSSF Scorecard - - - Yes
Poison-pill / below-the-fix - - - Yes
Cross-ecosystem (npm/PyPI/Cargo/Go/Maven/NuGet) - - - Yes (--sbom)
CI quality gates - Exit code - Yes (6 gate flags)

With bundler-audit installed alongside, still_active merges its ruby-advisory-db advisories with its own deps.dev + OSV sources, so running both no longer means reconciling two vuln counts by hand.

Installation

gem install still_active

Requires an actively-maintained Ruby (the gemspec floor tracks Ruby's EOL schedule). You don't have to run it on the Ruby you audit: it reports on the version pinned in Gemfile.lock, so run it from any current Ruby and it still flags an EOL target.

Quick start

# audit your Gemfile (auto-detects output format)
still_active

# cross-ecosystem: audit any CycloneDX SBOM (npm, PyPI, Cargo, Go, Maven, NuGet)
syft dir:. -o cyclonedx-json > sbom.json && still_active --sbom=sbom.json

# fail CI if any gem is critically stale or vulnerable
still_active --fail-if-critical --fail-if-vulnerable

# markdown table for a pull request
still_active --markdown

Full flags: docs/cli.md. Tokens for private registries and self-hosted forges: docs/authentication.md.

GitHub Action & CI

The still_active-action uploads findings to your GitHub Security tab as SARIF, with inline PR annotations on Gemfile.lock:

permissions:
  contents: read
  security-events: write   # required for SARIF upload

jobs:
  audit:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: ruby/setup-ruby@v1
        with: { ruby-version: '3.4' }
      - uses: SeanLF/still_active-action@v0
        with:
          github-token: ${{ github.token }}
          sarif: still_active.sarif.json
      - uses: github/codeql-action/upload-sarif@v3
        if: always()
        with: { sarif_file: still_active.sarif.json }

Gate the build on what you care about (all off by default, so nothing breaks until you opt in), and use --baseline for PR review.

CI gate flags and PR-review diff
still_active --fail-if-critical              # upstream critically stale or archived
still_active --fail-if-vulnerable            # any known vulnerability (or =low|medium|high|critical)
still_active --fail-if-outdated=3            # more than 3 libyears behind latest
still_active --fail-if-poison                # a dormant package caps a dep below its latest major
still_active --fail-if-language-ceiling      # a pin strands you on an EOL language runtime

# PR review: report only what got worse since a saved snapshot, exit 1 on any regression
still_active --json > /tmp/main.json && still_active --baseline=/tmp/main.json

Rule reference (SA001-SA009), suppression, and composing with dependency-review-action: docs/rules.md, docs/ci.md. This repo audits itself every push, so you can browse live findings in its Code Scanning tab.

Cross-ecosystem audit

Point --sbom at a CycloneDX SBOM (from Syft, Trivy, or any producer) and still_active assesses npm, pypi, cargo, go, maven, and nuget packages the same way it does gems, via deps.dev and ecosyste.ms. The SBOM is treated as untrusted input (only ecosystem/name/version are read, repositories resolve from deps.dev, and anything unassessable is surfaced rather than faked as ok). Most signals apply everywhere; a few are deliberately scoped.

Which signal covers which ecosystem
Signal (rule) Ruby (native) --sbom (cross-ecosystem)
Archived (SA001), no recent release (SA002), low OpenSSF (SA005), libyear (SA004) Yes Yes (all six ecosystems)
Vulnerabilities (SA003) deps.dev + OSV + ruby-advisory-db deps.dev + OSV
  ↳ "below the fix" (a dead package pins a vulnerable dep) Yes npm, Cargo, PyPI
Poison-pill (SA008) rubygems PyPI (flat resolution only)
Language-runtime ceiling (SA009) Ruby Python
Ruby EOL (SA006), yanked (SA007) Yes n/a

Full rule detail in docs/rules.md.

The play is maintenance, not CVE scanning, so compose Trivy/Grype for full vulnerability coverage.

Output formats

Auto-detected: a coloured terminal table on a TTY (above), JSON when piped. Or ask explicitly.

JSON (--json): a versioned, contract-tested schema for automation
{
  "gems": {
    "nested_form": {
      "source_type": "git",
      "version_used": "0.3.2",
      "repository_url": "https://github.com/ryanb/nested_form",
      "archived": true,
      "scorecard_score": 3.3,
      "vulnerability_count": 0,
      "status": "archived"
    }
  },
  "ruby": { "version": "4.0.5", "eol": false, "latest_version": "4.0.5" }
}

Fields are documented in docs/schema.md.

Markdown (--markdown): a table for pull requests, docs, or wikis
activity up to date? OpenSSF vulns name version last commit
5.9/10 nokogiri 1.19.4 2026/06
🚩 2/10 paperclip 6.1.0 2021/03

SARIF feeds GitHub Code Scanning (see GitHub Action & CI). CycloneDX (--cyclonedx) emits a standards-track SBOM so your graph and still_active's signals flow into Trivy, Dependency-Track, or Snyk.

Configuration

A committed .still_active.yml keeps policy in version control and replaces the blunt --ignore=GEM (which mutes every gate for a gem) with granular, expiring suppression. A vulnerability suppression must name an advisory id (so a new CVE is never pre-silenced), an expires: date makes accepted risk re-surface instead of rotting, and a suppressed finding still shows in output (and as a dismissed SARIF entry).

.still_active.yml example
fail_if_vulnerable: high        # true, or a minimum severity: low|medium|high|critical
fail_if_poison: warning         # true (=warning), or a tier: note|warning|critical

ignore:
  # accept ONE advisory by id; a different or new CVE on nokogiri still fails
  - advisory: CVE-2024-1234
    gem: nokogiri
    reason: "no fix released; not reachable from our code path"
    expires: 2026-09-01         # re-surfaces as a normal failure after this date

Full semantics, thresholds, and transitive behaviour: docs/configuration.md.

Data sources

Release dates and licenses from RubyGems / GitHub Packages / Artifactory; repo activity from the GitHub / GitLab / Codeberg API, or ecosyste.ms tokenless (CC-BY-SA 4.0); OpenSSF Scorecard and CVSS from deps.dev; advisory severities and fixed-version ranges from OSV (CVSS-4 scoring needs the optional cvss-suite); extra advisories from ruby-advisory-db; runtime EOL from endoflife.date.

Development

bin/setup installs dependencies and wires git hooks; rake runs the full lint + test suite. A pre-push hook runs rake automatically. Releases publish to rubygems.org automatically on a GitHub Release (trusted publishing). See CONTRIBUTING.md.

License

Open source under the MIT License.