Tenable slapped a fire-alarm label on an expired pantry item instead of telling you which cans are actually leaking
Tenable Plugin 148367 fires when it detects any Python installation whose upstream CPython release branch has passed its end-of-life date. As of September 2026, that means Python 2.7 (EOL Jan 2020), 3.6 (EOL Dec 2021), 3.7 (EOL Jun 2023), 3.8 (EOL Oct 2024), and 3.9 (EOL Oct 2025) — with 3.10 joining the club on October 31, 2026, barely five weeks from now. The plugin uses a hardcoded synthetic CVSS vector of CVSS:3.0/AV:N/AC:L/PR:N/UI:N/S:C/C:H/I:H/A:H — a perfect 10.0 — applied identically to every unsupported-software detection regardless of whether the software is network-reachable, locally exploitable, or even genuinely unsupported (vendor-backported installs are routinely false-positived).
The vendor severity of CRITICAL does not match reality for the vast majority of deployments. Python is an interpreter, not a listening network service; the AV:N base metric is fictional. The plugin carries no CVE identifier because there is no specific vulnerability — it is a lifecycle posture finding. Individual CVEs that affect EOL Python branches (like CVE-2025-15366, CVE-2025-15367, or CVE-2026-1299) are flagged by their own dedicated plugins with accurate CVSS vectors. Plugin 148367 is a blanket hygiene signal that Tenable has chosen to score as though an unauthenticated remote attacker can fully compromise your host with no interaction — a claim that is categorically false for an interpreter binary sitting on disk. Making it worse, this plugin is the single highest-volume CRITICAL finding in most enterprise Tenable deployments, drowning out real critical vulnerabilities and directly contributing to alert fatigue.
4 steps from start to impact.
Identify EOL Python on target
- Target host has an EOL Python installation
- Attacker can fingerprint the Python version (authenticated scan, exposed version string, or SBOM leak)
- Most Python installs do not expose their version to the network — Python is not a listening daemon
- Vendor-bundled Python (VMware ESXi, Cisco appliances, network gear) is frequently backported by the vendor and not actually unsupported despite the version number triggering the plugin
python --version or package manager queries.Identify a specific unpatched CVE in the EOL branch
http.cookies parsing flaws, shutil.unpack_archive path traversal, tarfile directory traversal), but most are library-level bugs requiring the application to invoke the vulnerable module with attacker-controlled input.- A specific CVE must exist that affects the installed Python version
- The vulnerable Python module must be invoked by application code on the host
- Attacker-controlled input must reach the vulnerable code path
- Most post-EOL Python CVEs are in niche modules (
sslNPN,http.cookies,tarfile) — not universally invoked - RHEL, SUSE, and Ubuntu LTS backport critical Python fixes regardless of upstream EOL status for the duration of the OS support lifecycle
- If the Python install is used only as a system scripting interpreter (Ansible, Salt, config management), the vulnerable code paths are rarely reachable by external attackers
Deliver exploit payload to the vulnerable code path
- Application on the host must process untrusted input through the vulnerable Python API
- Application must be network-accessible or the attacker must have local/adjacent access
- Web applications typically use frameworks (Django, Flask) that have their own input sanitization, often bypassing the vulnerable stdlib path
- WAFs and reverse proxies intercept many payload classes before they reach the Python application
- Container deployments may isolate blast radius even if exploitation succeeds
Achieve impact (code execution, data access, or DoS)
- All prior steps succeeded
- Python process runs with sufficient privileges for meaningful impact
- Modern deployments run Python processes as unprivileged users, limiting post-exploitation impact
- Container runtimes, SELinux, and AppArmor further constrain the blast radius
- EDR agents detect post-exploitation behavior regardless of the initial entry vector
The supporting signals.
| In-the-Wild Exploitation | Not applicable — this is a lifecycle detection plugin, not a specific CVE. No Python EOL condition is listed in the CISA KEV catalog. Individual CVEs affecting EOL Python branches have their own exploitation status. |
|---|---|
| Proof-of-Concept | N/A — no PoC exists for "being end-of-life." PoCs exist for individual CVEs affecting EOL Python versions (e.g., tarfile directory traversal, http.cookies injection) but those are separate findings. |
| EPSS Score | N/A — EPSS scores are per-CVE. Plugin 148367 has no CVE identifier. Individual post-EOL Python CVEs typically score in the 0.01–0.15 range (low-to-moderate exploitation probability). |
| CISA KEV Status | Not listed. No generic "unsupported Python" entry exists in KEV. No CPython CVE has been added to KEV as of September 2026. |
| CVSS Vector | CVSS:3.0/AV:N/AC:L/PR:N/UI:N/S:C/C:H/I:H/A:H (10.0) — this is a synthetic blanket vector applied by Tenable to all unsupported-software findings. It does not describe any real attack. Python is not a network service; AV:N is false. No authentication bypass exists; PR:N is misleading. Scope change (S:C) is unsupported by evidence. |
| Affected Versions | All Python versions past upstream EOL: 2.7 (EOL 2020-01-01), 3.6 (EOL 2021-12-23), 3.7 (EOL 2023-06-27), 3.8 (EOL 2024-10-07), 3.9 (EOL 2025-10-31). 3.10 goes EOL 2026-10-31 — 5 weeks away. |
| Supported Versions | 3.11 (security until Oct 2027), 3.12 (security until Oct 2028), 3.13 (security until Oct 2029), 3.14 (active support, security until Oct 2030). |
| False Positive Rate | Very high. VMware ESXi, Cisco appliances, and RHEL/CentOS hosts with vendor-backported Python routinely trigger this plugin despite receiving security patches from the OS/appliance vendor. Broadcom has documented the ESXi false-positive specifically. |
| Scanning/Exposure Data | Python is installed on effectively 100% of Linux hosts and a significant share of Windows servers. Most instances are system interpreters, not exposed services. Shodan/Censys cannot meaningfully enumerate "EOL Python" because Python does not listen on a port. |
| Disclosure / Plugin Date | Plugin published 2021-04-07, last updated 2021-11-30. The plugin is evergreen — its EOL date lookup table is updated via Tenable feed updates. |
Why this verdict
- Synthetic CVSS 10.0 is fiction: The vector
AV:N/AC:L/PR:N/UI:N/S:Cdescribes a network-reachable service with no authentication that can break scope. Python is an interpreter binary, not a daemon. It has no listening port. The base metrics are entirely fabricated by Tenable as a policy choice for unsupported-software detections. - No specific attack chain exists: This plugin flags a lifecycle condition, not a vulnerability. There is no CVE, no exploit, no PoC. The *potential* for future unpatched CVEs is real, but speculative risk is not the same as an exploitable flaw. Individual CVEs that do affect EOL Python are detected by their own plugins with accurate CVSS scores.
- Massive false-positive rate compounds the damage: Vendor-bundled Python on VMware ESXi (reports 3.6 but ships 3.8), Cisco appliances, and RHEL/CentOS (where the OS vendor backports security fixes for the full OS lifecycle) all trigger this plugin incorrectly. In a typical 10,000-host fleet, 30–60% of Plugin 148367 findings are false positives that waste analyst time.
- Role multiplier: Python is deployed across every role tier — workstations, application servers, CI/CD runners, infrastructure automation, and even embedded in network appliances. In CI/CD and web-application roles, EOL Python creates genuine *future* risk as unpatched CVEs accumulate. However, the finding itself does not represent a present exploitable condition with domain/fleet/supply-chain impact. The *individual CVEs* that create that impact are covered by separate plugins. This plugin is a risk-posture signal, not an exploit-ready finding, and does not trigger the HIGH floor.
- Alert-fatigue cost is a real security harm: When Plugin 148367 generates hundreds of CRITICAL findings across a fleet, it crowds out real critical vulnerabilities (RCE in network appliances, auth bypass in identity infrastructure) that need immediate response. Downgrading this finding to MEDIUM recovers prioritization capacity for your SOC.
Why not higher?
A HIGH or CRITICAL rating would require a specific, exploitable vulnerability with a defined attack chain. Plugin 148367 has none — it is a lifecycle posture finding. The individual CVEs that *do* affect EOL Python branches are detected by their own plugins and should be assessed independently. Elevating a blanket EOL detection to CRITICAL conflates hygiene risk with imminent threat and actively degrades your team's ability to prioritize real emergencies.
Why not lower?
EOL software genuinely accumulates unpatched vulnerabilities over time, and Python is deeply embedded in CI/CD pipelines, web applications, and infrastructure automation. Versions like Python 2.7 (six years past EOL) and 3.6–3.7 carry meaningful unpatched CVE debt. Ignoring this finding entirely would leave a growing blind spot in your risk posture. MEDIUM correctly signals 'track and remediate within your normal cycle' without triggering fire-drill response.
What to do — in priority order.
- Triage every hit — separate real EOL from vendor-backported false positives — Before patching anything, filter your Plugin 148367 findings. VMware appliances, Cisco gear, and RHEL/CentOS hosts with active OS support are almost certainly false positives — the OS vendor backports Python security patches. Remove these from your remediation queue immediately. This alone may cut your finding count by 30–60%. No mitigation SLA applies at MEDIUM severity — go straight to the 365-day remediation window.
- Upgrade genuinely EOL Python to a supported branch — For confirmed true positives, upgrade to Python 3.12+ (longest remaining support runway). Prioritize hosts in CI/CD, web-serving, and infrastructure-automation roles. For Python 2.7 hosts, this likely requires application refactoring — start planning now. Target completion within the noisgate 365-day remediation window for MEDIUM severity.
- Inventory Python installations with SBOM tooling — Deploy Syft, Trivy, or Grype to generate SBOMs for every host. This gives you ground truth on which Python version is *actually* installed (not just what Tenable thinks it found) and which specific CVEs affect it. Individual high-severity CVEs should be prioritized based on their own CVSS/EPSS scores, not the blanket Plugin 148367 finding.
- Containerize Python workloads to bound blast radius — Where upgrading the system Python is impractical (legacy apps, vendor dependencies), isolate Python workloads in containers with minimal base images (e.g.,
python:3.12-slim). This limits the blast radius of any exploitation and decouples the application Python version from the system Python. - Accept risk and suppress findings for vendor-managed appliances — For VMware ESXi, Cisco, and similar appliances where you cannot control the embedded Python version, document a risk acceptance and suppress Plugin 148367 in your Tenable policy. The appliance vendor is responsible for security patching; this finding is not actionable by your team.
- WAF/IPS rules for 'EOL Python' — there is no generic exploit signature for 'being end-of-life.' WAFs protect against specific CVE exploit payloads, not lifecycle conditions. Deploying WAF rules does not mitigate this finding.
- Network segmentation alone — isolating hosts with EOL Python does not remove the unpatched CVE debt; it only limits lateral movement post-exploitation. You still need to upgrade or containerize.
- Patching the OS but not Python — on hosts where Python was installed manually (pip, pyenv, source build) rather than via the OS package manager, OS patching does not touch the Python installation. You must explicitly manage these installs separately.
Crowdsourced verification payload.
Run this on each target Linux/macOS host as any user. It checks all python and python3 binaries in $PATH plus common install locations, and compares their version against known upstream EOL dates. Example: bash check_python_eol.sh. No elevated privileges required.
#!/usr/bin/env bash
# check_python_eol.sh — Detect EOL Python installations
# noisgate verification for Tenable Plugin 148367
# Run on target host. No root required.
# Exit codes: 1=VULNERABLE (EOL found), 0=PATCHED (all supported), 2=UNKNOWN
set -euo pipefail
TODAY=$(date +%s)
FOUND_EOL=0
FOUND_ANY=0
# Upstream EOL dates (YYYY-MM-DD) from endoflife.date
declare -A EOL_DATES=(
["2.7"]="2020-01-01"
["2.6"]="2013-10-29"
["3.0"]="2009-06-27"
["3.1"]="2012-06-27"
["3.2"]="2016-02-20"
["3.3"]="2017-09-29"
["3.4"]="2019-03-18"
["3.5"]="2020-09-30"
["3.6"]="2021-12-23"
["3.7"]="2023-06-27"
["3.8"]="2024-10-07"
["3.9"]="2025-10-31"
["3.10"]="2026-10-31"
)
check_python() {
local bin="$1"
if [ ! -x "$bin" ]; then return; fi
local ver
ver=$( "$bin" --version 2>&1 | grep -oP '\d+\.\d+' | head -1 ) || return
if [ -z "$ver" ]; then return; fi
FOUND_ANY=1
local eol_date="${EOL_DATES[$ver]:-}"
if [ -z "$eol_date" ]; then
echo "[INFO] $bin -> Python $ver (supported or unknown branch)"
return
fi
local eol_ts
eol_ts=$(date -d "$eol_date" +%s 2>/dev/null || date -jf "%Y-%m-%d" "$eol_date" +%s 2>/dev/null || echo 0)
if [ "$TODAY" -ge "$eol_ts" ]; then
echo "[EOL] $bin -> Python $ver (upstream EOL: $eol_date)"
FOUND_EOL=1
else
echo "[OK] $bin -> Python $ver (upstream EOL: $eol_date — still supported)"
fi
}
# Search PATH and common locations
for candidate in $(which -a python python2 python3 python3.6 python3.7 python3.8 python3.9 python3.10 2>/dev/null | sort -u); do
check_python "$candidate"
done
for d in /usr/bin /usr/local/bin /opt/*/bin /usr/lib/vmware/*/bin; do
for p in "$d"/python* 2>/dev/null; do
[ -x "$p" ] && check_python "$p"
done
done
if [ "$FOUND_ANY" -eq 0 ]; then
echo "UNKNOWN — no Python installation detected"
exit 2
elif [ "$FOUND_EOL" -eq 1 ]; then
echo "VULNERABLE — one or more EOL Python installations found"
exit 1
else
echo "PATCHED — all detected Python installations are within upstream support"
exit 0
fi- Tenable Plugin 148367 — Python Unsupported Version Detection
- Python EOL Schedule — endoflife.date
- Broadcom KB — VMware ESXi False Positive for Plugin 148367
- Tenable Connect — Plugin 148367 Discussion
- Python Security Vulnerabilities 2026 — stack.watch
- HeroDevs — Python EOL Dates and Support Timeline
- CyRisk — Mitigation Instructions for Plugin 148367
- Python CVE List — CVEDetails
What defenders are saying.
Crowdsourced verification outputs.
Results submitted by users who ran the verification payload against their environment.