When a vulnerability is fixed upstream, the question most teams actually need answered is narrower: has my distribution shipped the fix in the package I run? The upstream version number won't tell you. Debian, Ubuntu and Red Hat backport security fixes into the version they already ship, so a RHEL 9 Libreswan "4.15" can contain a fix that upstream only released in 5.3.2. Answering the question means reading the distribution's own security data.
This guide is for engineers who run Linux servers or build container images on distribution packages. It covers where each major distribution publishes fix status, what their status values mean, a script that checks Debian, Ubuntu, Red Hat and Alpine for any CVE in one go, and what this week's data shows about how differently they move.
The short answer
Don't compare your package version with the upstream fixed version. Check the distribution's security data for the CVE: Debian's security tracker, Ubuntu's CVE tracker (both mirrored into OSV as DEBIAN-CVE-* and UBUNTU-CVE-* records), Red Hat's security data API, and Alpine's secdb. On the host itself, the package changelog is the final word. For the same CVE, distributions can be weeks apart. On 14 October, Alpine had shipped this week's Libreswan fix in every supported branch while Debian, Ubuntu and RHEL had not, and a July Libreswan fix still hadn't reached Debian stable or any Ubuntu LTS release.
Why version numbers mislead
Stable distributions freeze a version and then patch it. Red Hat fixed July's Libreswan CVE-2026-14957, which upstream fixed in 5.3.2, in packages called libreswan-4.12-2.el8_10.6 (RHEL 8) and libreswan-4.15-10.el9_8 (RHEL 9). A scanner that compares 4.15 with 5.3.2 reports a vulnerability that has already been fixed. The reverse mistake matters more. A version that looks new enough upstream can still lack a fix the distribution hasn't backported, and only distribution data says so.
The release suffix is where the fix lives: -10.el9_8 in RPMs, -2.5 or +deb12u2 in Debian packages, -r0 in Alpine. That's why serious container and host scanners read distribution security feeds rather than upstream advisories for OS packages.
Where each distribution publishes it
| Distribution | Source | Per-CVE status values | Notes |
|---|---|---|---|
| Debian | security-tracker.debian.org, also as OSV DEBIAN-CVE-* records | open, resolved (with fixed version), not-affected, plus no-dsa and unimportant notes | The full JSON export covers every package and is large. OSV is easier per CVE |
| Ubuntu | ubuntu.com/security/cves, also as OSV UBUNTU-CVE-* records | needs-triage, needed, deferred, released, not-affected, ignored | Includes Ubuntu Pro releases for older LTS versions |
| Red Hat | Security data API, access.redhat.com/hydra/rest/securitydata/cve/<CVE>.json, plus CSAF/VEX files | affected_release lists shipped errata (RHSA). package_state gives Affected, Not affected, Will not fix, Fix deferred, Out of support scope | Covers RHEL, OpenShift and layered products |
| Alpine | secdb.alpinelinux.org per branch and repository (main, community) | Lists fixes only: a CVE appears under the package release that fixed it, or under 0 if Alpine was never affected | No entry means no fix recorded, not "safe" |
Check any CVE across all four
This script queries OSV for Debian and Ubuntu, the Red Hat API, and Alpine's secdb for the main and community repositories of the newest branches, and prints one status line per release:
#!/usr/bin/env python3
"""Has my distribution shipped the fix? For each CVE, show per-release fix status
from Debian and Ubuntu (via OSV's DEBIAN-CVE / UBUNTU-CVE records), Red Hat (its
security data API) and Alpine (secdb). Distros backport fixes into old version
numbers, so compare against these, not against the upstream fixed version.
Usage: python3 distro_fix_status.py CVE-2026-94453 [CVE-...]"""
import json, sys, urllib.error, urllib.request
ALPINE = ["v3.23", "v3.24", "edge"]
def get(url):
try:
with urllib.request.urlopen(urllib.request.Request(url, headers={"User-Agent": "distro-fix"}), timeout=60) as r:
return json.load(r)
except urllib.error.HTTPError as e:
if e.code == 404:
return None
raise
alpine = {f"{b}/{repo}": get(f"https://secdb.alpinelinux.org/{b}/{repo}.json") for b in ALPINE for repo in ("main", "community")}
def osv_distro(prefix, cve):
rec = get(f"https://api.osv.dev/v1/vulns/{prefix}-{cve}")
if not rec:
return [" no record"]
out = []
for a in rec.get("affected", []):
fixed = [e["fixed"] for r in a.get("ranges", []) for e in r.get("events", []) if "fixed" in e]
rel = a["package"]["ecosystem"].split(":", 1)[1]
out.append(f" {rel:<16} {a['package']['name']:<14} {'fixed in ' + fixed[0] if fixed else 'NO FIX YET'}")
return out or [" record has no affected packages"]
def redhat(cve):
d = get(f"https://access.redhat.com/hydra/rest/securitydata/cve/{cve}.json")
if not d:
return [" no record"]
out = [f" {r['product_name'][:40]:<40} fixed by {r.get('advisory')} ({r.get('package')})" for r in d.get("affected_release", [])]
out += [f" {p['product_name'][:40]:<40} {p.get('package_name') or '':<14} {p.get('fix_state')}" for p in d.get("package_state", [])]
return [f" severity: {d.get('threat_severity')}"] + (out or [" no product entries"])
def alpine_status(cve):
out = []
for branch, db in alpine.items():
hits = [(p["pkg"]["name"], v) for p in (db or {}).get("packages", [])
for v, ids in p["pkg"].get("secfixes", {}).items() if cve in ids]
for name, v in hits:
out.append(f" {branch:<16} {name:<14} {'not affected' if v == '0' else 'fixed in ' + v}")
if not hits:
out.append(f" {branch:<16} (not listed: no fix recorded, or not packaged here)")
return out
for cve in sys.argv[1:]:
print(f"\n{cve}")
for name, lines in (("Debian", osv_distro("DEBIAN", cve)), ("Ubuntu", osv_distro("UBUNTU", cve)),
("Red Hat", redhat(cve)), ("Alpine", alpine_status(cve))):
print(f" {name}")
for line in lines:
print(line)
Run on 14 October for this week's Libreswan use-after-free and OpenVPN's NUL-byte certificate bug:
$ python3 distro_fix_status.py CVE-2026-94453 CVE-2026-84790
CVE-2026-94453
Debian
12 libreswan NO FIX YET
13 libreswan NO FIX YET
14 libreswan NO FIX YET
Ubuntu
no record
Red Hat
severity: Important
Fast Datapath for RHEL 9 libreswan Affected
Red Hat Enterprise Linux 10 libreswan Affected
Red Hat Enterprise Linux 6 libreswan Out of support scope
Red Hat Enterprise Linux 7 libreswan Affected
Red Hat Enterprise Linux 8 libreswan Affected
Red Hat Enterprise Linux 9 libreswan Affected
Red Hat OpenShift Container Platform 4 libreswan Affected
Red Hat OpenShift Container Platform 4 openshift/ose-rhel-coreos-9 Affected
Alpine
v3.23/main (not listed: no fix recorded, or not packaged here)
v3.23/community libreswan fixed in 5.3.3-r0
v3.24/main (not listed: no fix recorded, or not packaged here)
v3.24/community libreswan fixed in 5.3.3-r0
edge/main (not listed: no fix recorded, or not packaged here)
edge/community libreswan fixed in 5.3.3-r0
CVE-2026-84790
Debian
12 openvpn NO FIX YET
13 openvpn NO FIX YET
14 openvpn fixed in 2.7.8-1
Ubuntu
Pro:14.04:LTS openvpn NO FIX YET
Pro:16.04:LTS openvpn NO FIX YET
Pro:18.04:LTS openvpn NO FIX YET
20.04:LTS openvpn NO FIX YET
22.04:LTS openvpn NO FIX YET
24.04:LTS openvpn NO FIX YET
26.04:LTS openvpn NO FIX YET
Red Hat
no record
Alpine
v3.23/main (not listed: no fix recorded, or not packaged here)
v3.23/community (not listed: no fix recorded, or not packaged here)
v3.24/main (not listed: no fix recorded, or not packaged here)
v3.24/community (not listed: no fix recorded, or not packaged here)
edge/main (not listed: no fix recorded, or not packaged here)
edge/community (not listed: no fix recorded, or not packaged here)
What this week's data shows
The same three CVEs, summarised:
| CVE (upstream fix date) | Debian | Ubuntu | Red Hat | Alpine |
|---|---|---|---|---|
| Libreswan CVE-2026-94453 (5 Oct) | No fix in 12, 13 or 14 | No record yet | Affected on RHEL 7 to 10, no erratum | Fixed in 5.3.3-r0 on v3.23, v3.24 and edge |
| OpenVPN CVE-2026-84790 (7 Oct) | Fixed in 14 (2.7.8-1) only | No fix in any listed LTS | No record (not a RHEL package) | No fix recorded |
| Libreswan CVE-2026-14957 (15 Jul) | Fixed in 14 (5.2-2.5) only | No fix in 18.04 to 26.04 | Errata for RHEL 8, 9 and 10, including EUS streams | Fixed (5.3.2-r0 or 5.3.3-r0) |
Three things stand out. Rolling and fast-moving releases (Alpine, Debian testing) pick up upstream versions quickly. Stable releases wait for a backport. And three months after July's Libreswan fix, Debian stable and every Ubuntu LTS still showed no fixed package, while Red Hat had shipped errata across its supported streams. None of that is visible from the upstream advisory, and your scanner only knows if it reads these feeds.
On the host: read the changelog
Tracker data tells you what has shipped. The changelog on the machine tells you what is installed:
# RPM-based (RHEL, Fedora, Rocky, Alma)
rpm -q --changelog libreswan | grep -E 'CVE-2026-(94453|14957)'
# Debian and Ubuntu
zgrep -E 'CVE-2026-(94453|14957)' /usr/share/doc/libreswan/changelog.Debian.gz
# Alpine (the package's secfixes are recorded in secdb; check the installed release)
apk version libreswan
If the CVE ID appears in the changelog of the installed package, the fix is in, whatever the version number says. Most distributions mention CVE IDs in changelog entries for security uploads, so a script can check this across a fleet.
What to do when your distribution lags
- Apply the upstream workaround first. For Libreswan's use-after-free,
listen-tcp=noremoves the exposure without any package change. - Check whether the CVE matters to your configuration. Distributions sometimes defer fixes for issues that need a non-default setting. Their trackers often say so in a note.
- Watch the tracker entry, not just your scanner. The tracker status changes when the distribution ships or decides on a fix, and it often carries a note explaining a deferral.
- For internet-facing services, consider the release you build on. If a component sits on your attack surface, a distribution that moves quickly for that package, or a supported upstream build, may be the better trade than the newest stable release.
- Don't silence the finding because the version looks old. Use the changelog check above to tell a backported fix from a missing one.
The fair view
Slower isn't careless. Stable distributions exist so that a security update doesn't also change behaviour, and backporting a fix into an older code base takes engineering time, especially when the fix touches code that has since been refactored. Some CVEs are deliberately left for a point release because the risk is low or depends on non-default settings. What isn't reasonable is assuming the upstream fix date is your fix date. For base images in particular, see how the main options compare in our Alpine vs distroless vs Ubuntu comparison.