How I Track EOL Dates and CVEs in My README With One Badge
Source: Dev.to
Introduction
Every README has badges—build passing, coverage 94 %, license MIT—but none answer the question that actually matters: is this project running on supported versions?
You can have 100 % test coverage on a project pinned to Node 16 (EOL September 2025). The CI badge says “healthy,” but the runtime does not.
I wanted a badge that shows version health—whether the thing you depend on is still alive. So I built one.
Live badge showing the current Python health grade. It auto‑updates, requires no tokens, config, or API keys—just an image URL.
What you need
| Badge | Markdown |
|---|---|
| Overall health grade |  |
| EOL countdown |  |
| Known CVEs |  |
| Latest version |  |
How health grades work
Health grades run A through F. The scoring is:
- 35 % freshness – how current the version is
- 35 % security – known CVEs
- 30 % EOL status – support timeline
A critical unfixed CVE caps the grade at D. Anything past EOL for ≥ 1 year forces an F.
URL pattern
https://img.releaserun.com/badge/{type}/{product}[/{version}].svg
300 + products are supported—everything listed on endoflife.date: Python, Node.js, Go, Rust, Kubernetes, Docker, PostgreSQL, React, TypeScript, Ruby, PHP, .NET, and virtually every runtime and infrastructure tool in a production stack.
Scenario that prompted this
While reviewing a PR, I saw a green CI, 87 % coverage, active contributors—everything looked great. Then I checked the Dockerfile:
FROM node:16-alpine
Node 16 hit EOL in September 2025. No CVE scanner would flag this because the image itself isn’t vulnerable; the runtime lifecycle is the problem.
If the README had shown

anyone opening the repo would have seen the red badge immediately. Version currency is a signal, and badges make signals visible.
Adding version‑health badges to your README
## Version Health
[](https://releaserun.com/badges/python/)
[](https://releaserun.com/badges/nodejs/)
[](https://releaserun.com/badges/kubernetes/)
Wrapping the badge in a link is optional but useful—it takes readers to a landing page with full version timelines, embed snippets, and context on what the grades mean.
GitHub Action to keep badges up‑to‑date
name: Update Badges
on:
schedule:
- cron: '0 6 * * 1' # Weekly Monday
workflow_dispatch:
permissions:
contents: write
pull-requests: write
jobs:
badges:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: Matheus-RR/badges@v1
with:
products: |
python:3.12
node:20
kubernetes:1.34
badge-types: health,eol,cve
github-token: ${{ secrets.GITHUB_TOKEN }}
The Action scans for the / markers, updates the badge URLs, and opens a PR with the changes. Reviewing the PR lets you see what changed before merging.
Why a PR instead of a direct commit?
Badge content changes (a version goes EOL, a new CVE is published). A PR gives you a chance to verify the update before it lands in main.
Badge Builder
If you don’t want to type URLs, the Badge Builder lets you:
- Search 300 + products
- Pick badge types (health, EOL, CVE, latest version)
- Preview live
- Copy embed code in Markdown, HTML, reStructuredText, or AsciiDoc
Comparison with shields.io
- shields.io – static labels and CI metrics (build status, coverage, npm version). Great for pipeline status.
- ReleaseRun – live version intelligence: health grades that age, real‑time EOL countdowns, CVE counts that reflect the current threat landscape.
Use both: shields.io for CI pipeline status, ReleaseRun for dependency health.
Query parameters
All badges accept optional query parameters, e.g.:
https://img.releaserun.com/badge/health/python.svg?style=flat-square&label=runtime
| Parameter | What it does |
|---|---|
style | flat (default) or flat-square |
label | Custom left‑side text |
color | Override right‑side color |
labelColor | Override left‑side color |
Service architecture
The service queries endoflife.date for version lifecycle data, enriches it with CVE data from NVD, computes health grades, and renders SVG badges on the fly via pybadges.
Four cache layers keep it fast:
- In‑memory SVG cache (2 min) → sub‑50 ms for repeat requests
- Data cache (5 min) → limits upstream API calls
- HTTP cache headers → browser + CDN caching
- Cloudflare CDN → global edge
Badges are never more than 5 minutes stale.
Example badges




Documentation & resources
- Full docs & product list:
- GitHub Action:
- Badge Builder:
- ReleaseRun tracks software releases across 300 + technologies. The badge service is free.