Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,15 @@ against the source-package minimum. A newer downloaded table cannot silently rem
the kernel mappings shipped with this client. If it lacks those mappings,
the client reports the mismatch and retains its installed table.

On Ubuntu 22.04 and 24.04, the `generic` and `generic-64k` kernels built from
the GA `linux` source package (5.15 and 6.8) are also graded per CVE against
the Ubuntu tracker for
[CVE-2026-64531](https://ubuntu.com/security/CVE-2026-64531) and
[CVE-2026-64378](https://ubuntu.com/security/CVE-2026-64378). A `needed` or
`pending` tracker state fails because Ubuntu has not released a fix. A
`released` state compares the running ABI with the published fixed ABI after
the standard bulletin grace period. Other kernel trains are not applicable.

An absent host Docker installation or an absent CUDA Toolkit in the inspected
scope remains not applicable. This differs from an unreadable tool or failed
probe, which remains unknown. A complete bare-metal PCI scan with no VFIO
Expand Down
4 changes: 4 additions & 0 deletions cmax/audit_report.py
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,10 @@ def _harness_not_applicable(harness: str) -> str:
"security.guestKernel.newerInstalled": (
"The audit did not find a newer installed kernel that is waiting for a reboot."
),
"security.guestKernel.ubuntuCveStatus": (
"Ubuntu tracks a released fix for each graded kernel CVE and the running "
"kernel meets it."
),
"security.ubuntuNobleKernelMinimum.status": (
"The running Ubuntu Noble kernel meets the aggregate published security minimum."
),
Expand Down
1 change: 1 addition & 0 deletions cmax/criteria_links.py
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,7 @@
"securityVersions.dpuHostIsolation.status": _SECURITY_ISOLATION,
"security.januscape.status": _SECURITY_ESCALATION,
"security.guestKernel.newerInstalled": _SECURITY_PATCHING,
"security.guestKernel.ubuntuCveStatus": _SECURITY_PATCHING,
"security.ubuntuNobleKernelMinimum.status": _SECURITY_PATCHING,
"security.fragnesia.status": _SECURITY_PATCHING,
"security.badEpoll.status": _SECURITY_PATCHING,
Expand Down
44 changes: 44 additions & 0 deletions cmax/minimum_refresh.py
Original file line number Diff line number Diff line change
Expand Up @@ -232,6 +232,28 @@ def validate_bulletin_lists() -> None:
{"key": "linuxJanuscape", "cve": "CVE-2026-53359", "package": "linux"},
)

# Container-relevant GA kernel CVEs that the audit grades per CVE on Ubuntu
# 22.04 (5.15) and 24.04 (6.8). Ubuntu can track either CVE as `needed` or
# `pending` before it releases a fix. That state is a vulnerability finding, so
# `allowUnfixed` lets the entry publish without a fixed version.
UBUNTU_KERNEL_CVE_PACKAGES: tuple[dict[str, Any], ...] = (
{
"key": "linuxOpenvswitchNestedActions",
"cve": "CVE-2026-64531",
"package": "linux",
"abi": True,
"allowUnfixed": True,
},
{
"key": "linuxCgroupWriteback",
"cve": "CVE-2026-64378",
"package": "linux",
"abi": True,
"allowUnfixed": True,
},
)
UBUNTU_PACKAGES += UBUNTU_KERNEL_CVE_PACKAGES

# Ubuntu 26.04 (resolute) GA kernel fixes the audit grades by source package.
UBUNTU_RESOLUTE_PACKAGES: tuple[dict[str, Any], ...] = (
{"key": "linuxPwnescape", "cve": "CVE-2026-99999", "package": "linux"},
Expand Down Expand Up @@ -1901,6 +1923,8 @@ def resolve(spec: dict) -> tuple[str, dict]:
abi = kernel_abi(entry.get("fixed"))
if abi is not None:
entry["abi"] = abi
if spec.get("allowUnfixed"):
entry["allowUnfixed"] = True
return spec["key"], entry

# Independent package lookups must not add every slow Ubuntu response to
Expand Down Expand Up @@ -2739,6 +2763,7 @@ def build_minimums(
"package": "linux-hwe-6.8"},
{"key": "linuxPwnescape", "cve": "CVE-2026-99999",
"package": "linux-hwe-6.8"},
*UBUNTU_KERNEL_CVE_PACKAGES,
),
package_policy=(),
fetch=fetch,
Expand Down Expand Up @@ -2965,6 +2990,25 @@ def verify(doc: dict, existing: dict | None = None) -> None:
problems.append(f"{name}.{key}: released PwnEscape fix disappeared")
if state == "needed" and not old_entry.get("fixed"):
continue
# A per-CVE kernel entry graded from the tracker state. `needed`
# and `pending` are valid findings without a fixed version, but a
# released fix must never regress.
if entry.get("allowUnfixed") is True and not pwnescape:
state = entry.get("status")
if old_entry.get("fixed") and not entry.get("fixed"):
problems.append(
f"{name}.{key}: released fix {old_entry.get('fixed')} for "
f"{entry.get('cve')} disappeared"
)
continue
if state in {"needed", "pending"} and not entry.get("fixed"):
continue
if state not in {"needed", "pending", "released"}:
problems.append(
f"{name}.{key}: Ubuntu tracker status for {entry.get('cve')} "
f"is unverified ({state!r})"
)
continue
if entry.get("fixed"):
continue
was_fixed = old_entry.get("fixed")
Expand Down
76 changes: 75 additions & 1 deletion cmax/scripts/1-audit/audit-common.sh
Original file line number Diff line number Diff line change
Expand Up @@ -133,6 +133,75 @@ minimum_version_grace() {
fi
}

# grade_ubuntu_kernel_cves - grade the running Ubuntu general-availability
# kernel against the exact tracker state for the two container-relevant CVEs.
# A tracker status of needed or pending is vulnerable because Ubuntu has not
# released a supported fix. A released status compares the running ABI with the
# generated fixed ABI. Other Ubuntu kernel trains use different source packages
# and stay outside this check.
grade_ubuntu_kernel_cves() {
local os_id="${1:-unknown}" release="${2:-unknown}" running="${3:-unknown}"
local component="" expected_prefix="" key="" cve="" tracker="" fixed_abi=""
local running_abi="" vulnerable="" grace="" grace_periods=""
local unknown_count=0 checked=0
UBUNTU_KERNEL_CVE_STATUS="not-applicable"
UBUNTU_KERNEL_VULNERABLE_CVES_JSON="[]"
UBUNTU_KERNEL_CVE_GRACE_PERIODS_JSON="[]"

[[ "$os_id" == ubuntu ]] || return 0
case "$release" in
22.04) component="ubuntuJammy"; expected_prefix="5.15.0-" ;;
24.04) component="ubuntuNoble"; expected_prefix="6.8.0-" ;;
*) return 0 ;;
esac
[[ "$running" == "${expected_prefix}"* ]] || return 0
case "$running" in
*-generic|*-generic-64k) ;;
*) return 0 ;;
esac
running_abi=$(printf '%s\n' "$running" | sed -nE 's/^[0-9]+\.[0-9]+\.0-([0-9]+).*/\1/p')

for key in linuxOpenvswitchNestedActions linuxCgroupWriteback; do
cve=$(minimum_version "components.${component}.packages.${key}.cve")
tracker=$(minimum_version "components.${component}.packages.${key}.status")
fixed_abi=$(minimum_version "components.${component}.packages.${key}.abi")
case "$(printf '%s' "$tracker" | tr '[:upper:]' '[:lower:]')" in
needed|pending)
vulnerable="${vulnerable:+${vulnerable},}${cve}"
checked=$((checked + 1))
;;
released)
checked=$((checked + 1))
if [[ "$running_abi" =~ ^[0-9]+$ && "$fixed_abi" =~ ^[0-9]+$ ]]; then
if (( running_abi < fixed_abi )); then
if grace=$(minimum_version_grace "$component" "$key"); then
grace_periods="${grace_periods:+${grace_periods},}{\"cve\":\"${cve}\",\"policy\":${grace}}"
else
vulnerable="${vulnerable:+${vulnerable},}${cve}"
fi
fi
else
unknown_count=$((unknown_count + 1))
fi
;;
not-affected|dne)
checked=$((checked + 1))
;;
*) unknown_count=$((unknown_count + 1)) ;;
esac
done

UBUNTU_KERNEL_CVE_GRACE_PERIODS_JSON="[${grace_periods}]"
if [[ -n "$vulnerable" ]]; then
UBUNTU_KERNEL_CVE_STATUS="fail"
UBUNTU_KERNEL_VULNERABLE_CVES_JSON="[\"${vulnerable//,/\",\"}\"]"
elif (( unknown_count > 0 || checked == 0 )); then
UBUNTU_KERNEL_CVE_STATUS="unknown"
else
UBUNTU_KERNEL_CVE_STATUS="pass"
fi
}

# build_security_advisory_json - emit the Ubuntu Noble advisory members that
# every collector reports: fragnesia, januscape, qemuCve20243446, and vmscape.
#
Expand Down Expand Up @@ -1286,6 +1355,8 @@ build_audit_json() {
local security_advisory_json
local security_version_audit_json="${SECURITY_VERSION_AUDIT_JSON:-}"
januscape_exposed_json=$(json_bool_or_unknown "${WORKER_JANUSCAPE_EXPOSED:-}")
grade_ubuntu_kernel_cves "${WORKER_OS_ID:-unknown}" \
"${WORKER_OS_VERSION_ID:-unknown}" "${WORKER_GUEST_KERNEL_RUNNING:-unknown}"
if [[ "${AUDIT_TYPE:-}" == "standalone" \
&& "${WORKER_NVLINK_TOPOLOGY_CHECKED:-false}" == "true" ]]; then
nvlink_topology_coverage_complete=true
Expand Down Expand Up @@ -1613,7 +1684,10 @@ build_audit_json() {
"running": "${WORKER_GUEST_KERNEL_RUNNING:-unknown}",
"newestInstalled": "${WORKER_GUEST_KERNEL_NEWEST_INSTALLED:-unknown}",
"newerInstalled": ${WORKER_GUEST_KERNEL_NEWER_INSTALLED:-false},
"rebootRequired": ${WORKER_GUEST_REBOOT_REQUIRED:-false}
"rebootRequired": ${WORKER_GUEST_REBOOT_REQUIRED:-false},
"ubuntuCveStatus": "${UBUNTU_KERNEL_CVE_STATUS:-unknown}",
"ubuntuVulnerableCves": ${UBUNTU_KERNEL_VULNERABLE_CVES_JSON:-[]},
"ubuntuCveGracePeriods": ${UBUNTU_KERNEL_CVE_GRACE_PERIODS_JSON:-[]}
},
${security_advisory_json}
"nvidiaMay2026": {
Expand Down
22 changes: 22 additions & 0 deletions cmax/scripts/1-audit/audit_findings.py
Original file line number Diff line number Diff line change
Expand Up @@ -890,6 +890,12 @@ def _tenant_pod_guidance(
CONFIG,
_status_is("unknown"),
),
Rule(
"security.guestKernel.ubuntuCveStatus",
"Running Ubuntu kernel is vulnerable under the distribution CVE tracker",
VERSION,
_status_is("fail"),
),
Rule(
"security.fragnesia.status",
"Running kernel is exposed to Fragnesia and Dirty Frag",
Expand Down Expand Up @@ -1584,6 +1590,7 @@ def classify_suppression(key: str, audit: dict[str, Any]) -> tuple[str, str]:
"securityVersions.dpuHostIsolation.status": "security-dpu-host-isolation",
"security.januscape.status": "security-januscape",
"security.guestKernel.newerInstalled": "guest-kernel-current",
"security.guestKernel.ubuntuCveStatus": "guest-kernel-current",
"security.ubuntuNobleKernelMinimum.status": "ubuntu-kernel-minimum-version",
"security.fragnesia.status": "ubuntu-kernel-fragnesia-dirty-frag",
# CLI-only until the website catalog publishes a dedicated Bad Epoll row.
Expand Down Expand Up @@ -2088,6 +2095,21 @@ def detect_findings(values: dict[str, Any], *, source: str = "") -> list[Finding
detected, recommendation, cves, advisories = _finding_guidance(
audit, finding_rule, guidance_value
)
if rule.key == "security.guestKernel.ubuntuCveStatus":
# The finding names only the CVEs this kernel is vulnerable to.
vulnerable_cves = nested_get(
audit, "security", "guestKernel", "ubuntuVulnerableCves"
)
cves = (
tuple(
cve
for cve in vulnerable_cves
if isinstance(cve, str)
and re.fullmatch(r"CVE-\d{4}-\d+", cve)
)
if isinstance(vulnerable_cves, list)
else ()
)
findings.append(
Finding(
title=finding_rule.title,
Expand Down
7 changes: 6 additions & 1 deletion cmax/scripts/1-audit/cluster-audit-k8s.sh
Original file line number Diff line number Diff line change
Expand Up @@ -3569,6 +3569,8 @@ SECURITY_ADVISORY_JSON=$(build_security_advisory_json \
--januscape-status "${HP_JANUSCAPE_STATUS:-unknown}" \
--qemu-status "${HP_QEMU_3446_STATUS:-unknown}" \
--vmscape-status "${HP_VMSCAPE_STATUS:-unknown}")
grade_ubuntu_kernel_cves "${HP_BAD_EPOLL_OS:-unknown}" "${HP_BAD_EPOLL_RELEASE:-unknown}" \
"${HP_GUEST_KERNEL_RUNNING:-unknown}"

JSON_OUTPUT=$(cat <<EOF
{
Expand Down Expand Up @@ -3798,7 +3800,10 @@ JSON_OUTPUT=$(cat <<EOF
"running": "${HP_GUEST_KERNEL_RUNNING:-unknown}",
"newestInstalled": "${HP_GUEST_KERNEL_NEWEST:-unknown}",
"newerInstalled": ${HP_GUEST_KERNEL_NEWER:-false},
"rebootRequired": ${HP_GUEST_REBOOT_REQUIRED:-false}
"rebootRequired": ${HP_GUEST_REBOOT_REQUIRED:-false},
"ubuntuCveStatus": "${UBUNTU_KERNEL_CVE_STATUS:-unknown}",
"ubuntuVulnerableCves": ${UBUNTU_KERNEL_VULNERABLE_CVES_JSON:-[]},
"ubuntuCveGracePeriods": ${UBUNTU_KERNEL_CVE_GRACE_PERIODS_JSON:-[]}
},
${SECURITY_ADVISORY_JSON}
"nvidiaMay2026": {
Expand Down
80 changes: 80 additions & 0 deletions cmax/scripts/1-audit/minimum-versions.json
Original file line number Diff line number Diff line change
Expand Up @@ -1076,6 +1076,38 @@
},
"status": "released"
},
"linuxCgroupWriteback": {
"allowUnfixed": true,
"cve": "CVE-2026-64378",
"fixed": "",
"package": "linux",
"priority": "low",
"status": "needed"
},
"linuxOpenvswitchNestedActions": {
"abi": 190,
"allowUnfixed": true,
"cve": "CVE-2026-64531",
"fixAvailability": {
"available": "2026-08-20T22:05:40.365417",
"bulletinReleased": "2026-08-20T22:05:40.365417",
"feed": "ubuntu-security-notice",
"id": "USN-8658-1",
"status": "confirmed",
"url": "https://ubuntu.com/security/notices/USN-8658-1.json",
"version": "5.15.0-190.200"
},
"fixed": "5.15.0-190.200",
"package": "linux",
"priority": "high",
"released": "2026-08-20T22:05:40.365417",
"source": {
"feed": "ubuntu-security-notice",
"id": "USN-8658-1",
"url": "https://ubuntu.com/security/notices/USN-8658-1.json"
},
"status": "released"
},
"linuxPwnescape": {
"cve": "CVE-2026-99999",
"fixed": "",
Expand Down Expand Up @@ -1165,6 +1197,30 @@
},
"status": "released"
},
"linuxCgroupWriteback": {
"abi": 147,
"allowUnfixed": true,
"cve": "CVE-2026-64378",
"fixAvailability": {
"available": "2026-10-13T14:54:50.078429",
"bulletinReleased": "2026-10-13T14:54:50.078429",
"feed": "ubuntu-security-notice",
"id": "USN-8917-1",
"status": "confirmed",
"url": "https://ubuntu.com/security/notices/USN-8917-1.json",
"version": "6.8.0-147.147"
},
"fixed": "6.8.0-147.147",
"package": "linux",
"priority": "low",
"released": "2026-10-13T14:54:50.078429",
"source": {
"feed": "ubuntu-security-notice",
"id": "USN-8917-1",
"url": "https://ubuntu.com/security/notices/USN-8917-1.json"
},
"status": "released"
},
"linuxFragnesia": {
"abi": 124,
"cve": "CVE-2026-46300",
Expand Down Expand Up @@ -1240,6 +1296,30 @@
},
"status": "released"
},
"linuxOpenvswitchNestedActions": {
"abi": 138,
"allowUnfixed": true,
"cve": "CVE-2026-64531",
"fixAvailability": {
"available": "2026-08-18T18:08:07.783247",
"bulletinReleased": "2026-08-18T18:08:07.783247",
"feed": "ubuntu-security-notice",
"id": "USN-8643-1",
"status": "confirmed",
"url": "https://ubuntu.com/security/notices/USN-8643-1.json",
"version": "6.8.0-138.138"
},
"fixed": "6.8.0-138.138",
"package": "linux",
"priority": "high",
"released": "2026-08-18T18:08:07.783247",
"source": {
"feed": "ubuntu-security-notice",
"id": "USN-8643-1",
"url": "https://ubuntu.com/security/notices/USN-8643-1.json"
},
"status": "released"
},
"linuxPwnescape": {
"cve": "CVE-2026-99999",
"fixAvailability": {
Expand Down
Loading
Loading