{"id":51638201,"url":"https://github.com/seanlf/still_active","last_synced_at":"2026-07-13T17:00:50.457Z","repository":{"id":44655374,"uuid":"425492873","full_name":"SeanLF/still_active","owner":"SeanLF","description":"Cross-ecosystem dependency maintenance auditor: flags unmaintained, archived, stale, and below-the-fix deps across the full transitive graph. Ruby gems natively; npm/pypi/cargo/go/maven/nuget via CycloneDX SBOM. Signals: activity, OpenSSF Scorecard, OSV advisories, libyear, poison-pill, runtime-ceiling. Outputs SARIF/JSON/CycloneDX with CI gates.","archived":false,"fork":false,"pushed_at":"2026-07-09T01:25:51.000Z","size":1323,"stargazers_count":18,"open_issues_count":3,"forks_count":1,"subscribers_count":2,"default_branch":"main","last_synced_at":"2026-07-09T03:11:21.152Z","etag":null,"topics":["bundler","ci-cd","cyclonedx","dependency-checker","dependency-health","devops","gem-maintenance","libyear","openssf-scorecard","outdated-dependencies","ruby","rubygems","sarif","sbom","security-audit","supply-chain-security","vulnerability-scanner"],"latest_commit_sha":null,"homepage":null,"language":"Ruby","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/SeanLF.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE.txt","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":"SECURITY.md","support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":"AGENTS.md","dco":null,"cla":null}},"created_at":"2021-11-07T12:07:27.000Z","updated_at":"2026-07-09T01:25:11.000Z","dependencies_parsed_at":"2024-06-23T11:58:43.534Z","dependency_job_id":"eef6a3ce-6e97-48b8-b01b-3752d003e6a0","html_url":"https://github.com/SeanLF/still_active","commit_stats":{"total_commits":39,"total_committers":1,"mean_commits":39.0,"dds":0.0,"last_synced_commit":"19856551c923f91b5593b52597c83db8a8142448"},"previous_names":[],"tags_count":21,"template":false,"template_full_name":null,"purl":"pkg:github/SeanLF/still_active","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/SeanLF%2Fstill_active","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/SeanLF%2Fstill_active/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/SeanLF%2Fstill_active/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/SeanLF%2Fstill_active/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/SeanLF","download_url":"https://codeload.github.com/SeanLF/still_active/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/SeanLF%2Fstill_active/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":35429403,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-26T15:22:16.424Z","status":"online","status_checked_at":"2026-07-13T02:00:06.543Z","response_time":119,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["bundler","ci-cd","cyclonedx","dependency-checker","dependency-health","devops","gem-maintenance","libyear","openssf-scorecard","outdated-dependencies","ruby","rubygems","sarif","sbom","security-audit","supply-chain-security","vulnerability-scanner"],"created_at":"2026-07-13T17:00:27.457Z","updated_at":"2026-07-13T17:00:50.447Z","avatar_url":"https://github.com/SeanLF.png","language":"Ruby","funding_links":[],"categories":[],"sub_categories":[],"readme":"# `still_active`\n\n**How do you know the dependencies you ship are still maintained?**\n\n[Install](#installation) · [Quick start](#quick-start) · [GitHub Action \u0026 CI](#github-action--ci) · [Cross-ecosystem](#cross-ecosystem-audit) · [Configuration](#configuration) · [Rules](docs/rules.md)\n\nYour 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.\n\n`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.\n\n```\nName            Version          Activity  OpenSSF  Vulns  License\n────────────────────────────────────────────────────────────────────\nbackbone-rails  1.2.3 (latest)   archived  2.6/10   0      -\nnokogiri        1.19.4 (latest)  ok        5.9/10   0      MIT\npaperclip       6.1.0 (latest)   archived  2/10     0      MIT\n  ↳ poison: caps terrapin ~\u003e 0.6.0 (1 major behind, latest 1.x)\nrake            13.4.2 (latest)  ok        5.5/10   0      MIT\n\n4 gems: 4 up to date · 2 active, 2 archived · 0 vulnerabilities · 1 poison-pill\nRuby 4.0.5 (latest)\n```\n\n## Why `still_active`?\n\nNo 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.\n\nOn Ruby, where it runs natively:\n\n|                              | `bundle outdated` | `bundler-audit`        | `libyear-bundler` | **`still_active`**       |\n| ---------------------------- | ----------------- | ---------------------- | ----------------- | ------------------------ |\n| Outdated versions            | Yes               | -                      | Yes               | Yes                      |\n| Known vulnerabilities (CVEs) | -                 | Yes (ruby-advisory-db) | -                 | Yes (deps.dev + OSV + ruby-advisory-db) |\n| Libyear drift                | -                 | -                      | Yes               | Yes                      |\n| **Last-commit activity**     | -                 | -                      | -                 | **Yes**                  |\n| **Archived repo detection**  | -                 | -                      | -                 | **Yes**                  |\n| **OpenSSF Scorecard**        | -                 | -                      | -                 | **Yes**                  |\n| **Poison-pill / below-the-fix** | -              | -                      | -                 | **Yes**                  |\n| **Cross-ecosystem** (npm/PyPI/Cargo/Go/Maven/NuGet) | - | -              | -                 | **Yes** (`--sbom`)       |\n| CI quality gates             | -                 | Exit code              | -                 | Yes (6 gate flags)       |\n\nWith `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.\n\n## Installation\n\n```bash\ngem install still_active\n```\n\nRequires an actively-maintained Ruby (the gemspec floor tracks Ruby's [EOL schedule](https://endoflife.date/ruby)). 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.\n\n## Quick start\n\n```bash\n# audit your Gemfile (auto-detects output format)\nstill_active\n\n# cross-ecosystem: audit any CycloneDX SBOM (npm, PyPI, Cargo, Go, Maven, NuGet)\nsyft dir:. -o cyclonedx-json \u003e sbom.json \u0026\u0026 still_active --sbom=sbom.json\n\n# fail CI if any gem is critically stale or vulnerable\nstill_active --fail-if-critical --fail-if-vulnerable\n\n# markdown table for a pull request\nstill_active --markdown\n```\n\nFull flags: [`docs/cli.md`](docs/cli.md). Tokens for private registries and self-hosted forges: [`docs/authentication.md`](docs/authentication.md).\n\n## GitHub Action \u0026 CI\n\nThe [`still_active-action`](https://github.com/SeanLF/still_active-action) uploads findings to your **GitHub Security tab** as SARIF, with inline PR annotations on `Gemfile.lock`:\n\n```yaml\npermissions:\n  contents: read\n  security-events: write   # required for SARIF upload\n\njobs:\n  audit:\n    runs-on: ubuntu-latest\n    steps:\n      - uses: actions/checkout@v4\n      - uses: ruby/setup-ruby@v1\n        with: { ruby-version: '3.4' }\n      - uses: SeanLF/still_active-action@v0\n        with:\n          github-token: ${{ github.token }}\n          sarif: still_active.sarif.json\n      - uses: github/codeql-action/upload-sarif@v3\n        if: always()\n        with: { sarif_file: still_active.sarif.json }\n```\n\nGate the build on what you care about (all off by default, so nothing breaks until you opt in), and use `--baseline` for PR review.\n\n\u003cdetails\u003e\n\u003csummary\u003eCI gate flags and PR-review diff\u003c/summary\u003e\n\n```bash\nstill_active --fail-if-critical              # upstream critically stale or archived\nstill_active --fail-if-vulnerable            # any known vulnerability (or =low|medium|high|critical)\nstill_active --fail-if-outdated=3            # more than 3 libyears behind latest\nstill_active --fail-if-poison                # a dormant package caps a dep below its latest major\nstill_active --fail-if-language-ceiling      # a pin strands you on an EOL language runtime\n\n# PR review: report only what got worse since a saved snapshot, exit 1 on any regression\nstill_active --json \u003e /tmp/main.json \u0026\u0026 still_active --baseline=/tmp/main.json\n```\n\u003c/details\u003e\n\nRule reference (SA001-SA009), suppression, and composing with `dependency-review-action`: [`docs/rules.md`](docs/rules.md), [`docs/ci.md`](docs/ci.md). This repo audits itself every push, so you can browse live findings in its [Code Scanning tab](https://github.com/SeanLF/still_active/security/code-scanning?query=tool%3Astill_active+is%3Aopen).\n\n## Cross-ecosystem audit\n\nPoint `--sbom` at a CycloneDX SBOM (from [Syft](https://github.com/anchore/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](https://deps.dev) and [ecosyste.ms](https://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.\n\n\u003cdetails\u003e\n\u003csummary\u003eWhich signal covers which ecosystem\u003c/summary\u003e\n\n| Signal (rule) | Ruby (native) | `--sbom` (cross-ecosystem) |\n| ------------- | ------------- | -------------------------- |\n| Archived (SA001), no recent release (SA002), low OpenSSF (SA005), libyear (SA004) | Yes | Yes (all six ecosystems) |\n| Vulnerabilities (SA003) | deps.dev + OSV + ruby-advisory-db | deps.dev + OSV |\n| \u0026nbsp;\u0026nbsp;↳ \"below the fix\" (a dead package pins a vulnerable dep) | Yes | npm, Cargo, PyPI |\n| Poison-pill (SA008) | rubygems | PyPI (flat resolution only) |\n| Language-runtime ceiling (SA009) | Ruby | Python |\n| Ruby EOL (SA006), yanked (SA007) | Yes | n/a |\n\nFull rule detail in [`docs/rules.md`](docs/rules.md).\n\u003c/details\u003e\n\nThe play is **maintenance**, not CVE scanning, so compose Trivy/Grype for full vulnerability coverage.\n\n## Output formats\n\nAuto-detected: a coloured terminal table on a TTY (above), JSON when piped. Or ask explicitly.\n\n\u003cdetails\u003e\n\u003csummary\u003e\u003cstrong\u003eJSON\u003c/strong\u003e (\u003ccode\u003e--json\u003c/code\u003e): a versioned, contract-tested schema for automation\u003c/summary\u003e\n\n```json\n{\n  \"gems\": {\n    \"nested_form\": {\n      \"source_type\": \"git\",\n      \"version_used\": \"0.3.2\",\n      \"repository_url\": \"https://github.com/ryanb/nested_form\",\n      \"archived\": true,\n      \"scorecard_score\": 3.3,\n      \"vulnerability_count\": 0,\n      \"status\": \"archived\"\n    }\n  },\n  \"ruby\": { \"version\": \"4.0.5\", \"eol\": false, \"latest_version\": \"4.0.5\" }\n}\n```\n\nFields are documented in [`docs/schema.md`](docs/schema.md).\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\u003csummary\u003e\u003cstrong\u003eMarkdown\u003c/strong\u003e (\u003ccode\u003e--markdown\u003c/code\u003e): a table for pull requests, docs, or wikis\u003c/summary\u003e\n\n| activity | up to date? | OpenSSF | vulns | name | version | last commit |\n| -------- | ----------- | ------- | ----- | ---- | ------- | ----------- |\n|          | ✅          | 5.9/10  | ✅    | [nokogiri](https://github.com/sparklemotion/nokogiri) | 1.19.4 | 2026/06 |\n| 🚩       | ✅          | 2/10    | ✅    | [paperclip](https://github.com/thoughtbot/paperclip) | 6.1.0 | 2021/03 |\n\u003c/details\u003e\n\n**SARIF** feeds GitHub Code Scanning (see [GitHub Action \u0026 CI](#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.\n\n## Configuration\n\nA 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).\n\n\u003cdetails\u003e\n\u003csummary\u003e\u003ccode\u003e.still_active.yml\u003c/code\u003e example\u003c/summary\u003e\n\n```yaml\nfail_if_vulnerable: high        # true, or a minimum severity: low|medium|high|critical\nfail_if_poison: warning         # true (=warning), or a tier: note|warning|critical\n\nignore:\n  # accept ONE advisory by id; a different or new CVE on nokogiri still fails\n  - advisory: CVE-2024-1234\n    gem: nokogiri\n    reason: \"no fix released; not reachable from our code path\"\n    expires: 2026-09-01         # re-surfaces as a normal failure after this date\n```\n\u003c/details\u003e\n\nFull semantics, thresholds, and transitive behaviour: [`docs/configuration.md`](docs/configuration.md).\n\n## Data sources\n\nRelease dates and licenses from [RubyGems](https://rubygems.org) / [GitHub Packages](https://docs.github.com/en/packages) / [Artifactory](https://jfrog.com/artifactory/); repo activity from the [GitHub](https://docs.github.com/en/rest) / [GitLab](https://docs.gitlab.com/ee/api/) / [Codeberg](https://forgejo.org/docs/latest/user/api-usage/) API, or [ecosyste.ms](https://ecosyste.ms) tokenless ([CC-BY-SA 4.0](https://creativecommons.org/licenses/by-sa/4.0/)); OpenSSF Scorecard and CVSS from [deps.dev](https://deps.dev); advisory severities and fixed-version ranges from [OSV](https://osv.dev) (CVSS-4 scoring needs the optional [`cvss-suite`](https://rubygems.org/gems/cvss-suite)); extra advisories from [ruby-advisory-db](https://github.com/rubysec/ruby-advisory-db); runtime EOL from [endoflife.date](https://endoflife.date).\n\n## Development\n\n`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](https://rubygems.org) automatically on a GitHub Release (trusted publishing). See [`CONTRIBUTING.md`](CONTRIBUTING.md).\n\n## License\n\nOpen source under the [MIT License](https://opensource.org/licenses/MIT).\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fseanlf%2Fstill_active","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fseanlf%2Fstill_active","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fseanlf%2Fstill_active/lists"}